読者です 読者をやめる 読者になる 読者になる

なおすけの落書き帳

てきとーに。

SLP KBIT AdventCalendar2014 @3日目

なんこれ

この記事はSLP KBIT AdventCalendar2014 3日目の記事です。 何書こうか悩みながら書いてます。

まえがき

ネタが思い浮かばないんで1年生置いてきぼりな記事書いてます。
スマソ

本題

何について書こうか考えた結果、いろいろな脆弱性について書こうと思います。
まあ、XSSSQLインジェクションとかその辺程度。

脆弱性

脆弱性って言葉、多分皆さん聞いたことがあると思います。
意味を調べるとこんなことが書いてありました。

一般的には「脆くて弱い性質または性格」のことをさす。vulnerability。
コンピュータ用語としては、現在では、コンピュータやソフトウェア、ネットワークなどが抱える保安上の弱点のことを指すことがほとんどであり、
正規の管理者や利用者など以外の第三者が保安上の脅威となる行為(システムの乗っ取りや機密情報の漏洩など)に
利用できる可能性のある欠陥や仕様上の問題点のこと。
新聞などでは「ぜい弱性」と表記されることもある。

はてなキーワード
まあこんなかんじです。

で、これが何

CGIとかかいてると、formタグをつかって入力を受け付けたり、SQLをつかってデータを色々格納したりすることがあると思います。
で、何も考えずにやってると痛い目見てしまうってのが今日の話。
まあ、何個か紹介しようと思います。

脆弱性のいろいろ

XSS

なんそれ

いきなりアルファベット3文字! 正式名称はクロスサイトスクリプティングといいます。
XSSとは、他人のWebサイトへ悪意のあるスクリプトを埋め込むことです。
「悪意のあるスクリプトを埋め込むってどういうこっちゃ」という感じですが…。

実際にやってみた

じゃあ、実例を示してみましょう。
あるPHPのプログラムを利用します。

<html>
<body>
    <form action="" method="post" accept-charset="utf-8">
        <input type="text" name="xss_text" value="">
        <p><input type="submit" value="submit"></p>
    </form>
    value: <?php echo $_POST['xss_text']; ?>
</body>
</html>

まあこれを表示するとこんな感じ。
入力をそのまま出力する簡単なPHPプログラムです。

f:id:naosuke2dx:20141203002738p:plain

で、この入力にこんな文字列を入れてみると… <script>alert('XSS');</script>

f:id:naosuke2dx:20141203002743p:plain

こんなふうにスクリプトが実行されてしまいます。 value移行の、<?php ~~~ ?>で、入力を表示させていますが、ここに入力した<script>~</script>が埋め込まれているわけですね。
<script>タグって、JavaScriptのアレですよね。
JavaScriptって意外となんでも出来て、掲示板のリンクになんか仕込んでやると、セッションハイジャックやパスワードの流出などが割りとできちゃうわけです。
ね、怖いでしょ。

対策法

タグに使われる<>などを&lt;&gt;に置換するって方法があります。
他には、タグの属性値を"~"で囲むなど、そういう方法が必要です。

SQLインジェクション

なんそれ

データベースの管理システムに、リレーショナルデータベース管理システム(RDBMS)というものがあります。
RDBMSにおいて、データの操作や定義を行う問い合わせ言語をSQLって言います。
SELECT * FROM table;みたいなこんなやつです。1年生わかるかな…。

で、SQLインジェクションとは、アプリケーションが想定していないSQL文を実行することによって、データベースを不正に操作する攻撃手法です。
SQLに別のSQLを注入(inject)されるため、SQLインジェクションって呼ばれます。
ちなみに、このSQLインジェクション、2011年4月から発生しているPlayStation Networkの個人情報漏洩の原因だったりします。

実際にやってみた

と思ったのですが、昔授業で作った脆弱性満載のPHPプログラムが見つからなかったので、口頭解説

例えば、フォームから受け取った値から、以下のSQL文を実行することを考えます。
SELECT * FROM users WHERE name = '(入力値)';
簡単な説明をすると、usersテーブルから、入力値に一致したユーザを表示するというSQL文です。
これは、WHERE以降のname = '(入力値)'がtrueのとき、ユーザが一致したというふうに認識します。

じゃあここで、入力値にt' OR 't' = 'tという入力値を与えてやるとどうなるでしょう…。
WHERE以降はこんなふうになります。
WHERE name = 't' OR 't' = 't';
さっき、WHERE以降がtrueのとき、ユーザが一致したという認識をする、と書きましたが、今回のSQL文はどうでしょう。
WHERE以降は常にtrueになってますね。
C風に書くと

if ( name == 't' || 't' == 't') {
  printf("%s\n", users);
}

みたいな。
まあifの条件式が常にtrueになっちゃってますね。
つまり、usersテーブルに格納されているすべてのデータが引っ張ってこれるわけですよ。
もしusersテーブルにパスワードとか住所とかが格納されていたら…どうなるでしょうね。

対策方法

まあ、文字のエスケープが一般的ですね。
他にはO/Rマッピングと呼ばれる方法をつかうのもひとつの手です。

紹介しないけど

などなど。気になる人は調べてください。

まとめ

脆弱性こわいから、アプリケーション書くときは気をつけましょう。


参考文献 - XSS脆弱性のあるPHPコード簡易サンプル