【入門編】JavaScriptのeval()やsetTimeout(string)の危険性と代替案 – アプリケーションセキュリティ & 安全な開発防御ガイド

「便利だから」で済ませてはいけない。JavaScriptの「禁断の魔術」を安全なコードに書き換えよう

こんにちは。現場の最前線でセキュリティと向き合っているエンジニアです。

今日は、プログラミングを始めたばかりの方がつい使いがちな、でもセキュリティの観点からは「絶対にやってはいけないこと」の代表格、eval()関数のお話です。

「え、これを使うと簡単に動的な処理が書けて便利なのに…」そう思う気持ち、よく分かります。でも、これが「家に泥棒を招き入れるための合鍵」を渡しているのと同じだと言われたら、どう感じますか?

一歩ずつ、その危険性と正しい解決策を学んでいきましょう!

—

そもそも、eval()って何が悪いの?

eval()やsetTimeout(string)、setInterval(string)といった関数は、「文字列として渡されたものを、プログラムとしてそのまま実行する」という魔法のような機能を持っています。

泥棒の侵入経路に例えると…

想像してみてください。あなたは自分の家の玄関(プログラム)に、「玄関を通る時、ここに書かれた指示を何でも実行してね」という魔法のポストを設置しました。

本来なら、家族(正しいプログラム)だけが暗号を使って入るべきです。しかし、このポストは「通りすがりの泥棒が書いた指示」であっても、忠実に実行してしまいます。

もし誰かがここに、
"あなたの家の全財産を、泥棒の口座に転送する"
という文字列を書き込んだら? プログラムはそれを「命令」だと勘違いして、あなたの許可なく実行してしまうのです。これがインジェクション攻撃の入り口です。

—

具体的にどんな攻撃を受けるの?

例えば、ユーザーが入力した名前を画面に表示するプログラムがあったとします。

// 悪い例:ユーザーの入力をそのまま実行してしまう
const userInput = “alert(‘ハッキングしました!’)”; // 攻撃者が入力したとする
eval(userInput);

このコードを実行した瞬間、ブラウザ上で攻撃者が用意した命令が動いてしまいます。これは単なるポップアップですが、実際には「Cookie(ログイン情報)を盗んで外部に送信する」「悪意のあるサイトへ強制的にリダイレクトさせる」といった操作が、あなたのサイト上で自由に行われてしまうのです。

—

じゃあ、どうすればいいの?「安全な代替案」

コードを動的に実行したいシーンは確かにありますよね。でも、eval()を使わずに安全に書く方法は必ずあります!

1. JSONデータの取り扱い:JSON.parse()を使う

外部から受け取ったデータがJSON形式なら、絶対にeval()を使ってはいけません。代わりに、ブラウザに標準装備されている安全な解析機能を使います。

// 安全な例:JSON.parseを使う
const jsonString = ‘{“name”: “田中”, “age”: 25}’;

// JSON.parseは「文字列をただのデータとして解釈する」だけなので、コードは実行されません!
const data = JSON.parse(jsonString);
console.log(data.name); // 田中

2. 関数を動的に呼び出す:関数参照を使う

特定の条件で関数を切り替えたいときは、関数を「変数」として辞書のように管理しましょう。

// 安全な例:関数参照の辞書を作る
const actions = {
“greet”: () => console.log(“こんにちは!”),
“farewell”: () => console.log(“さようなら!”)
};

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

// 文字列をキーにして、安全に登録された関数だけを呼び出す
if (actions[command]) {
actions[command]();
} else {
console.error(“そんなコマンドは存在しません!”);
}

—

最後に:防御の意識を「習慣」に

セキュリティ対策は、特別なことではありません。日頃のプログラミングで「外部からの入力は、すべて悪意があるかもしれない」と疑う癖をつけること。これが最強の防犯対策です。

  • eval()は使わない(これだけでリスクが激減します)
  • setTimeoutやsetIntervalには文字列ではなく「関数オブジェクト」を渡す
  • setTimeout("alert('hi')", 1000); ではなく、
  • setTimeout(() => alert('hi'), 1000); と書くのが正解です!

もし今、自分のコードにeval()や文字列を渡している場所があったら、今日のうちに書き換えてしまいましょう。

「便利さ」よりも「堅牢さ」を選ぶこと。それが、信頼されるエンジニアへの第一歩です。また次の記事で、一緒にセキュリティを学んでいきましょう!

コメント

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