กลับมาแล้วกับโจทย์ Weekly Challenge ของ Bugforge.io นะครับ สัปดาห์ก่อนทีมไม่ได้เขียนลงเพราะโจทย์มันง่ายเกินไป ไม่สนุก แต่สัปดาห์นี้ค่อนข้างน่าสนใจกว่าก็เลยเอามาเขียน writeup ครับ

None

สำหรับโจทย์สัปดาห์นี้จะเป็นเว็บ FurHire เว็บไซต์จ้างงาน/สมัครงานที่เราคุ้นเคย โดย Hint ของโจทย์นี้คือ Tokens are Fun! ดีเลยครับ ทีมชอบโจทย์แนวนี้ มีอะไรให้เล่นเยอะดี

None
None

เพื่อทดสอบว่า Token ของเว็บนี้มันมีรูปแบบอย่างไร ทีมจะสมัครสมาชิกในฐานะของคนจ้างงาน (Recruiter) ทั้งสองบัญชี คือ teammyinside และ recruit ครับ

None
None

ทีนี้เราจะเอา request จาก /api/my-jobs ของแต่ละอันมาเทียบกันครับ รูปบนเป็นของ teammyinside และรูปล่างเป็นของ recruit จะเห็นว่าสิ่งที่คล้ายคลึงกันคือ refresh token ที่จะเหมือนกันทั้งชุด ต่างแค่จุดเดียวคือตัวอักษรตัวท้ายครับ

- teammyinside: refresh_token=xpxyigcywhqxgsidrbufxstutxbwpfwu

- recruit: refresh_token=xpxyigcywhqxgsidrbufxstutxbwpfwv

None
Teammyinside
None
Recruit

และเพื่อพิสูจน์ว่า refresh token มันเปลี่ยนที่ตัวอักษรตัวสุดท้ายจริง เดี๋ยวจะลองล็อกอินบัญชี teammyinside ใหม่ แล้วจับ request มาดู ซึ่งพบว่าก็ได้ refresh_token=xpxyigcywhqxgsidrbufxstutxbwpfww แสดงว่ามันเรียงตัวอักษรไปเรื่อย ๆ จริง ๆ ครับ

None
Teammyinside (New session)

ทีนี้ แล้วเราจะเอา refresh token ไปทำอะไรได้บ้าง? เราจะไปดูที่ page source กันก่อนเผื่อมันมีข้อมูลเรื่องของการเรียกใช้ api เกี่ยวกับ refresh token ซึ่งเราเจอว่ามันมี app.js ครับ เดี๋ยวลองเปิดดูกัน

None

ใน app.js ให้ข้อมูลว่า ถ้า refresh token เราสามารถเรียกใช้ /api/refresh ส่งแบบ POST request พร้อม content-type แบบ json ส่วนใน json body ให้ระบุ username ของบัญชีที่จะขอให้ทำการ refresh token

None

ทีมก็เลยเอา /api/my-jobs ของ teammyinside อันล่าสุดมาปรับแต่งเพื่อเรียกใช้ /api/refresh ก็จะได้ตามภาพเลยครับ

None

ดังนั้น เราจะมาลองเรียกของ refresh token ของแอดมินกันบ้าง โดยเปลี่ยน username เป็น admin แล้วอย่าลืมให้เปลี่ยน JWT token ใน Authorization และ refresh token อันใหม่ที่ได้มาจาก response ก่อนหน้านี้ด้วยนะครับ

แต่พอลองเรียกโดยใช้ refresh_token=xpxyigcywhqxgsidrbufxstutxbwpfww งั้นเราลองปรับมาเป็น refresh_token=xpxyigcywhqxgsidrbufxstutxbwpfwx ก็ยังเรียกไม่ได้อีก เอ๊ะ! ทำยังไงดีนะ?

None
None

อ๋อ เรามี Burp pro งั้นเราก็ใช้ Intruder เลยสิ ทีมจึงนำ request ล่าสุดใส่ลงใน intruder เลือกตำแหน่งที่จะเปลี่ยนคืออักษรตัวสุดท้ายของ refresh token จากนั้น payload type เลือกเป็น brute forcer กำหนดเซตเป็นตัวอักษรอังกฤษพิมพ์เล็ก และ length กำหนดไว้แค่ 1 ครับ จากนั้นเริ่มยิงเลย

None

ผลลัพธ์คือเราได้ข้อมูล token ของ admin มาแล้วครับ ใน refresh_token=xpxyigcywhqxgsidrbufxstutxbwpfwy และ refresh_token=xpxyigcywhqxgsidrbufxstutxbwpfwt ซึ่งเราจะใช้ refresh_token=xpxyigcywhqxgsidrbufxstutxbwpfwy ละกัน

None

กลับไปที่หน้า dashboard ของ teammyinside ให้เปิด Inspect ขึ้นมา แล้วไปที่ Application แก้ไขค่า JWT ใน LocalStorage และแก้ไข refresh_token ใน Cookies ครับ

None
None

พอแก้แล้วลองรีเฟรชหน้า dashboard ปรากฏว่าเข้าใช้ไม่ได้ เพราะสงวนให้เฉพาะ recruiter เท่านั้น

None

แต่ไม่เป็นไรครับ โจทย์แบบนี้เราเดาได้อยู่แล้วว่าหน้าแอดมินมันต้องเป็น /admin ทีมก็เปลี่ยนจาก dashboard เป็น admin เท่านี้ก็เข้าได้แล้วครับ

None

และ Flag ของโจทย์ข้อนี้คือ bug{LnOftQLACuNu0YYP9TpTLa6peyTWuoPp}

สนใจแนวนี้ฝากกดติดตามด้วยนะครับ หรือติดตามได้ในช่องทางเหล่านี้