やられアプリ BadTodo - 21 A10:2021-サーバーサイドリクエストフォージェリ(SSRF)

前回:やられアプリ BadTodo - 20 A4:2017 - XML外部エンティティ参照 (XXE) - demandosigno

SSRF攻撃とは

SSRF(Server Side Request Forgery)徹底入門 | 徳丸浩の日記
SSRF 攻撃とは、攻撃者から直接到達できないサーバーに対する攻撃手法の一種です。下図にSSRF 攻撃の様子を示します。

攻撃者からは、公開サーバー(203.0.113.2)にはアクセスできますが、内部のサーバー(192.168.0.5)はファイアウォールで隔離されているため外部から直接アクセスできません。しかし、公開サーバーから内部のサーバーにはアクセスできる想定です。
攻撃者は "何らかの方法" で公開サーバーから内部のサーバーにリクエストを送信することにより、内部のサーバーを攻撃できる場合があります。これがSSRF 攻撃です。

まず前回の XXEを使ったSSRFを再掲します(CWE-611)

XMLファイルをインポートするページ(import.php)にて、読み込むXML(import.xml)のENTITYにURLを指定します。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY schedule SYSTEM "http://internal.example.jp/">
]>
<todolist>
  <todo>
    <owner>test</owner>
    <subject>&schedule;</subject>
    <memo>test</memo>
    <url>https://www.example.com/</url>
    <url_text>Example Domain</url_text>
    <c_date>2023-08-10</c_date>
    <due_date>2023-08-16</due_date>
    <done>0</done>
    <public>1</public>
  </todo>
</todolist>

データをインポート後、指定したURLへのアクセス結果が表示されました。

このアクセス先http://internal.example.jp/index.htmlは内部からはアクセスできますが、外部からはアクセスできません。
/usr/local/apache2/conf/httpd.conf でアクセス制限されているためです。

113 <Directory /var/www/internal>
114     Require all denied
115     Require local
116 </Directory>

内部から internal を見てみるには BurpSuiteのUpstreamProxyServerにinternal.example.jp:23128を追記します。

URLプレビュー画面でのSSRF(CWE-918)

Todoの編集画面を見ると、入力したURLのプレビューを閲覧できることが分かります。

ここでURLにhttp://internal.example.jp/と入力すると、XXEの場合と同じく外部からは直接アクセスできない内容を閲覧できます。

プレビュー機能のソースコード(proxy.php)は次の通り。
PHP: cURL 関数 - Manual

<?php
$url = filter_input(INPUT_GET, "url"); //GETリクエストで受け取ったurlを$urlに格納
//  ini_set("openssl.cafile", "/etc/ssl/certs/ca-certificates.crt"); //HTTPS接続の際にサーバー証明書の検証を行う
$ch = curl_init(); //cURL セッションを初期化する
curl_setopt($ch, CURLOPT_URL, $url);  //取得する URL を指定
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //取得したコンテンツを文字列で返す
curl_setopt($ch, CURLOPT_TIMEOUT, 3); //3 秒以内にデータを取得できない場合タイムアウト
$output = curl_exec($ch); //cURLリクエストを実行
curl_close($ch); //cURL セッションを閉じる
if ($output === false) {
  header("HTTP/1.1 404 Not Found");
  exit;
}
echo $output;

file:///etc/passwdなども可能です。

対策

URL の取り扱いには要注意! SSRF の攻撃と対策 | yamory Blog
では仮に SSRF を見つけた場合、どのように修正すればいいでしょうか?
実は SSRF の対策は、非常に難しいという特徴があります。
一番最初に思いつく修正方法の「バリデーション」ですが、この方法は何個もの落とし穴が隠されています。
~(略)~
入力チェックは至難の業です。
~(略)~
果たして開発者はこれらのブラウザの挙動や悪性な入力を防ぎきれるでしょうか?
上記の問題が存在するため、SSRF の対策は困難を極めます。

SSRF 対策の難しさと問題点
基本的なベストプラクティスは「そもそも外部からの入力でリクエストを送る機能を作らない」となっており、次に「推移先の URL を固定にし、ドメインなどの許可リストを利用する」という対策が推奨されます。
しかし、これらの対策方法は機能そのものをユーザへ提供できなくなる場合があり、実装できないケースが存在します。
この問題点について OWASP ASVS v4 では対策について議論がなされたことがありますが、多くの対策方法については、その対策自体をすり抜ける攻撃シナリオが存在することが言及されています。
このように、SSRF の完璧な対策は「SSRF が発生しそうな機能を作らない」や「許可リストを作成し、それ以外をブロックする」といった強い制約を行う方法以外に存在しない状態にあります。
そのため他の脆弱性と違って SSRF は非常に厄介であり、危険な脆弱性として認識されています。

A10 サーバーサイドリクエストフォージェリ (SSRF) - OWASP Top 10:2021

youtu.be

logmi.jp

scgajge12.hatenablog.com

次回:やられアプリ BadTodo - 22 A8:2017 - 安全でないデシリアライゼーション - demandosigno

/* -----codeの行番号----- */