+4

🔐Node.js Expressでファイルアップロードを安全に行う方法:詳細で視覚的なガイド

ファイルのアップロードは、現代のWebアプリケーションで一般的な機能です。ユーザーは、画像、ビデオ、ドキュメントなどのさまざまな種類のファイルを提出して、サービスとやりとりすることができます。ただし、ファイルのアップロードには潜在的なセキュリティリスクも伴います。この記事では、Node.js Expressアプリケーションでファイルのアップロードを安全に行う方法について、詳細で視覚的なガイドを提供します。アプリが安全で効率的であることを確認するために、これに従ってください。

1:ファイルアップロードのリスクを理解する

セキュリティ対策に取り掛かる前に、ファイルのアップロードに関連する潜在的なリスクを理解することが重要です。これらのリスクには次のようなものがあります。

  • 悪意のあるファイルのアップロード: アタッカーは、アプリケーションやサーバーを危険にさらす可能性のある悪意のあるスクリプトが含まれたファイルをアップロードすることがあります。
  • サービス拒否(DoS)攻撃: 大量のファイルアップロードにより、サーバーのリソースが枯渇し、アプリが応答しなくなる可能性があります。
  • 機密データの漏洩: 不正なユーザーが機密情報が含まれるファイルにアクセスする可能性があります。

2:基本的なNode.js Expressアプリケーションのセットアップ

ファイルアップロードを安全にする方法を示すために、基本的なNode.js Expressアプリケーションをセットアップしましょう。まず、必要なパッケージをインストールします。

npm init -y
npm install express multer

次に、app.jsファイルを作成し、必要なモジュールをインポートします。

const express = require('express');
const multer = require('multer');

const app = express();
const port = process.env.PORT || 3000;

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

3:Multerを使用したファイルアップロードの実装

Multerは、Expressでファイルアップロードを処理するための一般的なミドルウェアです。まず、Multerを設定し、ストレージエンジンを設定します。

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, './uploads');
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
    cb(null, file.fieldname + '-' + uniqueSuffix);
  },
});

const upload = multer({ storage });

次に、ファイルアップロードのためのルートを作成します。

app.post('/upload', upload.single('file'), (req, res) => {
  res.status(200).send({ message: 'File uploaded successfully.' });
});

4:ファイルアップロードのセキュリティ

4.1 ファイルサイズの制限

最初のセキュリティ対策は、ファイルサイズを制限することです。これにより、DoS攻撃を防ぎ、サーバーリソースが枯渇するリスクを減らすことができます。Multerを設定する際に、ファイルサイズの制限を設定します。

const upload = multer({
  storage,
  limits: { fileSize: 2 * 1024 * 1024 }, // 2MB
});

4.2 ファイルタイプの検証

特定のファイルタイプのみが許可されるようにします。これにより、悪意のあるファイルのアップロードのリスクが減ります。Multer設定にファイルフィルター関数を追加します。

const allowedFileTypes = ['image/jpeg', 'image/png', 'image/gif'];

const fileFilter = (req, file, cb) => {
  if (allowedFileTypes.includes(file.mimetype)) {
    cb(null, true);
  } else {
    cb(null, false);
  }
};

const upload = multer({
  storage,
  limits: { fileSize: 2 * 1024 * 1024 },
  fileFilter,
});

4.3 リジェクトされたファイルの処理

ファイルがリジェクトされた場合、適切なエラーメッセージをユーザーに提供することが重要です。リジェクトされたファイルを処理するために、/uploadルートを更新します。

app.post('/upload', upload.single('file'), (req, res) => {
    if (!req.file) {
        return res.status(400).send({ message: 'Invalid file type or file too large.' });
    }
    res.status(200).send({ message: 'File uploaded successfully.' });
});

4.4 ファイルをマルウェアからスキャンする

アプリケーションをさらに保護するために、アップロードされたファイルをマルウェアからスキャンします。ClamAVアンチウイルスエンジンを使用することができます。clamscanパッケージをインストールします。

npm install clamscan

次に、ClamScanモジュールをインポートして設定します。

const { NodeClam } = require('clamscan');
const clamscan = new NodeClam();

clamscan.init({
  clamdscan: {
    path: '/usr/bin/clamdscan', // お使いのサーバー上のclamdscanバイナリへのパス
    config_file: '/etc/clamd.d/scan.conf', // お使いのサーバー上のClamAV設定ファイルへのパス
  },
  preference: 'clamdscan',
});

/uploadルートでアップロードされたファイルをマルウェアからスキャンします。

app.post('/upload', upload.single('file'), async (req, res) => {
  if (!req.file) {
    return res.status(400).send({ message: 'Invalid file type or file too large.' });
  }

  try {
    const scanResult = await clamscan.scan_file(req.file.path);
    if (scanResult.is_infected) {
      fs.unlinkSync(req.file.path); // 感染したファイルを削除する
      return res.status(400).send({ message: 'File is infected with malware.' });
    }
    res.status(200).send({ message: 'File uploaded successfully.' });
  } catch (error) {
    res.status(500).send({ message: 'Error scanning file for malware.' });
  }
});

fsモジュールをインポートすることを忘れないでください。

const fs = require('fs');

4.5 ファイルをWebルートの外に保存する

Webルートの外にアップロードされたファイルを保存することで、それらのファイルへの直接アクセスを防ぐことができます。この例では、uploadsフォルダを使用し、Webルートディレクトリの外に配置します。

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, '../uploads');
  },
  // ...
});

4.6 ファイルを安全に提供する

ファイルを安全に提供するために、ユーザーの認証を確認し、res.sendFile()メソッドを使用してファイルを提供する新しいルートを作成します。

app.get('/files/:filename', (req, res) => {
    // ユーザーの認証をここで確認する
    const filename = req.params.filename;
    const filePath = path.join('../uploads', filename);
    res.sendFile(filePath);
});

pathモジュールのインポートを忘れないでください。

const path = require('path');

結論

この包括的なガイドに従うことで、Node.js Expressアプリケーションで安全なファイルアップロードシステムを作成できます。ファイルサイズの制限、ファイルタイプの検証、マルウェアからのファイルスキャン、安全なファイル提供など、適切なセキュリティ対策を実装することで、ファイルアップロードに関連するさまざまなリスクからアプリを保護できます。

Mình hy vọng bạn thích bài viết này và học thêm được điều gì đó mới.

Donate mình một ly cafe hoặc 1 cây bút bi để mình có thêm động lực cho ra nhiều bài viết hay và chất lượng hơn trong tương lai nhé. À mà nếu bạn có bất kỳ câu hỏi nào thì đừng ngại comment hoặc liên hệ mình qua: Zalo - 0374226770 hoặc Facebook. Mình xin cảm ơn.

Momo: NGUYỄN ANH TUẤN - 0374226770

TPBank: NGUYỄN ANH TUẤN - 0374226770 (hoặc 01681423001)

image.png


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí