前言#
如果你不清楚什麼是 XSS ,可以先觀看我上一篇貼文「網頁漏洞 XSS (Cross-Site-Scripting) 攻擊 (上) 基礎原理解說」。
( 提醒您,本文技巧請勿用於非法用途,一切行為請自行負責,與本站無關。本站僅作為學術研討用途。 )
上一篇文章中所模擬的環境是比較誇張的狀況,任何參數都沒過濾這種事情不大可能發生 (還是頗多,只是比例上來說少),大多數網站多少都會有過濾機制,但是有設計過濾機制難道就安全了嗎?這其中許多過濾是不完全的,只要花點小巧思就能繞過!你需要的是「創意」。
<script>標籤失效!?#
上篇中說過,我們可以透過輸入「 abc123</p><script>alert(1)</script><p>
」來觸發<script>標籤來執行 Javascript 語法,可是當該網站過濾一切的「 <script> 」時呢?
加強上次模擬的貼文系統:
1<!-- index.html -->
2<form action="post.php" method="POST">
3 <input type="text" name="title">
4 <input type="text" name="content">
5 <input type="submit">
6</form>
1// post.php
2$title=trim(str_replace("<script>", "", $_POST['title'])); //過濾<script>標籤
3$content=trim(str_replace("<script>", "", $_POST['content'])); //過濾<script>標籤
4if(empty($title) || empty($content)) exit();
5
6$connection=mysql_connect("localhost","root","password");
7mysql_select_db("post");
8$sql = "INSERT INTO `post` (`title`, `content`)
9VALUES('$title', '$content');"
10if($result = mysql_query($sql, $connection);){
11 echo "貼文成功!";
12}
「 既然<script>
這麼危險,那我過濾掉不就好了。 」
有些網站認為,只要過濾<script>
標籤就安全了。
很多人不知道,這種過濾方法是有漏洞的!可以使用「 <sc<script>ript>
」來繞過此過濾方法。
因為當「 <sc<script>ript>
」輸入時,中間的 <script>
被過濾掉後會…
「<sc<script>ript>」 => 「 <script>」
雖然說不建議,但若是真的必須要用這種方式過濾某個字串,可以使用迴圈。
利用 strpos()
來檢查字串中是否含有「 <script>
」,若是存在就使用 str_replace()
過濾:
1$title=trim($_POST['title']);
2while(strpos($title, "<script>")){
3 $title=trim(str_replace("<script>", "", $title));
4}
實際上,執行 Javascript 語法的方式有千千萬萬種,考驗的只是駭客們的創意,以下提供常見的幾種進階技巧給各位參考。
自動觸發 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!#
這時候可能你又會想,那把雙引號「"」也過濾基本上任何屬性跟事件不就不能觸發了!?
理論上… 沒錯。
但也僅僅只是理論上,別忽略HTML的一個大特點 - 極高的彈性。
HTML 提供極高的「 容錯性 」。
很多時候不需要照著 HTML 原本的寫法,只要「意思」到了,就可以執行!
例如你運行該語法:
1<html>
2 <body>
3 <!-- something -->
4
5</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編碼」後再餵進資料庫。