😈

【intigritiクイズ】DNS Rebinding Attack

2022/12/21に公開約2,800字

今回はローカルでの再現ができませんでした。
解答を読みながらDNS Rebinding Attackを理解することを目標に進めていきます。
https://twitter.com/intigriti/status/1600837243308244992

ターゲット

このWebサーバはGETリクエストを受け付けるエンドポイント/copy_fileを持っています。
URLクエリパラメータfileの値からURLを作成し、そのURLのホスト名をDNSルックアップします。
ホスト名に対応するIPアドレスが123.61.186.155であれば次の処理を行い。そうでなければNot allowed!という文字列をレスポンスします。

エンドポイントでは、setTimeout関数を使用して3秒の遅延を設定しています。
その後、URLクエリパラメータ 'file' の値を使用してHTTP GETリクエストを送信。
リクエストが成功すると、レスポンスデータを含む文字列'Done: ' + response.dataをレスポンスとして送信します。

公開されているアプリケーションサーバー

const app = require('express')();
const a = require('axios'); const d = require('dns');

function antiSSRF(req, res, next) {
    const url = new URL(req.query.file);
    d.lookup(url.hostname, (err, addr) => {
        if (addr === '123.61.186.155') next();
        else res.send('Not allowed!');
    })
}
app.get('/copy_file', antiSSRF, (req, res) => {
    setTimeout(function() {
        a.get(req.query.file).then((response) => {
            res.send('Done: ' + response.data);
        })
    }, 3000);
})
app.listen(3000, '0.0.0.0')

公開サーバーから内部のサーバーにアクセスできる場合、脆弱性がある可能性があります(SSRF)。ただし、ここではAntiSSRFという関数を通して適切なホストかをDNSに問い合わせているため、そこは対策されています。

ローカルホストのみに開いているサーバー

const app = require('express')();
app.get('/flag', (req, res) => {
    res.send('flag{s4mpl3_fl4g}');
});
app.listen(3000, '127.0.0.1');

内部からのアクセスのみを許可しているこのサーバーから、フラグを奪取するのが今回のクイズです。

解答

intigritiは良い回答に、プレゼントとしてSWAGを渡しているのですが、今回のベスト回答者はChatGPTを用いて答えを導き出していました(凄い)
https://twitter.com/akincibor1/status/1600852618078605312/photo/1
解答をもとに自分が理解できるようにに訳して編集したものが次になります。

  1. 攻撃者は、あるホスト名の解決を「123.61.186.155」もしくは「127.0.0.1」に切り替えることができるDNSサーバーを作成する。(ここではそのホスト名をswitch.fooと置きます。)
  2. 攻撃者は、ターゲットサーバー(target.com/copy_file)に対し、URLクエリパラメーター(file)にホスト名(switch.com)と取得したい場所(flag)を持たせてリクエストを送信します。
http://target.com/copy_file?file=switch.foo/flag
  1. antiSSRFはホスト名をDNSルックアップし、IPアドレスとして「123.61.186.155」を受信します。(攻撃側のDNSサーバーは最初、ホスト名を 123.61.186.155 に解決するようにしておく)
  2. 「/copy_file」ルートは、setTimeout関数を使っているため、3秒間遅れて次のリクエストが送信されます。
  3. 遅延の間、攻撃側のDNSサーバーはホスト名を「127.0.0.1」に解決するように切り替える
  4. 遅延後、「/copy_file」ルートは「127.0.0.1」にリクエストを送信、「/flag」ルートにアクセスしフラグを取得してレスポンスが攻撃者に返ってくる。

DNSリバインディング攻撃と呼ばれるもののようで、詳細は徳丸さんのサイト・動画がわかりやすかったので参照ください。
https://blog.tokumaru.org/2022/05/dns-rebinding-protection.html

難しかったポイント

そもそもDNSサーバーを自分で立てるという発想が出なかった。
https://www.youtube.com/watch?v=rFzmlkbwjKI
↑解説動画もあり、そこではDNS Rebinding脆弱性の有無を調べることが出来るあるサイトを使えば、簡単にflagを取れるとあったのですが...

AとBにそれぞれ切り替えたいIPアドレスを入れると、下のフィールドにホスト名が表示されます。
最初は意味が分かりませんでしたが、どうやらここで生成されたホスト名は一定時間ごとにAとBで指定したIPアドレスに切り替わるようです。
どういう仕組みか分かりませんが、まさにDNS Rebindingです。

感想

DNSリバインディング攻撃は、この問題のおかげである程度理解することが出来たと思います。
自分の知識レベルより上の内容は、最初は分からないことだらけで苦しいですが、Google検索の他に今ではAIも知識のサポートをしてくれるので、難しい勉強にも挑戦しやすくなったように感じます。
intigritiは、毎回面白いクイズを出題してくれるので、なんとか食らい付きながらまた記事にしていこうかと思います。

Discussion

ログインするとコメントできます