【実務・中級編】JavaScriptのeval()およびsetTimeout()への文字列渡しによるリスク – アプリケーションセキュリティ & 安全な開発防御ガイド

そのeval()、まだ使っているのか?――動的コード実行が招く地獄と現代的な回避策

現場でコードレビューをしていると、今でもたまに遭遇するんだ。「これ、動的に関数を呼び出したいからeval()使っちゃいました」というコードに。

結論から言うと、eval()やsetTimeout()への文字列渡しは、セキュリティの文脈では「核兵器の起爆スイッチを外部公開する」のと同義だ。

今回は、なぜこれらが悪魔の所業なのか、そしてモダンな開発現場でどう代替すべきかを、実務的な視点で叩き込んでおく。

—

1. なぜeval()は「死」を招くのか

eval()は、引数に渡された文字列を「その場のJavaScriptコード」として解釈・実行する。もし、その文字列の中にユーザーが入力したデータが混入していたらどうなるか?

攻撃者は、あなたのアプリケーションのコンテキスト(セッション情報やCookie、DOM)を自由自在に操れるようになる。

攻撃のPoC(概念実証)

例えば、ユーザーのプロフィール表示機能でこんな実装があったとしよう。

// 危険な実装例
const userInput = new URLSearchParams(window.location.search).get(“name”);
eval(“console.log(‘Hello, ” + userInput + “‘);”);

攻撃者が以下のURLを送りつけるだけで、XSS(クロスサイトスクリプティング)が成立する。
?name='); alert(document.cookie); //

ブラウザはこれを以下のコードとして解釈する。
console.log('Hello, '); alert(document.cookie); //');

これで君のアプリのセッションハイジャックは完了だ。setTimeout()やsetInterval()も同様に、第一引数に文字列を渡すと内部でeval()相当の処理が走る。これは言語仕様上の「負の遺産」と言ってもいい。

—

2. 脱eval():現代的な代替実装

「動的に処理を切り替えたい」というニーズは理解できる。だが、文字列でコードを組み立てる必要はない。「マップ(連想配列)」を使えばいいんだ。

安全な実装サンプル(JavaScript)

// 悪用を許さない、安全なコマンド実行パターン
const commandMap = {
“greet”: () => console.log(“Hello!”),
“farewell”: () => console.log(“Goodbye!”),
“error”: () => console.error(“Unknown command”)
};

const userInput = “greet”; // ユーザーからの入力値

// 文字列を直接実行せず、プロパティとして参照する
const action = commandMap[userInput] || commandMap[“error”];
action();

これなら、存在しないキーが指定されても関数が実行されることはない。これが、境界防御の基本だ。

—

3. インフラレベルでの防御:CSP(Content Security Policy)

コードレベルで完璧を期すのは当然だが、万が一の脆弱性混入に備えて、CSPでトドメを刺しておくべきだ。

CSPの script-src ディレクティブで unsafe-eval を許可しなければ、たとえコード内にeval()が残っていても、ブラウザは実行を拒否する。

NginxでのCSP設定例

HTTPレスポンスヘッダーにセキュリティポリシーを注入
add_header Content-Security-Policy “default-src ‘self’; script-src ‘self’; object-src ‘none’;”;

  • script-src 'self' : 自分のドメインのスクリプトしか実行させない。
  • 'unsafe-eval' を記述しない : これだけで、eval()やnew Function()の使用はブラウザ側でブロックされる。

—

4. 最後に:エンジニアとしての矜持

「動的に処理を書きたい」という欲求は、プログラマーの怠慢(良い意味での)から生まれることが多い。だが、その怠慢がセキュリティホールを生むなら、それはプロとして失格だ。

1. 文字列をコードとして解釈させるな。
2. 実行したい処理は、事前に定義したオブジェクトのキーにマッピングせよ。
3. CSPを導入し、ブラウザに「疑わしいコードは動かすな」と命令せよ。

これらは教科書的な知識じゃない。現場で数々のインシデントを見てきた人間が辿り着く、最低限の「防弾チョッキ」だ。

もし君のプロジェクトでeval()を見かけたら、即座にリファクタリングのチケットを切ってくれ。それが、君のシステムとユーザーを守るための、最も手っ取り早くて確実な投資になる。

コメント

タイトルとURLをコピーしました