Webアプリケーションでファイルアップロード機能を実装することは珍しくありません。 プロフィール画像、添付ファイル、資料アップロードなど、多くのシステムで使われる機能です。
一方で、ファイルアップロードは セキュリティ上の問題が発生しやすい機能としても知られています。 自分用のメモとして、代表的な脆弱性を整理しておきます。
1 任意ファイルアップロード(Unrestricted File Upload)
もっとも典型的で危険なものです。
例えば攻撃者が次のようなファイルをアップロードできてしまうとします。
shell.php
このファイルがWeb公開ディレクトリに保存されると、
https://example.com/uploads/shell.php
のようにアクセスすることで サーバー上でPHPが実行される可能性があります。
このようなファイルは一般に Webシェル と呼ばれ、次のような操作を行われる可能性があります。
- サーバーコマンドの実行
- データベース情報の取得
- ファイルの改ざん
- 他のマルウェアの設置
つまり、サーバー侵害につながる可能性があります。
2 パストラバーサル(Directory Traversal)
ファイル名に
../
を含めることで、ディレクトリ階層を遡る攻撃です。
例えば次のような値を指定されるケースです。
../../../../var/www/html/shell.php
アプリケーションがそのまま保存パスを組み立てると
/var/www/app/uploads/../../../../var/www/html/shell.php
となり、OSの解釈では
/var/www/html/shell.php
になります。
結果として 本来のアップロードディレクトリ以外にファイルを書き込める可能性があります。
3 拡張子偽装(Extension Spoofing)
拡張子チェックを回避する攻撃です。
例えばアプリケーションが
jpg
png
のみ許可している場合、攻撃者は次のようなファイルをアップロードすることがあります。
shell.php.jpg
環境によっては
shell.php.jpg
が PHPとして実行されてしまうケースがあります。
他にも次のようなパターンがあります。
shell.php.png
shell.phtml
shell.php5
4 MIMEタイプ偽装
HTTPリクエストには Content-Type ヘッダがあります。
例えば画像アップロードでは
Content-Type: image/jpeg
のような値になります。
しかし、この値は クライアント側で自由に設定できるため、簡単に偽装できます。
例えば次のような内容のファイルでも
<?php system($_GET['cmd']); ?>
HTTPヘッダを
Content-Type: image/jpeg
として送信することが可能です。
そのため、MIMEタイプだけでファイル種類を判定するのは安全ではありません。
5 巨大ファイルアップロード(DoS)
非常に大きなファイルをアップロードすることで、サーバーリソースを消費させる攻撃です。
例えば
10GB
100GB
のようなファイルを送信されると、
- ディスク容量の枯渇
- メモリ消費
- CPU負荷
などが発生する可能性があります。
結果としてサービス停止(DoS)につながる場合があります。
実務でよく言われる安全設計
実務では、ファイルアップロードを安全に扱うために次のような設計がよく推奨されています。
① 保存ファイル名はサーバー側で生成する
ユーザー入力のファイル名をそのまま使わないようにします。
例えば
3f8a2c9b.jpg
のように、UUIDやランダム文字列などで生成する方法がよく使われます。
② Web公開ディレクトリ外に保存する
例えば
/var/data/uploads
など、Webサーバーから直接アクセスできない場所に保存します。 ダウンロードさせる場合は、アプリケーション経由で配信します。
③ 拡張子はホワイトリスト方式にする
許可する拡張子のみ受け付けるようにします。
jpg
png
pdf
④ MIMEタイプだけで判定しない
MIMEタイプだけでなく、ファイル内容も確認するようにします。
⑤ アップロードサイズ制限を設定する
例えば
10MB
など、アップロード可能なサイズを制限します。
まとめ
ファイルアップロード機能では、次のような脆弱性がよく問題になります。
| 脆弱性 | 内容 |
|---|---|
| 任意ファイルアップロード | 実行可能ファイルを置かれる |
| パストラバーサル | 保存場所を突破される |
| 拡張子偽装 | 拡張子チェックを回避 |
| MIME偽装 | Content-Type を偽装 |
| 巨大ファイル | DoS攻撃 |
ファイルアップロードは一見単純な機能ですが、 セキュリティの観点では注意点が多い部分なので、 実装時には基本的な対策を忘れないようにしたいところです。