SSTエンジニアブログ

SSTのエンジニアによるWebセキュリティの技術を中心としたエンジニアブログです。

Burp で HTTP/2 を無効化(OFF)する方法と、リクエストヘッダー名の大文字小文字にまつわるトラブルシュート

こんにちは、SSTでWeb脆弱性診断用のツール(スキャンツール)開発をしている坂本(Twitter, GitHub)です。

今回は診断で遭遇した Burp の奇妙な挙動と、そのトラブルシュートで知った「HTTP2の無効化(OFF)方法」について紹介します。

検証環境:

  • Burp Suite Community Edition v2023.12.1.3

「x-foo: bar」が「X-Foo: bar」になる怪現象

きっかけは、とある診断対象が「Burpを通したときだけエラーを返す」という問い合わせでした。

詳細は省きますが、見えてきた状況として、フロントJSの fetch() でカスタムヘッダーを付けているのですが、ヘッダー名が全部小文字なら正常遷移し、大文字小文字混じりならエラーになりました。 不思議なのは、フロントJSのソースでは明らかに x-foo: bar と小文字で送っているはずなのに、Burp 上でリクエストを見てみると X-Foo: bar となり、ヘッダー名が capitalize されていることでした。

試しに curl コマンドで送ってみても、やっぱり x-foo: barX-Foo: bar になってしまいます。

原因 : HTTP/2 無効化の設定漏れ

結論から書きますと、この謎現象の原因は HTTP/2 無効化の設定漏れでした。

2024年1月時点のWeb診断では、使用しているツールの仕様制限としてHTTP/2 が使えないため、HTTP/1.1 で送るよう Burp の設定などを揃えています。

Burp で HTTP/2 を無効化するには以下の2箇所を設定します。

  1. Settings -> Network -> HTTP -> HTTP/2 -> "Default to HTTP/2 if the server supports it" のチェックを外す。
    Network設定でのHTTP/2無効化
  2. Settings -> Tools -> Proxy -> Proxy listeners -> 稼働してるlistener(ほとんどのデフォルトでは 127.0.0.1:8080) を選択して Edit -> HTTP タブ -> "Support HTTP/2" のチェックを外す。
    Proxy ListenerでのHTTP/2無効化

本来は上記2箇所の設定が必要なのですが、1. の設定しかしていないと、今回のようなリクエストヘッダーの大文字・小文字のズレが発生します。

これは Burp Suite User Forum でも紹介されてました。教えてくれた同僚に感謝です。

forum.portswigger.net

これまでは 1. の設定だけで特にトラブルも無かったので、2. の設定が必要なことに気づきませんでした。 今回はアプリ側でヘッダー名の大文字・小文字の差異にセンシティブだったため、2. の設定漏れの影響を受けた次第です。

なぜこのようなズレ(Burp側でのヘッダー名のcapitalize)が発生するのかですが、上記の Burp Suite User Forum に詳しいロジックが紹介されていますので、気になる方は読んでみてください。

検証

phpinfo() の結果を返すテストサイトを使って検証してみます。

まず Network 設定からのみ HTTP/2 のチェックを外し、Proxy Listener の方はHTTP/2 のサポートが有効なままの状態で curl コマンドで小文字ヘッダーを送ってみます。

$ curl -ks -x localhost:8080 -H 'x-foo: bar' https://localhost:8303/phpinfo.php | grep bar
<tr><td class="e">HTTP_X_FOO </td><td class="v">bar </td></tr>
<tr><td class="e">X-Foo </td><td class="v">bar </td></tr> ##<<<<<<<<<<<< 
<tr><td class="e">_SERVER["HTTP_X_FOO"]</td><td class="v">bar</td></tr>

診断で遭遇したときと同様、すべて小文字で送ったはずのヘッダー名「x-foo」が「X-Foo」 に capitalize されてアプリまで届いてしまったことを確認できました。 Burp 上でリクエストを確認すると、以下のように capitalize されてしまっていました。

GET /phpinfo.php HTTP/1.1
Host: localhost:8303
User-Agent: curl/7.87.0
Accept: */*
X-Foo: bar
^^^^
Connection: close

続いて Proxy Listener 設定からも HTTP/2 のチェックを外し、もう一度同じcurlコマンドを送ってみます。

$ curl -ks -x localhost:8080 -H 'x-foo: bar' https://localhost:8303/phpinfo.php | grep bar
<tr><td class="e">HTTP_X_FOO </td><td class="v">bar </td></tr>
<tr><td class="e">x-foo </td><td class="v">bar </td></tr> ##<<<<<<<<<<<< 
<tr><td class="e">_SERVER["HTTP_X_FOO"]</td><td class="v">bar</td></tr>

今度は x-foo: bar のままアプリまで届いたことを確認できました。 Burp 上でリクエストを確認すると、以下のように小文字のままになっていました。

GET /phpinfo.php HTTP/1.1
Host: localhost:8303
User-Agent: curl/7.87.0
Accept: */*
x-foo: bar
^^^^
Connection: close

以上より、Burpを使うときにHTTP/2を無効化したい場合、Network 設定とProxy Listener 設定の両方でチェックを外す必要があることを確認しました。

なお http の場合は影響を受けないようです。 試しに Network 設定のみ チェックを外した状態で、http で curl コマンドを叩いてみます。

$ curl -s -x localhost:8080 -H 'x-foo: bar' http://localhost:8302/phpinfo.php | grep bar
<tr><td class="e">HTTP_X_FOO </td><td class="v">bar </td></tr>
<tr><td class="e">x-foo </td><td class="v">bar </td></tr> ##<<<<<<<<<<<< 
<tr><td class="e">_SERVER["HTTP_X_FOO"]</td><td class="v">bar</td></tr>

→ curlで送った小文字のまま、アプリまで届いていることを確認できました。

HTTP/2 の普及とヘッダー名の大文字・小文字問題

HTTP/1.1 までの時代では、ヘッダー名を X-Foo-Bar のように Upper camel case で表記することが多かったように感じます。(例: X-Content-Type-Options: nosniff)

HTTP/2 になると、ヘッダー名はすべて小文字となります。

ブラウザ、サーバ、そして中間のミドルウェアのそれぞれの互換性や仕様で、今回のようにヘッダー名の大文字・小文字がズレてしまうことが今後も出てくる可能性があります。

ヘッダーを扱うロジックを書く際は、ヘッダー名の大文字・小文字が揃っていなくても扱えるよう normalize してあげると、互換性も向上するかもしれません。

まとめ

本記事では Burp で HTTP/2 を無効化(OFF)するときに遭遇した、リクエストヘッダー名が capitalize される現象とその原因について紹介しました。 対処方法としては、HTTP/2 の無効化を以下の2箇所、両方とも忘れずに設定することになります。

  1. Settings -> Network -> HTTP -> HTTP/2 -> "Default to HTTP/2 if the server supports it" のチェックを外す。
  2. Settings -> Tools -> Proxy -> Proxy listeners -> 稼働してるlistener(ほとんどのデフォルトでは 127.0.0.1:8080) を選択して Edit -> HTTP タブ -> "Support HTTP/2" のチェックを外す。

Burp をお使いの方で、HTTP/2 を無効化したいときはこの記事を思い出してみてください。