ユーザーが認証なしでURL(存在しないURLを含む)にアクセスしようとすると、私のWebサービスはHTTP 401応答を返します。この応答はJSONエンコードされており、この応答の本文には、おそらく診断目的でユーザーが要求したパスが含まれています。応答には、www-authenticate
ヘッダーも含まれます。ユーザーがブラウザでこのURLにアクセスすると、ブラウザが認証情報を要求します。
ただし、自動スキャンツールは、これがXSSの脆弱性であることを報告しています。これは、要求されたパスが含まれているためであり、要求されたパスも有効なJavaScriptである場合は、このパスが応答とともに返されます。以下のcURL出力を参照してください。
curl -i 'https://myservice.example.com/<script>alert(1)</script>'
HTTP/2 401
server: nginx
date: Tue, 19 May 2020 15:02:20 GMT
content-type: application/json;charset=UTF-8
content-length: 167
strict-transport-security: max-age=31536000 ; includeSubDomains
www-authenticate: Basic realm="Spring"
{"timestamp":1589900540080,"status":401,"error":"Unauthorized","message":"Full authentication is required to access this resource","path":"/<script>alert(1)</script>"}%
この質問のように、API応答はJSONエンコードされているため、これは誤検知であると思います: Burpで実行されたJSONを介してXSSを反映しましたが、現実的な条件でそれを行う方法は?
私は正しいですか?
XSSの脆弱性は通常、2つのコンポーネントで構成されます。ユーザーが指定した文字列をフィルタリングせずに反映するバックエンドと、入力をフィルタリングせずにHTMLドキュメントに入力するフロントエンドです。
したがって、サーバーが何をしているのかを見るだけでなく、そのJSON応答を消費するアプリケーションを見る必要もあります。
最初にHTMLタグをエスケープせずに、path
をそのままHTMLドキュメントに挿入する可能性はありますか?または、JSONドキュメントをJSON.parse
ではなくeval
で処理すると、サーバーが実行可能なコードを渡せるようになりますか?
その場合は、消費するアプリケーションを修正することが最優先されます。ただし、多層防御戦略の一環として、サーバーが有効なHTMLを含む文字列をクライアントに渡さないようにすることも推奨されます。良い方法は、<
および>
を<
および>
としてエンコードすることです。
また、ユーザーが指定した文字列に"
が含まれている場合は、JSON応答が不正な形式にならないようにしてください。これは単に煩わしいだけでなく、場合によっては、応答を消費するツールを混乱させるために悪用される可能性もあります。
これは多くの自動化されたスキャナーが見つける発見のように見えます:彼らはURLに何かを入れて、それが応答の本文に反映されているのを見ます。
あなたの場合、これは有効なJSONで報告されますので、これは問題ではありません。笛のようにきれいではありませんが、そこにあるテキストで失敗するブラウザーまたはAPIコンシューマーを見つけるのは難しいでしょう。ご存じのように、その危険に見えるHTMLは有効である可能性があり、それをうまく処理するかどうかはクライアント次第です。
Text/htmlコンテキストではそれほど多くありませんが、そのシナリオにはこれが当てはまるケースがあります。
現在のところ、ありません。発生したのは、クライアントがJSON応答に特注の文字列を配置したことだけです。 XSSが発生するためには、安全でないリソース(HTMLファイル)にカスタムの文字列を書き込む必要があります。
何らかの理由でこのリクエストのパスを出力するWebページ(おそらくリクエストロギングページ)がある場合、何か厄介なことが考えられます。たとえば、次のコードは脆弱です。
.
.
.
output.Append($"<tr><td>{request.path}</td></tr>\n");
.
.
return Ok(output.ToString());
これは非現実的な例です。通常、この例のようにC#を使用している場合は、このようなマークアップを生成せず、Razorを使用するか、AJAXを使用してフロントエンドで生成します。この例を選んだのは、それが簡潔で、あなた自身が.NETプログラマーでない場合に理解される可能性が高いためです。
XSSとほとんどの注入は、2つの方法で防止できます。すべての文字列をエスケープ(別名サニタイズ)できます。あなたにとってそれは<
および>
と<
および>
。または、安全でない文字列がneverがコード(またはこの場合はマークアップ)として扱われることを確認できます。 Reactなどの多くのフロントエンドが2番目のオプションに使用されます。
Reactを使用し、JSXが次のようになっている場合:
.
.
.
return <h1>{foo}</h1>
変数foo
の内容に関係なく、これを行わない限り、マークアップ/コードとして扱われることはありません。
.
.
.
return <h1 dangerouslySetInnerHTML={{_html : foo}}/>
1つのオプションを選択する必要があります。既にReactまたは類似の機能を使用している場合を除いて、文字列をサニタイズする方が簡単です。APIで文字列をサニタイズする方が簡単です。それを使用するすべてのものが安全であることがわかっていますが、それが必ずしも文体的に最も適切であるとは限りません。文字列のサニタイズはAPIの問題ではなく、APIを使用して解決するための問題であると感じるかもしれません。