[WTCTT2022] Qualification Round Writeup #2

Chananya Choosak
4 min readDec 19, 2022

--

กลับมาแล้วหลังจากที่ไปแงะอีก 4 ข้อที่เหลือมาและจบรอบไฟนอล ก็ไม่ขอพูดพร่ำทำเพลงอะไรมาก ก็มาเริ่มกันต่อเลยค่ะ โกโก!

Challenge #7

จากรหัสผ่านที่ได้จากข้างในไฟล์ KeePass (ไม่ใช่รหัสผ่านที่เอาไว้ปลดล็อก) ในโจทย์ข้อ 5 และโค้ดของเว็บหลังบ้านโรงแรม Cyberspace ที่ได้จากโจทย์ข้อ 6 ให้ทำการหาช่องโหว่ ที่จะสามารถยกระดับสิทธิ์ เป็น changming ให้ได้ โดยการเรียกใช้งาน API บางอย่างที่เจอจากโค้ด

หลังจากที่เราปลดล็อค Keepass ได้แล้ว เราก็จะเห็นว่ามีข้อมูลอื่นๆที่ชี้ไปที่ Web Backoffice ได้จากในข้อ 6 ซึ่งข้อมูลที่เรามีตอนนี้:

http://backoffice.ctf.p7z.pw:8000
admin:[password from keepass]

ทีนี้เราก็ลองเข้าหน้าเว็บแล้ว login ด้วย username & password ตามที่ได้มา แล้วก็จะเจอกับหน้า Check in

หน้าเว็บ Backoffice
พอ login ได้แล้วก็จะเจอเป็นหน้าตาแบบนี้
อ้าว มันช็อตฟีลกุละ

พอถึงตรงนี้ โจทย์ได้บอกว่ามีข้อมูลในโค้ดที่เราโหลดมาจาก .git และเราก็สังเกตว่า path ปัจจุบันที่เราอยู่ตอนนี้คือ checkin.html ลองไปดู source code ไฟล์นี้กัน

$(document).ready(function() {
// Send a GET request to the auth endpoint to check for user authentication
$.get('/api/checkin.php?action=auth', function(data) {
// If the API does not return a status of 1, redirect the user to the index.html page
if (data.status !== 0) {
alert(data.msg);
window.location.href = 'index.html';
}
});

แล้วเราก็จะเจอว่าได้มีการเช็ค authentication ที่ path /api/checkin.php ก็ไปดูต่อที่โค้ดถัดไป

case 'checkin':
// Handle the checkin action
if (isAuthenticated()) {
// For demo purpose w/ our boss, Mr. Chang Ming (changming)
if($_SESSION['token'] === 'dc2d8fab4e2f3c35ebee66e3afe74625'){
header('FLAG: '.$envVars['FLAG7']);
...[SNIP]...

เลื่อนลงมาเรื่อยๆก็จะเจอ action checkin ที่มีการเช็คเงื่อนไขว่าถ้าได้ Token ออกมาตามในรูป (ซึ่งถ้าไปดูเงื่อนไขของการได้มาซึ่ง token นี้ก็คือต้อง login ในเส้น /api/login.php ให้ได้ก่อนถึงจะได้ token ออกมาในรูปแบบของค่า md5 ของ username) ซึ่งเราเองก็ลองเอา changming ไป hash md5 ก็จะได้ค่าตรงกับใน source code พอดี

เนื่องจากว่าชี้โพรงให้กระรอกขนาดนี้ก็ลองเอาค่า token ที่ว่าไปใส่ใน PHPSESSID ใน checkin request ไปเล้ย

โป๊ะ flag ออกเป็นที่เรียบร้อย

แต่งงนะ ตอนทำตอนแข่งจนถึงก่อนวันนี้ ก็ทำท่านี้แล้วทำไมไม่ได้หว่า พอวันนี้ลองเอา token มาลองใส่อีกรอบ แม่งได้เฉย งง

ปล. มีพี่ในทีมท่านหนึ่งกระซิบมาว่าอีกทางนึงสามารถใช้ท่าเปลี่ยน action parameter เป็น debug ก็จะสามารถ bypass เป็น changming ได้เหมือนกัน แต่ไม่ทำจ้า ขี้เกียจ

Challenge #8

โจมตีช่องโหว่ SSRF เพื่อขโมยค่า API Key ในระบบออกมา

หลังจากที่ได้ flag ข้อที่แล้วมาแบบงงๆหลังจากที่ struggle มานานมากก็ได้เวลาไปทำข้อ 8 ซึ่งก็วนเวียนกับการทำ source code review เหมือนเดิม โดยข้อนี้มาสั้นๆแค่ให้ทำ SSRF ไปเอา API Key

ถ้าจำกันได้จากข้อ 6 เราจะเห็นว่า FLAG ข้อ 8 อยู่ที่ไฟล์ getSecret.php

ว่าแล้วก็ย้อนความทรงจำกันสะน่อย

ว่าแล้วเราก็ไปดู source code กันต่อว่าในเจ้าไฟล์นี้มันมีอะไรน่าสนใจบ้าง

getSecret.php

ก็จะพบว่ามีการรับค่า allowedInternalIP มาซึ่งรับค่า php ด้วย!! ถึงจะให้ค่า API Key และ flag แล้วก็ลองไปดูที่ไฟล์อื่นต่อว่ามีอะไรที่เชื่อมโยงกับเจ้าตัวแปรนี้บ้าง ซึ่่งตัวเชื่อมโยงที่ว่ามันอยู่ในไฟล์ checkin.php ที่ action roomAvailability ซึ่งก็มีตัวแปรหนึ่งที่น่าสนใจ นั่นก็คือ เจ้า roomNumber ยังไงล่า

// For internal network only  
case 'roomAvailability':
// Get the IP address of the client that made the request
$clientIp = $_SERVER['REMOTE_ADDR'];

// Check if the request originated from the localhost
if ($clientIp === $allowedInternalIp) {
$roomNumber = $_GET['no'];
// TODO: Check room availability in the database
echo htmlentities($roomNumber);
exit;
}
$roomNumber = $xml->roomNumber->__toString();
// With the emerging of MicroServices ! (<https://www.youtube.com/watch?v=y8OnoxKotPQ>)
// We will pass roomNumber to our internal server (/flag9.txt)
$roomNumber = checkRoomAvailability($roomNumber);

และเราก็ได้ค้นพบว่าเจ้าตัวแปร roomNumber ที่ควรจะต้องรับค่าตัวเลขอย่างเดียว ดั๊นสามารถรับค่าเป็น string ได้ มีข้อมูลครบแล้วก็ลุย!!!

ซึ่งเราก็รู้กันอยู่แล้วว่า flag ข้อนี้อยู่ใน getSecret.php พอจิ้มไปที่ path ของ file นั้นเสร็จแล้วก็จะมีการ return API Key พร้อม flag มาให้พร้อมกันเลย

ปล. ก็คือหลงไปหา Endpoint ตั้งนาน สรุป อ๋อ แค่นี้เองเลย ผิดที่ฉันคิดลึกเกินไป

Challenge #9

โจมตีช่องโหว่ SSRF เพื่อขโมยไฟล์ /flag9.txt ในระบบออกมา

พอพ้นข้อ 7–8 มาแล้วก็ไม่มีอะไรที่น่าจะยากไปกว่านั้นแล้ว

ก่อนจะไปต่อก็ลองย้อนไปดูโค้ด checkin.php เพราะว่ามันมีเงื่อนไขที่จะได้มาซึ่ง flag ของข้อนี้อยู่

$roomNumber = $xml->roomNumber->__toString();
// With the emerging of MicroServices ! (<https://www.youtube.com/watch?v=y8OnoxKotPQ>)
// We will pass roomNumber to our internal server (/flag9.txt)
$roomNumber = checkRoomAvailability($roomNumber);

ซึ่งจากโจทย์ข้อ 8 ที่เราได้มาก็อนุมานได้ว่าการจะไปเอา flag.txt มานั้นเราก็ต้องมีการหยิบ API Key มาใช้ด้วย ซึ่งถ้าเราย้อนกลับไปเช็คที่ไฟล์ getSecret.php อีกรอบก็จะพบว่ามีการกำหนดค่า header ที่จะระบุค่า API key

echo $envVars['X_API_KEY'].PHP_EOL;

พอรู้แบบนี้แล้วก็จัดต่อค่ะ ยัด X_API_KEY ด้วย API Key ที่เรามีแล้วส่งไป พร้อมเปลี่ยน roomNumber เป็น file ที่โจทย์ต้องการได้เลยจ้า

Challenge #10

หาชื่อ Username ของผู้ใช้งาน Linux ในเซิร์ฟเวอร์ backoffice.ctf.p7z.pw:8000 ที่ชื่อลงท้ายด้วยคำว่า oss ให้ตอบคำถามเป็นรูปแบบเป็น FLAG_WTCTT_10{ค่า MD5 ของ username} ตัวอย่างเช่น ถ้า Username คือ floss ให้ตอบว่า FLAG_WTCTT_10{f433a73faa163a3a0209f0a50556afd0}

ก็ยังคงต่อเนื่องจากข้อที่แล้วที่หยิบเอา parameter roomNumber มาตีป้อมเรื่อยๆ และก็มาถึงข้อสุดท้ายแล้วที่มีการถามหา linux user ในระบบ ที่มาแบบนี้รู้เลยนะคะว่าต้องมีการ LFI (Local File Inclusion) กันเกิดขึ้น

และอย่างที่ก็รู้กันว่าใน Linux จะมีการเก็บพวกตัว user ในระบบไว้ที่ /etc/passwd แบบนี้ก็หวานหมูสิ จัดไปสิครัชรออะไร

และเมื่อโจทย์ต้องการให้หาว่ามี user ไหนที่ลงท้ายด้วย -oss จากการไปดูไฟล์นี้แล้วก็จะพบว่านัง user ต้นเรื่องที่ว่าก็คือ changmingtherealboss ว่าแล้วก็เอาค่านี้ไปเข้า md5 ก็เป็นอันเสร็จเรียบร้อย

echo -n changmingtherealboss | md5sum

และก็เดินทางมาถึงตอนจบของ Writeup รอบคัดเลือกกันแล้วจ้าาาาา บอกเลยว่าเซ็ตหลังนี่คือก็แอบ tricky เล็กน้อยจนต้องทักไปขอเบิก hint จากพี่ในทีมทั่นหนึ่งที่ลง writeup ไปก่อนหน้านี้แล้วเลยทีเดียว โจทย์ตื้นเกินไปหรือผิดที่ฉันคิดลึกเกินไปเอง

สุดท้ายนี้ก็ขอขอบคุณทีมงานทุกๆท่านที่ร่วมจัดงานนี้ขึ้นมา และขอบคุณทุกท่านที่อ่านกันมาจนจบนะคะ

สำหรับซีรี่ส์รอบไฟนอลก็ ไม่ขอคอนเฟิร์ม แต่ดูจากเวลาแล้วก็ แหะ

สำหรับ PART 1 สามารถไปตำได้ที่
https://medium.com/@re_pair/wtctt2022-qualification-round-writeup-1-8d2fac52d9d3

สำหรับวันนี้ สวัสดีค่า

#RE_PAIR

--

--