2008.03.05 Wednesday
お問い合わせフォーム、登録フォーム、キャンペーンの申込フォーム。
Webにはいろいろなフォームがある。
Webプログラマーであれば誰もが一度は作ったことがあると思う。
新人プログラマーの初めての実務がフォームであることも多いだろう。
新人が作っているというのにもかかわらず、技術的にも面白い部分がないせいか、正しい知識のある人がレビューすることが少ないと思われる。
単純さゆえにテストが不足しているということもあるかもしれない。
上記の理由は憶測にすぎないが、杜撰なフォームがたくさん出回っているのは事実だ。
もう、CAPTCHAの話とか以前の問題だ。
よく見かける悪い例を簡単にあげておく。新人が初めての実務に当たるときにこれを気にしてくれれば、世の中のフォームがだいぶ良くなると思う。
1. クライアントサイド(JavaScript)でのチェックのみ。
2. 選択肢式の入力欄に対するチェックの漏れ。
3. 確認画面に遷移するときにはチェックするのに、完了画面に遷移するときにはチェックしない。
4. postのみを許可すれば入力値をいじることはできないという勘違い。
5. フロントエンドはSSLなのに、裏では管理者にメールを飛ばしている。
6. フロントエンドはSSLなのに、蓄積されたデータをFTPでダウンロードする。
それぞれの項目を簡単に説明してみよう。
1. クライアントサイド(JavaScript)でのチェックのみ。
JavaScriptで入力チェックを行っているフォームを見かける。http通信の前段階でエラーのチェックができるので、親切な設計だといえる(僕は面倒なのでやらないけど)。でも、だからといってサーバサイドでのチェックをしなくて良いということにはならない。クライアント側でのチェックなんて所詮おまけで、それをくぐり抜けることはたやすいのだから。
入力チェックは基本的にはサーバサイドで。
おまけとしてクライアント側のチェックもあり。
そう考えていなければならない。
SQLインジェクション対策をクライアントサイドでだけやるなんて、もってのほかだ。
2. 選択肢式の入力欄に対するチェックの漏れ
チェックボックスやラジオボタン、それにプルダウンメニューなどの選択肢式の項目の入力値についての誤解。
渡されてくる値が選択肢のいずれかになるなんて考えるのは勘違いだ。methodがgetであればブラウザのアドレス欄をいじるだけで簡単に好きな値を入力することができるのは明白だと思う。後述するが、methodをpostに限定したところで問題は解決されない。
どんなデータが渡されてきてもいいように、適切に入力チェックを行うようにしよう。
3. 確認画面に遷移するときにはチェックするのに、完了画面に遷移するときにはチェックしない。
完了画面が確認画面からしか呼び出せないなんて考えるのは勘違いだ。完了画面でも確認画面と同じ入力チェックをするべきだ。完了画面のURLに対して直接ブラウザのアドレス欄から入力してデータを渡すことなんて簡単なのだから。これもmethodをpostに限定したところで解決されない。
4. postのみを許可すれば入力値をいじることはできないという勘違い。
例えば、フォームのHTMLソースをローカルに保存して、<input type="text" ... />とかに書き換えるだけでも簡単にpostする入力値を自由に改変できる。そもそもこんなくだらない理由で2つのメソッドを使い分けるのは、RESTの観点から考えても完全に間違っているといえる。
確認画面の時点でデータをDBに格納しないのであれば、確認画面はアルゴリズムリソースと考えられるのでGETがふさわしい。そして、完了画面では登録情報というリソースを作成するので、こちらはPOSTがふさわしい。
もし、確認画面の時点で一時的にデータをDBに作成して、完了画面でそれを確定する(例えばフラグをたてる)というようなプロセスをとるのであれば、確認画面の時点でPOSTを行って、生成されたリソース情報をformタグのaction属性に埋め込んで、完了画面ではその新しく生成されたリソースに対してPUTするのが正しいプロセスとなる。(ただし現状ではブラウザはPUTメソッドを送出できないのでPOSTで代用することになる)
すこし話はそれたけど、とにかくGETを「セキュリティ的に強固にする」という理由でPOSTにするのは意味がない。
5. フロントエンドはSSLなのに、裏で管理者にメールを飛ばしている。
メールは平文だからね。
メールで送っていいのは、「フォームに入力された」という事実の通知のみ。入力された内容はしかるべき暗号化された別の手段で手に入れるべきだ。一番簡単なのはサーバサイドで蓄積してSCPで取得してもらう方式だろうか。
こういう部分は提案のときに発注元(以下、クライアント)にも説明しないとダメだね。
要件定義や仕様になかったなんてのは、請け負った側の怠慢としかいえない。
6. フロントエンドはSSLなのに、蓄積されたデータをFTPでダウンロードする。
そしてFTPも平文だということを忘れてはいけないよ。
これも提案のときにクライアントに説明しないとダメだ。
5と6についてはソースコードの問題では無いけど、フォームの問題としては最悪。ユーザーはSSLで暗号化されていると信じて個人情報を入力しているのに、裏側では平気で平文で垂れ流されているのだから。ユーザーは気が付くわけがない。だいたい、クライアントにWebアプリのセキュリティの知識を求めるのは酷だ。彼らはプロじゃないから僕たちに依頼してくるのだ。そう考えると、請け負った開発会社にはこういうことを正しく説明する義務がある。個人情報が流出して被害を被ってしまうのはユーザーだけじゃない。クライアント企業だって信用にかかわるのだから。
ただね、セキュリティ的に全然イケてないけど安いものと、セキュリティ的にばっちりでそこそこのコストがかかるものとを比較したとき、クライアントが望んでいるものがどちらなのかはいまだに謎なんだ。
セキュリティに留意することを意識した見積もり(A)と、そうでない見積もり(B)とがあるとしよう。金額勝負になりがちな見積もりコンペでは往々にしてAが負けてしまう。
続きを書いたので参考に。
確認画面でhiddenに入力値を埋め込むのはセキュリティ的にダメか?
Webにはいろいろなフォームがある。
Webプログラマーであれば誰もが一度は作ったことがあると思う。
新人プログラマーの初めての実務がフォームであることも多いだろう。
新人が作っているというのにもかかわらず、技術的にも面白い部分がないせいか、正しい知識のある人がレビューすることが少ないと思われる。
単純さゆえにテストが不足しているということもあるかもしれない。
上記の理由は憶測にすぎないが、杜撰なフォームがたくさん出回っているのは事実だ。
もう、CAPTCHAの話とか以前の問題だ。
よく見かける悪い例を簡単にあげておく。新人が初めての実務に当たるときにこれを気にしてくれれば、世の中のフォームがだいぶ良くなると思う。
1. クライアントサイド(JavaScript)でのチェックのみ。
2. 選択肢式の入力欄に対するチェックの漏れ。
3. 確認画面に遷移するときにはチェックするのに、完了画面に遷移するときにはチェックしない。
4. postのみを許可すれば入力値をいじることはできないという勘違い。
5. フロントエンドはSSLなのに、裏では管理者にメールを飛ばしている。
6. フロントエンドはSSLなのに、蓄積されたデータをFTPでダウンロードする。
それぞれの項目を簡単に説明してみよう。
1. クライアントサイド(JavaScript)でのチェックのみ。
JavaScriptで入力チェックを行っているフォームを見かける。http通信の前段階でエラーのチェックができるので、親切な設計だといえる(僕は面倒なのでやらないけど)。でも、だからといってサーバサイドでのチェックをしなくて良いということにはならない。クライアント側でのチェックなんて所詮おまけで、それをくぐり抜けることはたやすいのだから。
入力チェックは基本的にはサーバサイドで。
おまけとしてクライアント側のチェックもあり。
そう考えていなければならない。
SQLインジェクション対策をクライアントサイドでだけやるなんて、もってのほかだ。
2. 選択肢式の入力欄に対するチェックの漏れ
チェックボックスやラジオボタン、それにプルダウンメニューなどの選択肢式の項目の入力値についての誤解。
渡されてくる値が選択肢のいずれかになるなんて考えるのは勘違いだ。methodがgetであればブラウザのアドレス欄をいじるだけで簡単に好きな値を入力することができるのは明白だと思う。後述するが、methodをpostに限定したところで問題は解決されない。
どんなデータが渡されてきてもいいように、適切に入力チェックを行うようにしよう。
3. 確認画面に遷移するときにはチェックするのに、完了画面に遷移するときにはチェックしない。
完了画面が確認画面からしか呼び出せないなんて考えるのは勘違いだ。完了画面でも確認画面と同じ入力チェックをするべきだ。完了画面のURLに対して直接ブラウザのアドレス欄から入力してデータを渡すことなんて簡単なのだから。これもmethodをpostに限定したところで解決されない。
4. postのみを許可すれば入力値をいじることはできないという勘違い。
例えば、フォームのHTMLソースをローカルに保存して、<input type="text" ... />とかに書き換えるだけでも簡単にpostする入力値を自由に改変できる。そもそもこんなくだらない理由で2つのメソッドを使い分けるのは、RESTの観点から考えても完全に間違っているといえる。
確認画面の時点でデータをDBに格納しないのであれば、確認画面はアルゴリズムリソースと考えられるのでGETがふさわしい。そして、完了画面では登録情報というリソースを作成するので、こちらはPOSTがふさわしい。
もし、確認画面の時点で一時的にデータをDBに作成して、完了画面でそれを確定する(例えばフラグをたてる)というようなプロセスをとるのであれば、確認画面の時点でPOSTを行って、生成されたリソース情報をformタグのaction属性に埋め込んで、完了画面ではその新しく生成されたリソースに対してPUTするのが正しいプロセスとなる。(ただし現状ではブラウザはPUTメソッドを送出できないのでPOSTで代用することになる)
すこし話はそれたけど、とにかくGETを「セキュリティ的に強固にする」という理由でPOSTにするのは意味がない。
5. フロントエンドはSSLなのに、裏で管理者にメールを飛ばしている。
メールは平文だからね。
メールで送っていいのは、「フォームに入力された」という事実の通知のみ。入力された内容はしかるべき暗号化された別の手段で手に入れるべきだ。一番簡単なのはサーバサイドで蓄積してSCPで取得してもらう方式だろうか。
こういう部分は提案のときに発注元(以下、クライアント)にも説明しないとダメだね。
要件定義や仕様になかったなんてのは、請け負った側の怠慢としかいえない。
6. フロントエンドはSSLなのに、蓄積されたデータをFTPでダウンロードする。
そしてFTPも平文だということを忘れてはいけないよ。
これも提案のときにクライアントに説明しないとダメだ。
5と6についてはソースコードの問題では無いけど、フォームの問題としては最悪。ユーザーはSSLで暗号化されていると信じて個人情報を入力しているのに、裏側では平気で平文で垂れ流されているのだから。ユーザーは気が付くわけがない。だいたい、クライアントにWebアプリのセキュリティの知識を求めるのは酷だ。彼らはプロじゃないから僕たちに依頼してくるのだ。そう考えると、請け負った開発会社にはこういうことを正しく説明する義務がある。個人情報が流出して被害を被ってしまうのはユーザーだけじゃない。クライアント企業だって信用にかかわるのだから。
ただね、セキュリティ的に全然イケてないけど安いものと、セキュリティ的にばっちりでそこそこのコストがかかるものとを比較したとき、クライアントが望んでいるものがどちらなのかはいまだに謎なんだ。
セキュリティに留意することを意識した見積もり(A)と、そうでない見積もり(B)とがあるとしよう。金額勝負になりがちな見積もりコンペでは往々にしてAが負けてしまう。
続きを書いたので参考に。
確認画面でhiddenに入力値を埋め込むのはセキュリティ的にダメか?