Spring Bootでは、URLエンコードされたスラッシュをURLパスとして使えない

こんにちは。 エキサイト株式会社の三浦です。

Web開発をしていると、URL周りを触ることが多々あります。

URLには特殊文字と呼ばれる「URL内で使う場合に特別な意味を持つ文字」がいくつか存在し、それらをあくまで普通の文字として使いたい場合はURLエンコード処理をする必要があるのですが、Spring Bootを使っている場合には、それでもなお使えないパターンが存在します。

今回は、そのような事例を紹介します。

URLとURLエンコード

この記事を見てくださるような方であれば、ほとんどの方はURLをよく見かけるでしょう。

https://example.com/sample_path/

このように、文字列を使ってWeb上の特定のサイト・ページを示しているのがURLです。

このURLですが、URLで使う場合に特別な意味を持つ「特殊文字」が存在します。

上記のURLにも含まれている /: などがそれに相当しており、区切り文字などとして使われているため、そのままだと通常の文字としての /: とは認識してくれません。

// これでは、正しく文字としては認識してくれない
https://example.com/sample_path/?key=/:

文字として使いたい場合は、エンコード処理をします。

// エンコード処理により、正しく認識してくれるようになる
https://example.com/sample_path/?key=%2F%3A

人の目からは見づらくなりましたが、プログラム上では正しく認識してくれるようになります。

基本的にはこれで問題ないのですが、特定の状況下ではURLエンコードしても問題になる場合があります。

Spring Bootとエンコードしたスラッシュ

先程書いたように、スラッシュをエンコードすると %2F という文字列になり、これを使えばURL内でも「特殊文字としてのスラッシュ」ではなく「通常の文字としてのスラッシュ」として認識してくれるようになります。

では、以下のようなURLはどうなるでしょうか?

https://example.com/sample%2Fpath/

これはつまり、 sample/path というパスを持つURLということになります。

一見問題なさそうに見えますが、これをSpring Bootで作ったAPI等に投げると以下のようなエラーが返ってきます。

400エラー

実はSpring Bootでは、脆弱性の観点からパス内にURLエンコードしたスラッシュを使用することは出来ないようになっています。

設定を変更すればできるようですが、そもそも脆弱性から禁止していることでもあるので、できる限りパス内では使わないようにしたほうが良いでしょう。

クエリパラメータとして使う分には問題ないので、もし通常の文字としてスラッシュを使いたいのであれば、クエリパラメータとして持たせましょう。

最後に

URLエンコードしたから大丈夫、と思って使っていると、このようなケースにはまってしまう場合もあるかもしれません。

ただし、逆に言えば知らなかった脆弱性に対処してくれているということでもあるので、適切に対応していきましょう。