2015.12.13
0からはじめるPHP#62【セキュリティを学ぶ#3-その他セキュリティまとめ-】
もはや掲示板とは関係ない話になってるのでサブタイトル変えました。(笑)
今回もエラーについて云々垂れようと思ったのですが、僕自身そんなに深い造詣がなく、もはや言うことがないことに気づいてしまったので、最後のセキュリティ対策、とします。
といっても、実は掲示板には関係ないことが多いですが、大事な話だと思うので個人的にまとめてみます。
まず、というか終始
PHP Web アプリケーションセキュリティ対策の良スライドまとめというページを見ることになるのですが、少なくともここに挙げられている知識をインプットしておけば大丈夫かなとは思います。
CSRF、XSS、SQLインジェクションなんかは今までに散々やってきましたね。
・CSRF(クロスサイトリクエストフォージェリ)
概要:FORMのACTIONがクロスドメインで指定できることによる、不正なフォーム送信
対策:トークン
Laravelでは・・・・・・デフォルトでCSRF対策トークンが入ってるので考慮しなくても良さそう。
・XSS(クロスサイトスプリクティング)
概要:被害者のブラウザ上で攻撃者が自由にJavascriptを実行できる。
対策:HTMLエスケープ 属性値はダブルクオートで囲む htmlspecialcharasの第三引数はなるべく指定する
Laravelでは・・・・・・ビューでは特に何もしなければHTMLエスケープはされるはず。ただし自前でechoする場合はきちんとエスケープすること。
・SQLインジェクション
概要:文字列連結によるSQL文の誤動作を狙って任意の命令を実行させる。
対策:プレーズホルダ 列の型を意識
Laravelでは・・・・・・無視してOK。生で書く際はプレースホルダを使う。
まぁ大体こんな感じです。太字にしたところは僕が今まで意識したことなかったものです。
ちなみに僕の作った掲示板では
普通にXSS脆弱性が存在していました。危ない。ヒアドキュメントで出力してたのですっかり対策を忘れていました。危ない。
ここで挙げたのがWebアプリケーションの脆弱性対策の基本ですが、他にもいろいろあるんですね。
・HTTPヘッダインジェクション
概要:改行による不正なレスポンスヘッダ出力
対策:PHPのバージョン(PHP5.3.10以降)
Laravelでは・・・・・・たぶんフレームワークとは無関係だから大丈夫。
変なリンクを生成させて不正なスクリプトを実行させるものですね。このサイトのPHPのバージョンは5.5だったかな。なのでたぶん大丈夫です。
・セッション固定
概要:他人の(もしくは用意したものを他人に使わせた)セッションIDを使って不正ログインをする
対策:ログイン直後にセッションIDを変更する
Laravelでは・・・・・・対策しないとたぶん詰みそう
セッションIDでログイン状態を判別しているのであれば、そのセッションIDを使うと
ログイン画面を通さずともログインしてることになるんですよ。
つまり、他人にログインさせて、そのログインした状態で別のPCからアクセスするって感じですね。こいつは割とマズい。
ただ、異なるマシンで行われるものなので、ログインが終わったらセッションIDを変えちゃえばいいわけですね。Laravelでは
$request->session()->regenerate();を実行するだけで再生成できるみたいです。
やっぱフレームワークってラクですね。
・ログイン前セッションフィクセイション(SSLを使う場合や、セッションIDを外部から強制できる場合)
概要:セッション固定と似たようなもの
対策:セッション情報に秘密情報をセットする時はIDを振り直す ログイン前にはセッションを開始しないでhiddenパラメータを使う
Laravelでは・・・・・・知らん
主にSSLを使っている場合の脆弱性になります。Laravelの認証システムはどういう仕組みなのかは今調べるのはしんどいので、使う時にまた考えましょう。←
なんでSSLだけ?ってのが実はよく分からないんですが、図を見る限り
http://でもアクセスできるのが問題だと思うので、SSLを使う場合はリダイレクトして制限した方が良いのかも知れません。
が、いくらでも抜け道があると想定して、対策に挙げたようなことをやっておくと良いかなと。分かんないところはとりあえず飛ばしましょう。後でやる機会はいくらでもありますし・・・・・・。
ちなみに、URLからのセッション乗っ取り対策として
できるだけCookieを使うなどが挙げられています。
他にも、
外部サイトに飛ぶ時はセッションIDを消すために1ページ挟むとか
canonicalurlを指定するとかですね。
もうとにかく、可能である限りCookie使え、と。サーバー側にデータを残すな、と。
ちなみに、この記事を読んでこのサイトのトップページにもcanonicalurlを設定し、www有り、index.php有りでアクセスした場合は301リダイレクトするように.htaccsessを設定したりしました。
別に当サイトにセキュリティが必要なところは実はないんですけど(笑)将来への布石というかなんというか。
あと、
パスワードについても面白い事項が挙げられてます。
・パスワード解読or突破
概要:読んで字の如く
対策:ソルト ハッシュ ストレッチング
Laravelでは・・・・・・Laravelは関係ない
ハッシュにすると
平文復元が不可能という特性があるため、鍵管理の必要性がなくなり安全性は高まります。ただしパスワードリマインダが使えなくなるという問題があります。
ソルトってのは、パスワードにさらに付与する値のことで
パスワードの見た目上の長さを長くするという効果を持ちます。これでレインボーテーブルやブルートフォースアタックに対する耐性がつきますね。重要なのは、ユーザー毎に異なる値を用いることです。別にこれは機密情報じゃないのでハッシュ値と一緒に保存しちゃって大丈夫のようです。
ハッシュを用いたパスワード管理はまだ手を出したことがないので、次に認証を用いる時に考えてみると楽しそうですね。
本当は怖いパスワードの話ってとこにまとまってるんで、興味あればこちらで大体わかります。
まぁセキュリティ対策としてはこんなもんですかね。めちゃくちゃ知識量が増えた気がしますね。
認証機能が必要なプロダクト開発は次にいつするかは不明ですが、必要になった時こういう知識を参照して制作したいところですね。
あと
mysqli_real_escape_string()という関数があります。これは、SQL文で使用する文字列の特殊文字をエスケープするものです。
でもLaravelはその辺を勝手にやってくれるっぽいので、なんもしなくても良さそう・・・・・・?
最後に・・・・・・積極的にtryとcatch使いましょう。というか、積極的にエラー投げましょう。
個人的に、プログラム全体をtryでくくって、随時エラーを投げてエラー処理は最後のcatchでまとめて行う、ってのがスマートな気がしてるんですが、どうなんでしょうね。
あ、ちなみに今日ハマったPHPという言語の話にも少し触れておきます。
foreachでオブジェクトを回す時の話です。
foreach($d as $key => $value){
$value=h($value);
}
これ動かないんですよね。
いや、動くんですけど、元々のオブジェクト、つまり$dに影響がないんですね。
ここで分かるのはforeachのキー=>値って
参照じゃなくてクローンになってるんですよ。
foreach($d as $key => $value){
$d->$key=h($value);
}
正解はこうです。こうすることで元々のオブジェクトの中身をいじくれます。
foreachは読み替えだと思ってたんですが、実はそうじゃなくオブジェクトの場合はクローンを作っちゃうようです。なるほど。
こんなとこでハマらないように皆さんもお気をつけください。(笑)