LDAP Injection Attack

LDAP Injection เป็นการโจมตีที่ใช้การเเทรกคำสั่งอันตรายที่สามารถเเก้ไข LDAP Query โดยที่แอปพลิเคชันไม่กรองพารามิเตอร์อย่างถูกต้อง ทำให้สามารถเข้าถึง LDAP Server หรือดึงข้อมูลที่ละเอียดอ่อนจาก LDAP Directory ได้โดยที่ตนเองนั้นไม่มีสิทธิ์เข้าถึง ซึ่งคล้ายกับการโจมตี SQL Injection

คำศัพท์พื้นฐานที่ใช้ใน LDAP

Directory (ไดเรกทอรี)

คือโครงสร้างที่ใช้เก็บข้อมูล และข้อมูลขององค์ประกอบต่าง ๆ ในรูปแบบของรายการ (Entry) ภายในรายการแต่ละรายการจะมี Attributes ที่ใช้กำหนดลักษณะเฉพาะของข้อมูล


Entry (รายการ)

คือหน่วยข้อมูลที่เก็บข้อมูลในรูปแบบของ attributes ที่มีค่าที่เกี่ยวข้องกับข้อมูล Entry นั้น ๆ


Attribute (แอททริบิวต์)

คือคุณสมบัติ หรือลักษณะเฉพาะของรายการหรือข้อมูลนั้น ๆ ในแต่ละ attribute จะมีชื่อ และค่าที่ถูกจัดเก็บ ตัวอย่างเช่น “cn” สามารถเก็บชื่อรวม (Common Name) ของบุคคล หรือ “mail” สามารถเก็บที่อยู่อีเมลของบุคคล เป็นต้น


ObjectClass (ออบเจ็กต์คลาส)

เป็น Attribute ใช้กำหนดลักษณะประเภทของวัตถุใน LDAP Directory เช่น “Person” หรือ “Organization” ซึ่งกำหนดคุณสมบัติ และ Attributes ที่เกี่ยวข้อง


Distinguished Name (DN)

เป็นรหัสที่ระบุองค์ประกอบใน LDAP Directory ในลักษณะเป็นลำดับชั้น ก็คือการเอา RDN (Relative Distinguished Name) ของ Entry ตั้งแต่ root จนถึงตัวมันเองมาต่อกัน เช่น อย่างรูปด้านล่างจะเป็นเเบบนี้ “ou=people ,ou=location2 ,dc=company ,dc=com”


Base DN (Distinguished Name)

เป็นระดับเริ่มต้นที่ใช้เป็นจุดเริ่มค้นหาใน LDAP Directory เมื่อค้นหาข้อมูล ใน LDAP Server จะเก็บข้อมูลในลักษณะ subtree อย่างรูปด้านล่าง Base DN จะเป็น “dc=example,dc=com”


Filter (ตัวกรอง)

เงื่อนไขที่ใช้ในการค้นหาข้อมูลใน LDAP Directory สามารถระบุเงื่อนไขแบบต่าง ๆ เพื่อค้นหาข้อมูลที่ตรงกับเงื่อนไขนั้น เช่น (cn=John) จะหาข้อมูลที่มี Common Name (cn) เป็น “John”


Query

เป็นข้อความที่ใช้ในการส่งคำสั่งค้นหาไปยัง LDAP ServerP เพื่อค้นหา และคืนค่าข้อมูลที่ตรงกับเงื่อนไขที่ระบุใน Query


มาดูการใช้คำสั่ง Query LDAP ขั้นพื้นฐานกัน

ใน Search Filter ที่ใช้งานใน LDAP Query นั้นจะต้องเขียนตาม Syntax (ไวยากรณ์) ที่ถูกต้องตามใน RFC 4515 โดยภายในตัวของ Filter นั้นจะประกอบไปด้วย Attribute มากกว่า 1 ตัว เเละจากนั้นนำ Attribute ที่กำหนดมารวมกันได้โดยใช้ตัวดำเนินการเชิงตรรกะ ทั้งหมดออกมาเป็น LDAP Query เพื่อนำไปค้นหาข้อมูลของ Entry


ตัว Search filter ของ LDAP สามารถใช้ตัวดำเนินการเชิงตรรกะเพื่อรวม Attribute เข้าด้วยกันในการค้นหา ตามตารางด้านล่างนี้


ตัวอย่างการใช้งาน


>> ค้นหาทุกรายการที่ common name มีตัวอักษร Jonh นำหน้าอยู่ (เครื่องหมายดอกจัน (*) หมายถึงตัวอักษรอะไรก็ได้)

(cn=Jonh*) 


>> ค้นหาทุกรายการที่ common name ไม่มีตัวอักษร Jonh นำหน้าอยู่

(!(cn=Jonh*)) 


>> ใช้ดำเนินการเชิงตรรกะ AND ซึ่งก็คือสัญลักษณ์ “&” เพื่อค้นหา entry ทุกรายการที่ common name มีตัวอักษร J นำหน้าอยู่เเละลงท้ายด้วยคำว่า Doe

(&(cn=J*)(cn=*Doe)) 


>> ใช้ดำเนินการเชิงตรรกะ OR ซึ่งก็คือสัญลักษณ์ “|” เพื่อค้นหา entry ทุกรายการที่ common name มีตัวอักษร Jonh หรือ Elisa นำหน้าอยู่

(|(cn=Jonh*)(cn=Elisa*)) 



LDAP Injection Attack ทำงานอย่างไร?

ผู้ใช้งานจะส่งคำขอ LDAP Query ไปยัง LDAP Server เพื่อหา/เเก้ไขข้อมูลตัว entry ที่ตรงกับ Filter ที่เจาะจงไว้ในคำขอ หากพบรายการที่ตรงกับ Filter ใน LDAP Query ตัวของ LDAP Server จะส่งคืนข้อมูลของตัว Entry ที่ผู้ใช้งานร้องขอกลับมา ซึ่งจะทำงานคล้าย ๆ กับ SQL injection โดยในช่องโหว่ของ LDAP injection มีสาเหตุที่เกิดจาก แอปพลิเคชันไม่กรองข้อมูลที่รับจากผู้ใช้งานอย่างถูกต้อง ทำให้สามารถอินพุตเข้าไปในโค้ดคำสั่งของ LDAP Query ได้โดยตรง ส่งผลให้สามารถเเก้ไขค่าสตริงของ LDAP Syntax เพื่อใช้ Filter ค้นหาอย่างไม่เหมาะสม


ซึ่งจะทำให้ LDAP Server ทำการดำเนินการค้นหารวมถึงเเก้ไขโครงสร้าง LDAP Directory ต่าง ๆ ที่อาจเป็นอันตรายเเละนอกเหนือการสิทธิ์ที่ได้รับในระบบ



ชนิดของ LDAP Injection Attack

1. Authentication Bypass

ในหน้าที่ใช้เข้าสู่ระบบมักจะมีช่องสำหรับกรอกข้อความอยู่สองช่อง หนึ่งสำหรับชื่อผู้ใช้งาน เเละอีกหนึ่งสำหรับรหัสผ่าน โดยตัวที่อินพุตที่ผู้ใช้งานต้องกรอกคือ USER (Uname) และ PASSWORD (Pwd) เพื่อใช้ยืนยันการมีอยู่ของทั้ง 2 อย่างนี้ในระบบ โดยจะสร้าง Search Filter ที่ใช้งานใน LDAP Query เเละส่งไปยัง LDAP Server ตามด้านล่างนี้

(&(USER=Uname)(PASSWORD=Pwd))


สำหรับผู้ใช้ทั่วไปที่ไม่ประสงค์ร้าย Filter ผลลัพธ์ควรเป็นดังนี้

(&(USER=johndoe)(PASSWORD=johnspwd))

หากตัว USER เเละ PASSWORD ทั้งคู่นี้เป็นจริง ชื่อผู้ใช้งาน และรหัสผ่านจะมีอยู่ใน LDAP Directory ดังนั้นผู้ใช้งาน จึงสามารถเข้าสู่ระบบได้


เเต่ถ้าเป็นผู้ไม่ประสงค์ดีป้อนชื่อผู้ใช้งานที่มีอยู่ในระบบ เช่น “johndoe” เเละตามด้วย “)(&)” เพื่อทำให้ข้ามการตรวจสอบรหัสผ่านได้สำเร็จ ทำให้เมื่อทราบชื่อผู้ใช้งานแล้ว สตริงใด ๆ ก็สามารถใช้เป็นค่า PASSWORD ได้จากนั้น LDAP Query ต่อไปนี้จะถูกส่งไปยัง LDAP Server ดังนี้

(&(USER=johndoe)(&))(PASSWORD=Pwd))


หรืออีกวิธีที่ทำให้ผู้ไม่ประสงค์ดี สร้าง Filter ที่เป็นจริงเสมอ ทำให้สามารถเข้าถึงได้โดยไม่ต้องมีชื่อผู้ใช้หรือรหัสผ่านที่ถูกต้องโดยการใส่ “*)(USER=*))(|(USER=*”

(&(USER=*)(USER=*))(|(USER=*)(PASSWORD=Pwd))

ซึ่งจะอ่านได้เป็น (USER=*) AND (USER=*) ซึ่งเป็นจริงเสมอ กับอีกส่วนที่ไม่ทำงานจะเป็น (USER=*) OR (PASSWORD=Pwd) ซึ่งส่งผลให้ ถ้าหากเราเข้าสู่ระบบสำเร็จเราจะเป็นผู้ใช้งาน ที่เป็นคนเเรกสุดที่อยู่ใน LDAP Directory


2. Information Disclosure

หากแอปพลิเคชันที่มีช่องโหว่ใช้ Filter LDAP สำหรับตรวจสอบปริมาณทรัพยากร โดยการแจ้งให้ผู้ใช้งานทราบว่าทรัพยากรใดมีอยู่ในระบบบ้าง ขอยกตัวอย่างเป็น เว็บไซต์ขายของที่ให้ผู้ใช้งานสามารถมองหาสินค้า1 หรือสินค้า2 ที่ต้องการ และดูว่ามีจำหน่ายหรือไม่ ในสถานการณ์นี้จะสร้าง Search Filter ที่ใช้งานใน LDAP Query ออกมาเป็น:


(|(type=Resource1)(type=Resource2))

ทั้ง Resource1 และ Resource2 แสดงประเภทของทรัพยากรในระบบ Resource1=สินค้า1 และ Resource2=สินค้า2 เพื่อแสดงสินค้า1 และสินค้า2 ทั้งหมดที่มีจำหน่ายในระบบ ถ้าผู้ไม่ประสงค์ดีต้องการรู้รายชื่อผู้ใช้งานทั้งหมดสามารถทำได้ โดยการใส่ “)(uid=*)” เข้าไปใน Resource1=สินค้า1 ซึ่งจะได้ Search filter ที่ใช้งานใน LDAP Query ออกมาเป็น


(|(type=สินค้า1)(uid=*))(type=สินค้า2))

จากนั้น LDAP Server จะแสดงสินค้า1 เเละ Object ผู้ใช้งาน (uid) ทั้งหมดในระบบ


3.BLIND LDAP Injections

ในการใส่โค้ดที่ใส่เข้าไปใน Filter LDAP อาจจะทำให้แอปพลิเคชันสร้างการตอบสนองอื่น ๆ ออกมาซึ่งเเตกต่างจาก 2 ข้อเเรกที่จะเเสดงข้อมูลที่เราต้องการอย่างชัดเจน อย่างเช่นไม่สามารถเห็นความแตกต่างของการแสดงผลที่หน้าเว็บไซต์ได้อย่างชัดเจน แต่เราจะสามารถเห็นความแตกต่างก็ต่อเมื่ออินพุตที่เราพยายาม Inject เข้าไป ตรงตามเงื่อนไขที่เราตั้งไว้ ผลลัพธ์จริงหรือผลลัพธ์เท็จ(true/false) ผู้ไม่ประสงค์ดีสามารถสังเกตเเละใช้ประโยชน์จากพฤติกรรมนี้ เพื่อรับคำตอบสำหรับคำถามที่จริงหรือเท็จจาก LDAP Server ได้ เราเรียกเทคนิคเหล่านี้ว่า Blind Attacks แม้ว่าการโจมตีแบบ Blind LDAP Injection ผู้ไม่ประสงค์ดีใช้การแทรก LDAP แบบ BLIND เพื่อรับข้อมูลที่ละเอียดอ่อนจาก LDAP Directory ได้


3.1 AND Blind LDAP Injection

ยกตัวอย่างคร่าว ๆ ที่ใช้ AND Blind LDAP Injection


ลองนึกภาพร้านค้าออนไลน์ที่สามารถเเสดงรายการสินค้า ทั้งหมดจาก LDAP Directory ซึ่งจะได้ Search filter ที่ใช้งานใน LDAP Query ออกมาเป็น:

(&(objectClass=ชนิดสินค้า)(type=ชื่อสินค้า))

สินค้าที่มีอยู่ จะแสดงผลออกมาในหน้าแอปพลิเคชันให้ผู้ใช้เห็นรูปหรือไม่ก็รายการสินค้า หากไม่พบสินค้าที่ระบุไว้ในระบบเลยผู้ใช้งานจะไม่เห็นรายการใด ๆ ในหน้าเเอป นี่คือที่มาของ Blind LDAP Injection ลองเเทรก

“*)objectClass=*))(&(objectClass=void”

ลงในช่องกรอกชนิดสินค้า ซึ่งจะได้ Search filter ที่ใช้งานใน LDAP Query ออกมาเป็น:


(&(objectClass=*)(objectClass=*))(&(objectClass=void)(type=ชื่อสินค้า))

ซึ่งจะทำให้ตัว LDAP Server จะทำงานเเค่คำสั่ง “(&(objectClass=*)(objectClass=*))” อย่างเดียว คือชื่อสินค้าทุกชนิดจะขึ้นในหน้าแอปพลิเคชัน เพราะ objectClass=* นี้จะ Filter ส่งสินค้าทุกอย่างที่มีใน objectClass (ชนิดสินค้า) มาซึ่งเราจะขอกำหนดให้การตอบสนองหน้าแอปพลิเคชันเมื่อชื่อสินค้าทุกชนิดจะขึ้นในหน้าแอปพลิเคชันนั้น คือ true (จริง) เเละในขณะที่การตอบสนองหน้าแอปพลิเคชันไม่ขึ้นสินค้าใด ๆ เป็น false (เท็จ)


ทีนี้ผู้ไม่ประสงค์ดีก็จะมีตัวเลือกในการใช้เทคนิค Blind Injection อีกหลาย ๆ เเบบเพื่อใช้ในการหาข้อมูลในระบบ อย่างเช่นตัวอย่างด้านล่างนี้


(&(objectClass=*)(objectClass=users))(&(objectClass=foo)(type=ชื่อสินค้า))
(&(objectClass=*)(objectClass=Resources))(&(objectClass=foo)(type=ชื่อสินค้า))

เราสามารถใช้คำสั่งตัวอย่างทั้ง 2 ในการหาว่ามี ObjectClass นี้อยู่ในระบบหรือไม่ ถ้ามีหน้าแอปพลิเคชันก็จะตอบสนองโดยขึ้นชื่อสินค้าออกมา เเต่ถ้าไม่ก็จะไม่ขึ้นอะไร


3.2 OR Blind LDAP Injection

ตัวอย่างในการ OR Blind LDAP Injection

(|(objectClass=void)(objectClass=void))(&(objectClass=void)(type=ชื่อสินค้า))

ตัว LDAP Query ตัวนี้จะไม่มีชื่อสินค้าอะไรตอบกลับมาถ้าหากเป็นเท็จ หรือถ้าหากจริงก็จะยังขึ้นชื่อสินค้าอยู่ สามารถลองใช้ในการหาข้อมูลในระบบ อย่างเช่นตัวอย่างด้านล่างนี้


(|(objectClass=void)(objectClass=users))(&(objectClass=void)(type=ชื่อสินค้า))
(|(objectClass=void)(objectClass=Resources))(&(objectClass=void)(type=ชื่อสินค้า))

ขอเเนะนำ Payload ต่าง ๆ ของสำหรับ LDAP Injection ใน HackTrick : https://book.hacktricks.xyz/pentesting-web/ldap-injection เพื่อนำไปใช้เป็นตัวอย่างในการศึกษาเพิ่มเติม


สุดท้ายนี้ก็หวังว่าผู้อ่านทุกคนจะได้ความรู้เรื่อง LDAP Injection Attack กันไปบ้างไม่มากก็น้อย

0
209