セキュリティについて考えてみよう

目次

セキュリティ?

Webについて勉強しているうちに「こんなものを作りたい」「あんなものを作りたい」と思ってきていることでしょう。

Facebookやtwitterのようなものを作って、友達に

「○○作ったぜ!」

とアピールしたいと考えているかもしれません。

その気持ちは非常に大事ですが、そのようなものを作るにあたってセキュリティについてしっかりと考えなければいけません。 せっかく新しいサービスを作ったのに、セキュリティ対策がなっていないがために、被害を被ってしまっては元も子もないですよね。

ここでは、先ほど作ったログインフォームについて考えて、どのような危険があるのか、またどのように対処すればいいかを考えていきたいと思います。

SQLインジェクションとは

脆弱性(ぜいじゃくせい:安全上の欠陥)にも様々な種類がありますが、ここではMySQL インジェクションについて紹介します。

SQLインジェクションって何?

SQLインジェクションとは、MySQLの仕組みを逆手に取り、意図しないSQL文が実行されてしまう脆弱性です。

例えば、さきほどのログインフォームですが、ユーザーが入力したユーザー名、パスワードは

$username = $_POST["username"];
$userpass =  $_POST["password"];

のようにして、変数に格納され、

SELECT * FROM user_info WHERE name = '$username' AND password = '$userpass';

により、ユーザーが入力したユーザー名とパスワードのペアがデータベースに存在するかどうかで ログイン可否チェックをしています。

例えば、

$username : user1
$userpass : user1

とすれば、 生成されるSQL文は以下のようなものになります。

SELECT * FROM user_info WHERE name = 'user1' AND password = 'user1';

しかし、悪意あるユーザは以下のように入力します。

$username : user1
$userpass : ' OR 'A' = 'A

すると、生成されるSQL文は以下のようなものになります。

SELECT * FROM user_info WHERE name = 'user1' AND password = '' OR 'A' = 'A';

入力値「'」を含ませることで、パスワードに関するWHERE句の条件式(password = '')を一旦終わらせます。次にORを含ませ、「'A' = 'A'」のように必ず成り立つ式を入れます。

これにより、WHERE句全体が常にとなり、正しいパスワードを入力せずにユーザー名「user1」としてログインすることが可能となってしまいます。

もしも、自分のアカウントで勝手にログインされ、勝手に書き込みをされたり、何かを削除されてしまったら大変ですよね。

以上は、SQLインジェクションの一例に過ぎません。

このように起こりうる危険に対して、何かしらの対策を講じる必要があります。

課題1

課題1-A:実際に脆弱性のあるフォームに入力してみよう

  • 脆弱性のあるフォームに入力してみて挙動を確認してみましょう。
    • ' OR 'A' = 'Aのようなユーザー名・パスワードを入れてみて、ログインできてしまうことを確認してみましょう。

課題1-B:SQLインジェクションが起こらないようにコードを追加してみよう

ソースをいじって、' OR 'A' = 'Aのような入力でログインできないように変更して下さい。

エスケープではなく、プレースホルダを用いてください。

XSSとは

XSSって何?

  • Cross Site Scriptingの略です。
  • 本来はCSSと略されるべきであるが、Cascading Style SheetsCSSと同じになり紛らわしいので、XSSと略されることがほとんどです。(https://app.codegrid.net/entry/security-xss)
  • 他人のWebサイトへ悪意のあるスクリプトを埋め込むことです。(http://viral-community.com/blog/xss-1835/)

例えば、さきほどのログインフォームですが、

ログイン失敗時に、ユーザー名: userと入力して、userと表示されていることが分かります。

ここで、ユーザー名として、

<script>alert('XSS');</script>

を入れてみるとどうなるでしょうか?

以下のようになります。

本来<script>alert('XSS');</script>と表示されるべきですが、<script>がjavascriptのタグであると認識されてしまうがために、このような挙動をしてしまいます。

ログイン後に表示されるユーザー名ならまだログインしたその人だけですが、これが掲示板のコメントだったら?そのページを見に来た人全員が任意のスクリプトが実行されてしまうことになります。

ここで書いたスクリプトはalertの中身を表示しているだけですが、これを用いてクッキー情報を抜き出して、不正ログインすることが出来たり、Webページの改ざんが出来てしまいます。

課題2

課題2-A:実際に脆弱性のあるフォームに入力してみよう

  • 脆弱性のあるフォームに入力してみて挙動を確認してみましょう。
    • ユーザー名の入力欄です

課題2-B:XSSが起こらないようにコードを追加してみよう

ソースをいじって、どんな入力もそのまま表示されるように変更して下さい。

CSRFとは

  • Cross Site Request Forgeryの略です。
  • Webサイトにスクリプトや自動転送(HTTPリダイレクト)を仕込むことによって、閲覧者に意図せず別のWebサイト上で何らかの操作(掲示板への書き込みなど)を行わせる攻撃手法です。(http://e-words.jp/w/CSRF.html)

CSRFの例

クリックしたら勝手に掲示板に書き込みしちゃってる?

以前、ある罪のない人が、あるサイトにクリックすると掲示板に勝手に書き込みがされ、誤認逮捕される事件がありました。その時の真犯人はCSRF脆弱性を利用しました。 以下にクリックしてから勝手に書き込みがされる過程を示します。

  • 真犯人がCSRF脆弱性のある(外部から書き込める掲示板やSNSなど)サイトを見つけます。
  • 「クリックしたら自動的に掲示板やSNSに定型文を書き込む」という操作をする攻撃用のページ(一見普通のページ)を作成します。
  • この攻撃用のページを真犯人はユーザーがクリックしそうな場所(2ちゃんねるとか)に置きます。
  • ユーザーがクリックすると、真犯人が用意した攻撃用のサイトにアクセスされます。一見普通のページですが、裏ではユーザーが気づかないうちに書き込みがされてしまいます。

http://www.yomiuri.co.jp/it/security/goshinjyutsu/20121026-OYT8T00824.html

CSRFの対策

  • ユーザーが出来る対策としてはクリックしないぐらいです。
  • 基本的に脆弱性のあるサイトがCSRFに対応するしかありません。