上一篇「網頁漏洞 XSS (Cross-Site-Scripting) 攻擊 (上) 基礎原理解說」中提到了基礎的 XSS 原理,這次要來介紹更深入更進階的思路了。
前言
如果你不清楚什麼是 XSS ,可以先觀看我上一篇的貼文「網頁漏洞 XSS (Cross-Site-Scripting) 攻擊 (上) 基礎原理解說」。
(提醒您,本文技巧請勿用於非法用途,一切行為請自行負責,與本站無關。本站僅作為學術研討用途。)
上一篇文章中所模擬的環境是比較誇張的狀況,任何參數都沒過濾這種事情不大可能發生 (還是頗多,只是比例上來說少),大多數網站多少都會有過濾機制,但是有設計過濾機制難道就安全了嗎?這其中許多過濾是不完全的,只要花點小巧思就能繞過!你需要的是「創意」。
<script>標籤失效!?
上篇中說過,我們可以透過輸入「abc123</p><script>alert(1)</script><p>」來觸發<script>標籤來執行 Javascript 語法,可是當該網站過濾一切的「<script>」時呢?
加強上次模擬的貼文系統:
1 | <!-- index.html --> |
1 | // post.php |
「既然<script>這麼危險,那我過濾掉不就好了。」
有些網站認為,只要過濾<script>標籤就安全了。
很多人不知道,這種過濾方法是有漏洞的!可以使用「<sc<script>ript>」來繞過此過濾方法。
因為當「<sc<script>ript>」輸入時,中間的<script>被過濾掉後會…
「<sc<script>ript>」 => 「<script>」
雖然說不建議,但若是真的必須要用這種方式過濾某個字串,可以使用迴圈。
利用「strpos()」來檢查字串中是否含有「<script>」,若是存在就使用「str_replace()」過濾:
1 | $title=trim($_POST['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 | <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編碼」後再餵進資料庫。