WEB相談室

Webページ作成に関しての何でも掲示板です。

タイトル:ゲット引数オブジェクト

0:[投稿] yuu [URL] [2002/11/15 03:07 ][環境:その他 その他]

http://www.parkcity.ne.jp/~chaichan/src/javasc32.htm
ここのサンプルですが。

受け取った値をエスケープしてないので
http://www.parkcity.ne.jp/~chaichan/src/t207081.htm?modefg=9&xxx=<script>alert('hello')</script>&yyy=888&zzz=9999
とかで、そのままスクリプトが実行されちゃいますよね。

このようなものをサンプルとして提示しているのは、あんましよろしくないんじゃないかと思うわけですが。
ふつう、受け取るデータをあたまから信頼しているようなプログラムを書くと、まあ簡単にXSS脆弱性などのモトとなったりするわけですから、このサンプルで勉強しただけで色々書き始めるようになってしまうと、後々何かとアレなことになってしまう可能性があると思うわけです。

こういった解説サイトのたぐいであれば、はじめから「常に引数はチェックする」とか「信頼できないデータを受け取る可能性がある場合は必ずエスケープする」とか、そういったことを踏まえた解説をしたほうが良いんじゃないかなー と、思う次第なのでありました。

余計なお世話かもしれませんが。


#関係ないけど、的を射たつもりのタイトル「ゲット引数オブジェクトのサンプルについて」にしたら、15文字以下にしろとか言われて残念な思いをしました。どうすりゃいいんでしょうか【謎】。


1:[関連] yuu [2002/11/15 04:24 ]

む、( が入ると自動リンクが切れちゃってアレ【どれ】ですね。
http://www.parkcity.ne.jp/~chaichan/src/t207081.htm?modefg=<marquee><blink>
とかならイイかな。

#何が?


2:[回答] 管理人 [2002/11/15 09:22 ]

yuuさん、いつもありがとうございます。
大変、有り難いご指摘、ありがとうございました。
時間が空き次第、そのページをバージョンアップしたいと思います。
最近、本業が凄く忙しくなってしまってなかなか...。

しかし、
>>1
のリンクをクリックたら、なんか、感動を覚えました。

最近、また、yuuさんがここに来られるようになって、すごくうれしいです。あと、えびさんとよしみちゃんが、また、来てくれるとうれしいなと思うこのごろです。


3:[回答] 管理人 [2002/11/15 09:26 ]

>15文字以下にしろとか言われて残念な思いをしました。
実は、こちらも、前からアクションアイテムにあがっていまして...。
なんとかする予定です。

ご迷惑お掛けしています。


4:[回答] ひじ [URL] [2002/11/15 19:59 ]

時間が空き次第、なんて悠長なことは言わずに、バージョンアップまで公開停止にすべきです。攻撃の踏み台にされても私は知りません。

クロスサイトスクリプティング脆弱性への対策は、以下のURLが分かりやすいです。
http://www.ipa.go.jp/security/awareness/vendor/programming/a01_02.html

>>0
<で切れずに(で切れるのが何とも…。
この掲示板の作者は、何を根拠にこの文字列がURLだと言っているのだろうか。


5:[関連] ポインタ君 [2002/11/15 21:15 ]

参考: HTTP URLの正規表現
http://www.din.or.jp/~ohzaki/perl.htm#httpURL


6:[回答] 管理人 [2002/11/15 23:37 ]

ひじさんとポインタ君へ
>バージョンアップまで公開停止にすべきです。
ご忠告、ありがとうございます。
早速、公開停止にしました。
URLの正規表現については、勉強してみます。

yuuさんへ
「人のよいところをどんどん見つよう」キャンペーンへの参加ありがとうございました。
http://www.parkcity.ne.jp/~chaichan/chai/essay03.htm
この場を借りて、お礼申し上げます。


7:[完了] yuu [URL] [2002/11/16 03:26 ]

相互リンクに賛同したおぼえはないのですが、リンクをはられること自体に関しては、「何処からでも何処にでも好きなようにリンクしてください」というのが基本の考えでもありますので、全くもって問題ないったらありゃしないだけに、こだわりません:-)


8:[回答] yuu [2003/02/14 23:49 ]

現在 >>1 の URL をクリックしますと、「`<` または `>` を引数にすることはできません」というダイアログが出ているのですが、なんか対策として違うというか……。

繰り返しますが、スクリプトの書き方のサンプルとして提示しているわけですよね、これは。
そうであれば尚のこと、引数を受け取るときは必ず*エスケープする*というコードを、確実に含めるようにしたほうが良いと思うのです。引数の妥当性を頭から信用しないという考え方は、大前提として身に付けておいて何ら損することは無いのですから。


9:[回答] ちゃいぱ [MAIL] [URL] [2003/02/15 09:50 ]

yuuさん、いつもありがとうございます。

了解しました。
といあえず、公開をやめ、
後日、修正後、出直します。


10:[回答] yuu [2003/02/17 10:36 ]

あと、この掲示板の、URLの正規表現も早く直して欲しい……。


11:[回答] ちゃいぱ [2003/02/17 12:55 ]

>引数を受け取るときは必ず*エスケープする*というコード
もう少し具体的にお願いします。
(今、unescape関数使っていますが、これとは、関係ない?)

>URLの正規表現も早く直して欲しい……。
大崎さんのを参考にして、以下にします。

$body =~ s/(s?https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)/<a href=\"$1\">$1<\/a>/g;


12:[回答] yuu [2003/02/17 19:21 ]

>もう少し具体的にお願いします。

別に何のことはない、

& → &amp;
< → &lt;
> → &gt;
" → &quot;
' → &#39;

です。


13:[回答] ちゃいぱ [MAIL] [URL] [2003/02/18 23:01 ]

以下、修正いたしました。なにか、勘違い等がありましたら、ご指摘ください。

http://www.parkcity.ne.jp/~chaichan/src/javasc32.htm


14:[回答] yuu [2003/02/19 00:16 ]

うーん、何が直ったというか、どこを直されたのかよくわからないのですが……。


15:[回答] 謎の人R [2003/02/19 03:44 ]

<html>
<head>
<title>ゲット引数オブジェクトのサンプル</title>
</head>
<body>
<script type="text/javascript">
function Hikisuu( buf ){
    if( !buf || buf == "" ){
        return false;
    }
    this.string = buf.split('&');
    for( var i=0; i<this.string.length; i++ ){
        var v = this.string[i].split('=');
        this[Escape( v[0] )] = Escape( v[1] );
    }
    return this;
}
function Escape( str ){
    str = str.replace( /\&/g, '&amp;' );
    str = str.replace( /</g, '&lt;' );
    str = str.replace( />/g, '&gt;' );
    str = str.replace( /\"/g, '&quot;' );
    str = str.replace( /\'/g, '&#39;' );
    return str;    
}

var buf = location.search.substring(1);//?をサプレス
status = buf;    //内容確認用


var objHikisuu = new Hikisuu( buf );

document.write("<p>");
document.write("modefgの値は、" + objHikisuu.modefg +"<br>");
document.write("xxxの値は、" + objHikisuu.xxx +"<br>");
document.write("yyyの値は、" + objHikisuu.yyy +"<br>");
document.write("zzzの値は、" + objHikisuu.zzz +"<br>");
document.write("</p>");
</script>

<p>もう一度<br>
<a href="t207081.htm?modefg=9&amp;xxx=11&amp;yyy=222&amp;zzz=3333">t207081.htm?modefg=9&amp;xxx=11&amp;yyy=222&amp;zzz=3333</a></p>
<p><a href="javasc32.htm">戻る</a></p>
</body>
</html>

こういうのでいいのでしょうか……?
※ほかにもいくつか手を加えてみました。このほうがオブジェクト指向的?かと


16:[回答] yuu [2003/02/19 10:48 ]

ああ、そういう感じですね。
ようするに、引数をそのまま使わないというのがポイントになってくるわけなので。


17:[回答] ちゃいぱ [2003/02/19 13:00 ]

yuuさん、謎の人Rさん、いつもありがとうございます。
>>14
すみません、全然、理解していなかったです。
>>15
これを参考に作り直してみました。

<html>
<head>
<title>ゲット引数オブジェクトのサンプル</title>
</head>
<body>
<script type="text/javascript">

function getHikisuu(){
    getHikisuu.data = new Array();
    getHikisuu.string = location.search.substring(1);//?をサプレス
    getHikisuu.string = getHikisuu.string.split('&');
    for(var i = 0; i != getHikisuu.string.length; i++) {
        getHikisuu.data[ck_shikibetushi(getHikisuu.string[i].split('=')[0])]
                              =  unescape(Escape(getHikisuu.string[i].split('=')[1]));
    }

    function ck_shikibetushi(shiki){ //識別子(プロパティ)の命名チェック
        shiki_TOP = shiki.substring(0,1);
        if(shiki_TOP != '_' && shiki_TOP != '$' && shiki_TOP.match(/[a-zA-Z]/g) == null){
           alert(shiki+"の引数が不正です。(一文字目は、ASCII、_、$のいずれかです。)");
           return null;
        }
        else if(shiki.match(/[^a-zA-Z0-9]/g) != null){
           alert(shiki+"の引数が不正です。(命名文字は、ASCII、_、$、数字のいずれかです。)");
           return null;
        }
        return shiki;
    }

    function Escape(str){ //文字参照へ変換
         str = str.replace( /\&/g, '&amp;' );
         str = str.replace( /</g, '&lt;' );
         str = str.replace( />/g, '&gt;' );
         str = str.replace( /\"/g, '&quot;' );
         str = str.replace( /\'/g, '&#39;' );
         return str;
   }
} new getHikisuu();
document.write("<p>");
document.write("modefgの値は、" + getHikisuu.data.modefg +"<br>");
document.write("xxxの値は、" + getHikisuu.data.xxx +"<br>");
document.write("yyyの値は、" + getHikisuu.data.yyy +"<br>");
document.write("zzzの値は、" + getHikisuu.data.zzz +"<br>");
document.write("</p>");
</script>

<p>もう一度<br>
<a href="t207081.htm?modefg=9&amp;xxx=11&amp;yyy=222&amp;zzz=3333">t207082.htm?modefg=9&amp;xxx=11&amp;yyy=222&amp;zzz=3333</a></p>
<p><a href="javasc32.htm">戻る</a></p>
</body>
</html>


18:[回答] yuu [2003/02/19 14:18 ]

>//文字参照へ変換

このコメントは、コード中のものなのでまあこれでも良いと思いますが、あとはこのサンプルの説明ページの中で、「与えられた引数が信頼できる値であると、頭から信用しないこと」というようなことを啓蒙する説明をきちんとしたほうが良いかなと思います。


19:[回答] ween [2003/02/19 14:57 ]

>>17
> unescape(Escape(getHikisuu.string[i].split('=')[1]));
引数に %3C が含まれていた場合を考えてみてください。
せっかく文字参照使って安心して出力できる文字に変換しても、
その後の操作が安全でない文字を出現させるのでは台無しです。
Escape のような処理は、後はもう出力するだけの状態で行う方がよいと思います。


20:[回答] yuu [2003/02/19 15:03 ]

>Escape のような処理は、後はもう出力するだけの状態で行う方がよいと思います。

このサンプルでは最後でも構わないでしょうが、引数を使う前にチェックするという観点からすれば、最初にすべきです。
ていうか、そこでunescape()している意味がよくわからんのですが、何のためにやっているのでしょう。


21:[回答] ちゃいぱ [2003/02/19 15:41 ]

>「与えられた引数が信頼できる値であると、頭から信用しないこと」というようなことを啓蒙する
了解しました。いつも、有用なアドバイス、ありがとうございます。

>>17
のck_shikibetushi()を修正。
    function ck_shikibetushi(shiki){ //識別子(プロパティ)の命名チェック
        shiki_TOP = shiki.substring(0,1);
        if(shiki_TOP.match(/[a-zA-Z_$]/g) == null){
           alert(shiki+"の引数が不正です。(一文字目は、ASCII、_、$、のいずれかです。)");
           return null;
        }
        else if(shiki.match(/[^a-zA-Z0-9_$]/g) != null){
           alert(shiki+"の引数が不正です。(命名文字は、ASCII、数字、_、$、のいずれかです。)");
           return null;
        }
        return shiki;
    }


22:[回答] ちゃいぱ [2003/02/19 15:47 ]

>>19
>>20
を知らないで、21を投稿しました。
今、熟慮しています。


23:[回答] ちゃいぱ [2003/02/19 16:01 ]

以下で、どうでしょうか。

function getHikisuu(){
    getHikisuu.data = new Array();
    getHikisuu.string = location.search.substring(1);//?をサプレス
    getHikisuu.string = unescape(getHikisuu.string);
    getHikisuu.string = getHikisuu.string.split('&');
    for(var i = 0; i != getHikisuu.string.length; i++) {
        getHikisuu.data[ck_shikibetushi(getHikisuu.string[i].split('=')[0])]
                              =  Escape(getHikisuu.string[i].split('=')[1]);
    }

    function ck_shikibetushi(shiki){ //識別子(プロパティ)の命名チェック
        shiki_TOP = shiki.substring(0,1);
        if(shiki_TOP.match(/[a-zA-Z_$]/g) == null){
           alert(shiki+"の引数が不正です。(一文字目は、ASCII、_、$、のいずれかです。)");
           return null;
        }
        else if(shiki.match(/[^a-zA-Z0-9_$]/g) != null){
           alert(shiki+"の引数が不正です。(命名文字は、ASCII、数字、_、$、のいずれかです。)");
           return null;
        }
        return shiki;
    }

    function Escape(str){ //文字参照へ変換
         str = str.replace( /\&/g, '&amp;' );
         str = str.replace( /</g, '&lt;' );
         str = str.replace( />/g, '&gt;' );
         str = str.replace( /\"/g, '&quot;' );
         str = str.replace( /\'/g, '&#39;' );
         return str;
   }
} new getHikisuu();


24:[回答] ween [2003/02/19 21:46 ]

>>20
> 引数を使う前にチェックするという観点からすれば、最初にすべきです。
用途に関係なく一律に特定用途のチェックを勧めているようにも聞こえて
なんだか附に落ちない感じです。観点は理解しているつもりなのですが。

実体参照によるエスケープが重要になるのは、document.write とか innerHTML とか
文字列がマークアップ解析対象になる場合だけです。
getHikisuu が想定する取得した引数の使用法はそれだけなんでしょうか?
確かにこのサンプルではそのまま document.write してるだけですが、
文字数取得や文字列の正規表現検索・置換、といった
解析されない文字列操作全般も想定用途に入っているならば、
getHikisuu() 内部でとにかく文字参照にしてもしょうがないと思うのです。

初期にそうした処理を行うにしても、
それは必要な引数に対して個別に getHikisuu() 外部で行えばよいことだと思います。


25:[回答] yuu [2003/02/19 22:09 ]

>実体参照によるエスケープが重要になるのは、document.write とか innerHTML とか
>文字列がマークアップ解析対象になる場合だけです。

いえ、たとえばフォームのhiddenでなんかの値を持たせているようなページがあって、そこからsubmitされた場合も、やはりそのなんかの値が正しいものかチェックする必要があります。
また、世の中には恐ろしいことに、入力された内容をそのままSQL構文に貼り付けて、DBへ投げてしまうような乱暴なプログラムも存在しています。これの場合でも、エスケープするなり、そもそもはじくなりといったかたちで、いずれにしても入力された内容を確認するロジックが必要になります。

明らかにプログラム内部で生成された値を使う場合など、引数のチェックを省略しても構わない場面というのもあるでしょう。しかし、このサンプルというか、このサイトでプログラムを覚えることになる人がいる場合、そういった良い作法のプログラムの書き方というものをベースの知識として覚えておいたほうが良いと思いますし、そういったことを啓蒙できるサイトのひとつであるとも考えます。

作法を良くしたところで、別に難しさが増すわけではないですし。


26:[回答] yuu [2003/02/19 22:13 ]

↑あれ? なんか反応として変かも? とか思いましたが、とりあえずこだわらないことにして、まあ、とにかくそういうことです(謎)。


27:[回答] TOM neko [2003/02/19 22:53 ]

わたしもHTML出力時にエスケープした方が理にかなうと思ってたりするのですが。

つまり、「<>」てのはWebアプリケーションにとって特別に危険な文字として、入力時点からずっとエスケープした状態で扱う必要がある、ということでしょうか。


28:[回答] ween [2003/02/19 23:54 ]

>>25
もちろん、受け取る引数にはそれぞれチェックが必要だとは思います。
ですが、妥当性の条件や要求される対策が
引数ごとに違っている場合もあると思うんですよ。
そうした場合に、たまたま一つのチェック方法で済むからといって
クエリーを分解しながら同時にチェックを行うようなサンプルでは
参考にする側として応用しにくいのではないかと。


29:[回答] yuu [2003/02/20 00:12 ]

>>27
ええと、なんというか。
明らかに信頼できる値である場合以外は、常に信頼できない値として、引数をチェックする必要がある、という話です。
たまたまこのサンプルの場合はXSS脆弱性と密接だったけど、別に`<`や`>`をエスケープすればそれでいいということじゃなくて、「入力された値を信用しない」という大前提のもとでコードを書く必要があるということです。
だからここのサイトでプログラミングすることのきっかけになったりする人のために、常にそういうサンプルとか説明とかを提供したほうがいいんじゃないかという、まあ要するに余計なお世話です。


30:[回答] ちゃいぱ [MAIL] [URL] [2003/02/20 00:18 ]

>まあ要するに余計なお世話です。
いや、有り難いです!


31:[回答] TOM neko [2003/02/20 02:04 ]

>>29
なるほど、「入力された値を信用しない」ことの教育的配慮として入力時のチェックが欲しいのですね。その内容が<>のエスケープなのは、たまたま、サンプルでその後にdocument.writeしてるからってことで。

となると、document.writeするのは、いかがなものか、というか、適切な例でないような気もしてきますが、じゃあどうすればいいかと言われても、すぐに思い付かないのでこのへんで。


32:[回答] ひじ [2003/02/20 12:24 ]

クロスサイトスクリプティング脆弱性への対処の場合、
>>4 で挙げたURL
http://www.ipa.go.jp/security/awareness/vendor/programming/a01_02.html
でもかかれている通り、HTML生成時でなくては意味がありません。

あと、もう2点気になりました。
・queryに%26とか%3dとか含まれていると…
・ck_shikibetushi()の存在意義が分からない。
 arrayオブジェクトの添え字は任意のUNICODE文字列でOKのはず(ECMAScriptの場合)


33:[回答] ちゃいぱ [2003/02/20 14:16 ]

ひじさん、いつもありがとうございます。

>・queryに%26とか%3dとか含まれていると…
>>17

なら、大丈夫かな。

> arrayオブジェクトの添え字は任意のUNICODE文字列でOKのはず
今回の場合、プロパティになりますので、チェックを入れました。
プロパティは、一文字目がASCII、_、$で、一文字目以外が、ASCII、_、$、数字です。


34:[回答] ween [2003/02/20 14:55 ]

> プロパティは、一文字目がASCII、_、$で、一文字目以外が、ASCII、_、$、数字です。
ECMA-262 初版の場合はその通りです。
第3版の場合は識別子に使える文字に非ASCIIの多くのUnicode文字が追加されていて
記号類でなければ大抵の文字はプロパティ名に使用できます。


35:[回答] ひじ [2003/02/20 22:16 ]

>>33
&, = のパースを行った後にunescapeすればよいです。
もっとも、unescapeした結果が非ASCII文字の場合、どんな文字コードか分からないで困りそうですが…。

>今回の場合、プロパティになりますので、チェックを入れました。
document.writeの部分を見落としていました。失礼しました。


36:[回答] しなのむし [2003/02/22 03:13 ]

データの流れとして

WEB → HTML
WEB → DB
DB → HTML
DB → DB

などが主に特別な意味を持つ文字のエスケープや変換を考慮する必要がある場合だと思いますが
セキュリティ以前に「データやプログラムの挙動がおかしくなる」といった観点で啓蒙する方が
とっつきやすい(というかより正確に理解出来る)のではないでしょうか?
(信用出来るユーザーしか居ない環境もあるでしょうし)

簡単に言えば

HTMLに文字列として出力するデータの場合はHTML生成時に
「&」「<」「>」「"」「'」
をHTMLエンティティに変換する

データベースへ行くデータの場合はSQL文実行時に
「'」「"」「\」、場合により「%」「_」
などの文字列をエスケープする
(考慮すべき文字は使用データベースにより多少異なると思います)

ということですよね。

実際に動くサンプルに問題があるのは困りますが
単に何かを説明するだけで且つソースのみの公開であるなら
「入力データのチェックはしておりません」
と一言書いておけばいいような気もしますが。

>>31
データ元のソースやシステムの設計次第でエスケープ・変換をどう行うかは異なるでしょうね。
WEBから入って来るデータに関しては全面的に信用出来ないので必須でしょうし
DBから渡ってくるデータはシステムの作成者次第でエスケープ・変換が不要な場合もあるでしょう。
ちなみに今件(ゲット引数オブジェクト)は、WEB → HTML なので必須ですね。

回答(必須): 状態:

お名前(必須):

e-mail:

URL:




[戻る]

ChaichanPAPA's World