Flatt Security Blog

株式会社Flatt Securityの公式ブログです。プロダクト開発やプロダクトセキュリティに関する技術的な知見・トレンドを伝える記事を発信しています。

株式会社Flatt Securityの公式ブログです。
プロダクト開発やプロダクトセキュリティに関する技術的な知見・トレンドを伝える記事を発信しています。

Webサービスにおけるファイルアップロード機能の仕様パターンとセキュリティ観点

はじめに

こんにちは。株式会社Flatt Securityセキュリティエンジニアの村上です。セキュリティ・キャンプ卒業後、新卒入社組としてFlatt Securityでセキュリティエンジニアをしています。

本稿では、Webアプリケーション上で実装される「ファイルアップロード機能」の実装パターンをいくつか示し、「開発者が設計をする上で気をつけるべき脆弱性」とその対策について解説していきます。

「ファイルアップロード機能」の脆弱性は特定の言語やサービスによって発生する脆弱性だけでなく、特定の拡張子のファイルでのみ発生する脆弱性など非常に多岐にわたります。そのため、本稿では全ての脆弱性を網羅する事は目的としておりません。しかし、「ファイルアップロード機能」のセキュリティについて考えるための基本となる知識と対策観点を本記事で知って、今後の開発に応用していただければ幸いです。

ファイルアップロード機能の仕様パターンとセキュリティ観点

パターンA: アイコンや写真のアップロード

SNSや掲示板サイトなどでよく見るシンプルな画像ファイルのアップロード機能です。この場合、画像ファイルのみを受け入れてそれ以外のファイルは適切に拒否される必要があります。

観点1: 拡張子のチェックに不備があり、画像ファイル以外がアップロード可能

アップロードされるファイル形式が適切に制限されていない場合、画像ファイル以外のファイルがサーバーに設置されることによりサイトの改竄やサーバーの乗っ取りといった攻撃が行われる危険性があります。

例えばApacheなどで動いているサービスに対して任意のPHPファイルを設置できる場合、PHPを経由してWebサーバーに対してシェルコマンドの実行を行うことができます。Node.jsの場合においても、サーバーサイドのJavaScriptのコードを書き換える事によってシェルコマンドの実行ができてしまうパターンがあります。

他にも、フィッシング攻撃に利用されたり攻撃者によって意図しないファイル(マルウェア等)が設置されたりと攻撃に加担させられる危険性も存在します。

このような意図していないファイルをアップロードする攻撃に対して、具体的にどういったケースで問題が発生するかを解説します。

観点1-1: クライアントサイドのみでファイル形式のチェックを行う

ファイルアップロード機能を設計する場合、HTMLのinput要素のaccept属性を利用することによって画像ファイルのみ選択できるようにする場合や、JavaScriptを利用してファイルをアップロードする前にクライアント側で適切なファイルであるかをチェックするといった事を行う場合があります。

このようにクライアントサイドでファイル形式やアップロードされるファイルの安全性をチェックする場合、その制限を回避される危険性があります。例えばブラウザでアップロードするファイルの表示設定を変更することによって画像ファイル以外をアップロードしたり、リクエストを書き換えることによってクライアントサイドでのチェックを回避したりといった方法です。

HTMLのinput要素のaccept属性による指定はユーザー側で変更できるので、単独ではセキュリティ対策としては効果的ではない

ではどのように対策をすればよいかについて簡単に説明していきます。

対策1-1: サーバーサイドでのチェック

ファイルが意図された適切な種類のものかのチェックは原則としてクライアントサイドではなくサーバーサイドで実行します。先ほども述べた通り、クライアントサイドでのチェックはさまざまな回避方法が存在しています。

たとえ、クライアントサイドでアップロード前にチェックを行った場合でも欠かさずにサーバーサイドでのチェックが必要となります。

観点1-2: 前方一致や一部一致などによるチェックの危険性

アップロードされたファイルの拡張子が開発者の意図したものであるかの確認を行うために正規表現を利用する場合は注意が必要です。後方一致による正規表現のチェックでない場合、example.jpg.phpのような二重拡張子がついているファイルを用いることによってチェックを回避される危険性があります。

対策1-2: 適切な方法による拡張子のチェック
正規表現の適切な利用

拡張子のチェックは前方一致や部分一致ではなく、後方一致によって行うことで二重拡張子などによるチェックの回避を防ぐことができます。

言語ごとの関数の利用

言語ごとに用意されている関数を利用して拡張子のチェックを行う関数を作成する場合も正しく後方一致のロジックが実装されているか気をつける必要があります。

後方一致による拡張子のチェックのフローの例:

  1. 受け取ったファイル名をドット( . )で分割します。
  2. 分割されたファイル名の末尾の拡張子の部分(index(-1)の部分)を取り出す。
  3. 取り出した拡張子を許可リストとして定義された有効な拡張子の一覧と比較する。
  4. 拡張子がリスト中に含まれていた場合有効なファイルとして次の処理を実行する。
観点1-3: 有名でない拡張子を利用した回避

一般的でない拡張子を利用する事により拒否リスト型の拡張子の制限を回避される危険性があります。

例えばPHPの場合.php以外に以下のような拡張子の種類があります。このような拡張子を利用する事によって、.phpの拡張子が制限されている場合もPHPのファイルをアップロードすることができてしまいます。

  • .phtml
  • .php3
  • .php4 など
対策1-3: 許可リストによるチェック

利用できる拡張子の制限は拒否リストではなく許可リストによって行ってください。それにより想定外の拡張子のファイルがアップロードされる事を防げます。

その他の対策
  • アップロードされたファイルは、直接ユーザーがアクセスできないように公開ディレクトリ以外の場所に保存してください。
    • これによって、危険な拡張子のファイルがアップロードされた場合でも直接ユーザーがアクセスしてファイルが実行される事を防げます。
    • サーバーがアップロードされたファイルを利用する際には、ダウンロードスクリプトを用いてファイルを取得し拡張子をチェックした上でファイルの内容をユーザーに返すようにしてください。
  • サーバーの設定によっては二重拡張子のファイルに対して末尾の拡張子ではないものが利用される危険性があるため、アップロードされたファイルに対しては「ランダムな値 + 末尾の拡張子」としたものにファイルの名前を変更してください。
  • 拡張子が同じであるか確かめる方法に「マジックバイトが示すファイル形式とファイルの拡張子が同じであるかを確認する」という方法があります。
    • マジックバイトとは、ファイルの形式を示すためにファイルのバイナリ列の先頭に存在するバイト列のことです。

観点2: ファイル名のチェックに不備があり、ディレクトリトラバーサルによる任意のファイルの書き換えが可能

細工をしたファイル名を送信する事により意図しない場所にファイルを設置される危険性があります。設定ファイルの書き換えによるサーバーの乗っ取りや、Webサイトの書き換えを行うことが出来てしまいます。

対策2: ファイル名のチェック

アップロードされたファイルのファイル名に対して、「/」「\」「:」などの利用するとディレクトリトラバーサルが可能な記号が含まれていない事を確認してください。

観点3: 悪意のある画像ファイルをアップロード可能

観点3-1: 巨大なファイル

巨大なファイルをアップロードする事によってサーバーのリソースを意図的に消費したり、サーバーでの処理に負荷をかけることにより正常な操作を行えなくしたりするDoS攻撃が発生する危険性があります。

対策3-1: ファイルサイズの制限

サーバーの設定にてリクエストボディサイズの制限を行う事によって巨大なファイルを処理してしまう事を防ぎます。

多くの場合は言語やフレームワークごとに設定方法が用意されているため、リクエストのサイズを計測するプログラムを自作するのではなく適切な既存のプログラムを利用してください。

観点3-2: ImageMagickなどのミドルウェアの脆弱性を攻撃するファイル

画像ファイルを編集するソフトウェアの脆弱性を攻撃する方法も存在しています。

例えば、ImageMagickはその最たる例と言えるでしょう。対応するファイル形式の多さやその利便性から広く使われているImageMagickですが、毎年多くの脆弱性が報告されています。CVE Detailsによると2021年には16件、2020年には43件もの脆弱性がCVEに登録されています。そのうちの3件は任意コード実行(RCE)が可能な非常に危険なものとなっています。

それだけ多くの脆弱性が発生する理由の一つとしては、対応しているファイルフォーマットの多さがあります。一般的なJPEGやPNGだけでなくさまざまなファイルフォーマットに対応しているため、それだけ脆弱性が発生する要因が存在してしまっています。

対策3-2: ミドルウェアの適切な利用
利用できるファイル形式の制限

ImageMagickのポリシーから必要なファイルフォーマットのみを許可してください。それにより、脆弱性につながる危険性のあるファイルをImageMagickが処理してしまう危険性を減らす事が可能です。

ソフトウェアアップデート

最新のバージョンのImageMagickを利用することによって既知の脆弱性を利用した攻撃を防ぐ事が可能です。バージョンによっては既存のプログラムがうまく動かなくなるという危険性もありますが、セキュリティ上の観点からは最新のバージョンを利用してください。

観点4: 画像ファイルからの個人情報の漏洩

画像ファイルに登録されている情報を適切に削除しない場合、画像ファイルにアクセスできるユーザーに意図せずファイルに紐づく情報を取得される危険性があります。それにより、個人名や撮影場所や撮影時間といった情報が漏洩する危険性があります。

対策4-1: Exifの削除

サーバーに画像ファイルがアップロードされた際に、写真を撮影した場所や時間の特定に利用できるExif情報を削除してください。

対策4-2: ファイル名を変更する

ファイル名に氏名などが使われている場合、そこから意図せず個人情報が漏洩する危険性があるため、例えばランダムな文字列などにファイル名を変更してください。

パターンB: 業務データのCSV bulk import

業務アプリ等でデータを移行する際にCSV形式のファイルを利用するパターンです。BtoB SaaS等でかなりポピュラーな機能だと思います。

観点1: 信用できないデータによる攻撃

データを移行するために作成されるCSVファイルは多くの場合ユーザーが作成するのではなく、信用できるWebアプリケーション上で作成されたものをインポートして利用されます。

CSVファイル自体は信用できるWebアプリケーションが生成したものであっても、CSVファイルを攻撃者が直接加工できる場合や、CSVファイルに集計されることを見越して元々悪意のある値がアプリケーションに渡っていた場合にはリスクが発生します。

対策1: 適切な値のチェック

信用できるWebアプリケーション上で生成されたCSVファイルに対して、攻撃者が悪意のある変更を行える場合を考えます。アプリケーションが生成したCSVテンプレートに対し、従業員情報をローカルでExcelなどを用いて入力し、アプリケーションに一括アップロードする機能が考えられます。

この時、信用できない値をCSVファイルをアップロードされたWebアプリケーションが受け取ってしまう事になります。これにより、XSS(Cross-Site Scripting)やSQLインジェクションをはじめとした一般的なWebアプリケーションの脆弱性が引き起こされます。

また、アプリケーションの仕様として意図していない値を入力(正の正数しか想定していない箇所にマイナスを入力される、少数を入力される、文字列を入力される等)されてしまいシステムの整合性が取れなくなる等の可能性もあります。

それらの攻撃を防ぐためにCSVファイルから受けとった値に対しても通常のWebアプリケーションで行うような、特殊記号のエスケープ処理や値のチェックのような対策を行ってください。

観点2: CSV Excel Macro Injection

CSVファイルによるデータのやりとりで頻繁に発生するのがこの脆弱性です。悪意のある値を含むCSVファイルを第三者がダウンロードできる形にすることにより、ExcelでCSVファイルを開いた第三者に対してExcelの関数を実行させることが可能です。

例えばWebフォームのアンケート機能において、最終的にCSVファイルに集計されることを見越して悪意のある値を入力しておき、エクスポートされたCSVファイルがExcelで開かれた時に脆弱性が発現するようなパターンです。攻撃を受けた側としては信用できるアプリケーションからダウンロードしたファイルを開いただけで攻撃が成立してしまうわけです。

この攻撃によりCSVファイル内のデータが第三者に流出する危険性や、DDE関数を利用する事により任意のシェルコマンドの実行が引き起こされる危険性があります。

対策2: 特殊記号が先頭に来ないようにする

CSVファイル内の値がExcelによって関数だと認識されないように=/+/-/@/Tab(0x09)/改行コード(\n,\r)/フィールド区切り文字(;/,)が値の先頭に来る場合にはシングルクオーテーション(')を先頭につける事により関数ではなく単なる文字列と扱わせる処理を実装してください。

問題として、負の値(-1等)を利用できなくなる問題があるため、必要に応じて負の値を利用する際には数字以外の文字が入らないようにするなどの処理を追加する必要があります。

パターンC: 本人確認書類をアップロード

免許証や健康保険証などによる本人確認を行う際に利用される本人確認書類のアップロード機能では、これまでの対策に加えて第三者による閲覧を防ぐための対策が必要になります。 toCの金融系サービスやマッチングアプリでほぼ必須と言える機能です。

観点1: 古い画像が正しく削除されない

本人確認実施後そのまま本人確認書類をWebアプリケーション上に保存していた場合、潜在的なリスクとなります。何かしらの攻撃により攻撃者に本人確認書類が漏洩した際に、適切に不要な本人確認書類の消去が行われていた場合影響は小規模なものになります。しかし、古い本人確認書類を削除していないと、最悪の場合サービス利用者全体にまで影響が拡大する危険性があります。

対策1: 不要なデータの削除

不要な機密情報は適切に削除することにより攻撃が発生した際の潜在的なリスクを低下させてください。

観点2: 他者のデータが閲覧可能

パターンAで紹介したようなアイコン画像のアップロードであれば、その画像が他のユーザーに見えることが期待される挙動のことも多いでしょう。しかし、本人確認書類のような機微な情報が他のユーザーから閲覧可能だと大きなリスクとなります。

対策2-1: 適切なアクセス制限

アップロードされたファイルに対して適切なアクセス制限を行ってください。

よくあるパターンとしては、そもそもアクセス制限が行われておらずファイルに割り振られたIDがわかれば誰でもアクセスできる場合や、Cookieの値などユーザー側が変更可能な値を元にアクセス制御が行われている場合があります。このような実装においてはアクセス制限を回避して攻撃者がアクセスを行える可能性が高いです。

対策2-2: ファイル名を推測困難にする

対策1を行なった上でアクセス制限を回避された場合の緩和策として、ファイル名を推測困難にするというのがあります。ファイル名に対してUUIDなどを割り当てる事により第三者がファイル名を推測することが難しくなります。

まとめ

本稿では、現代のWebサービスでよくみる3つのパターンに関してファイルアップロード機能の主要な脆弱性を解説しました。しかし、今回紹介することのできなかった脆弱性もまだまだたくさんあります。それは利用しているサービスやWebサービス自体の設計、扱うファイルの形式などさまざまな要因によって引き起こされてしまいます。

そのため、これをすれば全てのパターンで脆弱性を防げるという対策はありません。しかし、どのような攻撃への対策も本稿で紹介した知識が基本となるため、強固なWebサービスを作成する第一歩として本稿がお役に立てると幸いです。

Flatt Securityでは、今回ご紹介したような脆弱性を洗い出すため、セキュリティエンジニアの手動検査とツールを組み合わせたセキュリティ診断サービスを提供しています。

過去に診断を実施したが不安や課題がある、予算やスケジュールに制約がありどのように診断を進めるべきか悩んでいる等、お困り事にあわせて対応策をご提案いたしますので、まずはお気軽にお問い合わせください。

お問い合わせは下記リンクよりどうぞ。

https://flatt.tech/assessment/contact

Flatt Securityはセキュリティに関する様々な発信を行っています。 最新情報を見逃さないよう、公式Twitterのフォローをぜひお願いします!

twitter.com

ここまでお読みいただきありがとうございました!

更新履歴

2022年6月16日 「画像ファイルからの個人情報の漏洩」にて画像ファイルから意図しない漏洩が発生する危険性について追記しました。 こちらの観点は以下のご両名よりご提案いただき追記させていただきました。ありがとうございました。

@shioshiota (Exifの削除), @kyohei_shimada (ファイル名の変更)