網頁漏洞 XSS (Cross-Site-Scripting) 攻擊 (下) 進階思路解說

  1. 1. 前言
  2. 2. <script>標籤失效!?
  3. 3. <input onclick=”” onload=””>
  4. 4. 想看圖片?我給你看Alert! <img src=”” onerror=””>
  5. 5. 那我該如何預防!?

上一篇「網頁漏洞 XSS (Cross-Site-Scripting) 攻擊 (上) 基礎原理解說」中提到了基礎的 XSS 原理,這次要來介紹更深入更進階的思路了。



前言

如果你不清楚什麼是 XSS ,可以先觀看我上一篇的貼文「網頁漏洞 XSS (Cross-Site-Scripting) 攻擊 (上) 基礎原理解說」。

(提醒您,本文技巧請勿用於非法用途,一切行為請自行負責,與本站無關。本站僅作為學術研討用途。)

上一篇文章中所模擬的環境是比較誇張的狀況,任何參數都沒過濾這種事情不大可能發生 (還是頗多,只是比例上來說少),大多數網站多少都會有過濾機制,但是有設計過濾機制難道就安全了嗎?這其中許多過濾是不完全的,只要花點小巧思就能繞過!你需要的是「創意」。


<script>標籤失效!?

上篇中說過,我們可以透過輸入「abc123</p><script>alert(1)</script><p>」來觸發<script>標籤來執行 Javascript 語法,可是當該網站過濾一切的「<script>」時呢?
加強上次模擬的貼文系統:

1
2
3
4
5
6
<!-- index.html -->
<form action="post.php" method="POST">
<input type="text" name="title">
<input type="text" name="content">
<input type="submit">
</form>
1
2
3
4
5
6
7
8
9
10
11
12
// post.php
$title=trim(str_replace("<script>", "", $_POST['title'])); //過濾<script>標籤
$content=trim(str_replace("<script>", "", $_POST['content'])); //過濾<script>標籤
if(empty($title) || empty($content)) exit();

$connection=mysql_connect("localhost","root","password");
mysql_select_db("post");
$sql = "INSERT INTO `post` (`title`, `content`)
VALUES('$title', '$content');"
if($result = mysql_query($sql, $connection);){
echo "貼文成功!";
}

既然<script>這麼危險,那我過濾掉不就好了。
有些網站認為,只要過濾<script>標籤就安全了。
很多人不知道,這種過濾方法是有漏洞的!可以使用「<sc<script>ript>」來繞過此過濾方法。

因為當「<sc<script>ript>」輸入時,中間的<script>被過濾掉後會…
<sc<script>ript>」 => 「<script>

雖然說不建議,但若是真的必須要用這種方式過濾某個字串,可以使用迴圈。
利用「strpos()」來檢查字串中是否含有「<script>」,若是存在就使用「str_replace()」過濾:

1
2
3
4
$title=trim($_POST['title']);
while(strpos($title, "<script>")){
$title=trim(str_replace("<script>", "", $title));
}

實際上,執行 Javascript 語法的方式有千千萬萬種,考驗的只是駭客們的創意,以下提供常見的幾種進階技巧給各位參考。


<input onclick=”” onload=””>

其實在HTML語言中,有許多標籤的屬性及事件是可以觸發Javascript的,因為那些本身就是Javascript下去運作的。
例如標籤<input type=”button”>中的 onclick:

1
<input type="button" onclick="alert(1)" value="Click Me!">

我們在onclick中加入語法「alert(1)」是可以被執行的,像這樣:

在onclick中不需要特別加上<script>標籤聲明是Javascript。

有時候我自己在滲透網站時,更偏好使用這樣的方法,而不是直接塞入<script>標籤,一方面<script>標籤被過濾的機率太高了,另一方面可以讓攻擊語法顯的比較優雅(X。

有些人可能會說:「這必須要點擊才能觸發,不點不就沒事了。」
的確,「onclick」需要透過點擊才能觸發內容,總不能要求使用者去點擊你植入的按鈕吧。

那就在推薦各位幾個常見的方式。

同樣是「input」標籤,我們可以透過「onload」,「onload」事件是指當該物件「載入完成後」觸發。例如我們可以使用該語法來植入:

1
<input type="text" onload="alert(1)">

這麼一來,就會在此標籤載入完成後自動觸發「alert(1)」了!


想看圖片?我給你看Alert! <img src=”” onerror=””>

這時候可能你又會想,那把雙引號「”」也過濾基本上任何屬性跟事件不就不能觸發了!?

理論上… 沒錯。
但也僅僅只是理論上,別忽略HTML的一個大特點 - 極高的彈性

HTML 提供極高的「容錯性」。
很多時候不需要照著 HTML 原本的寫法,只要「意思」到了,就可以執行!
例如你運行該語法:

1
2
3
4
5
<html>
<body>
<!-- something -->

</html>

正常來說,沒有將<body>標籤結尾應該是個錯誤的寫法,可是如果你運行這段語法你會發現,瀏覽器幫你加上了!
而 HTML 的高容錯特性則可以用在 XSS 的創意上。
現在要介紹的這是透過「<img>」標籤來觸發。

1
<img src=xss onerror=alert(1)>

簡單說明下,「onerror」是指當此圖片未能正常顯示時而觸發的事件,
而因為「src」所指定的目錄並無名為「xss」的檔案,所以必定會因為 not found error 而觸發「onerror」事件。

去除了雙引號「”」,但該語法是可以正常運作的!
這就是 HTML 的容錯性!


那我該如何預防!?

其實在PHP裡,有一個函式可以防止XSS,這個函式是「htmlentities()」,它並不是著重在存入資料庫時的過濾,而是在「輸出時防止」,他的作用是將敏感符號轉換成html編碼,這可以有效的防止語法被解釋成標籤的問題。

另外,在此呼籲一個重要的觀念!
請善用「白名單」而非「黑名單」!
這個意思是說,與其限制使用者「不能輸入什麼」,不如限制「只能輸入什麼」。
因為要擋的東西太多了!
如果你使用黑名單的方式可能是永遠都擋不完的,並且你的程式碼將會很長很亂。
我喜歡使用正規表達法,或者乾脆把一些文字經過「base64編碼」後再餵進資料庫。