コマンドインジェクション

コマンドインジェクション

説明

検証していないユーザー入力をOSコマンドとして実行すると、コマンドインジェクションが発生します。Node.jsの child_process.exec と execSync はシェルを使用します。spawn と spawnSync は既定ではシェルを使いませんが、shell: true を指定するか、例のように sh -c に入力を渡すと、シェルコマンドを挿入されるおそれがあります。ユーザーが実行ファイルや引数を選ぶ場合も、許可する動作を制限する必要があります。

想定される影響

  • アプリケーションプロセスの権限による意図しないコマンドの実行
  • ファイルへのアクセスや削除などによるデータの漏えい・改ざん
  • サービス拒否やシステム障害

対処方法

  • ユーザー入力をコマンド文字列として実行せず、固定の実行ファイルに検証した引数を配列で渡してください。
  • 入力で動作を選択する場合は、許可リストで制限してください。
  • sh -c のように入力をコードとして再解釈するインタープリターの呼び出しを避け、実行ファイルの場所と PATH を信頼できる状態に保ってください。

例

変更前

javascript
const {spawnSync} = require('child_process');
function runCommand(userInput) {
  // ユーザーが指定したコマンドを直接実行
  spawnSync('sh', ['-c', userInput]);
}

変更後

javascript
const {spawnSync} = require('child_process');
function runCommandSafe(userInput) {
  // 事前に定義したコマンドだけを許可
  const allowedCommands = ['ls', 'pwd'];
  if (!allowedCommands.includes(userInput)) {
    throw new Error('허용되지 않은 명령어입니다.');
  }
  spawnSync(userInput, []);
}

解説:

  • 変更前: userInput を sh -c に渡し、シェルコマンドとして実行しています。
  • 変更後: 入力を ls と pwd に限定し、シェルを介さずに実行しています。これらの名前が意図した実行ファイルに解決されるよう、信頼できる PATH を使う必要があります。

参考資料