ikepyonのだめ人間日記

セキュリティに関することを書いていく予定。

ほんとに安全なアプリ開発に高いコストが必要か?

http://www.atmarkit.co.jp/fsecurity/rensai/talk13/talk01.html
を読んで、違和感を感じたので書いてみる。
まず、セキュリティというのは当たり前のことを当たり前にさえやっていれば、ある程度防げるものだと思っている。そしてその当たり前のことはそれほど大きくコストがかかるわけではないことが多いんだと思う。現状はその当たり前のことができてないために、いろいろな問題が出てきているのではないか?
なぜできないかというと、関係者全員にセキュリティ=難しいもの、コストがかかるものという誤った認識が出来上がっているために、必要以上に大きく見積もってしまっているのではないか?それこそ、「幽霊の正体見たり枯れお花」ってやつなのだと思うのだけど・・・

その上で、現状のアプリ開発において、発注側が適切にセキュリティ対策について考えていないことがセキュリティ要件を入れると高い見積もりが出てくるということになるのではないだろうか?
例えば、「セキュリティには十分に注意すること」なんてRFPに書かれていれば、何をどこまでやればいいのかわからないからちゃんとした会社は非常に大きくリスクを見積もって、高い見積もりが出てくるのではないだろうか?
逆に詳しくセキュリティ要件を書いているつもりが、実は実装をぎちぎちに制限してしまって、他の機能要件の実現が難しくなってないだろうか?あるいはあまり意味のないセキュリティ要件をたくさん書いてないだろうか?
本来、セキュリティ要件では、どのデータ、処理がどのくらい重要で、それがもれたり、使えなかったりしたらどういう損害が出るか?ということを考慮したうえで、どういった対策をとるか?というのを決定して、(要するにリスク分析)それを発注側が記述しなければいけないと思う。
ところが、発注側がよくわからないという理由で、その手順をやらず、話題になっていることを適当に取り入れて作っているのではないか?
アプリケーションなんて、機能を細分していくとそれほど複雑なものではないと思う。そうすると、リスクもテンプレート化できるのではないかなぁと思うのだけどどうだろう?

開発側だけに問題を押し付けるのではなく、もっと発注側も開発に責任を持つべきではないだろうか?

開発側についてはまた後で書こうっとw

安全なアプリへのアプローチ

と言うことをたまに考える。
アプローチとしては2つあって、一つは、フレームワークや、言語側で安全で無い実装は出来ないようにしちゃうというもの。もうひとつは、プログラマを教育すること(これにはコーディング規約を作ってそれを守らせると言うのも含む)があるんじゃないかな?と思う。
安全で無い実装が出来ないようにするというのは、それだけ自由度が制限されるのでプログラマとしてはやり辛い環境なんじゃないかなぁ?でも、それこそ初心者プログラマには、安全なアプリが作れるので、重宝するだろう。その分、そこから先になかなか進めなくなっちゃうのでは?とも思う。
一方、教育についてはコストが馬鹿にならない。しかも、ミスすることがあるし・・・
とはいえ、今の教育では、プログラミング技術とセキュリティ技術とが乖離しすぎているのではないかなぁと思うんだよなぁ。そのために、セキュリティ対策=コスト増というおかしな常識がまかり通っている気がする。もちろん、アプリを作るに当たってコストのかかるセキュリティ対策と言うのはある。でも、今大きな問題になっているXSSSQLインジェクションと言った脆弱性は、プログラミングレベルだけでも、対策できることなので、これらに関して言えばセキュリティ対策を行うことが、それほど大きくコストに響いてくるとは思えないんだけどなぁ。
もっとプログラムの教育方法を考え直すべきときなんじゃないかと思う今日この頃。

あと、安全なアプリを作るための簡単なフレームワークや言語ってのを誰か作らないかなぁ?w

セキュアプログラミング教育

Webアプリを作るうえで、SQLやプログラム言語、HTMLの知識は必須だと思うんだ。HTTPは無いよりあったほうがいいが必須か?と言われるとちょっとそうでも無い気がしている。で、SQLとプログラム言語、HTMLを一から勉強する場合、SQLならSQLだけ、プログラム言語ならプログラム言語だけ、HTMLならHTMLだけと別々に勉強しているのではないか?
例えばuserテーブルから「ikepyon」というuseridを検索するというSQLを書けと言われると、以下のものになると思う。

SELECT * FROM user WHERE userid = 'ikepyon';

で、ここからプログラムを書くときに、ユーザーから指定された任意のユーザーを検索する場合どういうSQLを書けばいいか?と考えると

SELECT * FROM user WHERE userid = '指定されたユーザー';

ということになっちゃう。結果、それを元にプログラムを書けっていわれると、

sql = "SELECT * FROM user WHERE userid = '" + uid + "';"
ここでuidはユーザーから入力されたデータとする

というSQLを動的に組み立ててしまうのではないだろうか?これってSQLとプログラム言語を別々に学習した結果、ユーザーが入力するデータってどんなのかわから無いという視点が抜けてしまうからとか無いだろうか?
HTMLもおんなじで、ユーザーからの入力をそのままレスポンスに埋め込んでしまう。
例えば先の例であれば、「O'Reilly」を検索するSQLを書けと言われれば、以下のようになり、誰でもおかしいと直ぐに気づくだろう(多分、きっと、だったらうれしいなぁorz)。

SELECT * FROM user WHERE userid ='O'Reilly';

でも、プログラムに埋め込むとこれが見えなくなっちゃう。
こういうのって、SQLとHTML、プログラム言語を全く別のものとして学習してしまった結果かなぁ?とか思うんだけどどうだろう?
アプリを作る際に、SQLもHTMLもプログラム言語もひっくるめて考えなきゃいけないのに、別々の知識としてあるだけで、それぞれ関係しているんだという意識が無いのかもしれない。だから、平気で「sql = "SELECT * FROM user WHERE userid = '" + uid + "';"」のようなコードを書いちゃうんじゃないのかなぁ?

それに、「O'Reilly」みたいなのを検索できるようなプログラムをサンプルにすりゃいいのに、入門用の解説では「分かりづらくなるので、問題のあるコードにします。セキュリティについては後で書きます」とか出てくるのも、別物として学習させようというのがあるんじゃなかろうか?
「分かりづらくなる」って何だよ!正しく動かないことがあるプログラムを入門用のサンプルとするほうが問題だろうと思うんだけどなぁ?

XHRその後

http://d.hatena.ne.jp/ikepyon/20080825#p2
の続き。IE8で検証してみたら、未だに治っていない様子orz
でも、一部でできないと言う報告もあるのでよくわからん。少なくとも私のwininet.dllのバージョン8.00.6001.18828(longhorn_ie8_gdr.090826-1700) では出来ちゃうんですが?報告上げてないと直んないのかな?

動的に検索項目を指定したい場合のSQLインジェクション対策

バインド機能を使えば、ほぼすべてのSQLインジェクション脆弱性を防ぐことが出来るのは良く知られていると思いたい。しかし、アプリケーションの仕様によっては、検索項目やソート順を自由に変更したい場合がある。この場合、バインド機能では残念ながら対応できない。
そこで、以下のようなSQL文を組み立てることがあるのでは無いだろうか?

sql = "select * from table1 where " + (入力データ1) + "= ? order by " + (入力データ2) + ";";

「(入力データ*)」はここでブラウザから渡されたデータとする。この場合、いくらバインド機能使ってても、「(入力データ*)」の妥当性チェックがなされていなければSQLインジェクションが起こってしまう。
では、こうすればいいか?

sql = "select * from table1 where ? = ? order by ?;";

これは検索項目が文字データとし取り扱われるため、目的のことと違ってしまう。
検索項目を自由に指定できるようにし、安全にSQLを組み立てるには以下のようにすればよいと思う。まあ、入力値チェックをやってりゃいいんだけど、それを忘れたときのために・・・

param={"field1", "field2", "field3"};
sql = "select * from table1 where " + param[(入力データ1)] + "= ? order by " + param[(入力データ2)] + ";";

検索項目名、やソートキーはテーブルに存在するものしか存在しないのであるから、それらすべてを配列に格納し、配列の添え字をパラメータとして指定するようにすれば、数値チェックだけで済むので、非常に楽になると思う。
こういったロジックって使ってないことがたまにあるような?