Web安全學習筆記 XSS上
Web安全學習筆記 XSS上
繁枝插雲欣 ——ICML8
- XSS的分類和基本認識
- XSS的危害
- 同源策略的基本認識
一.XSS的分類和基本認識
1. 簡介
XSS全稱為Cross Site Scripting
,為了和CSS分開簡寫為XSS,中文名為跨站指令碼
。該漏洞發生在使用者端
,是指在渲染過程中發生了不在預期過程中的JavaScript程式碼執行
。XSS通常被用於獲取Cookie
、以受攻擊者的身份進行操作
等行為。
2. 分類
1.反射型XSS
反射型XSS是比較常見和廣泛的一類,舉例來說,當一個網站的程式碼中包含類似下面的語句:
<?php echo "<p>hello, $_GET['user']</p>";?>
那麼在訪問時設定
/?user=</p><script>alert("hack")</script><p>
則可執行預設好的JavaScript程式碼。
反射型XSS通常出現在搜尋等功能中,需要被攻擊者點選對應的連結才能觸發,且受到XSS Auditor、NoScript等防禦手段的影響較大。
2.儲存型XSS
儲存型XSS相比反射型來說危害較大,在這種漏洞中,攻擊者能夠把攻擊載荷存入伺服器的資料庫中,造成持久化的攻擊
。
3.DOM XSS
DOM型XSS不同之處在於DOM型XSS一般和伺服器的解析響應沒有直接關係
,而是在JavaScript指令碼動態執行的過程中產生的
例如
<html>
<head>
<title>DOM Based XSS Demo</title>
<script>
function xsstest()
{
var str = document.getElementById("input").value;
document.getElementById("output").innerHTML = "<img src='"+str+"'></img>";
}
</script>
</head>
<body>
<div id="output"></div>
<input type="text" id="input" size=50 value="" />
<input type="button" value="submit" onclick="xsstest()" />
</body>
</html>
輸入
x' onerror='javascript:alert(/xss/)
即可觸發
4.Blind XSS
Blind XSS是儲存型XSS的一種,它儲存在某些儲存中,當一個“受害者”訪問這個頁面時執行,並且在文件物件模型(DOM)中呈現payload。
它被稱為Blind的原因是因為它通常發生在通常不暴露給使用者的功能上。
二.XSS的危害
存在XSS漏洞時,可能會導致以下幾種情況:
1.使用者的Cookie
被獲取,其中可能存在Session ID
等敏感資訊。
若伺服器端沒有做相應防護,攻擊者可用對應Cookie
登陸伺服器。
2.攻擊者能夠在一定限度內記錄使用者的鍵盤輸入。
3.攻擊者通過CSRF
等方式以使用者身份執行危險操作。
4.XSS蠕蟲。
5.獲取使用者瀏覽器資訊。
6.利用XSS漏洞掃描使用者內網。
三.同源策略的基本認識
1. 簡介
同源策略限制了不同源之間如何進行資源互動,是用於隔離潛在惡意檔案的重要安全機制。 是否同源由URL
決定,URL由協議、域名、埠和路徑組成,如果兩個URL的協議、域名和埠相同,則表示他們同源。
1.1. file域的同源策略
在之前的瀏覽器中,任意兩個file域的URI被認為是同源的。本地磁碟上的任何HTML檔案都可以讀取本地磁碟上的任何其他檔案。
從Gecko 1.9開始,檔案使用了更細緻的同源策略,只有當原始檔的父目錄是目標檔案的祖先目錄時,檔案才能讀取另一個檔案。
1.2. cookie的同源策略
cookie使用不同的源定義方式,一個頁面可以為本域和任何父域設定cookie,只要是父域不是公共字尾(public suffix
)即可。
不管使用哪個協議(HTTP/HTTPS
)或埠號,瀏覽器都允許給定的域以及其任何子域名訪問cookie。設定 cookie時,可以使用 domain / path / secure 和 http-only 標記來限定其訪問性。
所以 https://localhost:8080
/ 和 http://localhost:8081
/ 的Cookie是共享的。
1.3. Flash/SilverLight跨域
瀏覽器的各種外掛也存在跨域需求。
通常是通過在伺服器配置crossdomain.xml
設定本服務允許哪些域名的跨域訪問
客戶端會請求此檔案,如果發現自己的域名在訪問列表裡,就發起真正的請求,否則不傳送請求。
2. 源的更改
同源策略認為域和子域屬於不同的域,例如 child1.a.com
與a.com
/ child1.a.com
與 child2.a.com
/ xxx.child1.a.com
與 child1.a.com
兩兩不同源。
對於這種情況,可以在兩個方面各自設定 document.domain='a.com'
來改變其源來實現以上任意兩個頁面之間的通訊。
另外因為瀏覽器單獨儲存埠號,這種賦值會導致埠號被重寫為 null
。
3. 跨源訪問
同源策略控制了不同源之間的互動,這些互動通常分為三類:
1.通常允許跨域寫操作(Cross-origin writes)
連結(links)
重定向
表單提交
2.通常允許跨域資源嵌入(Cross-origin embedding)
3.通常不允許跨域讀操作(Cross-origin reads)
可能嵌入跨源的資源的一些示例有:
<script src="..."></script> 標籤嵌入跨域指令碼
語法錯誤資訊只能在同源指令碼中捕捉到
<link rel="stylesheet" href="..."> 標籤嵌入CSS
由於CSS的鬆散的語法規則
CSS的跨域需要一個設定
正確的Content-Type 訊息頭
<img> / <video> / <audio> 嵌入多媒體資源。
<object> <embed> 和 <applet> 的外掛。
@font-face 引入的字型
一些瀏覽器允許跨域字型( cross-origin fonts)
一些需要同源字型(same-origin fonts)
<frame> 和 <iframe> 載入的任何資源
站點可以使用X-Frame-Options訊息頭
來阻止這種形式的跨域互動
3.1. JSONP跨域
JSONP就是利用 <script>
標籤的跨域能力實現跨域資料的訪問,請求動態生成的JavaScript指令碼同時帶一個callback函式名作為引數。
服務端收到請求後,動態生成指令碼產生資料,並在程式碼中以產生的資料為引數呼叫callback函式。
JSONP也存在一些安全問題,例如當對傳入/傳回引數沒有做校驗就直接執行返回的時候,會造成XSS問題。沒有做Referer或Token校驗就給出資料的時候,可能會造成資料洩露。
另外JSONP在沒有設定callback函式的白名單情況下,可以合法的做一些設計之外的函式呼叫,引入問題。這種攻擊也被稱為SOME攻擊。
3.2. 跨源指令碼API訪問
Javascript的APIs中,如 iframe.contentWindow
, window.parent
, window.open
和 window.opener
允許文件間相互引用。當兩個文件的源不同時,這些引用方式將對 window
和 location
物件的訪問新增限制。
window
允許跨源訪問的方法有
window.blur window.close window.focus window.postMessage
window
允許跨源訪問的屬性有
window.closed window.frames window.length window.location window.opener window.parent window.self window.top window.window
其中 window.location
允許讀/寫,其他的屬性只允許讀
3. 跨源資料儲存訪問
儲存在瀏覽器中的資料,如 localStorage
和 IndexedDB
,以源進行分割。每個源都擁有自己單獨的儲存空間,一個源中的Javascript指令碼不能對屬於其它源的資料進行讀寫操作。
4. CORS
CORS是一個W3C標準,全稱是跨域資源共享(Cross-origin resource sharing)。通過這個標準,可以允許瀏覽器讀取跨域的資源。
4.1. 常見請求頭
Origin
預檢請求或實際請求的源站URI,
瀏覽器請求預設會發送該欄位
Origin: <origin>
Access-Control-Request-Method
宣告請求使用的方法
Access-Control-Request-Method: <method>
Access-Control-Request-Headers
宣告請求使用的header欄位
Access-Control-Request-Headers: <field-name>[, <field-name>]*
4.2. 常見返回頭
Access-Control-Allow-Origin
宣告允許訪問的源外域URI
對於攜帶身份憑證的請求不可使用萬用字元 *
Access-Control-Allow-Origin: <origin> | *
Access-Control-Expose-Headers
宣告允許暴露的頭
e.g. Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
Access-Control-Max-Age
宣告Cache時間
Access-Control-Max-Age: <delta-seconds>
Access-Control-Allow-Credentials
宣告是否允許在請求中帶入
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods
宣告允許的訪問方式
Access-Control-Allow-Methods: <method>[, <method>]*
Access-Control-Allow-Headers
宣告允許的頭
Access-Control-Allow-Headers: <field-name>[, <field-name>]*
4.3. 防禦建議
如非必要不開啟CORS 定義詳細的白名單,不使用萬用字元,僅配置所需要的頭 配置 Vary: Origin
頭部 如非必要不使用 Access-Control-Allow-Credentials
限制快取的時間
5. 阻止跨源訪問
阻止跨域寫操作,可以檢測請求中的 CSRF token
這個標記被稱為Cross-Site Request Forgery (CSRF) 標記。
阻止資源的跨站讀取,因為嵌入資源通常會暴露資訊,需要保證資源是不可嵌入
的。但是多數情況下瀏覽器都不會遵守 Content-Type
訊息頭
例如如果在HTML文件中指定 <script>
標記
則瀏覽器會嘗試將HTML解析為JavaScript