สรุป Exploiting an SSRF: Trials and Tribulations
มาลองดู thought process ในการทำ SSRF บน blackbox กัน
โอเค ก่อนอื่น
การโจมตีแบบ SSRF คืออะไร
ยกตัวอย่างถ้ามี infra แบบนี้
ถ้า user request ไปหา server 1
และ server 1 ไม่ได้ตั้งใจจะ fetch ข้อมูลจาก server 2 มาให้ user
ช้อมูลใน server 2 ก็คงไม่หลุด
แต่ถ้า server 1 มี service เช่น ให้ server ไป fetch ข้อมูลจากเว็บอื่นมาให้ user ได้ ดังรูป
สมมติว่า user fetch url
server1?url=เว็บภายนอก
user ก็จะได้รับ content ของเว็บภายนอกนั้น หรืออาจจะได้รับข้อมูลอื่นๆเพิ่ม เช่น ข้อมูล performance ของเว็บ แล้วแต่ logic ของ server1
ทีนี้ถ้า server 2 รันที่ port 8080 (port นี้เข้าถึงจากนอก vpc ไม่ได้)
และ attacker เข้า server1?url=http://localhost:8080 จะเกิดอะไรขึ้น
คำตอบคือ ข้อมูลของ server 2 จะหลุดไปยัง attacker นั่นเอง
เราเรียกการโจมตีในลักษณะนี้ว่า SSRF (Server Side Request Forgery)
การโจมตีแบบ SSRF มีจุดที่ยากตรงไหนได้บ้าง ?
- ทาง dev อาจจะรู้ถึงช่องโหว่อยู่แล้ว และพยายามที่จะป้องกันไว้แล้ว
เช่น input url ต้องไม่เท่ากับ localhost/127.0.0.1
ข้อนี้ attacker สามารถ bypass ได้ แต่ทาง dev ก็สามารถเขียนดักการ bypass นั้นไว้ได้อีกชั้นเช่นกัน
หรือ input จะต้องเป็น domain ที่ dev กำหนดไว้ เช่น ต้องเป็น domain company.com
อันนี้จะยากขึ้นมาอีกขั้น เพราะ attacker ไม่ได้เป็นเจ้าของ domain นั้น ดังนั้น server1 จึงไม่มีโอกาสที่จะ load code ของ attacker ไปรันบน server 1 ได้เลย
attacker อาจจะแก้ข้อนี้ด้วยการ
a. หา endpoint ของ domain company.com ที่เปิดให้ redirect ได้
เช่น
attacker เรียก get server1?url=a.company.com?redirect=attacker.com
server1 เรียก a.company.com?redirect=attacker.com
a.company.com redirect server1 ไปที่ attacker.com
ที่ attacker.com เขียน code ให้ redirect server1 ไปยัง server2
สุดท้ายแล้ว attacker จะเห็นข้อมูลใน server2
แบบนี้เป็นต้น
แต่ปัจจัยในการ attack สำเร็จก็มีหลายอย่าง เช่น server1 อาจจะแค่ไป fetch url แต่ไม่ได้รัน code
นั่นอาจทำให้ redirect ที่ซ่อนใน code ของ attacker.com ไม่ทำงาน เป็นต้น
โอเค วิธีในการแก้ case whitelist domain อีกข้อ นั่นคือ
b. subdomain takeover
นั่นคือการหา whitelist subdomain ที่ถูกขายออกมาแล้ว หรือ whitelist subdomain ที่ attacker สามารถนำ code ของตัวเองไปวาง/ทำให้รัน ได้นั่นเอง
โอเค จุดยากของ SSRF อีกอย่างหนึ่งนั่นคือ
2. ใน vpc/infra ของ server1 อาจจะไม่มี server2 ให้เรา attack เลยก็ได้
เช่นใน infra่dev deploy แค่ server1 เลย (database อาจจะอยู่อีก network หนึ่ง และต้องใช้รหัสเข้า)
ดังนั้นเราจะให้ server1 ไป fetch ความลับอะไรมาละ ?
อาจจะเป็น
a. ข้อมูลของตัว vpc/infra ที่ server1 deploy อยู่เอง
โดยปกติแล้ว เมื่อ dev ใช้ cloud เช่น ec2, compute engine นั้น cloud เหล่านี้จะให้บริการ endpoint ภายในแถมมาให้ เพื่อจัดการข้อมูลของ cloud เช่น user, role ต่างๆบน ec2
b. ไม่ต้อง fetch ความลับ แต่ใส่ payload ของ attacker ไปโจมตึลูกค้าแทน
เช่น ในกรณี url server1?url=a.company.com?redirect=attacker.com
เมื่อลูกค้าเห็นว่านำหน้าด้วย server1 ก็อาจจะเข้า link นี้ที่ attacker ส่งให้
จากนั้นเมื่อลูกค้าถูก redirect มาถึง attacker.com
attacker ก็จะได้โอกาสในการรัน code javascript บนเครื่องลูกค้า
เราเรียกการโจมตีแบบปั้น payload ส่งให้ลูกค้าแบบนี้ว่า XSS (cross-site scripting)
โอเค จุดที่ยากของ SSRF ก็ประมาณนี้ละกัน
เอาละมาเข้าเรื่องสรุปบทความ Exploiting an SSRF: Trials and Tribulations (link https://medium.com/a-bugz-life/exploiting-an-ssrf-trials-and-tribulations-14c5d8dbd69a) กัน
สรุป Exploiting an SSRF: Trials and Tribulations
ทางผู้เขียนบทความ ได้ทำ bug bounty แบบ blackbox
แน่นอนว่าการ attack แบบ blackbox คือ attacker จะไม่รู้ข้อมูลเกี่ยวกับ target
ดังนั้น process จึงเริ่มจาก
- หา endpoint และ function ของ target
โดยในขั้นนี้เค้าน่าจะใช้ burp http history ในการเก็บข้อมูล ร่วมกับ wayback machine ในการ list endpoint
โดย wayback machine ให้ข้อมูล endpoint ที่น่าสนใจที่โผล่ขึ้นมาบนหลายๆ subdomain ดังรูป
จากรูปจะเห็นว่า company.com เปิดรับ url ไป และพยายามแสดง url นั้นกลับมาให้ user
โอเค pattern นี้น่าจะทำ SSRF ได้
โดยจากภาพเค้าใช้ burp collaborator เป็น payload
ซึ่ง burp collaborator เนี่ยเป็น tool ของ burpsuite ที่จะเปิด monitorserver และ gen domain ให้ จึงเป็น tool ที่สะดวกสำหรับการ test ว่าปลายทางเรียกกลับมาที่ domain เรามั้ยนั่นเอง
แต่ประเด็นคือ company.com ตอบกลับมาว่า url burp ที่ส่งไป ไม่ได้เป็น whitelist เนี่ยสิ
ต่อมาเขาลองส่ง subdomain ของ company.com ไป
เช่น a.company.com b.company.com
ปรากฎว่า target นำหน้าเว็บตาม payload มาแสดงได้
ทำให้ ณ จุดนี้ เขาคิดว่า whitelist rule คือ
*.company.com
ทำให้เขาพยายามหา subdomain ของ compay.com เพื่อที่จะ takeover หรือ หา subdomain ที่เปิดให้ redirect ได้
โดยในขั้นนี้เขาใช้
a. https://github.com/Findomain/Findomain เพื่อหา subdomain
b. https://github.com/tomnomnom/waybackurls เพื่อหา subdomain ที่เปิดให้ redirect ได้
c. https://github.com/tomnomnom/httprobe เพื่อหาว่า subdomain ไหน มี server เปิดอยู่บ้าง
โดยจาก waybackurls เขานำผลลัพธ์มา query ด้วย
grep "=http" wayback.txt
เพื่อหาว่ามี subdomain ไหนเปิดให้ query ได้บ้าง
เช่น b.company.com?input=http://…. เป็นต้น
จาก process นี้เขาเจอ x.company.com ที่เปิดให้ redirect ได้ ดังนั้นเขาจึงลองส่ง payload ไปเพื่อให้ redirect ไปยังเว็บของ attacker ดู
ปรากฎว่าได้ result เป็น 302 ตลอด
ตรงจุดนี้น่าจะเป็นเพราะว่า
/proxy ไป fetch ข้อมูลที่ x.company.com
x.company.com บอก /proxy ว่ามี redirect อีกต่อ (ด้วยการส่ง 302 กลับไป)
/proxy ไม่ไปตาม redirect นั้น แต่เอา 302 มาแสดงเลย
เมื่อวิธีนี้ไม่ work เขาจึงกลับไปรวบรวม subdomain ทั้งหมดที่หาได้ตอนนี้ แล้วมาป้อนให้ /proxy?url=subdomain อีกรอบ
เผื่อว่าบาง subdomain นั้นมีข้อมูลความลับ และเปิดให้เข้าได้จากภายใน infra ได้เท่านั้น
แต่ปรากฏว่าไม่ work
ต่อมาเขาจึงลองหาว่าใน subdomain นั้นมีอันไหนที่ DNS record ชี้ไปที่ localhost หรือ 127.0.0.1 รึเปล่า
เพราะในเมื่อป้อน /proxy?url=localhost ตรงๆไม่ได้
ก็ป้อน /proxy?url=subdomainที่ชี้ไปยังlocalhost แทนเลย
แต่ก็ปรากฎว่าหาไม่เจอ
แล้วถ้า internal ip ไม่ได้มีแค่ 127.0.0.1 ละ
เขาจึงลองวนลูป internal ip แต่ก็ปรากฎว่าไม่ผ่าน whitelist rule (ตรงนี้ไม่แน่ใจว่าเขาวนลูป port number ด้วยไหม)
ถ้า whitelist rule ไม่ได้ดักเลข ip ใน format อื่นๆละ ?
เช่น
127.0.0.1 แปลงเป็น hex ได้ 0x7f.0x0.0x0.0x1
ตรงนี้เขาลองใช้ท่า bypass whitelist ต่างๆ แต่ก็ปรากฎว่าไม่ work
เอาละ ณ จุดนี้ เขาลองกลับมาคิดว่า
whitelist rule เป็น *.company.com อย่างที่เขาคิดจริงรึเปล่า
whitelist rule อาจจะเป็น *.company.com หรือ abcd.com ก็ได้นะ
เขาจึงลองนำ domain จาก https://gist.github.com/jgamblin/62fadd8aa321f7f6a482912a6a317ea3
มาใช้ทำ SSRF ดู ปรากฎว่า amazonaws.com ผ่าน whitelist
โอเค ได้ progress ละ!
เขาจึงนำ code xss ไปวางบน aws s3 แล้วนำ domain ของ s3 นั้นมา test SSRF
ณ จุดนี้ เขาได้ช่องโหว่ XSS+SSRF ละ
แต่เขายังต้องการ impact ที่มากกว่าการหลอกลูกค้าของ company.com
เขาจึงลองแก้ code บน s3 เป็น
<iframe src="http://169.254.169.254/latest/meta-data/"></iframe>
เพื่อให้ company.com มาอ่าน code ตรงนี้ แล้วเขาก็จะเข้าไปดูข้อมูล server ของ company.com ได้ (http://169.254.169.254/latest/meta-data/ เป็น link ภายในของ server ec2 ถ้านำช่องโหว่นี้มาลองตอนนี้ aws น่าจะบังคับให้ส่ง header อันนึงไปด้วย ซึ่งทำไม่ได้ผ่านการ SSRF แบบนี้)
ซึ่งตอนนั้นเขา attack ไม่สำเร็จ เพราะ /proxy นำข้อมูลของ attacker มาแสดงเฉยๆ ไม่ได้รัน code ของ attacker
จากนั้นเขาก็ลอง code แบบนี้
<img src="file:///etc/passwd">
เพื่ออ่านไฟล์บน server ซึ่งไม่สำเร็จด้วยเหตุผลเดียวกัน
ณ จุดนี้ เขาคิดว่า บางทีถ้า server ของเขา return http code บางอันออกไป /proxy อาจจะทำการเข้ามา execute code แทนที่จะนำไปแสดงเฉยๆก็ได้
เขาจึงมาเปิด server ec2 ใหม่ แล้วให้ /proxy มา fetch แบบนี้
https://my-ec2.amazonaws.com/redirect?1&url=...&code=302
https://my-ec2.amazonaws.com/redirect?2&url=...&code=303
เพื่อ loop HTTP status นั่นเอง
โดย redirect?1 redirect?2 เป็น trick ในการทำให้ฝั่ง /proxy ไม่เก็บ cache ของแต่ละเส้น เพื่อให้ทุกเส้นส่ง HTTP status ที่ต่างกันกลับมาได้
ปรากฎว่า ไม่ work
เขาจึงลองกลับไปใช้ท่าเดิมนั่นคือหา DNS record ของ *.amazonaws.com ที่ชี้ไป 127.0.0.1/localhost ซึ่งไม่มี
และลอง /proxy?url=http://169.254.169.254 ไปเลย ซึ่งไม่ work (น่าจะเพราะไม่มี header ที่ aws ตั้งป้องกันไว้ ไม่ก็ไม่ผ่าน whitelist rule ของ server)
ตรงจุดนี้เขากลับมาคิดอีกรอบว่า
whitelist rule = *.company.com หรือ *.amazonaws.com จริงๆรึเปล่า ?
ถ้า whitelist rule = *company.com หรือ *.amazonaws.com ละ ?
ซึ่ง *company.com ยังไม่มีใครจดซะด้วย ดังนั้นเขาจึงยังไม่เคยลอง case นี้เลย
เขาจึงไปซื้อ domain neemacompany.com มาซะเลย
โดยตั้งให้
md.neemacompany.com ชี้ไปที่ 169.254.169.254
และ local.neemacompany.com ชี้ไปที่ 127.0.0.1
ซึ่งตอนนี้เขาสามารถไป get metadata ภายใน ec2 ของ target ได้แล้ว
เข้าใจว่า target เป็น ec2 แบบ IMDS version 1 มั้ง เลยยังใช้ท่านี้ได้ (ยังไม่ต้องส่ง header ไปเพิ่มเพื่อ bypass ตามข้อมูลจาก https://aws.amazon.com/th/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/)
เอาละตอนนี้ get ข้อมูล ec2 metadata ของ target ได้สำเร็จ
ส่วน 127.0.0.1 เข้าใจว่าเขาหา service อื่นๆข้างใน ec2 ไม่เจอ หรืออาจจะไม่มีตั้งแต่แรก
เอาละ case ศึกษา thought process ของการทำ SSRF แบบ blackbox ก็จะประมาณนี้ครับ