PHPでセキュリティを真面目に考える

Takuya Sato
Takuya SatoSoftware Developer
オープンソースカンファレンス2011 Hokkaido



   PHPで
 セキュリティを
 真面目に考える
               LOCAL PHP部   佐藤琢哉(nazo)
配布向け注意事項
 この資料はOSC2011Hokkaido用の45分資料を、
 配布用に再編集したものです。
 セキュリティという広いテーマを扱うのに45
 分という時間はすごく足りなく、最初から全
 てを網羅するつもりはありません。そのため、
 抜けている内容が多いと思いますが、[後で吊
 す]タグを付けたりするのはご遠慮下さい。
少   向




        •
            PHP
                  セ




                      •
な   け   基         ミ   セ   今
い   で   本   の     ナ   キ   回
か   す   的   ネ     ー   ュ   の
も   が   に   タ     と   リ   内
し   、   初   が     被   テ   容
れ   細       メ     る   ィ
    か   心             ネ
ま       者   イ     か
    い       ン         タ
せ       ~         と   で
ん   解       で     思
    説   中             他
。       級   す     っ
    は       。     た   の
        者         の
                  で
これだけ覚えて!
常に最新のPHPを使う

最新のライブラリなどを使う

正しい情報、一次情報を確認する

何も信用しない
自己紹介
佐藤琢哉
nazo
LOCAL PHP部
8月からニートフリーランス
twitter : @nazo
PHPはセキュリティに弱い?


            弱い
            弱くない
            知らない
            最強




      (nazo脳内調べ)
PHP=セキュリティに弱い
       という印象




   ※この内容は現在は修正されています。
なんでそういうイメージなの?


• 利用者が多い

 • =レベルが低い人も多い

• PHPに落とし穴が多い
うへへ、よく知らない
  から適当に
 作っちゃうZE☆



 警察の
ものです
 がー
知らないことは
 罪である
知らないことを
回避するために


 「調べられる知識」を
 付けることが重要
セキュリティの極意


  守破離
守 基礎を知る

破 基礎を実践できるようになる・
組み合わせて考えれるようになる

離 自分でセキュリティを考えられ
るようになる
…それを全て話すと終わらないので




    今回はPHPの話
PHPでセキュリティを真面目に考える
古いPHPを使うとこんなに危険!
最近見つかった脆弱性が修正されていない

脆弱性対策になる関数が入っていない

最新の脆弱性の情報が流れてこない
古いPHP+古いソフトウェアの組み
    合わせはもっと危険
特定の脆弱性を狙い撃ちにできる

BOT等でその脆弱性だけを無差別に狙う

動作しているプログラムも知られている
ため、簡単に攻撃できる
PHP本体のバグ
基本的にはそれほど多くない

きわどい使い方をするとまれにひっかかる

最新バージョンを使うことが大事

PHP4は使ってはいけない
 可能な限りPHP5.3
PHP本体のバグ 最近の例
文字列“2.2250738585072011e-308”をdouble
 にキャストするとハングアップする
  内部で無限ループになる

32bitプロセスのみで再現
$d = (double)"2.2250738585072011e-308";
PHP5.3.5/PHP5.2.17で修正済
PHPでセキュリティを真面目に考える
PHPの駄目な設定
 safe_mode=On
 register_globals=On
 magic_quotes_gpc=On
 allow_url_include=On
 allow_url_fopen=On
 error_reporting=E_ALL^E_NOTICE
safe_mode
 共用サーバー向けの設定
 名前からして、設定すると安全になりそうな風に見えるが…
 「他の人のファイル参照を難しくする」程度で、「完全に他の人の
  ファイルを参照できなくする」ことはできない。
 特に必要がない限りOFFにすべき
    自分で設定できるのであれば基本的にOFF
 PHP5.3では非推奨(E_DEPRECATED)
    PHP6では廃止予定
 http://php.net/manual/ja/ini.sect.safe-mode.php
registar_globals
 $_GETや$_POSTに入る値をグローバル変数に自動展開
 する
 グローバル変数の初期値が変わってしまうことにより、
 バグになる可能性
 外部からやりたい放題になる可能性がある
 無条件でOFFにすべき
 PHP5.3では非推奨(E_DEPRECATED)
 他のregister_xxx系も禁止
magic_quotes_gpc
 怪しい記号を¥でエスケープしてくれる
 必要がなくてもエスケープされてしまう
 漏れるケースが存在する
 無条件でOFFにすべき
 PHP5.3では非推奨(E_DEPRECATED)
 他のmagic_quotes_xxx系も禁止
allow_url_include
 include()やrequire()の対象にURLを指定できる
 プログラムのバグや、DNSの改ざんなどによって、任
 意のプログラムを読み込ませられる可能性が
 無条件でOFFにすべき
 PHP5.3では非推奨(E_DEPRECATED)
 他のallow_url_xxx系も禁止
error_reporting
なぜかE_NOTICEを切っている人が多い
思わぬバグに気づかないことが多い
ちゃんと手抜きせずに修正しよう
可能であればE_STRICTやE_DEPRECATEDも
 CMSやフレームワークによっては対応していな
  いこともあるので難しい
つまりPHP5.3がいい
危ない設定はE_DEPRECATED

ここで紹介したもの以外にも
 E_DEPRECATEDなものがある(eregなど)

エラーをちゃんと表示することが大事
よ廃   古
う墟   い




     PHP
なの
も    な
の    ん
     て
PHPでセキュリティを真面目に考える
PHPには罠のような関数が沢山
セキュリティ意識が低い時代に作られた

PHP6くらいになったら消えてほしい

少しずつE_DEPRECATED入りしている
strip_tags
HTMLタグと思われるものを削除する

誤動作する方法が沢山

絶対に使ってはいけない

htmlspecialcharsを使おう(詳しくは後で)
addslashes
 文字列をクオートする
 DBにデータを入れる時に使いたくなる
 実際には各RDBMSによって特殊な挙動があるため、
 脆弱性に繋がる可能性がある
 MySQLならmysql_real_escape_string、PostgreSQLな
 らpg_escape_stringを使用すべき
htmlspecialcharsと文字コード
 htmlspecialcharsの正しい使い方

htmlspecialchars($var, ENT_QUOTES,
 'UTF-8');
 ENT_QUOTESを指定しないとシングルクオートが変
 換されない
 文字コードを指定しないと、文字コードに起因する
 変換漏れが発生する
文字コード?
Shift_JISで「表」は0x955C

0x5C=¥

0x955Cを、0x95と0x5Cで別々に処理する
 関数の場合、0x5C=¥記号を何らかの特殊
 記号と判定されてしまう可能性がある
<?php
// 「表」をSJISにする
$a = mb_convert_encoding('表', 'SJIS-win',
'UTF-8');
// addslashesでエスケープ
$b = addslashes($a);
// UTF-8に戻す
$c = mb_convert_encoding($b, 'UTF-8', 'SJIS-
win');
//出力
var_dump($c);


=> string(4) "表¥"
htmlspecialcharsと文字コード
 htmlspcialcharsの例はまた別
 詳細はhttp://www.tokumaru.org/d/20090930.html
   「htmlspecialchars 文字コード」とかでぐぐれ

 PHP5.2.5から、不正な文字エンコーディングをチェッ
 クするようになった
 それ以前だと意味のない指定なので、必ず最新の
 PHPを
そもそもShift_JISは使うな
 0x5C(¥)が文字コードに含まれるため危険
 Shift_JIS以外だから安全だというわけではないが、
 危険要素の多い文字コードなので避けるべき
 そもそもUTF-8でほとんどの場合は十分
 携帯サイトで出力にShift_JISが要求される場合は、
 内部はUTF-8で処理し、入出力時にShift_JISで変換
 するのが望ましい
先行バイトによる問題
マルチバイト文字コードの1バイト目だけ
を不正に出力することで、それ以降の文字
をマルチバイト文字の一部として認識さ
せ、本来の役割を破棄させることができる
ブラウザ側で対応されていることが多い
(IE6とかはアウト)
文字コードとPHP
文字コードを考慮されていない関数は危
 険

ereg,fgetcsv,addslashes,strlen,etc…

正規表現はpregを、mb_xxxがある関数は
 mb_xxxを使用すべき
標準関数だからといって
安心してはいけない


必ず公式ドキュメントなどで
確認を
PHPでセキュリティを真面目に考える
SQLインジェクションとは
本来正常に実行されるSQL文に、不正なコー
 ドを挿入することによって、本来意図しな
 いSQL文を実行し、攻撃する攻撃方法
何かの文にDROP DATABASE xxx;とか追加し
 て、全データ削除したりとか
他人のパスワードを不正に取得したり
SQLインジェクションの種類
本来1つであるSQL文に、2つ目のSQLを追加
 して、任意のSQLを実行させる
1つのSQLのパラメータ指定に、本来指定で
 きないパラメータを指定させることによ
 り、意図しないデータを取得したり操作し
 たりする
PHPとSQLインジェクション
任意のSQLを挿入できるか?


$sql = 'SELECT * FROM   hoge WHERE foo = $foo';
$foo = '; DELETE   FROM hoge;';


// ここでSQL実行
mysql_query … できない

mysqli_query … できない

pg_query … できる

PDOStatement::execute … できない
問題なSQLインジェクション
例えばSELECT文に穴があってパスワードを
入手できたりとか

例えばDELETE文に穴があって全データ削除
できたりとか
回避方法
 プレースホルダが利用可能な場面では、極力
プレースホルダを使用する
 プレースホルダを使えない場面で、なるべく
文字列結合で値を渡さないようにする
 どうしても文字列結合で値を渡す必要がある
場合は、各DBMSに対応するエスケープ関数で
適切にエスケープする
プレースホルダ
$sql = 'SELECT * FROM hoge WHERE foo = ?;'

$stmt = $mysqli->prepare($sql);

$stmt->bind_param('s', $foo);

$stmt->execute( );
エスケープ関数で
$sql = 'SELECT * FROM hoge WHERE foo = %s;'

$new_sql = sprintf($sql, $mysqli-
>real_escape_string($foo));

$mysqli->query($new_sql);
テーブル名は特に危険
$sql = 'SELECT * FROM %s WHERE foo = 1;'

$new_sql = sprintf($sql, $foo);

$mysqli->query($new_sql);



// テーブル名なので'hoge'という指定はできない

// $foo に "hoge INNER JOIN …"とか入ると…?
DBMSと文字コード
不正な文字コードを入れることによって変
 なことをさせる攻撃はDBMSにも存在する

mysqlはUTF-8が3byteまでしか入らない(5.5
 で対応済)
MySQLのUTF-8
 ������ や ������ といった文字が入らない
 入れようとするとwarningになるが、空として入る
 (errorにはならない)
 例えばPHP側で入力チェックをして正常に通過して
 も、MySQL側には空文字として入ってしまう、という
 ことになる
 文字チェックはDB側で行うことが必要
SQLインジェクションは
大規模な漏洩事件に
繋がりやすい
PHPは関係ないので概要だけ
ケータイサイトを馬鹿にするな
基本的には普通のサイトと同じ
ケータイからソースが見えなくてもURLが
見えなくても、実際には同じ
PCサイトと同じレベルのチェックが必要
 PCサイトより大変な部分も多い
 特に最近はJavaScriptも使える
IPアドレスで
   制限しておけば
    余裕だぜー




いや他にも
 脆弱性は
 あるし…

しかもそのIPアドレスリストちゃんと更新してる?
URLからのセッション乗っ取り
Cookieが使えないケータイブラウザでは、
 セッションIDをURLにつけてやりとりする
 ことが多い
外部サイトに飛ぶと、refererでセッション
 IDが漏れる
そのセッションIDで接続すると…
URLからのセッション乗っ取り:対策
 できるだけCookieを使う
 セッションの有効期限を短めにする
 外部サイトに飛ぶ場合は、必ず1ページ挟み、そこでは
  セッションIDは消す
 検索エンジンに登録させない・登録させる場合は、
  canonical urlを指定する
 <link rel="canonical" href="http://example.com"/>
かんたんログインも怖い
ちょっとのミスで攻撃方法が多数

「限りなく防ぐ」方法は存在するが、「完璧に
 防ぐ」方法は存在しない

Cookieが使用可能であれば極力Cookieを使
 用すべき
か盗個ち
もま人ょ
しれ情っ
れて報と
ないがし
いる た
   ミ
   ス
   で
PHPでセキュリティを真面目に考える
既存のものを使うということ
 「それなりに」信頼性がある
 特によく使われていて頻繁に更新されているもの
  ほど、安全性が高い(可能性が高い)

 特にフレームワーク、CMSは、基礎的な脆弱性が
 起こらないような作りになっていることが多
 く、下手に自作するよりは安全なことが多い
しかし
使い方を間違えれば脆弱性が生まれる

最新のものを使わないと脆弱性が残ってい
る可能性がある
 特にCMSは、見た目で何を使っているかわかりや
 すいので、バージョンアップを怠ると狙われや
 すい
何が言いたいのか
 ライブラリやフレームワークなどは、ちゃんと
 メンテされているものであれば、(検証した上
 で)積極的に使おう
 バージョンアップされている場合は、(検証し
 た上で)対応していこう
 ライブラリやフレームワークを過度に信用せ
 ず、セキュリティチェックは必ず行おう
CakePHPの
securityコンポーネントにも
脆弱性があった
時代がありました
脆弱性以前の問題
 パスワードはちゃんと設定してますか?

 CMSやアプリの管理画面のURLはみんな知って
 る

 パスワードが簡単だと簡単に入られてしまう

 管理画面はIPアドレス制限、BASIC認証などで、
 直接見られなくしておいたほうがいい
PHPでセキュリティを真面目に考える
セキュリティに終わりはない
いつ新しい攻撃方法が発見されるかわか
らない

コンピュータの進化によって不可能が可能
になる場合も
 暗号とか
セキュリティ情報を追い続ける
致命的な脆弱性にすぐ対応できるように

→自分のサイトを守るために

→みんなの個人情報を守るために
今回話せなかった内容
XSS(クロスサイトスクリプティング)

セッション関係

CSRF

PHPと関係ない話

その他いろいろ
バグと脆弱性の境界
脆弱性の根本はバグ
バグ=脆弱性 ではない
バグのないプログラムのほうが脆弱性が
少ない可能性が高い
テストなどの、バグを減らすための手法も
実践すべき
バグが出ても…
 エラーは画面に表示しない!
 display_errors=OFF
 開発中はONにしよう
 バグがないことが当然だが、最悪の場合のた
 め
  MySQLが突然死した時にうっかりパスワードが見
     えたりとか
セキュリティ情報の探し方
php.net
  コピーサイトは見ない

JPCERT/CC
技術系ニュースサイト
 (slashdot,gihyo,@IT,etc…)
その他個人ブログなど
とてもいい情報
 gihyo.jp「なぜPHPアプリにセキュリティ
 ホールが多いのか?」
   http://gihyo.jp/dev/serial/01/php-security
 IPA「安全なウェブサイトの作り方」
   http://www.ipa.go.jp/security/vuln/websecu
    rity.html
 書籍「体系的に学ぶ 安全なWebアプリケー
 ションの作り方」
でも情報を探すのとか難しい
札幌でー

セキュリティのー

勉強会とかー

ないかなー
そうだ、せきゅぽろに参加しよう




 北海道情報セキュリティ勉強会 (通称:せきゅぽろ)
 http://secpolo.techtalk.jp/
PHPでセキュリティを真面目に考える
LOCAL PHP部 参加者募集中!
隔月で勉強会をしています
 次回は8月予定

特に内容にこだわりはないので、「これを知
 りたい」とか教えてくれれば誰かが用意し
 てくれるかもしれません
詳しくは「LOCAL PHP部」で検索!
画像提供(全てCC)

 http://www.flickr.com/photos/posteriormente/501245300
  6/
 http://www.flickr.com/photos/weightlifting/5065942769/
 http://www.flickr.com/photos/kentamabuchi/4616039938/
 http://www.flickr.com/photos/8mitsu/142336481/
 http://www.flickr.com/photos/sotome/2229496414/
1 of 80

More Related Content

What's hot(20)

ECMAScript没proposal追悼式ECMAScript没proposal追悼式
ECMAScript没proposal追悼式
京大 マイコンクラブ17.2K views
H2O and phpH2O and php
H2O and php
Junichi Ishida5K views
8時間耐久 PHP構築の教室8時間耐久 PHP構築の教室
8時間耐久 PHP構築の教室
Yusuke Ando4.1K views
Behat Driven DevelopmentBehat Driven Development
Behat Driven Development
Ryo Tomidokoro13.8K views

Similar to PHPでセキュリティを真面目に考える(20)

PHP With Windows binaryPHP With Windows binary
PHP With Windows binary
Masahiko Sakamoto6.7K views
2009年のPHPフレームワーク2009年のPHPフレームワーク
2009年のPHPフレームワーク
Takuya Sato3.1K views
徳丸本ができるまで徳丸本ができるまで
徳丸本ができるまで
Hiroshi Tokumaru4.9K views
Phpcon tokyo 20120_bigginerPhpcon tokyo 20120_bigginer
Phpcon tokyo 20120_bigginer
Hideo Kashioka251 views
PHPとJavaScriptの噺PHPとJavaScriptの噺
PHPとJavaScriptの噺
Shogo Kawahara17K views

More from Takuya Sato(11)

PHPでセキュリティを真面目に考える