ファイルアップロードの機能を利用した攻撃

ファイルアップロードを使った攻撃は、悪意あるコードを注入した不正ファイルをアップロードし、そのファイルにアクセスすることで成立します。この攻撃は、XSSを使って第三者に接続させる方法や攻撃する側が自らサーバにコードを注入して実行させる方法が知られています。

攻撃される場所

ファイルのアップロードが出来る場所。不正コードを挿入したPHPファイルをアップロードし、そのファイルを直接開くことでコードが実行されます。以下のようなスクリプトから攻撃用のPHPファイルをアップロードすると、任意の処理が実行できてしまいます。

危険性のあるスクリプト

// HTML
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="FileUpload" />
<input type="submit" value="アップロード" />
</form>
// PHP
$UpDirectory = $_SERVER['DOCUMENT_ROOT'].'/file/';
if((!empty($_FILES) === true && !empty($_FILES['FileUpload']) === true)
// is_uploaded_file()でHTTP POSTでアップロードされたファイルかどうかを判定
&& is_uploaded_file($_FILES['FileUpload']['tmp_name']) === true){
// move_uploaded_file()でアップロードされたファイルを新しい位置に移動
move_uploaded_file(
$_FILES['FileUpload']['tmp_name'],
$UpDirectory .$_FILES['FileUpload']['name']
);
echo 'ファイルアップロード成功';
}

攻撃用の実行ファイル

以下のファイルをアップロードして直接アクセスすると処理されます。

<?php
system('ls -la /');
?>

対策

move_uploaded_file()関数で「$_FILES['FileUpload']['name']」をハッシュ化します。ハッシュ化が終わった時点で元のファイル名とハッシュ化されて保存されたファイル名をデータベースに登録します。取り出すときには元のファイルのMIMEタイプなどから照合します。

$UpDirectory .sha1(microtime().$_FILES['FileUpload']['name'])

尚、getimagesize()関数で画像と認識されたファイルでも、GIFファイルに偽装されたPHPファイルがすり抜けることもあります。この関数は画像の大きさを取得します。第一引数に渡されたファイルが画像ファイルであることを想定していますが、画像以外のファイルでも画像として判断してしまうこともあります。