Web開発では、ファイルのアップロードとダウンロードは一般的な機能モジュールです。ただし、ユーザーの入力と出力が厳密に制御されていない場合、攻撃のエントリポイントになるのは簡単です。この記事では、PHP言語に焦点を当て、ファイルのアップロードとダウンロード中にセキュリティを効果的に制御するためにユーザー入力および出力関数を使用する方法を紹介します。
アップロード要求を処理する前に、最初のステップはファイルのタイプを確認することです。これは通常、ファイル拡張機能とMIMEタイプの2要素検証で実行できます。
$allowedExtensions = ['jpg', 'png', 'gif'];
$allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif'];
$uploadedFileExtension = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
$uploadedFileType = $_FILES['file']['type'];
if (!in_array($uploadedFileExtension, $allowedExtensions) ||
!in_array($uploadedFileType, $allowedMimeTypes)) {
// 違法ファイルタイプ,処理ロジックを実行します
}
悪意のあるスクリプトの実行とパスの上書き攻撃を防ぐために、ユーザーがアップロードしたファイルを自動的に変更することをお勧めします。
$uploadedFileName = $_FILES['file']['name'];
$uploadedFileExtension = strtolower(pathinfo($uploadedFileName, PATHINFO_EXTENSION));
$newFileName = uniqid() . '.' . $uploadedFileExtension;
$newFilePath = '/path/to/upload/directory/' . $newFileName;
if (move_uploaded_file($_FILES['file']['tmp_name'], $newFilePath)) {
// ファイルアップロードに正常にアップロードします
}
拡張機能とMIME検証に加えて、ファイルの実際のコンテンツをさらに分析することをお勧めします。たとえば、 getImagesize()またはサードパーティライブラリを使用して、アップロードされたファイルが実際の画像であるかどうかを判断できます。
$fileData = file_get_contents($_FILES['file']['tmp_name']);
if (!is_image($fileData)) {
// ファイルは実際の写真ではありません,処理ロジックを実行します
}
function is_image($fileData){
$allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif'];
if (function_exists('mime_content_type')) {
$fileMimeType = mime_content_type($fileData);
return in_array($fileMimeType, $allowedMimeTypes);
} else {
$finfo = new finfo(FILEINFO_MIME_TYPE);
$fileMimeType = $finfo->buffer($fileData);
return in_array($fileMimeType, $allowedMimeTypes);
}
}
ファイルのダウンロードロジックを実行する前に、ユーザーが要求したファイルが存在し、アクセス権があることを確認する必要があります。
$requestedFilePath = $_GET['file'];
if (!is_file($requestedFilePath) || !is_readable($requestedFilePath)) {
// ファイルは存在しないか、読み取れない
}
ブラウザが誤ってダウンロードコンテンツを実行するのを防ぐために、ファイルのダウンロードに必要なHTTPヘッダー情報を設定する必要があります。
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=" . basename($requestedFilePath));
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($requestedFilePath));
readfile($requestedFilePath);
ファイルのアップロードとPHPでダウンロードを実装する場合、基本機能のみに依存するだけでは十分ではありません。より信頼性の高い安全なファイル管理システムは、ファイルタイプの確認、処理の名前変更、セキュアなスキャン、許可制御などの複数の手段で構築する必要があります。さらに、アップロードファイルサイズを制限し、アップロードディレクトリアクセス許可を制御し、ダウンロードの乱用やその他の詳細な戦略を防ぐこともお勧めします。