Az - Function Apps

Reading time: 12 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 지원하기

기본 정보

Azure Function Apps서버리스 컴퓨트 서비스로, 기본 인프라를 관리하지 않고도 함수라고 불리는 작은 코드 조각을 실행할 수 있게 해줍니다. 이들은 HTTP 요청, 타이머 또는 Blob Storage나 Event Hubs와 같은 다른 Azure 서비스의 이벤트와 같은 다양한 트리거에 응답하여 코드를 실행하도록 설계되었습니다. Function Apps는 C#, Python, JavaScript, Java 등 여러 프로그래밍 언어를 지원하여 이벤트 기반 애플리케이션, 워크플로 자동화 또는 서비스 통합을 구축하는 데 유용합니다. 일반적으로 코드가 실행될 때 사용된 컴퓨트 시간에 대해서만 비용을 지불하므로 비용 효율적입니다.

note

Functions는 App Services의 하위 집합이므로, 여기서 논의된 많은 기능은 Azure Apps(webapp in cli)로 생성된 애플리케이션에서도 사용됩니다.

다양한 요금제

  • Flex Consumption Plan: 수요에 따라 함수 인스턴스를 추가하거나 제거하는 동적 이벤트 기반 스케일링을 제공하며, 사용한 만큼만 지불하는 요금제를 제공합니다. 가상 네트워킹사전 프로비저닝된 인스턴스를 지원하여 콜드 스타트를 줄여주며, 컨테이너 지원이 필요하지 않은 변동 작업 부하에 적합합니다.
  • Traditional Consumption Plan: 기본 서버리스 옵션으로, 함수가 실행될 때만 컴퓨트 리소스에 대해 지불합니다. 수신 이벤트에 따라 자동으로 스케일링되며 콜드 스타트 최적화가 포함되어 있지만, 컨테이너 배포는 지원하지 않습니다. 자동 스케일링이 필요한 간헐적 작업 부하에 이상적입니다.
  • Premium Plan: 일관된 성능을 위해 설계되었으며, 콜드 스타트를 없애기 위해 사전 예열된 작업자를 제공합니다. 연장된 실행 시간, 가상 네트워킹을 제공하며, 사용자 정의 Linux 이미지를 지원하여 높은 성능과 고급 기능이 필요한 미션 크리티컬 애플리케이션에 적합합니다.
  • Dedicated Plan: 예측 가능한 청구가 가능한 전용 가상 머신에서 실행되며, 수동 또는 자동 스케일링을 지원합니다. 동일한 요금제에서 여러 앱을 실행할 수 있으며, 컴퓨트 격리를 제공하고 App Service Environments를 통해 안전한 네트워크 액세스를 보장하여 일관된 리소스 할당이 필요한 장기 실행 애플리케이션에 이상적입니다.
  • Container Apps: 관리되는 환경에서 컨테이너화된 함수 앱을 배포할 수 있으며, 마이크로서비스 및 API와 함께 사용할 수 있습니다. 사용자 정의 라이브러리, 레거시 앱 마이그레이션 및 GPU 처리를 지원하여 Kubernetes 클러스터 관리를 없앱니다. 이벤트 기반, 확장 가능한 컨테이너화된 애플리케이션에 적합합니다.

저장소 버킷

컨테이너화되지 않은 새로운 Function App을 생성할 때, 코드 및 기타 Function 관련 데이터는 저장소 계정에 저장됩니다. 기본적으로 웹 콘솔은 코드를 저장하기 위해 함수당 새 저장소 계정을 생성합니다.

또한, 버킷 내의 코드를 수정하면 (저장될 수 있는 다양한 형식에서) 앱의 코드가 새 코드로 수정되고 다음에 함수가 호출될 때 실행됩니다.

caution

공격자의 관점에서 매우 흥미로운 점은 이 버킷에 대한 쓰기 권한이 공격자가 코드를 손상시키고 Function App 내의 관리되는 ID에 대한 권한을 상승시킬 수 있게 해준다는 것입니다.

이에 대한 자세한 내용은 권한 상승 섹션에서 확인할 수 있습니다.

저장소 계정의 azure-webjobs-secrets 컨테이너 내에 마스터 및 함수 키가 저장되어 있으며, <app-name> 폴더 내의 JSON 파일에서 찾을 수 있습니다.

Functions는 또한 코드를 원격 위치에 저장할 수 있으며, 그 URL을 지정하기만 하면 됩니다.

네트워킹

HTTP 트리거를 사용할 때:

  • 인터넷의 모든 사용자에게 함수에 대한 액세스를 제공하거나 IAM 기반으로 액세스를 제공할 수 있습니다. 이 액세스를 제한하는 것도 가능합니다.
  • **내부 네트워크(VPC)**에서 Function App에 대한 액세스를 제공하거나 제한할 수도 있습니다.

caution

공격자의 관점에서 매우 흥미로운 점은 취약한 Function이 인터넷에 노출되어 있을 경우 내부 네트워크로 피벗할 수 있는 가능성이 있다는 것입니다.

Function App 설정 및 환경 변수

앱 내에서 환경 변수를 구성할 수 있으며, 이 변수는 민감한 정보를 포함할 수 있습니다. 또한 기본적으로 AzureWebJobsStorageWEBSITE_CONTENTAZUREFILECONNECTIONSTRING (기타 포함)과 같은 환경 변수가 생성됩니다. 이들은 애플리케이션 데이터가 포함된 저장소 계정을 완전 권한으로 제어하는 계정 키를 포함하고 있기 때문에 특히 흥미롭습니다. 이러한 설정은 저장소 계정에서 코드를 실행하는 데에도 필요합니다.

이러한 환경 변수 또는 구성 매개변수는 Function이 코드를 실행하는 방식을 제어하며, 예를 들어 **WEBSITE_RUN_FROM_PACKAGE**가 존재하면 애플리케이션 코드가 위치한 URL을 나타냅니다.

Function Sandbox

리눅스 샌드박스 내에서 소스 코드는 **/home/site/wwwroot**의 function_app.py 파일에 위치하며 (Python을 사용하는 경우), 코드를 실행하는 사용자는 **app**입니다 (sudo 권한 없음).

Windows 함수에서 NodeJS를 사용하는 경우 코드는 **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의 일부입니다.

관리되는 ID 및 메타데이터

VMs와 마찬가지로, Functions는 시스템 할당사용자 할당의 두 가지 유형의 Managed Identities를 가질 수 있습니다.

시스템 할당된 ID는 해당 함수만 사용할 수 있는 관리되는 ID이며, 사용자 할당된 관리되는 ID는 다른 Azure 서비스가 사용할 수 있는 관리되는 ID입니다.

note

VMs와 마찬가지로, Functions는 1개의 시스템 할당 관리되는 ID와 여러 사용자 할당 관리되는 ID를 가질 수 있으므로, 함수를 손상시키면 모든 관리되는 ID를 찾는 것이 항상 중요합니다. 하나의 Function에서 여러 관리되는 ID로 권한을 상승시킬 수 있습니다.

시스템 관리 ID가 사용되지 않고 하나 이상의 사용자 관리 ID가 함수에 연결된 경우, 기본적으로 토큰을 얻을 수 없습니다.

PEASS 스크립트를 사용하여 메타데이터 엔드포인트에서 기본 관리 ID의 토큰을 얻을 수 있습니다. 또는 다음과 같이 수동으로 얻을 수 있습니다:

Cloud SSRF - HackTricks

모든 관리되는 ID를 확인하는 방법을 찾아야 하며, 이를 지정하지 않으면 메타데이터 엔드포인트는 기본 ID만 사용합니다 (자세한 내용은 이전 링크를 참조).

액세스 키

note

함수 호출을 위해 사용자에게 액세스를 부여하는 RBAC 권한이 없음을 유의하십시오. 함수 호출은 생성 시 선택된 트리거에 따라 달라지며, HTTP 트리거가 선택된 경우 액세스 키를 사용해야 할 수 있습니다.

HTTP 트리거를 사용하여 함수 내에서 엔드포인트를 생성할 때, 함수를 트리거하는 데 필요한 액세스 키 권한 수준을 지정할 수 있습니다. 세 가지 옵션이 있습니다:

  • ANONYMOUS: 모든 사용자가 URL을 통해 함수에 접근할 수 있습니다.
  • FUNCTION: 엔드포인트는 함수, 호스트 또는 마스터 키를 사용하는 사용자만 접근할 수 있습니다.
  • ADMIN: 엔드포인트는 마스터 키를 가진 사용자만 접근할 수 있습니다.

키 유형:

  • Function Keys: 함수 키는 기본 또는 사용자 정의일 수 있으며, Function App 내의 특정 함수 엔드포인트에 대한 액세스를 독점적으로 부여하도록 설계되었습니다. 이를 통해 엔드포인트에 대한 보다 세밀한 액세스가 가능합니다.
  • Host Keys: 호스트 키는 기본 또는 사용자 정의일 수 있으며, FUNCTION 액세스 수준으로 Function App 내의 모든 함수 엔드포인트에 대한 액세스를 제공합니다.
  • Master Key: 마스터 키(_master)는 모든 함수 엔드포인트에 대한 액세스를 포함하여 권한이 상승된 액세스를 제공하는 관리 키입니다. 이 키는 취소할 수 없습니다.
  • System Keys: 시스템 키는 특정 확장에 의해 관리되며, 내부 구성 요소에서 사용하는 웹훅 엔드포인트에 접근하는 데 필요합니다. 예를 들어, Event Grid 트리거 및 Durable Functions는 시스템 키를 사용하여 해당 API와 안전하게 상호작용합니다.

tip

키를 사용하여 함수 API 엔드포인트에 접근하는 예:

https://<function_uniq_name>.azurewebsites.net/api/<endpoint_name>?code=<access_key>

기본 인증

App Services와 마찬가지로, Functions는 SCMFTP에 연결하여 코드를 배포하기 위해 Azure에서 제공하는 사용자 이름과 비밀번호가 포함된 URL을 사용하여 기본 인증을 지원합니다. 이에 대한 자세한 내용은 다음에서 확인할 수 있습니다:

Az - Azure App Services

Github 기반 배포

함수가 Github 리포지토리에서 생성될 때 Azure 웹 콘솔은 특정 리포지토리에서 자동으로 Github Workflow를 생성할 수 있도록 하여 이 리포지토리가 업데이트될 때마다 함수의 코드가 업데이트됩니다. 실제로 Python 함수에 대한 Github Action yaml은 다음과 같습니다:

Github Action Yaml
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
# More info on Python, GitHub Actions, and Azure Functions: https://aka.ms/python-webapps-actions

name: Build and deploy Python project to Azure Function App - funcGithub

on:
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)

jobs:
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: Create and start virtual environment
run: |
python -m venv venv
source venv/bin/activate

- name: Install dependencies
run: pip install -r requirements.txt

# Optional: Add step to run tests here

- 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/

deploy:
runs-on: ubuntu-latest
needs: build

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

- 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: "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 }}

또한, Managed Identity가 생성되어 리포지토리의 Github Action이 이를 사용하여 Azure에 로그인할 수 있습니다. 이는 Managed Identity에 대해 Issuer https://token.actions.githubusercontent.comSubject Identifier repo:<org-name>/<repo-name>:ref:refs/heads/<branch-name>를 허용하는 Federated credential을 생성함으로써 이루어집니다.

caution

따라서, 해당 리포지토리를 손상시키는 사람은 함수와 이에 연결된 Managed Identities를 손상시킬 수 있습니다.

Container Based Deployments

모든 요금제가 컨테이너 배포를 허용하는 것은 아니지만, 허용하는 경우에는 구성에 컨테이너의 URL이 포함됩니다. API에서 linuxFxVersion 설정은 DOCKER|mcr.microsoft.com/...와 같은 형태를 가지며, 웹 콘솔에서는 구성에 image settings가 표시됩니다.

또한, 소스 코드는 함수와 관련된 스토리지 계정에 저장되지 않습니다. 필요하지 않기 때문입니다.

Enumeration

bash
# List all the functions
az functionapp list

# List functions in an function-app (endpoints)
az functionapp function list \
--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>
## 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>

# Get settings (and privesc to the sorage account)
az functionapp config appsettings list --name <app-name> --resource-group <res-group>

# Get access restrictions
az functionapp config access-restriction show --name <app-name> --resource-group <res-group>

# Check if a domain was assigned to a function app
az functionapp config hostname list --webapp-name <app-name> --resource-group <res-group>

# Get SSL certificates
az functionapp config ssl list --resource-group <res-group>

# Get network restrictions
az functionapp config access-restriction show --name <app-name> --resource-group <res-group>

# Get acess restrictions
az functionapp config access-restriction show --name <app-name> --resource-group <res-group>

# Get connection strings
az rest --method POST --uri "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/connectionstrings/list?api-version=2022-03-01"
az rest --method GET --uri "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/config/configreferences/connectionstrings?api-version=2022-03-01"

# Get SCM credentials
az functionapp deployment list-publishing-credentials --name <app-name> --resource-group <res-group>

# Get function, system and master keys
az functionapp keys list --name <app-name> --resource-group <res-group>

# Get Host key
az rest --method POST --uri "https://management.azure.com/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/functions/<function-endpoint-name>/listKeys?api-version=2022-03-01"

# Get source code with Master Key of the function
curl "<script_href>?code=<master-key>"
curl "https://<func-app-name>.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=<master-key>" -v

# Get source code using SCM access (Azure permissions or SCM creds)
az rest --method GET \
--url "https://<func-app-name>.azurewebsites.net/admin/vfs/home/site/wwwroot/function_app.py?code=<master-key>" \
--resource "https://management.azure.com/"

# Get source code with Azure permissions
az rest --url "https://management.azure.com/subscriptions/<subscription>/resourceGroups/<res-group>/providers/Microsoft.Web/sites/<app-name>/hostruntime/admin/vfs/function_app.py?relativePath=1&api-version=2022-03-01"
## Another example
az rest --url "https://management.azure.com/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Web/sites/ConsumptionExample/hostruntime/admin/vfs/HttpExample/index.js?relativePath=1&api-version=2022-03-01"

권한 상승

Az - Functions App Privesc

참고자료

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 지원하기