Applicationsの紹介Redditを眺めておりましたら以下の記事が目に止まりました。Applicationsざっくりというと以下の様な内容ですCGI.pmのparamメソッドの返り値をハッシュに突っ込んでいる箇所があるクエリ文字列に同名のパラメータを複数セットすると、配列値が返る配列をハッシュに突っ込むことにより、別のキーの値が変更される私はこの内容に興味を持ちましたので、以下に詳しく説明します。PoC元エントリにもPoCが出ておりますが、少し手をいれたものを以下に示します。$user{'password'}ENDご覧のように、キーとしてlogin、realname、passwordを取るハッシュを作成しています。loginとpasswordは定数(セッション変数などから取得する想定)、realnameはクエリ文字列realnameから取得します。呼び出すと結果は下記となります。a3k!sz9次に、以下のクエリ文字列で呼び出します。realname=hoge&realname=login&realname=yamada結果は以下となります。a3k!sz9なんと、定数で指定しているはずのloginがyamadaに化けています。?CGI.pmは同名パラメータ指定により配列を受け取ることができるCGI.pmのparamメソッドは、以下のようにすると、配列の形でパラメータを受け取ることができます。3を値にもつ配列となります。部分は以下のように呼び出されることになります。'a3!sz9');Perlの場合、=>とカンマ(,)はほぼ同じ意味だそうで、上記は以下のように展開されます。私はPerlの細かい文法には自信が無いため、以下の部分の説明に誤りがあればご指摘ください。'a3!sz9');整形すると、以下と同等です。したがって、配列をハッシュに変換する際に、キーloginに対する値は、'yamada'に上書きされます。'a3!sz9');以上の手順により、$user{'login'}が本来smithであるところ、外部からの入力により、yamadaに変更させられました。このようなケースはありえるのか?上記のPoCのようなことが現実にあり得るかというと、ちょっと微妙な気はするものの、ないこともないかなという印象です。APIなどで、入力はurlencodedだけど出力はJSONであって、そのJSONを作る際にいきなりハッシュ定義に入力値を放り込んでいるケースなどです。元記事のコメント欄には、ふつーバリデーションするだろというツッコミに対して、著者は、realnameは任意の文字を受け取るのでバリデーションは必要ないと答えています。制御文字などは弾く必要があるため、アプリケーション要件としても、最低限度のバリデーションは必要と考えます。対策この問題を避ける簡便な方法として、元エントリではrealnameの値をスカラーに変換する方法が紹介されています。$password);あるいは、値をいったんスカラー変数で受けるという方法があります。これにより、realnameがスカラであることが保証されます。$password);まとめ前回のエントリでも説明したように、スカラ値を想定している入力が、実は配列やハッシュになっている可能性を想定して、スカラであることのチェック、あるいはスカラに変換する等の処理が必要な場合があります。入力値のバリデーションをすれば脆弱性が顕在化することはありませんが、脆弱性が混入するその箇所で対策することを考えると、ハッシュに突っ込む箇所で、当該変数がスカラーであることが一目瞭然になっているのがよいでしょう。