半個月前發布了xscan掃描器,這期間又針對很多場景進行了優化,本文來做一個總結。

xscan是一次自動化漏洞賞金的探索,xscan的設計思想就是希望掛著機,打著游戲,漏洞就能自動上門。為此首先寫了一個能自己無限爬行的web爬蟲,爬蟲能幫我無限深度的獲取url,然后還做了一個xss檢測模塊(主要是xss比其他漏洞檢測起來更多更容易),簡單的框架就這么搭建好了。

憑XSS漏洞 刷了騰訊src 3000+分,暫列第一,漏洞賞金大概有15k

XSS掃描器的優化

很多自動化程序是一堆開源工具或掃描器的工作流組合,我基本上會使用開源軟件進行改造,不會使用閉源程序,因為掌控代碼細節可以進一步優化細節,然后用算法和策略去進一步提升效率。

優化掃描器的過程和機器學習的訓練很像,機器學習會將問題轉換為一個數學求最優解的過程,賦予不同的系數權重,經過gpu的運算在樣本范圍內求最優解。

而我就是xscan的gpu,通過爬蟲爬取大量數據集,并且學習了大量烏云、hackone的xss報告和手法,用人腦對數據集判斷,然后將它們轉換為規則。有時候規則緊了漏洞就少,規則松了就有大量誤報,有時候規則比較小眾,也掃不到。總的來說,這就像是一個加權重的過程。

基于dom相似度的爬蟲

獲取數據集的一個重要方式就是爬蟲,開源爬蟲中比較好的有projectdiscovery的katanacrawlergocrawlergo基于chromium爬蟲,katana分靜態爬蟲和動態爬蟲,但動態爬蟲規則不如crawlergo。

因為要進行大范圍掃描,考慮效率問題,我先使用的是katana的靜態模式,而且后續切換到動態爬蟲模式和修改細節也很容易。

在爬蟲的時候遇到一個問題,爬蟲重復率太高了,有些網站url不一樣,但是網站內容基本是模板生成出來的。

之前就有想法寫一個基于dom相似度的過濾器來解決這個問題,問了chatgpt大概的實現方式后,真的就實現了。

其實也很簡單,將網頁轉換為dom結構,使用hash算法將每個節點的內容轉換為一個數字,乘以節點深度和一個權重,將這個節點求余展開在自己定義的維度內。一個網頁就能得出一個類似這樣的embeding,eg:[1,2,3,4,5,6 ...]

用cos余弦函數對兩個網頁的embeding求值即是兩個網頁的相似度。技術是相同的,最近學習了一點深度學習的知識,沒想到轉頭就能用到爬蟲的身上,

掃描策略

xscan使用了html和javascript語義分析技術來檢測xss,最早在w13scan中有開源這部分模塊。

html語義會把dom結構按照標簽解析為Tag,Attribute,Content 這幾個屬性,Js按照詞法分析會把javascript語句解析為StringToken,IdentifyToken等等.

使用語義解析能準確確認回顯內容在html/js中的位置,只要再次根據所屬位置發送針對性payload,查看這些語義位置是否發生改變,就能知道是否存在xss,全程不會包含敏感payload。

https://brutelogic.com.br/xss.php?b1=asdsda

asdsda是我們能控制的內容

它的回顯位置用語義分析后,會發現是屬于Attribute屬性,value為 "asdsda"。

此時在之前payload基礎上加一個引號,就能破壞原有結構,

此時asdsda經過語義分析后,屬性為 Attribute的name,語義發生了改變,則說明可以XSS了。

  • 在bugcrowd中就掃到一個例子
  • 如果回顯出現在JavaScript中,除了使用構造js造成xss外,還能直接閉合<script>標簽造成XSS,如下
  • 還有很多返回頭Content-type是html的js部分,callback也能造成xss

掃描位置

用戶能接觸并自動觸發的位置,一般是在GET的query位置和POST的data位置,還有一個位置,就是url部分。對url每層路徑也進行一下檢測,也能發現很多XSS。

xscan也能掃描cookie,header的參數,但是不好利用,要結合多個漏洞來串聯,也發現了很多這種漏洞,但還沒有合適的例子串起來。


真實世界有趣的XSS

國外也有個xss掃描器叫knoxss,它的測試用例不錯,覆蓋了很多場景。https://knoxss.me/?page_id=766

這個靶場有很多姿勢學習,xscan也覆蓋了這些場景,然后就開動爬蟲對一些賞金項目進行了大范圍爬蟲和掃描,主要是測試掃描規則的命中率,正反饋再優化掃描器。

以下是一些真實世界中有趣的XSS

簡單js xss

原內容是

a = 'xxxx'

回顯內容可導致js引號逃逸

a= ''-alert()-''

直接造成xss

因為是核心業務范圍,獲得賞金¥3000

html編碼繞過

在一般情況都被過濾的情況下,xscan測得參數可以被html編碼,然后構造payload即可,由于可以html編碼,waf也是隨便繞了。

css 接管

微信的某個地方的登錄接口,href參數可以控制css的路徑

此時可以做一個遠程的css

#js_single_page_container{
    display: none;
}
.login_page_standalone:before{
    content:"hacked by w14";
}

如圖,可以將頁面文字篡改,并且把登錄二維碼改為了收款二維碼.

漏洞賞金 ¥60

輸出在src上

某某云 ,某個參數html編碼過濾了內容,但是輸出點在 script的src上,可以直接引用外部js。

可以看到還有個小細節,輸出的后面會有一堆內容,使用?=就可以無視了

都過濾了就安全了?

多個參數導致的XSS,每個參數都過濾到位了,但是兩兩組合起來,就會有意想不到的事情。

看以下數據包

authorappEventId,type參數都能在頁面中回顯,并且引號雙引號都會被html編碼。但是仔細觀察能發現,type參數有反斜杠,能夠吃掉引號,而authorappEventId參數可以控制后面的內容,就導致了xss誕生。

最后構造好js結構讓js不報錯,如下,就能造成xss了,同時還要bypass一下網站的waf(不讓彈alert)。

最終彈窗

js編碼造成的XSS

出現的原因是returnto參數回顯到document.write里了,過濾了引號,但是沒有過濾反斜杠,此時可以用js編碼,十六進制,八進制,繞過。

編碼轉換小工具:https://i.hacking8.com/encoding/

用以下

彈窗

雙參數繞過變態waf

waf很變態,檢測到惡意后有幾率封ip。為此還要換代理池去繞。

這個點有兩個參數,能回顯三個地方。

waf很變態,基本封死了所有可能觸發的事件。研究了一陣后,突破點就在那多處回顯的情況,我們可以將一個參數設為<img src=1,另一個參數設置為onerror=alert()

waf還會對 alert進行過濾,用console.log測試正常,但是換alert就攔了,但是這塊靈活多樣,花時間就可以了。最后

緩存中毒導致的存儲型XSS

普通訪問時發現首頁會緩存,并且發現當增加一些參數后,參數會回顯到頁面上,沒有任何的過濾

第一步

請求 https://www.rakuten.com/index.jsp?4jgia=ys828&callback=omico&categoryid=mh2cng1&code=vtb6t&emailto=i007y&id=mymtd&keyword=a9519&keywords=geeva&lang=fx3zt&list_type=adq0s&mod=xqard&monthx=rq2hr"-[1].find(alert)-"

數據包如下

GET /index.jsp?4jgia=ys828&callback=omico&categoryid=mh2cng1&code=vtb6t&emailto=i007y&id=mymtd&keyword=a9519&keywords=geeva&lang=fx3zt&list_type=adq0s&mod=xqard&monthx=rq2hr"-[1].find(alert)-" HTTP/1.1
Accept-Charset: utf-8
Referer: https://us.rakuten.com/
Accept-Encoding: gzip
Pragma: no-cache
Host: www.rakuten.com


能看到返回頁面已經注入了js

第二步:

去掉payload訪問,https://www.rakuten.com/index.jsp?4jgia=ys828&callback=omico&categoryid=mh2cng1&code=vtb6t&emailto=i007y&id=mymtd&keyword=a9519&keywords=geeva&lang=fx3zt&list_type=adq0s&mod=xqard

請求包如下

GET /index.jsp?4jgia=ys828&callback=omico&categoryid=mh2cng1&code=vtb6t&emailto=i007y&id=mymtd&keyword=a9519&keywords=geeva&lang=fx3zt&list_type=adq0s&mod=xqard HTTP/1.1
Accept-Charset: utf-8
Referer: https://us.rakuten.com/
Accept-Encoding: gzip
Pragma: no-cache
Host: www.rakuten.com


依然能看到我們的xss payload

網頁訪問后

繞csp

群友給的一個目標,有csp,把csp貼到 https://csp-evaluator.withgoogle.com/

script過濾的挺嚴的,標簽要有nonce+隨機數標記才能執行JavaScript。

但是百密一疏,疏忽了對base的過濾

所以插入一個base標簽,設置全局js的加載路徑

<base href="">

彈窗~

總結

結論分為 3 個部分:做對了什么,做錯了什么,學到了什么。

做對的地方

  • 使用Golang作為開發語言,go很適合寫掃描器,并且直接編譯為各個平臺的二進制,直接可以運行,在不斷更新的掃描器中,只用重新上傳即可,相比以前使用python的掃描器,環境的依賴,代碼的質量,到后面基本不可維護,一跑起來就報錯,又得費勁調試。

  • 開發自己的核心引擎
  • 從一開始就決定做自己的掃描器,其他引擎不完全符合自己需求,難以實現一些的創新想法,自己編寫核心引擎具有很多優點:
  • 可以更好地適應自己的需求
  • 具有更高的速度和可靠性
  • 可以加入自己的創新想法
  • 并不一味追求可控的代碼,
  • 用算法提升掃描器效率
  • dom相似度算法的爬蟲,爬蟲深度優先算法,小小的算法能解決大大的問題,爬蟲的提升提高了很多效率減少了很多誤報
  • 可配置選項
  • 內測版抽離了配置,可以在yaml文件上配置各種參數適配不同的機器。
  • 學習并驗證“經驗”
  • twitter上的trick,knoxss的靶場,一些bugbounty的文章和pdf,最終都經過爬蟲+掃描模塊的驗證,當效果比較好時才會正式納入它們成為xscan的掃描模塊。有時候有一些新點子,嗯,有沒有網站會有這種情況呢?就拉一批網站來試驗。總體來說很多想法在試驗中都不盡如人意。也有一些效果特別好的,暫且不表,大家自己實驗,哈哈。
  • 開放并交流經驗
  • 在星球開放了自己的工具,收到了很多反饋,和很多bughunter碰撞,優化xscan的策略和適配情況。
  • xscan不會直接發送敏感的payload,而是通過語義的方式發現這里存在問題并報告,由使用者自行判斷問題

做錯了什么

  • 在xss同時順手加了clrf和ssti掃描,但基本上沒有掃到什么,觸發打開爬蟲限制,讓它漫無目的爬蟲,會出現一些ssti漏洞,增加了請求數量但沒有什么實際效果,后面就基本關閉它們了。

  • 沒有寫測試用例,到后面一處代碼改動,這個情況能跑成功,之前的情況跑不成功了。

  • 應該針對每個場景的情況都應該寫一個測試用例,當修改代碼后,一鍵跑一下測試用例,就能知道代碼運行情況和質量了。索性后面慢慢補上了
  • 熬了很多個夜晚寫代碼,排查bug,排查誤報問題。
  • 白天上班,讓掃描器跑著,晚上回來根據生成的文檔改bug,半個月都在熬夜,業余所有時間都在它上面,有時候會在想值不值得,還好騰訊的獎勵夠大,可以讓我堅持。但是對身體的傷害是不可逆的了。
  • 一個人想完成所有事情

學到了什么

在國內SRC中,xss評級一般都是低微,只有騰訊和阿里對xss的評級是中危,特別的一些核心業務,騰訊對XSS的評分更高,這也是我一直拿騰訊SRC作為練手的原因。針對核心業務,因為范圍小,也對xscan做了特別優化,如基于burp的數據包掃描,有時候只會幫我查看哪些參數回顯以及過濾情況,不會直接使用策略,可以節省時間。

對于國外的賞金,我只掃了hackerone和bugbounty,它們把XSS定級一般在P3,賞金在200~1200美刀之間,折算成人民幣誘惑也很大了。但也不是那么好掃,全世界都盯著這些目標,它們也有自己的自動化掃描程序,簡單的xss重復率相當高,主要它們修復周期慢,一個xss幾個月不修,交上去全部重復。剩下的就是waf超級變態和一些需要奇淫巧計的了。國外網站的安全做的很好,CSP規則制定的很嚴,一定程度上預防了這類XSS。不過只針對賞金項目了,沒有賞金或賞金低的項目國內國外xss都很多。

XSS的危害沒有RCE來的刺激,對于漏洞賞金來說,提交十來份XSS報告的賞金可能還不如一個RCE來的多和有成就感,作為bughunter應該多研究這種類型的漏洞。但是對于剛接觸新手來說,xss是很容易獲得第一份漏洞賞金的漏洞,xscan則可以幫助你完成。

xscan只是我自動化賞金的其中一環,掃描策略方面已經跑通了,下一步就是擴大范圍的掃描,想做的是收集hackerone,bugbounty上賞金項目的資產,持續監控,掃描,畢竟國外的賞金報酬誘人,撿漏還是能一些的。這就是w15scan要做的(還在做)