説明
検証していないユーザー入力を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を使う必要があります。