SSRF基礎
- 9. SSRFの攻撃事例(多数あり)
Capital One 個人情報漏えい
- https://piyolog.hatenadiary.jp/entry/2019/08/06/062154
WYSIWYG型エディタのビデオ挿入でSSRF
- https://hackerone.com/reports/643622
oEmbedの機能からSSRF
- https://hackerone.com/reports/793704
shopify SSRFからインスタンスのルート取得
- https://hackerone.com/reports/341876
米国国防総省 ポートスキャニング
- https://hackerone.com/reports/326040
shopify 細工したSVGで内部サーバに保存されている画像ファイルをリーク
- https://hackerone.com/reports/223203
9
- 12. 脆弱なコード例(PHP)
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET[“url”]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$res = curl_exec($ch);
curl_close($ch);
$doc = new DOMDocument();
$doc->loadHTML($res);
$anchors = $doc->getElementsByTagName('a');
foreach($anchors as $anchor) {
echo "[-] ".$anchor->nodeValue, PHP_EOL;
}
?>
12
- 13. 脆弱なコード例(PHP)
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET[“url”]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$res = curl_exec($ch);
curl_close($ch);
$doc = new DOMDocument();
$doc->loadHTML($res);
$anchors = $doc->getElementsByTagName('a');
foreach($anchors as $anchor) {
echo "[-] ".$anchor->nodeValue, PHP_EOL;
}
?>
13
URLを外部から受け取っている。
url=http://127.0.0.1を送信する
とサーバ自身にリクエストを送
る。
※ 後続のloadHTML関数により
HTMLコンテンツを返さない場合は
エラーになる
- 14. 脆弱なコード例(Python)
14
import urllib3
from lxml import etree
from flask import Flask, request
# 省略
@app.route("/", methods=["GET"])
def index():
url = request.args.get("url", type=str) or None
if url:
http = urllib3.PoolManager()
res = http.request('GET', url)
root = etree.HTML(res.data)
anchors = root.findall(".//a")
for anchor in anchors:
print("[-] %s" % anchor.text)
- 15. 脆弱なコード例(Python)
15
import urllib3
from lxml import etree
from flask import Flask, request
# 省略
@app.route("/", methods=["GET"])
def index():
url = request.args.get("url", type=str) or None
if url:
http = urllib3.PoolManager()
res = http.request('GET', url)
root = etree.HTML(res.data)
anchors = root.findall(".//a")
for anchor in anchors:
print("[-] %s" % anchor.text)
PHPと同じ
- 16. SSRFの間違った対策
<?php
function validate_url($url) {
$parse_url = parse_url($url);
if ($parse_url["host"] !== '169.254.169.254') {
print("pass");
return $url;
} else {
print("block");
}
}
$url = validate_url($_GET["url"]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
#...
16
内部IPアドレスをブロックリス
トに指定する
- 17. SSRFの間違った対策
<?php
function validate_url($url) {
$parse_url = parse_url($url);
if ($parse_url["host"] !== '169.254.169.254') {
print("pass");
return $url;
} else {
print("block");
}
}
$url = validate_url($_GET["url"]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
#...
17
簡単に回避される
# validate_url("http://169.254.169.254");
# block
# validate_url("http://2852039166");
# pass
- 18. SSRFの間違った対策
<?php
function validate_url($url) {
$parse_url = parse_url($url);
if ($parse_url["host"] !== '169.254.169.254') {
print("pass");
return $url;
} else {
print("block");
}
}
$url = validate_url($_GET["url"]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
#...
18
ワイルドカードDNSサービス
nip.io など
#
validate_url("http://magic-169-254-169-254.
nip.io");
# pass
- 19. SSRFの間違った対策
<?php
function validate_url($url) {
$parse_url = parse_url($url);
if ($parse_url["host"] !== '169.254.169.254') {
print("pass");
return $url;
} else {
print("block");
}
}
$url = validate_url($_GET["url"]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
#...
19
リダイレクトさせる
※ リダイレクト追従する場合のみ
# validate_url("https://evil.example.com");
# pass
HTTP/2 302
…
location: http://169.254.169.254
他にもDNS Rebindingなどがある
- 24. 参考リンク
● payload チートシート
○ https://github.com/swisskyrepo/PayloadsAllTheThings/
tree/master/Server%20Side%20Request%20Forgery
● Cloud metadata URL リスト
○ https://gist.github.com/mrtc0/60ca6ba0fdfb4be0ba499c
65932ab42e
24
- 26. ハンズオン F&Q
Q なにするの?
A Aboutを見てください。FLAGを5つ探してください。
Q FLAGが分からない・・・。
A Hintを用意してます
Q クラウドメタデータを窃取してもいいの?
A コンテナ内に同じ構成を作ってるだけだから問題ないです!
26