攻撃のメカニズムを理解することは、強靭な防御につながります。
ということでメジャーすぎて今更な攻撃についてまとめてみます。





■ CSRF(XSRF)という攻撃


会員がログインして使うようなサイト(仮にサイトAとします)では、ログイン中である情報(セッションID)をクッキーに持たせる場合が多い。
ログイン認証が成功すれば、一旦どこか他のサイトBを見てきた後でも再びサイトAに戻れば今度はログインの手続き抜きに自分の管理ページなどをいきなり見ることができてとても便利です。


こうしたサイトはログイン中であればどの会員でも、登録情報の更新や会員用に用意された書き込みなどが自由にできる便利な作りになっていたりします。



つまり書き込みが出来る条件は、ログイン中(セッションIDを保持している)であるということだけです。



そんな中まったく別のサイトCに、サイトAの更新を自動的に行うスクリプトが埋め込まれていたとします。
そしてたまたまサイトCを訪れた人がサイトAログイン中であった場合に、スクリプトが勝手にサイトAの更新処理を進めてしまう過程で正規のセッションIDも送ってしまうので、更新処理が最終段階まで行く可能性が考えられます。
なので一体なにが起こったのか原因を特定するまでに時間がかかると思います。



□ ユーザ側の防衛策


これを防ぐために会員の方でできることは、他サイトに行く前にクッキーを消すことぐらいです。
どちらかというとこれは会員よりもサイトのシステム設計の問題なので防ぐ対策がサーバ側には必要です。



□ サーバ側の防衛策


ログイン中であっても情報更新の際はIDとパスワード入力を強制する。


特定URLへのセッション情報送信だけでいきなり更新確定させないで、間に確認画面をワンクッション置いてそこにワンタイムトークンを発行しておき、最後にワンタイムトークンが正規のものかをチェックしてから更新確定させる。





■ XSS(CSS)という攻撃


HTMLタグの入力がそのままタグとして反映される作りになっているサイトがあった場合、何らかの意図しない処理を実行するスクリプトを埋め込むことができてしまいます。
つまりHTMLタグを使ってでできることはなんでもできることになります。



まず考えられるのはそこがもしクッキーを使ってセッション管理しているサイトの場合、クッキーを他サーバに送って盗まれることによるセッションハイジャックがあります。
その他、いきなりダメージ(PC的・精神的)を与えるサイトに飛ばされる場合もあります。


あとは先ほどのCSRFにつながるスクリプトを埋め込まれる場合も考えられます。
他にはそのページそっくりの画面(フィッシングサイト)に切り替えられて、気づかないでそこに入力した情報が盗まれたり、ボタンを押した瞬間他サイトを攻撃し出したり様々なことができてしまうでしょう。



□ ユーザ側の防衛策


HTMLタグがそのまま反映されるサイトには近づかない。


PC的なダメージの場合はブラウザを素早く閉じる訓練を積む。
精神的ダメージの場合は表示される前に目を閉じる訓練を積む。見慣れる。


CSRFの場合は先ほど同様、クッキーを小まめに消す。


そっくりの画面に誘導された場合は被害が広からないようにサイト管理人に知らせましょう。
HTMLタグがそのまま反映されてしまう時点で管理人に知らせるのはいずれの場合も必要ですね。



□ サーバ側の防衛策


入力されてきたものはそのまま表示させない。
必ず表示に反映されるデータは「< ⇒ &lt;」「> ⇒ &gt;」「& ⇒ &amp;」「" ⇒ &quot;」のエンティティ変換を行う。





■ SQLインジェクションという攻撃


インジェクションとは、注入という意味 ドドスコ

想定外の入力がされてそれがプログラムに害を及ぼす攻撃法をインジェクション攻撃と言います。

ユーザ側から送られてきた値(GET POST COOKIE サーバ変数などの情報)でデータベース操作を行う場合に、適切にエスケープがされてないと引き起こされる可能性があります。


例えば以下のSQL文がシステム内で使われていたとします。


$sql = "SELECT * FROM tablename WHERE foo = '{$_POST['foo']}'";

このときもしfooに「' OR 'x' = 'x」と入力されてしまうと、


$sql = "SELECT * FROM tablename WHERE foo = '' OR 'x' = 'x'";

と展開されてしまい、SQL文の条件が常に真となる。



$sql = "SELECT * FROM userinfo WHERE id ='{$_POST['id']}' AND password='{$_POST['password']}'";

もしpasswordに「' OR 'id' = 'other」が入力されてしまうと


$sql = "SELECT * FROM userinfo WHERE (id ='username' AND password='') OR 'id' = 'other'";

このような意味になり、otherというIDのユーザがいればその情報が検索されてしまうことになる。


更新の場合もユーザ入力で更新対象が常に真となる条件にされれば、全レコードの値を更新されてしまう。


UPDATE userinfo SET password = 'dodosuko' WHERE id = '' OR 'x' = 'x';



□ 防衛策


適切なSQLエスケープを施すか、プリペアドステートメントみたいなエスケープを自動的に施してくれる方法を使う。





要するに、セッション中はセッションIDだけで一気に確定までできてしまう作りにしないようにして、ユーザ入力値はすべてバリデーション(検証)を行い、SQLに渡す入力値は確実にエスケープを行い、画面表示に反映される入力値は表示させる時にサニタイズ(無毒化)しましょうというお話でした。