web-dev-qa-db-ja.com

Javaでのサーバー側リクエスト偽造の防止

このアプリケーションでは、ユーザーがプロフィール写真のURLを指定できます。 URLからデータをフェッチし、サーバーに保存します。ただし、アプリはサーバー側のリクエストフォージェリ(SSRF)に対して脆弱です。file:///etc/passwdなどのURLを指定し、http://localhost:8080/などのローカルHTTPサービスにアクセスすることもできます。

これを修正する最良の方法は何ですか?私が持っていたいくつかのアイデア:

  • URLプロトコルをHTTPおよびHTTPSに制限します。
  • DNSがホスト名を検索し、ローカルアドレスでないことを確認します。
  • リダイレクトを無効にします。

これは良いスタートのようです-DNSルックアップにTOCTOUの問題があります(ローカルDNSがキャッシュするため、実際には問題ないかもしれません)。

私が持っていた別のアイデアは、インターネットのみを見ることができる制限されたネットワークセグメントにプロキシを配置し、それを介してリクエストを送信することでした。

私はこれをオンラインで調査しましたが、あまり情報がありません。 この記事 はかなり良いです。

11
paj28

これは私が現在使用しているコードです:

if(!url.getProtocol().startsWith("http"))
    throw new Exception();
InetAddress inetAddress = InetAddress.getByName(url.getHost());
if(inetAddress.isAnyLocalAddress() || inetAddress.isLoopbackAddress() || inetAddress.isLinkLocalAddress())
    throw new Exception();
HttpURLConnection conn = (HttpURLConnection)(url.openConnection());
conn.setInstanceFollowRedirects(false);
conn.connect();
IOUtils.copy(conn.getInputStream(), out);

HTTPまたはHTTPSを適用し、ローカルアドレスを禁止し、リダイレクトを無効にします。ただし、TOCTOU(チェックの時間、使用の時間)の欠陥がまだあります。

6
paj28