DataSight Analytics

Writeup NCSA AI CTF 2026
b
benzdeus
Apr 3, 2026·2 min read

Series note

หมายเหตุ: โพสต์นี้จัดทำขึ้นระหว่างการทดลอง workflow ที่มี AI เข้ามาช่วยในการเรียบเรียงและสรุปเนื้อหา เนื้อหาบางส่วนยังอยู่ระหว่างการเกลาเพิ่มเติม ทั้งในด้านความครบถ้วน ตัวอย่างประกอบ และการอธิบายบริบทของโจทย์

หมวด Secure Architecture & Design

ภาพรวมโจทย์

DataSight Analytics เป็นโจทย์ที่ตอนแรกดูเหมือนระบบ health check ธรรมดา แต่จริง ๆ แล้วซ่อน MCP server สำหรับการจัดการไฟล์ ไว้ด้านหลัง โจทย์บอกเพียงว่าระบบมีเครื่องมือเกี่ยวกับไฟล์อยู่ 4 ตัว และเป้าหมายคือหาข้อมูลลับที่รั่วจากการตั้งค่า access control ผิดพลาดให้เจอ

หน้าแรกตอบกลับมาแค่นี้ แค่นี้:

JSON
{"status":"ok","server":"datasight-file-manager-ctf"}

ถ้าไม่ลองต่อก็อาจนึกว่ามันไม่มีอะไร แต่ความจริง route ที่สำคัญอยู่ที่ ช่องทางสื่อสารของ MCP

หา ช่องทางสื่อสารของระบบก่อน

เมื่อไล่ path มาตรฐานของ agent หรือ MCP server จะพบว่า /sse ตอบกลับเป็น text/event-stream และส่ง event ที่มี endpoint ลักษณะ:

text
event: endpoint
data: /messages/?session_id=...

ตรงนี้ยืนยันแล้วว่าระบบใช้ MCP over SSE แบบตรงไปตรงมา:

  1. เปิด GET /sse

  2. รับ session_id

  3. ส่ง JSON-RPC ไปที่ /messages/?session_id=...

  4. รับผลลัพธ์กลับจาก stream เดิม

นี่เป็น pattern ที่เจอได้บ่อยในระบบ agent ภายใน และเมื่อรู้ ช่องทางสื่อสารแล้ว ขั้นต่อไปก็คือ ไล่ดูเครื่องมือ

ไล่ดูเครื่องมือที่เปิดให้ใช้

หลังส่ง initialize และ tools/list จะพบเครื่องมือที่โจทย์บอกไว้จริง:

  • fs_list_directories

  • fs_list_files

  • fs_read_file

  • fs_get_file_info

ลองเรียกใช้งานแบบปกติก่อน จะเห็นโฟลเดอร์ประมาณ:

  • reports/

  • models/

และไฟล์อย่าง:

  • annual_2025_highlights.txt

  • q4_2025_summary.txt

  • fraud_detector_v3_config.json

ทั้งหมดนี้เป็นตัวหลอก มากกว่า ไม่เจอ flag อยู่ในเส้นทางปกติ

จุดแตกอยู่ที่ path traversal

สิ่งที่น่าสงสัยตั้งแต่แรกคือ description ของ tool บอกว่าควรเข้าถึงได้เฉพาะ data directory เท่านั้น แต่ยังไม่มีหลักฐานว่าระบบตรวจ canonical path จริงหรือไม่

เมื่อเริ่มส่งค่า path ที่มี .. เข้าไป เช่น:

  • fs_list_files("../")

  • fs_list_files("../../")

  • fs_read_file("../../etc/passwd")

กลับพบว่าระบบยอมทำงานจริง ผลลัพธ์แสดงทั้งไฟล์ชั้นบน source code และแม้แต่ /etc/passwd

จุดนี้คือหลักฐานชัดเจนว่า service มี path traversal เพราะมันเอา user input ไปประกอบ path โดยไม่ตรวจว่าหลัง resolve แล้ว path ยังอยู่ภายใต้ root ที่อนุญาตหรือไม่

จาก traversal ไปสู่ การอ่าน source code

เมื่อ traversal ใช้ได้ ขั้นต่อไปไม่ควรรีบไล่หาค่า flag แบบสุ่ม แต่ควรอ่าน source หรือ startup scripts เพื่อเข้าใจว่าระบบเก็บ ค่าลับ ไว้ตรงไหน

ไฟล์ที่อ่านแล้วมีประโยชน์มาก ได้แก่:

  • ../src/main.py

  • ../src/challenges/file_access.py

  • ../../start.sh

  • ../../proc/self/environ

โดยเฉพาะ start.sh เผยให้เห็นว่า container startup script นำ environment variable ไปแทนค่าใน source ตอนเริ่มระบบ:

Bash
sed -i "s/\[\[RANDOM_SECRET\]\]/$RANDOM_SECRET/g" /app/src/challenges/file_access.py

นี่เป็น clue สำคัญทันทีว่า ค่าลับ น่าจะอยู่ใน environment มากกว่าจะเป็นไฟล์ static ธรรมดา

เจอ flag จาก environment ของ process

เมื่ออ่าน ../src/challenges/file_access.py จะเจอบรรทัดแปลก ๆ ลักษณะ:

Python
FLAG = os.environ.get("ai{egtKNaZEgj}")

ถึงโค้ดจะเขียนดูผิดธรรมชาติ แต่มันบอกอย่างน้อยว่า challenge นี้ inject ค่าบางอย่างผ่าน environment แน่นอน จากนั้นพออ่าน:

text
../../proc/self/environ

ก็พบค่า:

text
RANDOM_SECRET=ai{egtKNaZEgj}

นั่นคือ flag ของโจทย์

ทำไมโจทย์นี้ถึงสำคัญ

โจทย์นี้ไม่ใช่แค่ path traversal ธรรมดา แต่มันแสดง chain ที่อันตรายในระบบ เครื่องมือจัดการไฟล์ สำหรับ agent:

  1. ผู้โจมตีใช้ tool ที่ควรจำกัด path ได้

  2. หลุดออกจาก data directory ด้วย ..

  3. อ่าน source code และ startup script

  4. เดาได้ว่า ค่าลับ อยู่ใน environment

  5. อ่าน /proc/self/environ เพื่อดึงค่าจริงออกมา

นี่คือภาพของ "การใช้เครื่องมือผิดขอบเขต" ที่เกิดจาก lack of boundary enforcement ล้วน ๆ

บทเรียนจากโจทย์นี้

ถ้าจะ expose เครื่องมือเกี่ยวกับไฟล์ ให้ agent หรือผู้ใช้เรียกใช้ผ่าน API ต้องทำอย่างน้อย:

  • canonicalize path ก่อนทุกครั้ง

  • ตรวจว่า resolved path ยังอยู่ใต้ allowed root

  • block traversal patterns อย่าง ..

  • แยก source code และ runtime ค่าลับs ออกจากพื้นที่ที่ tool เข้าถึงได้

ถ้าไม่ทำ แม้จะเปิดแค่เครื่องมือดูไฟล์ที่ "ดู ไม่มีพิษภัย" ก็ยังกลายเป็นช่องทางอ่าน source และ ค่าลับใน environment ได้เต็มรูปแบบ

Flag

text
ai{egtKNaZEgj}

In This Series

View All Parts