跨站腳本攻擊,英文Cross-Site Scripting,縮寫原本應該是CSS,但與階層樣式表--Cascading Style Sheets的縮寫相同,所以通常已X當做「交叉」的Cross,就變成是XSS。
在今天算是一個很嚴重的漏洞攻擊,因為有可能做到身份偽造,然後去進行資料竊取或破壞。但防禦跨站腳本攻擊,不單單只是前端開發工程師的責任,很大程度上也與服務如何部署有關係。
跨站腳本攻擊,是在頁面上存在從其他來源引入的腳本,而這些腳本帶有惡意行為。要注意的是,腳本並不只是指JavaScript,HTML、CSS或其他資料內容也有可能是惡意注入的對象。
The malicious content sent to the web browser often takes the form of a segment of JavaScript, but may also include HTML, Flash, or any other type of code that the browser may execute.
比如說在A網站 http://a.127.0.0.1.nip.io:8000/index.html 有以下內容:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>XSS</title>
</head>
<body>
<h1>Hello, World</h1>
</body>
<script type="text/javascript" src="http://b.127.0.0.1.nip.io:8000/xss.js"></script>
</html>
在這個頁面中,使用了另一個網站B http://b.127.0.0.1.nip.io:8000 的JavaScript。但是其實xss.js
的檔案並不是自己可以掌控的,它的內容可能是:
let h1 = document.querySelector('h1');
h1.innerText = 'Hello, Bob';
alert('XSS');
因此,「Hello, World」被改成了「Hello, Bob」,而且還跳出了一個警告。
外部的CSS也有可能是惡意的,它可能讓你網站的瀏覽者看到不正確的訊息。 同樣A網站 http://a.127.0.0.1.nip.io:8000/index.html ,但換成有以下內容:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>XSS</title>
<link rel="stylesheet" href="http://b.127.0.0.1.nip.io:8000/xss.css" type="text/css" media="screen" />
</head>
<body>
<h1>Hello, World</h1>
</body>
</html>
這次換成使用 B網站的 xss.css
:
h1::after { content: "(this is injected contents)"; }
當開啟頁面,會發現顯示的內容是「Hello, World(this is injected contents)」。
非常簡單只是注入了一些文字內容,但是瀏覽者可不會知道這段訊息並不是A網站提供的。
上面的例子都還只是改動一下頁面內容,但想想其實光改動頁面內容就已經挺可怕的了。假設今天在一個電子商務網站,其價格被惡意修改顯示,之後很有可能造成交易糾紛。
之前也提到過,Cookie可以設定成HTTPOnly,也就是不讓JavaScript可以存取到,但如果沒有設定好,JavaScript就有可能洩漏出去,而Cookie又經常是作為維持HTTP狀態的一環,也就有可能竊取Cookie欺騙登入狀態,進而盜用身份進行非法行為。
有時候會將存取權杖(access_token
)儲存在SessionStorage
、LocalStorage
或IndexedDB
之中,這些儲存位置也是都可以透過JavaScript進行存取,若是權杖洩漏也可能存在資安風險。
因此在開發上要好好留意是不是應該使用外部資源,特別是免費的CDN服務,像是jsdelivr、cdnjs,在學習開發上真的很便利沒錯,不少知名套件也有可能提供了CDN的快速上手方式。但在部署的時候仍需要考量該如何做,因為外部資源無法保證內容永遠不變,若是被串改或是DNS遭到劫持,有可能就會讓網站注入惡意內容。
本文同時發表於我的隨筆