เข้าใจความเสี่ยงของ policy สอบถามเรื่อง policy ได้ด้วยภาษาทั่วไป ขอชมการสาธิต →
Published:
การตัด kill chain ของผู้โจมตีใน AWS: IAM Roles
by FireMon
ตลอดปีที่ผ่านมา ผมเห็นความสนใจเพิ่มขึ้นอย่างมากในคำแนะนำเชิงปฏิบัติสำหรับการรับมือ security incidents ภายในระบบคลาวด์ด้วยเทคนิคแบบ cloud native เมื่อองค์กรย้าย production workload ขึ้นคลาวด์ ไม่นานนักผู้เชี่ยวชาญด้านความปลอดภัยก็จะพบว่าหลักการพื้นฐานนั้น แม้จะคล้ายกันในเชิงแนวคิด แต่ในทางปฏิบัติกลับแตกต่างกันพอสมควร หนึ่งในแนวคิดหลักเหล่านั้นคือ kill chain ซึ่งเป็นคำที่ถูกบัญญัติขึ้นครั้งแรกโดย Lockheed Martin เพื่ออธิบายกระบวนการทำงานของผู้โจมตี หากตัดห่วงโซ่ใดห่วงโซ่หนึ่งได้ การโจมตีก็จะล้มเหลว แนวคิดนี้จึงสอดคล้องอย่างดีกับการผสมผสาน defense in depth เข้ากับองค์ประกอบเชิงรุกของ incident response
ในการใช้งานบนคลาวด์ การโจมตีแบ่งได้เป็นสี่ประเภทหลัก แต่ละประเภทมี kill chain ที่แตกต่างกัน
- การโจมตีตัวแพลตฟอร์มคลาวด์เอง หากไม่นับกรณีที่ผู้ให้บริการคลาวด์ถูกเจาะในระดับรากฐาน (ซึ่งอยู่นอกเหนือการควบคุมของลูกค้าคลาวด์) การโจมตีลักษณะนี้มักมุ่งไปที่การตั้งค่าบริการคลาวด์ที่ผิดพลาด หากคุณเปิด S3 bucket เป็นสาธารณะ ไม่ได้ตั้ง authorizer บน API Gateway หรือเปิดเผย credentials ของ AWS บน GitHub ทั้งหมดนี้จัดอยู่ในประเภทนี้
- การโจมตีทรัพยากรและแอปพลิเคชันที่ลูกค้าติดตั้งบนคลาวด์ การโจมตีแบบดั้งเดิมเหล่านี้ไม่ต่างจากที่เกิดขึ้นกับดาต้าเซ็นเตอร์ของคุณ ตัวอย่างที่พบบ่อยคือ SQL injection ในเว็บแอปพลิเคชัน และเซิร์ฟเวอร์ที่มีช่องโหว่ซึ่งเปิดพอร์ตผิดสู่อินเทอร์เน็ต โดยทั่วไปการโจมตีเหล่านี้จะถูกจำกัดขอบเขตมากกว่าในดาต้าเซ็นเตอร์ หากคุณใช้ account/subscription/project และ VPC หรือ virtual network เพื่อจำกัด blast radius
- การโจมตีผู้ดูแลระบบคลาวด์และนักพัฒนาของคุณ ครั้งหน้าที่คุณทำ penetration test ควรเปิดโอกาสให้ผู้ทดสอบลอง phish นักพัฒนาและผู้ดูแลระบบของคุณด้วย นี่เป็นหนึ่งในเส้นทางที่ดีที่สุดในการ pivot เข้าสู่คลาวด์ เพราะบ่อยครั้งการเข้าถึงเครื่องของนักพัฒนานั้นง่ายกว่าการเจาะตัวแอปพลิเคชันบนคลาวด์มาก เราจะกล่าวถึงเรื่องนี้ในโอกาสต่อไป แต่ตอนนี้ขอเริ่มด้วยประโยคที่ว่า “MFA คือมิตรของผม”
- การโจมตีแบบผสม นี่คือประเภทที่เราจะเจาะลึกในวันนี้ ในการโจมตีลักษณะนี้ ผู้ไม่ประสงค์ดีจะเจาะเข้าสู่สิ่งที่ติดตั้งอยู่บนคลาวด์ก่อน แล้วใช้สิ่งนั้น pivot เข้าสู่ management plane ของคลาวด์ (บางคนอาจมองว่าการโจมตีนักพัฒนาก็เป็นการโจมตีแบบผสมเช่นกัน แต่ผมเลือกแยกออกมาต่างหาก)
ตามหลักปฏิบัติ ผมจะเริ่มต้นด้วยสมมติฐานเสมอว่าการโจมตีที่สำเร็จในระดับใดก็ตามสามารถยกระดับหรือ pivot ไปสู่การโจมตีแบบผสมได้ ซึ่ง ณ จุดนั้น ความปลอดภัยของ management plane และ incident response คือแนวป้องกันที่ดีที่สุดของคุณ
วันนี้ผมจะโฟกัสที่กระบวนการโจมตีแบบผสมที่พบบ่อยที่สุดรูปแบบหนึ่ง และสรุปแนวทางผสมผสานระหว่าง detective control และ preventative control เพื่อช่วยตัด kill chain ก่อนจะลงรายละเอียด อย่ามองว่าบทความนี้คือการลดทอนปัญหาที่ซับซ้อนให้ง่ายเกินไป การบริหารจัดการสิ่งที่ผมกำลังจะพูดถึงในระดับสเกลใหญ่นั้นยากอย่างยิ่ง แม้คุณจะรู้ดีว่ากำลังทำอะไรอยู่ก็ตาม
ในอีกไม่กี่สัปดาห์ข้างหน้า เราจะเริ่มทยอยปล่อย Ops ชุดแรกที่ออกแบบมาเพื่อปัญหาเหล่านี้โดยเฉพาะให้กับลูกค้า early access และน่าจะพร้อมใช้งานจริงในเวลาไม่นานหลังจากนั้น
การโจมตีแบบผสมบน AWS: การดึง IAM Role Credentials
ในการโจมตีแบบผสม ผู้ไม่ประสงค์ดีจะเจาะเข้าสู่เป้าหมายแบบดั้งเดิมก่อน แล้วใช้สิ่งนั้น pivot เข้าสู่ management plane ของคลาวด์ โดยมีสามวิธีหลักที่เกิดขึ้นได้ ในทุกกรณี ผู้โจมตีจะดึงเอา static credentials ที่จัดเก็บไว้ หรือ IAM role credentials แบบชั่วคราวออกมา ซึ่งเราจะอธิบายในอีกสักครู่
- การเจาะ instance หรือ container โดยตรง ตัวอย่างเช่น หากคุณเปิดพอร์ต 22 ทิ้งไว้และผู้โจมตีสามารถเจาะเข้ามาหรือเข้าถึง shell ได้
- Server Side Request Forgery (SSRF) ผู้โจมตีอาศัยช่องโหว่ของเว็บเซิร์ฟเวอร์หรือเว็บเซอร์วิส (โดยทั่วไป) และสามารถรันคำสั่งได้โดยไม่ต้องเข้าถึง shell
- การเจาะ Lambda function แม้คุณจะไม่สามารถเข้าถึง shell บน Lambda ได้ แต่ Lambda ก็ยังมีความเสี่ยงจากช่องโหว่การรันโค้ด และแม้กระทั่งการรันโค้ดตามอำเภอใจหากมีข้อบกพร่องในแอปพลิเคชัน ผลกระทบที่เกิดขึ้นอาจมีลักษณะคล้ายกับ SSRF
ในทุกกรณี เป้าหมายของผู้โจมตีคือการได้มาซึ่ง credentials สำหรับ management plane ของ AWS แล้วใช้สิทธิ์ที่มีอยู่หรือยกระดับสิทธิ์ต่อไป เราจะพูดถึง privilege escalation ในบทความถัดไป ส่วนตอนนี้จะเน้นว่า credentials เหล่านั้นคืออะไร และคุณจะป้องกันการนำไปใช้ในทางมิชอบได้อย่างไร
คนส่วนใหญ่เข้าใจ static credentials ดีอยู่แล้ว ซึ่งใน AWS ก็คือ Access Key และ Secret Key ทั้งสองทำหน้าที่คล้ายชื่อผู้ใช้และรหัสผ่าน แต่ใช้สำหรับการเรียก AWS API เวอร์ชันปัจจุบันใช้กระบวนการเข้ารหัสที่เรียกว่า Signature 4 สำหรับการลงนาม HTTP request เมื่อคุณเรียก API เหล่านั้น คุณสามารถและควรปฏิบัติต่อมันเหมือนชื่อผู้ใช้และรหัสผ่าน และไม่ควรจัดเก็บไว้ในทรัพยากรบนคลาวด์อย่าง instance หรือ Lambda เป็นอันขาด
IAM role เป็นเรื่องที่ซับซ้อนกว่าสำหรับผู้ที่เพิ่งเริ่มใช้ AWS มันทั้งทรงพลังและน่ากังวลในเวลาเดียวกัน IAM Roleใน AWS คือภาชนะบรรจุสิทธิ์ที่คุณใช้งานในแต่ละเซสชัน IAM Role มีข้อดีตรงที่มันไม่ใช่ credentials โดยตัวมันเอง… เมื่อคุณ assume role นั้น AWS จะออกชุด credentials สำหรับเซสชันที่มีอายุจำกัดให้ Role เป็นสิ่งที่ใช้ได้ “ภายใน AWS เท่านั้น” คุณสามารถกำหนด role ให้กับทรัพยากรภายใน AWS (เช่น instance หรือ Lambda function) และทรัพยากรนั้นก็จะเรียก API ได้ โดยไม่ต้องมี static credentials ที่จัดเก็บไว้! เราใช้ role สำหรับการเชื่อมต่อ federated identity, instance, Lambda function และบริการอื่น ๆ ทั้งหมดภายใน AWS ส่วน access key นั้นใช้เฉพาะเมื่อคุณสร้าง user ใน AWS account เท่านั้น นอกเหนือจากนั้นเราใช้ role ทั้งหมด
Role มีประเภทของสิทธิ์ที่เกี่ยวข้องอยู่สี่แบบ
- สิ่งที่ role ทำได้ภายใน AWS นี่คือ permission policies ตรง ๆ ที่คุณผูกไว้กับ role
- ใครหรือสิ่งใดที่ใช้ role นั้นได้ (trust policy) การสร้าง role ไม่ได้หมายความว่าใครหรืออะไรก็ใช้ได้ นโยบายนี้จะจำกัดการเข้าถึงไว้เฉพาะ เช่น AWS instance หรือ Lambda function ที่ระบุเท่านั้น
- permission boundary เพื่อจำกัดขอบเขตของ role เรื่องนี้ซับซ้อนขึ้นเล็กน้อยและไม่เกี่ยวข้องกับหัวข้อวันนี้ เราจะกล่าวถึงในภายหลัง
- เมื่อคุณ assume role สำหรับเซสชันหนึ่ง คุณยังสามารถระบุชุดย่อยของสิทธิ์ที่มีอยู่เพื่อใช้ในเซสชันนั้นได้ นี่เป็นฟีเจอร์ที่ดีสำหรับหลัก least privilege แต่ก็ไม่เกี่ยวข้องโดยตรงกับหัวข้อวันนี้เช่นกัน
คงอธิบายได้ง่ายกว่าหากไล่ดูทีละขั้นว่าทำงานอย่างไร สมมติว่าผมมีแอปพลิเคชันที่ต้องเข้าถึง S3 bucket หรือ Dynamo Database ผมสร้าง IAM role สำหรับ instance และตั้ง trust policy เพื่อให้บริการ EC2 ใช้ role นั้นได้ จากนั้นผมเปิด instance และกำหนด role ให้ AWS จะรัน instance และให้ instance นั้น assume the role การ assume role จะเปิดเซสชันขึ้นมาและกำหนด access key, secret key และ session token ให้ จากนั้น AWS จะหมุนเวียน credentials เหล่านี้ทุก 1-6 ชั่วโมง และ instance ก็สามารถเรียก API ตามที่ permission policies อนุญาตได้
แม้ credentials จะไม่ได้ถูกเก็บอยู่ใน instance แต่ instance ก็ยังเข้าถึง credentials เหล่านั้นได้ โค้ดใด ๆ ที่รันอยู่ภายในจำเป็นต้องรู้ credentials เพื่อเรียก API เข้าถึง S3 และ Dynamo ได้จริง ดังนั้นสิ่งที่เรียกว่า metadata service จึงทำหน้าที่ส่งมอบให้ตามคำขอ metadata service เป็นองค์ประกอบพิเศษใน AWS สำหรับ instance และ container ที่เก็บข้อมูลทั้งหมดเกี่ยวกับการตั้งค่าของตัวมันเอง เช่น การที่เซิร์ฟเวอร์สามารถรู้ IP address ของตัวเองได้นั้นถือเป็นเรื่องสำคัญอย่างยิ่ง
และนี่คือจุดที่การโจมตีเข้ามา
metadata service คือ URL ที่คุณเข้าถึงแล้วได้ข้อมูลที่ร้องขอกลับมา คำสั่ง curl 169.254.169.254/latest/meta-data/ จะให้ข้อมูลพื้นฐานทั้งหมด และหากใช้พาธ curl 169.254.169.254/latest/meta-data/iam-security-credentials/ ก็จะได้ access key, secret key และ token (ในกรณีการโจมตีผ่าน Lambda ทุกอย่างจะมีหน้าตาต่างออกไป และคุณจะใช้โค้ด SDK แทน curl แต่หลักการเดียวกันยังคงใช้ได้)
จากนั้นผู้โจมตีสามารถคัดลอก credentials เหล่านั้นไปใช้ที่อื่น โดยฝังไว้ในเครื่องมือของตน แทนที่จะต้องโหลดและรันโค้ดบนเซิร์ฟเวอร์ที่ถูกเจาะ อีกทั้งเนื่องจากทำงานผ่าน URL metadata service จึงเปิดช่องให้กับการโจมตีแบบ SSRF ได้หลากหลายรูปแบบมากขึ้น เพราะไม่จำเป็นต้องรันโค้ดตามอำเภอใจได้อย่างเต็มรูปแบบ credentials จะหมดอายุในที่สุด แต่ขึ้นอยู่กับรูปแบบการโจมตี ผู้โจมตีอาจย้อนกลับมาขอชุดใหม่เมื่อพบว่าชุดเดิมใช้ไม่ได้แล้ว
ทุกวันนี้ผู้โจมตีที่ชาญฉลาดจะนำ credentials ไปใช้ภายใน AWS account ที่ตนควบคุมอยู่ เนื่องจาก Amazon มีเครื่องมือตรวจจับ credentials ที่ถูกดึงออกไปใช้นอกช่วงที่อยู่ที่ระบบรู้จัก
การตัด kill chain ของการขโมย IAM Role
ลองมาดูแผนภาพของ kill chain กัน ผู้โจมตีจำเป็นต้องทำสิ่งต่อไปนี้
- ค้นหาและใช้ประโยชน์จากช่องโหว่ใน instance, container หรือ Lambda ที่เปิดทางให้เข้าถึง credentials ของ role ได้ ซึ่งแทบทุกครั้งเกิดจากความผิดพลาดฝั่งลูกค้าเอง เช่น ไม่ patch ระบบ เปิด port ผิด หรือ deploy โค้ดที่มีช่องโหว่
- ดึง credentials ของ role ที่ใช้งานอยู่ออกมา
- เรียก API calls ที่ได้รับอนุญาตได้สำเร็จจากสภาพแวดล้อมที่ตนควบคุมอยู่
- ลงมือทำสิ่งที่เป็นอันตรายภายในขอบเขตของ permission policy ที่ IAM role นั้นอนุญาต คงต้องบอกว่า "น่าจะ" เป็นอันตราย เพราะผู้โจมตีส่วนใหญ่คงไม่ได้มา patch โค้ดให้คุณ
เทคนิคต่อไปนี้ช่วยตัดข้อต่อต่าง ๆ ของ chain นี้ได้ โดยผสมผสานทั้ง detective control และ preventative control หากดูแล้วรู้สึกว่าเยอะเกินไปก็ไม่ต้องกังวล เพราะมีองค์กรจำนวนน้อยมาก น้อยจริง ๆ ที่ผมทำงานด้วยแล้วนำทั้งหมดนี้ไปใช้ได้อย่างครบถ้วน โดยเฉพาะในระดับ scale ใหญ่
6 เทคนิคที่ช่วยตัดข้อต่อต่าง ๆ ของ attack chain
- Vulnerability Management
- IAM permissions policy แบบ least privilege พร้อม resource restrictions
- ใช้ conditional restrictions ตาม IP, VPC หรือต้นทางของ request อื่น ๆ ใน permissions policy
- ใช้ service endpoints ร่วมกับ policy + resource policy
- เพิ่ม metadata proxy พร้อม HTTP user agent filter (Metadata Service Protection)
- การป้องกันการใช้ role ซ้ำซ้อน
Vulnerability Management
- ความซับซ้อน: ปานกลาง
- ประสิทธิผล: ต่ำ
- ความสามารถในการขยายขนาด: ยาก
- ประเภท: Detective และ Preventative
ไม่น่าแปลกใจว่าจุดเริ่มต้นของคุณคือการกำจัดช่องโหว่และการตั้งค่าที่ผิดพลาดทั้งหมดที่ผู้โจมตีอาจใช้เพื่อ pivot และขโมย credentials ผมให้ความซับซ้อนอยู่ในระดับปานกลางเพราะเรื่องนี้ไม่ได้ใหม่หรือเฉพาะเจาะจงกับ cloud แต่อย่างใด ขณะเดียวกันผมให้ประสิทธิผลอยู่ในระดับต่ำ เพราะ vulnerability management ที่ครอบคลุมก็ไม่ได้ช่วยหยุดเหตุการณ์ข้อมูลรั่วไหลจำนวนมหาศาลตลอดหลายทศวรรษที่ผ่านมา แนวคิดนั้นเรียบง่าย แต่ซับซ้อนอย่างยิ่งเมื่อต้องทำในระดับ scale ใหญ่
IAM permissions policy แบบ least privilege พร้อม resource restrictions
- ความซับซ้อน: ปานกลาง
- ประสิทธิผล: สูง
- ความสามารถในการขยายขนาด: ปานกลางถึงยาก
- ประเภท: Preventative
IAM policy ใน AWS เป็นแบบ default deny และประกอบด้วย statement แบบ allow และ deny ที่ระบุไว้อย่างชัดเจน ตัวอย่างเช่น คุณสามารถเขียน policy ที่อนุญาตให้อ่าน S3 bucket ได้เท่านั้น นอกจากนี้ยังมี resource restrictions ด้วย ดังนั้นในขณะที่ allow statement ให้สิทธิ role เรียก read API ตัว resource restriction จะอนุญาตให้ role อ่านได้เฉพาะ bucket หรือ object ที่กำหนดเท่านั้น คุณควรเริ่มต้นการป้องกันที่จุดนี้เสมอ ย้ำว่าเสมอ เวลาผมทำ assessment ผมพบเกือบทุกโปรเจกต์ว่า IAM policy ให้สิทธิ (API calls) มากเกินไป และมี resource restrictions น้อยเกินไป ใช่ครับ service นั้นอาจต้องเข้าถึง Dynamo database จริง แต่จำเป็นต้องเข้าถึงทุก table เลยหรือ การควบคุมข้อนี้ไม่ได้ยากเกินไปนักเมื่อทำในระดับเล็ก แต่ยิ่งองค์กรใหญ่ขึ้นและยิ่งมีคนจำนวนมากเป็นผู้ตัดสินใจเรื่อง policy เหล่านี้ ก็ยิ่งยากที่จะรักษาความสอดคล้องในระดับ scale ใหญ่ อีกเรื่องที่สำคัญคือการเพิ่ม deny statement อย่างชัดเจน เผื่อกรณีที่มีคนเพิ่ม policy ใหม่พร้อมสิทธิใหม่ให้กับ role นั้น สิทธิต่าง ๆ จะสะสมรวมกัน แต่ deny statement ใด ๆ จะมีผลเหนือ allow statement เสมอ
ใช้ conditional restrictions ตาม IP, VPC หรือต้นทางของ request อื่น ๆ ใน permissions policy
- ความซับซ้อน: สูง
- ประสิทธิผล: ปานกลางถึงสูง
- ความสามารถในการขยายขนาด: ยาก
- ประเภท: Preventative
IAM policy รองรับ conditional statement ที่ครอบคลุมตัวเลือกหลากหลาย รวมถึง IP address หรือ VPC ต้นทาง หากคุณรู้ว่า role หนึ่งควรเรียก API calls จาก resource ที่เฉพาะเจาะจงใน application stack ของคุณเท่านั้น คุณก็สามารถล็อกการอนุญาตไว้กับ IP address หรือ subnet นั้นได้ หากผู้โจมตีขโมย credentials ไปและพยายามใช้จากที่อื่น API calls ก็จะล้มเหลว วิธีนี้เปรียบเสมือนค้อนปอนด์แบบนำวิถี คือเข้าใจง่ายแต่ลงมือทำยาก เพราะคุณอาจพบว่ามีความซับซ้อนอื่น ๆ เข้ามาขัดขวางการนำไปใช้อย่างถูกต้อง ตัวอย่างเช่น API calls ไปยัง AWS services อาจออกอินเทอร์เน็ตโดยตรง ผ่าน NAT Gateway หรือ route ภายในผ่าน Service Endpoint (ซึ่งเราจะพูดถึงในอีกสักครู่) IP address ที่ตรวจพบจะขึ้นอยู่กับเส้นทางของ API call ที่ออกสู่อินเทอร์เน็ต ทั้งหมดนี้บริหารจัดการได้ ตรวจจับได้ (และทำอัตโนมัติได้) แต่คุณควรศึกษาข้อมูลก่อนเพื่อให้เข้าใจรูปแบบที่เป็นไปได้ทั้งหมด
ดูตัวอย่างได้จากส่วนแรกของโพสต์นี้จาก Netflix
หากคุณไม่ได้รัน Lambda function บน VPC วิธีนี้จะใช้ปกป้อง function ที่ถูกเจาะไม่ได้
ใช้ service endpoints ร่วมกับ policy + resource policy
- ความซับซ้อน: ปานกลาง
- ประสิทธิผล: ปานกลางถึงสูง
- ความสามารถในการขยายขนาด: ปานกลาง
- ประเภท: Preventative
ใน AWS นั้น service endpoint เปรียบเสมือนจุดดักบนเครือข่าย ที่รับ traffic ซึ่งปกติจะวิ่งผ่านอินเทอร์เน็ตไปยัง AWS service แล้ว re-route เข้าสู่ภายในแทน เดิมทีถูกสร้างขึ้นเพื่อให้ subnet แบบ private เต็มรูปแบบใน AWS ซึ่งไม่มีช่องทางออกสู่อินเทอร์เน็ตเลย ยังสามารถเข้าถึง AWS service บางอย่างได้ Endpoint รองรับ policy ที่คุณใช้จำกัดการเข้าถึงและการกระทำได้ในลักษณะที่คล้ายกับ IAM policy มาก ในกรณีนี้คุณเพิ่มข้อจำกัดใน endpoint policy เพื่ออนุญาตเฉพาะการเข้าถึง resource ที่กำหนดไว้เบื้องหลัง endpoint นั้นเท่านั้น (S3 เป็นตัวอย่างที่พบบ่อยที่สุด) คุณระบุว่า bucket ใดได้รับอนุญาต และไม่มี resource อื่นใดใน subnet นั้นเข้าถึง service ดังกล่าวได้ มองว่านี่คือแนวป้องกันชั้นสำรองของ IAM policy เมื่อใช้ service endpoint ที่มี policy เข้มงวด ต่อให้มีใครบางคนเผลอ (หรือจงใจ) ให้สิทธิ role กว้างกว่าที่ควรจะเป็น role นั้นก็ยังเข้าถึงสิ่งที่ไม่ได้รับอนุญาตใน service endpoint policy ไม่ได้อยู่ดี นั่นหมายความว่าตอนนี้เรามี policy ถึงสามชั้น ซึ่งทุกชั้นต้องอนุญาตการเข้าถึง resource นั้น ได้แก่
- IAM permission policy ที่อนุญาตให้ role เข้าถึง resource นั้น
- service endpoint policy ที่อนุญาตให้เข้าถึง resource เมื่อ request มาผ่าน endpoint นั้น ไม่ว่า role ที่ใช้จะมีสิทธิอย่างไรก็ตาม
- bucket policy หรือ resource policy (ขึ้นอยู่กับประเภทของ resource) ซึ่งสามารถจำกัดการเข้าถึงให้มาจาก IP address ที่อนุมัติไว้เท่านั้น
เช่นเดียวกัน หากคุณไม่ได้รัน Lambda function บน VPC วิธีนี้ก็จะใช้ปกป้อง function ที่ถูกเจาะไม่ได้
เพิ่ม metadata proxy พร้อม HTTP user agent filter (Metadata Service Protection)
- ความซับซ้อน: สูง
- ประสิทธิผล: ปานกลาง
- ความสามารถในการขยายขนาด: ยาก
- ประเภท: Preventative
การควบคุมทั้งหมดนี้ตั้งอยู่บนสมมติฐานว่าผู้โจมตีสามารถขโมย credentials ของ role ได้ แต่จะเป็นอย่างไรหากเรามีวิธีลดโอกาสที่พวกเขาจะได้ credentials เหล่านั้น แม้จะเจาะ instance หรือ container ที่ได้รับอนุญาตไปแล้วก็ตาม (เทคนิคนี้ใช้กับ Lambda function ไม่ได้) ทางเลือกที่กำลังมาแรงคือการจำกัดการเข้าถึง metadata service ตั้งแต่ต้นทาง แม้จะเคยมีความพยายามทำสิ่งนี้ด้วย IPTables แต่ก็อาจทำให้ฟังก์ชันการทำงานที่จำเป็นของโค้ดที่รันอยู่บน instance เสียหายได้ ในเดือนพฤศจิกายน 2018 AWS และ Netflix ร่วมมือกันและเริ่มเพิ่ม user data สำหรับ API calls ที่มาจาก AWS SDK ลงใน HTTP header วิธีนี้เป็นการป้องกัน SSRF เพราะการโจมตีแบบ SSRF ส่วนใหญ่อาศัยการหลอกให้แอปพลิเคชันส่ง HTTP request แทนผู้โจมตี แต่ request เหล่านั้นมักมาจากเครื่องมือ command line อย่าง curl หรือ process อื่น จึงไม่มี user data header ที่มาจาก AWS SDK เพื่อให้วิธีนี้ทำงานได้ คุณต้องแทรก proxy สำหรับ request เหล่านั้น มีตัวเลือก open source อยู่หลายตัวสำหรับ instance และ container รวมถึง proxy ที่รันอยู่บน instance เองโดยไม่ต้อง route traffic ไปยัง virtual appliance หรือ squid proxy
เทคนิคนี้จะใช้ไม่ได้ผลหากผู้โจมตีเจาะเข้า host instance และเปิด shell ได้ เพราะพวกเขาสามารถปิดการทำงานของ Roxy หรือยึด process ที่ได้รับอนุมัติไว้ได้
อ่านรายละเอียดทั้งหมดได้ในโพสต์ของ Netflix นี้
การป้องกันการใช้ role ซ้ำซ้อน
- ความซับซ้อน: สูง
- ประสิทธิผล: สูง
- ความสามารถในการขยายขนาด: สูง
- ประเภท: Detective
อีกวิธีหนึ่งที่มาจากทีมงานของ Netflix พวกเขาเผยแพร่คู่มือสำหรับเทคนิคที่ยอดเยี่ยมในการตรวจจับเมื่อมีการใช้ IAM role จากตำแหน่งที่ไม่ได้รับอนุญาต แม้จะอยู่ภายใน AWS ก็ตาม ผมแนะนำอย่างยิ่งให้อ่านโพสต์ที่ลิงก์ไว้ แต่สรุปสั้น ๆ คือพวกเขานำ CloudTrail log มาผสานกับเครื่องมืออื่นเพื่อเก็บตารางว่า instance ใดใช้ role ใดจาก IP address ใด จากนั้นจึงเฝ้าติดตาม API calls อื่น ๆ เพื่อหาว่ามี role ใดถูกนำกลับมาใช้จาก IP address ใหม่ในขณะเดียวกับที่ยังถูกใช้งานจาก IP ที่อนุมัติไว้ ด้วยวิธีนี้คุณไม่จำเป็นต้องรู้ IP address ทั้งหมดที่ใช้งานอยู่ทั่วทั้งองค์กร แต่สร้างตารางของสิ่งที่ใช้งานอยู่แบบไดนามิก และตรวจจับได้เมื่อ role นั้นถูกใช้จากที่อื่นในเวลาเดียวกัน วิธีนี้ขยายขนาดได้ดีมาก เพราะคุณสามารถรัน logic แบบรวมศูนย์ได้หากรวมศูนย์ CloudTrail ไว้ ซึ่งก็เป็นแนวปฏิบัติที่ดีโดยทั่วไปอยู่แล้ว
สรุป
โพสต์นี้ยาวมากอีกแล้ว และเราไม่ได้คาดหวังว่าทุกคนจะนำทุกตัวเลือกเหล่านี้ไปใช้ได้ในทุกการ deploy เพื่อให้เข้าใจง่ายขึ้น เรามาไล่ดู kill chain ของการใช้ IAM Role ในทางที่ผิดกัน
- ค้นหาและใช้ประโยชน์จากช่องโหว่ใน instance, container หรือ Lambda ที่เปิดทางให้เข้าถึง credentials ของ role ได้ ซึ่งแทบทุกครั้งเกิดจากความผิดพลาดฝั่งลูกค้าเอง เช่น ไม่ patch ระบบ เปิด port ผิด หรือ deploy โค้ดที่มีช่องโหว่
- Vulnerability management (รวมถึงเครื่องมืออย่าง SASST และ DAST สำหรับแอปพลิเคชัน) และการประเมินการตั้งค่า cloud ของคุณ (ด้วยเครื่องมืออย่าง DisruptOps หรือเครื่องมือ open source อย่าง Prowler และ CloudMapper) คือแนวป้องกันด่านแรกของคุณ
- ดึง credentials ของ role ที่ใช้งานอยู่ออกมา
- Metadata Service Protection และ vulnerability management
- เรียก API calls ที่ได้รับอนุญาตได้สำเร็จจากสภาพแวดล้อมที่ตนควบคุมอยู่
- การตรวจจับการใช้ role ซ้ำซ้อน, การใช้ conditional restrictions ตาม IP, VPC หรือต้นทางของ request อื่น ๆ ใน permissions policy, การใช้ service endpoints ร่วมกับ policy + resource policy
- ลงมือทำสิ่งที่เป็นอันตรายภายในขอบเขตของ permission policy ที่ IAM role นั้นอนุญาต คงต้องบอกว่า "น่าจะ" เป็นอันตราย เพราะผู้โจมตีส่วนใหญ่คงไม่ได้มา patch โค้ดให้คุณ
- IAM permissions policy แบบ least privilege พร้อม resource restrictions
หวังว่าข้อมูลนี้จะช่วยให้คุณเห็นภาพชัดขึ้นว่าจะลดโอกาสสำเร็จของการโจมตีลักษณะนี้ได้อย่างไร