常常聽到有人說網站出現「XSS 漏洞」,那這所謂的 XSS 到底是什麼?其可怕之處又為何?以下,帶你淺談 XSS (跨站運行腳本) 原理及背後齷齪骯髒的技巧。
閱讀本文所需知識
在了解 XSS 之前,建議讀者最好先具備 HTML (超文字標記語言) 的基礎知識,否則可能會出現連範例都看不懂的窘境。
可能觸發 XSS 的先決條件
一般來說,XSS大多發生在「動態網頁」而不是「靜態網頁」,在此簡單解釋一下兩者差異,有興趣了解更深入者自行點選連結觀看。你可以這麼想像動態與靜態網頁:
- 伺服器 (Server)
- 翻譯:就如同一個「櫃台服務人員」展示著自家的商品,而 用戶端 (Client),就是圍觀的顧客。
- 原意:顧名思義為提供某特定服務的主機,而 用戶端 (Client) 則是使用這項服務的人。
- 靜態網頁
- 翻譯:「服務人員」照著公司的流程介紹自家商品,不與顧客有任何的對話跟交流 (即使顧客提問也不給予回應)。
- 原意:伺服器 (Server) 向 用戶端 (Client) 單向的展示服務,不接受任何來自 用戶端 (Client) 的請求 (連線請求例外)。
- 動態網頁
- 翻譯:「服務人員」在有限的範圍內,回答顧客的提問,或接受展示顧客所要求的內容。
- 原意:伺服器 (Server) 具有接受及自定義處理封包請求的能力,能與 用戶端 (Client) 擁有雙向的互動。
常見的狀況是 HTML + PHP 或者 HTML + ASP 等,都是在有「網頁後端語言」並且該網站處理封包不當的情況下發生。
一般使用者操作的HTML
以下是一些簡單的HTML標籤,我們模擬輸入名稱的功能。
(特別聲明:此範例單純使用HTML運作,模擬的環境是假設有傳入後端的情況。)
按鈕按下時,會將「使用者輸入」欄位的值傳入後端 PHP,後端再將接收到的值顯示給使用者看,這麼一來就有了雙向互動,同時後台運作是直接抓取接收到的值來顯示,這意味著沒有過濾參數。
後端環境、雙向互動、沒有過濾參數,再看看剛剛所說的觸發條件… 這是一個觸發的好環境啊!
【HTML 頁面 使用者輸入】
1
2
3
4<!-- index.html -->
<form action="name.php" method="POST">
<input type="input" name="my_name" value="abc123">
</form>【PHP 頁面 顯示傳入值】
你的名字:
1
2
3//name.php
$name=$_POST['my_name']; //接收參數
echo "<p>你的名字:".$name."</p>"; //沒過濾直接顯示
我們放大重點來討論,也就是說我們輸入什麼,就會反應在標籤上。
當使用者輸入「def456」則 HTML 標籤會長這樣
1 | <p>def456</p> |
輸入「ghi789」
1 | <p>ghi789</p> |
注意!上述都是一般使用者的作法,中規中矩的按造設計者的想法去做。
但… 駭客會這麼乖嗎?
駭客操作的HTML
人家常說調皮的小孩是聰明的,有時候換個思路,調皮點,一個漏洞就這麼發現了。
設計者要求這樣做,我就該這樣做嗎?
正常輸入「abc123」如此標籤:
1 | <p>abc123</p> |
你可以發現標籤內包著我們的語法,包著的是<p>標籤及標籤結尾</p>
那如果今天我們輸入「abc123</p>」呢?
1 | <p>abc123</p></p> |
你會發現我們所輸入的</p>居然被解釋成標籤結尾了!?
這是否意味著我輸入什麼語法他就執行什麼語法?
那我們將輸入的參數稍做修改,改成具有影響力的語法!
輸入「abc123</p><script>alert(1)</script><p>」
1 | <p>abc123</p><script>alert(1)</script><p></p> |
這則語法中的 alert(1) 是彈出警告視窗,其顯示內容為「1」
(Ps.「alert(1)」這是駭客們最常拿來測試 XSS 的語法)
隨意插入標籤?這麼一來我不就越權了嗎?
反射型 XSS
上述的 XSS 稱為「反射型」,其特點為「僅能自行觸發」,也就是我必須先向 伺服端 (Server) 發送請求,讓它回應給我一個因為該請求而觸發 XSS 的後果,這樣的漏洞不就太沒利用價值了嗎!?因為這意味著,你只能讓自己中招,而無法實質對 伺服端(Server) 產生傷害,或者危害到其他使用者權益,並且網頁將在重整後復原。整體來說該危害程度是許多管理者忽視且不願意花時間去處理的,但他們似乎忘了一個嚴重的問題… 社交工程 (Social Engineering)。(之後會撰寫一篇關於 社交工程 (Social Engineering) 的文章 點我連結)
預存型 XSS
該類型的 XSS 多半與 資料庫 (Database) 有著密切的關聯,上述的反射型是因為伺服端不會去儲存你的攻擊語法,所以不會發生該語法日後被再次觸發的問題,但現在要說的這種「預存型」就不同了。
「預存型」顧名思義就是伺服器將語法給紀錄下來了,並且在某些需要輸出紀錄時的場合被再次觸發到。
舉個常見的例子 - 「貼文系統」。以下模擬一個簡易的貼文系統 HTML + PHP + MYSQL:
1 | <!-- index.html --> |
1 | // post.php |
可以清楚看到 index.html 中所輸入的欄位分別有代表文章標題的「title」及代表文章內容的「content」,並且表單傳送至 post.php 中,在 post.php 裡將標題及內容寫入資料庫。
這時候假設貼文標題打上「abc213</p><script>alert(1)</script><p>」,內容隨意輸入「test」,正常來說此語法將會被成功寫入資料庫存放。
既然是貼文系統,照理來說會有個輸出文章的位置 (不然貼文就沒意義了):
1 | // display.php |
就這樣,資料庫裡存放的 html 標籤被輸出並解釋成標籤作用了。
任何只要看得到這篇文章的人,畫面上就會彈出我們所植入的「alert(1)」。
我們僅僅是用「alert()」來測試 XSS 而已,這還算不上是什麼危害,但是有心人士會透過其他語法來達成非法目的,例如可以利用「document.cookie」來獲取你的 Cookie ,很多時候明明沒有在其他地方登入過,電腦也沒有中毒,帳號卻莫名被盜,有可能就是你中了 XSS 。
總結
上述這些這顯然不是設計師希望我們做的,標籤植入越權思路這就是 XSS 的基本原理。
透過與網頁所設計的功能互動,而將標籤透過巧思植入網頁並使其觸發。
而更進階的 XSS 技巧請看下一篇「網頁漏洞 XSS (Cross-Site-Scripting) 攻擊 (下) 進階思路解說」。