• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:evalを使うinputがある場合も安全に運用する)

evalを使うinputがある場合も安全に運用するための方法

このQ&Aのポイント
  • evalを使うinputがある場合も安全に運用するための方法として、エスケープを行います。
  • 四則演算子、数字、括弧以外は削除され、式として成立しない文字列は計算できません。
  • エスケープの表記位置はevalを実行する前であればどこでも良いです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.22

>!"#$%&',:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ >をInputに入れてアラートの処理が実行されるか確かめてみます 「catch内が実行されるか(アラートの処理が実行されるか)」ではなく >r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); >r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/([ ]+)/g, ' '); ↑この「r」変数の値が''(ヌル文字)(文字が何も無い文字列)になるか、実際の「r」変数の値を表示してみて下さい。

その他の回答 (21)

回答No.21

>アラートが実行できなかったら他の関数は試さなくても問題ないとわかるということですかね。 (何か実行できるかと言うより)英文字、記号などが除去されていれば良い訳です。 !"#$%&',:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ↑ざっくりと言うと、これを入力して下記の「r」変数の値に何も返って来なければ基本的にOKです。 >r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); >r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/([ ]+)/g, ' ');

okweb12345
質問者

お礼

ありがとうございます。 !"#$%&',:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ をInputに入れてアラートの処理が実行されるか確かめてみます

回答No.20

>これでセキュアに使えるようになったと考えてよろしいでしょうか? >r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); ↑これで「四則演算子、数字、括弧」以外を除去してます。 これで基本的に関数類は実行できません。 ここは簡単なのでバグの入り込む余地はありません。 >r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); ↑これで(四則演算にならない)不正な「四則演算子」を除去してます。 ここはバグの入り込む余地がありますが、それほど複雑でもないので これで問題ないと思われます。 もしバグがあっても不正な「四則演算子」が残るだけなので、基本的に関数類は実行できません。 よって、(ハッキングでもされない限り)安全に「eval」を実行できるでしょう。

okweb12345
質問者

補足

アラートが実行できなかったら他の関数は試さなくても問題ないとわかるということですかね。

回答No.19

>>オブジェクトでも関数でもありません。 >>ざっくり言うと「if」文的な文です、「try」ブロック内で実行文がエラーになると例外が発生し、「catch」ブロック内が実行されます。 >whileなどと同じ構文の一種なのですね。 >tryはうまくいかずエラーが出た場合つまり、偽ならもう一つの処理を行うというものなのですかね。 ループではないので、「if」文的な文と考えて下さい、「try」ブロック内で実行文がエラーになると例外が発生し、「catch」ブロック内が実行されます。 >><input type="text" name="gakunen" value="" onKeyPress="Calculator(this.value, event.keyCode)"> >イベントリスナーを使うのでこれが何を示しているかいまいちわからないのですが、 >何かキーボードを押したときに自作のCalculator >関数が実行されるという事でしょうか? >つまり何かキーボードを操作したときに毎回 >>r = a; >>r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); >>r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >>r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >>r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >>r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >>r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); >>r = r.replace(/([ ]+)/g, ' '); >が実行されて、記載した文字が上記でエスケープされるという事でしょうか? 下記で「Enterキー」でない場合は「return」してます。 if (!(13==kcode)){return;} // ↑「13:Enterキー」でない場合は「return」 >エラー処理というものはエラーが起きてうまく計算できなかった時に出るalert()を作ればよさそうですね。 それ以外に「result = '';」とか代入しておかないと「result」変数が「undefined」になり、「Calculator」関数の帰り値が「undefined」になると思います。 >エンターを押した所、undefunedというアラートが出ました。 何か変な事をしてませんか?、例えば「test000.html」と言う新規ファイルを作って下記をコピペして下さい。 「四則演算子、数字、括弧」以外は除去されます。<br> また式として成立しない文字列は計算できません。<br> <input type="text" name="gakunen" value="" onKeyPress="Calculator(this.value, event.keyCode)"> <script type="text/javascript"> <!-- function Calculator(a, kcode){ var r; if (!(13==kcode)){return;} // ↑「13:Enterキー」でない場合は「return」 r = a; r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/([ ]+)/g, ' '); try{ alert(r+' = '+eval(r)); // ←ここで「eval」を使ってます。 }catch(ex){ alert(ex.message+' : '+r); } } // --> </script>

okweb12345
質問者

お礼

ありがとうございます。 おかげさまでalert();をいれるとエラー時のアラートが表記され、 計算式を入れるとちゃんと計算結果が出るようになりました。 これでセキュアに使えるようになったと考えてよろしいでしょうか? 他にもこんな関数を入れて調べたほうがいいというものがあれば教えていただければ幸いです。

okweb12345
質問者

補足

確認しました r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); の前までは文字列があり、 これ以降に空になりました。 ソースのご質問は別質問にしますので、よろしければ、お付き合いお願いします。

回答No.18

エラー処理に何か書いた方が良いです、下記は一例です、自分に合ったエラー処理を記述して下さい。 >}catch(ex){ >// エラー処理 >} }catch(ex){ // エラー処理 result = ''; }

okweb12345
質問者

お礼

これエラー処理というものはエラーが起きてうまく計算できなかった時に出るalert()を作ればよさそうですね。 結果計算がうまくいかなかった時に処理する部分なのでしょうから、 閲覧者さんにそれがわかるメッセージがあればいいのですね。

回答No.17

>イベントリスナーを使うのでこれが何を示しているかいまいちわからないのですが 実際にコピペして動作させててみれば分かると思います。 >何かキーボードを押したときに自作のCalculator >関数が実行されるという事でしょうか? Enterキーで実行されます。 >私の場合、freeBtnを押したときに計算が実行されるので、freeBtnを押したときに 大体、下記のようになるハズです。 var freeBtn = document.getElementById('freeBtn'); freeBtn.addEventListener('click', function() { var userInput = document.getElementById('freeUserInput').value; var freeResult = Calculator(userInput); freeResult = round(freeResult); if (!(userInput === '')) { } else { } }); function Calculator(a){ var r, result; r = a; r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/([ ]+)/g, ' '); try{ result = eval(r); } }catch(ex){ // エラー処理 } return result; }

回答No.16

>回答No.15 amanojaku1 例えばinputエレメントに「2*3」と入力したらEnterキーを入力してみて下さい。

回答No.15

>回答No.14 amanojaku1 >if (!(13==kcode)){return;} >// ↑「13:Enterキー」でない場合は「return」 Enterキーで「Calculator」関数内の それ以降が実行されます。

okweb12345
質問者

お礼

エンターを押した所、undefunedというアラートが出ました。 if (!(13==kcode))の部分が恐らくエンターを押した場合に内部の処理を実行という意味なのですね。 つまり13がキーボードの数値で他のキーを押しても反応しないようにしているのですね。 これを私の場合はエンターを押したときにエスケープして、私の計算処理をするから、ボタンを押したときにこの二つを行うと変更すれば終了という事とでよろしいでしょうか?

回答No.14

>>try{ >>alert(r+' = '+eval(r)); // ←ここで「eval」を使ってます。 >>}catch(ex){ >>alert(ex.message+' : '+r); >>} >これは、オブジェクトですか? >tryとはなんでしょうか? >関数にも似ていますが、この形は初めて見ました。 オブジェクトでも関数でもありません。 ざっくり言うと「if」文的な文です、「try」ブロック内で実行文がエラーになると例外が発生し、「catch」ブロック内が実行されます。 >結論としては下記でよいのですね >function Calculator(a, kcode){ >var r; >if (!(13==kcode)){return;} >// ↑「13:Enterキー」でない場合は「return」 >r = a; >r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); >r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/([ ]+)/g, ' '); > >try{ >var freeBtn = document.getElementById('freeBtn'); >freeBtn.addEventListener('click', function() { >var userInput = document.getElementById('freeUserInput').value; >var freeResult = eval(userInput); >freeResult = round(freeResult); >if (!(userInput === '')) { >} else { >} >}); >} 「input」タグから「onKeyPress」イベントで「Calculator(this.value, event.keyCode)」を呼ぶように作ってあるのですが?、実際に下記を実行してみましたか? 「四則演算子、数字、括弧」以外は除去されます。<br> また式として成立しない文字列は計算できません。<br> <input type="text" name="gakunen" value="" onKeyPress="Calculator(this.value, event.keyCode)"> <script type="text/javascript"> <!-- function Calculator(a, kcode){ var r; if (!(13==kcode)){return;} // ↑「13:Enterキー」でない場合は「return」 r = a; r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/([ ]+)/g, ' '); try{ alert(r+' = '+eval(r)); // ←ここで「eval」を使ってます。 }catch(ex){ alert(ex.message+' : '+r); } } // --> </script>

okweb12345
質問者

お礼

>>> オブジェクトでも関数でもありません。 ざっくり言うと「if」文的な文です、「try」ブロック内で実行文がエラーになると例外が発生し、「catch」ブロック内が実行されます。 whileなどと同じ構文の一種なのですね。 tryはうまくいかずエラーが出た場合つまり、偽ならもう一つの処理を行うというものなのですかね。 >>> <input type="text" name="gakunen" value="" onKeyPress="Calculator(this.value, event.keyCode)"> イベントリスナーを使うのでこれが何を示しているかいまいちわからないのですが、 何かキーボードを押したときに自作のCalculator 関数が実行されるという事でしょうか? つまり何かキーボードを操作したときに毎回 >r = a; >r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); >r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); >r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); >r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); >r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); >r = r.replace(/([ ]+)/g, ' '); が実行されて、記載した文字が上記でエスケープされるという事でしょうか? すると関係ないところに入力した場合も実行されてしまいますね。 私の場合、freeBtnを押したときに計算が実行されるので、freeBtnを押したときにだけ上記を実行し、 その下に >var userInput = document.getElementById('freeUserInput').value; >var freeResult = eval(userInput); >freeResult = round(freeResult); >if (!(userInput === '')) { >} else { >} >}); が来ればエスケープされたものがevalに渡されると思うのですが、どうでしょうか? evalに渡される前にevalに渡す入力文字だけを上記のエスケープをすればよいで素よね?

回答No.13

>回答No.12 amanojaku1 >(「try」ブロック内に「eval」を記述した場合)式として成立してない文字列の場合に例外が発生し、「catch」ブロック内の処理が実行されます。 「try~catch」は「eval」以外でも使用できます、「try」ブロック内でエラーが発生すると、「catch」ブロック内の処理が実行されます。

回答No.12

>ただこの記述をどこに記載したらいいのですか?evalを使う直前に記載したらいいのですか? そうです、下記のサンプルを参照して下さい。 (下記のサンプルのように)必ず「try」ブロック内に「eval」を記述して下さい。 (「try」ブロック内に「eval」を記述した場合)式として成立してない文字列の場合に例外が発生し、「catch」ブロック内の処理が実行されます。 実際に式として成立してない文字列を入力してみれば「catch」ブロック内の処理が実行されているのが分かると思います(例として「1.2.3」、「1+」、「2(1」、「3(2)」など)。 「四則演算子、数字、括弧」以外は除去されます。<br> また式として成立しない文字列は計算できません。<br> <input type="text" name="gakunen" value="" onKeyPress="Calculator(this.value, event.keyCode)"> <script type="text/javascript"> <!-- function Calculator(a, kcode){ var r; if (!(13==kcode)){return;} // ↑「13:Enterキー」でない場合は「return」 r = a; r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/([ ]+)/g, ' '); try{ alert(r+' = '+eval(r)); // ←ここで「eval」を使ってます。 }catch(ex){ alert(ex.message+' : '+r); } } // --> </script>

okweb12345
質問者

お礼

try{ alert(r+' = '+eval(r)); // ←ここで「eval」を使ってます。 }catch(ex){ alert(ex.message+' : '+r); } これは、オブジェクトですか? tryとはなんでしょうか? 関数にも似ていますが、この形は初めて見ました。 結論としては下記でよいのですね function Calculator(a, kcode){ var r; if (!(13==kcode)){return;} // ↑「13:Enterキー」でない場合は「return」 r = a; r = r.replace(/([^0-9\.\-\/\*\+\(\) ]+)/g, ' '); r = r.replace(/([\*\/])[ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2$3'); r = r.replace(/[\+\-][ \+\-\*\/]*([\+\-])[ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*([\+\-])/g, '$1$2'); r = r.replace(/(^|\()[ \+\-\*\/]*[\*\/]/g, '$1'); r = r.replace(/([\+\-\*\/])[ \+\-\*\/]*[\*\/][ ]*([0-9\.\(]+)/g, '$1$2'); r = r.replace(/([ ]+)/g, ' '); try{ var freeBtn = document.getElementById('freeBtn'); freeBtn.addEventListener('click', function() { var userInput = document.getElementById('freeUserInput').value; var freeResult = eval(userInput); freeResult = round(freeResult); if (!(userInput === '')) { } else { } }); }

関連するQ&A