Unrestricted file upload
無制限のファイルアップロード
説明
無制限のファイルアップロード(Unrestricted File Upload)は、アプリケーションにとって重大なリスクであり、システムの乗っ取り、ファイルシステムの過負荷、クライアントサイド攻撃、または改ざん(デフェイス)を引き起こす可能性があります。この脆弱性は、HTTPマルチパートフィールドなどの安全でないファイルメタデータの検証、または許可されていないファイル形式のアップロードなど、安全でないコンテンツやサイズの検証に起因する場合があります。
推奨事項
無制限のファイルアップロードに関連するリスクを緩和するために、以下の対策を検討してください。
- Validate File Type: サーバーサイドでの検証を実装し、許可されたファイルタイプのみがアップロードされるようにします。許可するファイル拡張子をホワイトリストに登録し、許可されていない拡張子を持つファイルはすべて拒否します。クライアントサイドの検証のみに依存することは避けてください。これは容易にバイパスされるためです。
- Check File Content: アップロードされたファイルのコンテンツを確認し、ファイルタイプと一致していることを検証します。例えば、画像のアップロードの場合、ライブラリやツールを使用してファイルヘッダーを検査し、実際に画像であることを確認します。
- Rename Uploaded Files: 攻撃者がファイル名を推測してファイルを実行するのを防ぐため、アップロードされたファイルの名前を変更します。ランダムな文字列とサーバーで生成された一意の識別子を組み合わせて、アップロードされたファイルの新しいファイル名を作成します。
- Store Uploaded Files in a Secure Location: URLを介した直接アクセスを防ぐため、アップロードされたファイルはWebルートディレクトリの外部に保存します。例えば、S3バケット等を使用できます。
- Scan Uploaded Files for Malware: アンチウイルスまたはアンチマルウェアスキャナを利用して、アップロードされたファイルに悪意のあるコンテンツがないかスキャンします。定期的なスキャンを実行し、サーバー上に悪意のあるファイルが存在しないことを確認してください。
- Monitor File Upload Activities: ファイルアップロードのアクティビティを追跡するためのログ記録および監視メカニズムを実装します。不審なまたは異常なファイルアップロードのパターンがないか監視し、検出時には即座に対応します。
const express = require('express');
const multer = require('multer');
const path = require('path');
const { v4: uuidv4 } = require('uuid');
const app = express();
// Define storage for uploaded files
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/');
},
filename: function (req, file, cb) {
const ext = path.extname(file.originalname);
cb(null, uuidv4() + ext);
}
});
// File filter to allow only specified file extensions
const fileFilter = (req, file, cb) => {
const allowedExtensions = ['.jpg', '.jpeg', '.png'];
const ext = path.extname(file.originalname).toLowerCase();
if (allowedExtensions.includes(ext)) {
cb(null, true);
} else {
cb(new Error('File type not allowed!'), false);
}
};
// Initialize multer with storage and file filter
const upload = multer({ storage: storage, fileFilter: fileFilter });
// POST endpoint for file upload
app.post('/upload', upload.single('file'), (req, res) => {
res.send('File uploaded successfully!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from django.http import HttpResponseBadRequest
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
import os
from uuid import uuid4
@require_POST
def upload_file(request):
if request.method == 'POST' and request.FILES['file']:
file = request.FILES['file']
allowed_extensions = ['.jpg', '.jpeg', '.png']
ext = os.path.splitext(file.name)[1]
if ext.lower() not in allowed_extensions:
return HttpResponseBadRequest('File type not allowed!')
fs = FileSystemStorage()
filename = fs.save(str(uuid4()) + ext, file)
return HttpResponse('File uploaded successfully!')
else:
return HttpResponseBadRequest('No file found!')
<?php
$uploadDir = 'uploads/';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$file = $_FILES['file'];
$allowedExtensions = array('.jpg', '.jpeg', '.png');
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($ext, $allowedExtensions)) {
http_response_code(400);
echo 'File type not allowed!';
exit;
}
$uploadFile = $uploadDir . uniqid() . '.' . $ext;
if (move_uploaded_file($file['tmp_name'], $uploadFile)) {
echo 'File uploaded successfully!';
} else {
http_response_code(500);
echo 'Error uploading file.';
}
} else {
http_response_code(400);
echo 'No file found!';
}
?>
リンク
標準
- CWE_TOP_25:
- CWE_434
- PCI_STANDARDS:
- REQ_2_2
- REQ_6_2
- REQ_6_3
- REQ_6_4
- REQ_11_3
- SOC2_CONTROLS:
- CC_2_1
- CC_3_4
- CC_4_1
- CC_6_1
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5
- HIPAA_CONTROLS:
- SECURITY221
- SECURITY212
- SECURITY213