Forkwell Press

SHARE

徳丸浩
Event report

フレームワークで脆弱性対策されているのに現実のアプリケーションに脆弱性が減らないワケ 徳丸 浩

エンジニアに役立つ情報を定期的にお届けします。

── ソフトウェアセキュリティの「つぎの一歩が見つかる、気づきと学びの場」 Security Studyシリーズ。 年々増加する不正アクセスや情報漏洩等のセキュリティインシデント。セキュリティ意識はありとあらゆるサービスで求められています。今回は、セキュリティに関する思想や向き合い方、具体的な技術論まで幅広く学びます。

登壇者紹介

徳丸 浩

EGセキュアソリューションズ株式会社 取締役CTO

1985年京セラ株式会社に入社後、ソフトウェアの開発、企画に従事。1999年に携帯電話向け認証課金基盤の方式設計を担当したことをきっかけにWebアプリケーションのセキュリティに興味を持つ。2004年同分野を事業化。2008年独立して、Webアプリケーションセキュリティを専門分野とするHASHコンサルティング株式会社(現EGセキュアソリューションズ株式会社)を設立。脆弱性診断やコンサルティング業務のかたわら、ブログや勉強会などを通じてセキュリティの啓蒙活動をおこなう。

「フレームワークで脆弱性対策されているのに現実のアプリケーションに脆弱性が減らないワケ」 

本日のテーマは「フレームワークでは脆弱性を担保する素晴らしい機能があるのにどうして脆弱性が残ってしまうのか?」です。先に答えを言ってしまうと、勝手に安全になるものと、フレームワークでは担保されておらず、開発者自身が意識しないといけないものがあるからです。開発者が意識すべき脆弱性を見ていきましょう。

『よくわかるPHPの教科書』を検証してみる

『よくわかるPHPの教科書』で紹介されているソースコードの一部を実際にデモで動かしてみます。

// ここまでで、認証済みであるこの検査が済んでいる
$id = $_REQUEST['id'];
// 投稿を検査する
$sql = sprintf('SELECT * FROM posts WHERE id=%d',
mysql_real_escape_string($id));
$record = mysql_query($sql) or die(mysql_error());
$table = mysql_fetch_assoc($record);
if ($table['member_id'] == $_SESSION['id']) { // 投稿者の確認
// 投稿した本人であれば、削除
mysql_query('DELETE FROM posts WHERE id=' .
mysql_real_escape_string($id)) or die(mysql_error()); }

【検証1】パスワード保存の安全性を検証してみる

  1. 用意したログイン画面にメールアドレスを入れます
  2. パスワードを「pas123」と入れます
  3. 「次回からは自動的にログインする」にチェックを入れます
  4. ログインしてみます

【結果】設定したパスワードが平文でCookieに保存されている

はい、ご覧ください。開発者ツールに先ほど設定したパスワードが平文でCookieに保存されています。

これは 徳丸本 に書いてあるダメな例です。

security-study1-01

【検証2】別人の投稿を削除してみる

ひとこと掲示板に削除ボタンがありますので、これを今から悪用してみます。「佐藤」でログインしている私が、すぐ下に投稿している徳丸さんの投稿を削除してみます。

security-study1-02

【結果】別人の投稿でも簡単に削除できてしまう

リンクをコピーし末尾を「id=91」と指定してみると 投稿は消えません。今度は末尾の引数を「id=92-1」と指定してみます。すると id91徳丸さんの投稿が消えました。

security-study1-03

なぜでしょうか?

下記はsprintf書式を%dで打っているので92-1が変換されて92だけが残ります。

$sql = sprintf('SELECT * FROM posts WHERE id=%d',
mysql_real_escape_string($id));

こちらはsprintfでも%dでもないので92-1がそのまま入ります。

mysql_query('DELETE FROM posts WHERE id=' .
mysql_real_escape_string($id)) or die(mysql_error());

下記のスライドで詳細を解説しています。

『いきなりはじめるPHP』を検証してみる

次は『いきなりはじめるPHP』ですが、こちらも大変よく売れているPHP入門書です。下記のコードはアンケート投稿の部分です。ポストパラメータを取り出し、それをHTMLエスケープしてインサートしています。prepareをexecuteしてるんですがプレースホルダを使ってないのでSQLインジェクションとなります。

security-study1-05

『いきなりはじめるPHP』のココが問題

SQLインジェクションがあるのは重大な点ですが、ここではひとまず置いておきます。何が問題かというと、インサートする前にHTMLエスケープしてるんですね。これはおかしいです。表示の際にやるべきです。しかし類似例はPHP入門書には極めて多いです。

■SQL呼び出しにプレースホルダを用いていない
□その結果SQLインジェクション脆弱性がある
■HTMLエスケープの場所がおかしい
□入力値を直ちにエスケープしてそのままINSERTしている
□本来は生データをINSERTして、表示の際にHTMLエスケープすべき
□類似例はPHP入門書には極めて多い
■これらの問題はアプリケーションフレームワークを使うことにより解決できる
□コントローラでHTMLエスケープする人いないでしょ
□SQLの問題はORマッパーやクエリビルダで解決できる

そこでアプリケーションフレームワークですよ!

security-study1-06

フレームワークとSQLインジェクション

フレームワークといえば Ruby on Rails を思い浮かべる方が多いと思いますが、 Ruby on Rails を正しく使っていればSQLインジェクションは防げます。 

Ruby on RailsのNG例を3パターン紹介

Ruby on Rails を使っているのにSQLインジェクションがある場合は、間違った使い方をしています。

NG例1:whereメソッドの引数に値を埋め込んでいる

@books = Book.where("price >= #{params[:price]}")

▲whereメソッド(where句を書けるメソッド)がありますが、ここに外部由来の値をそのまま埋め込んでしまってるという素朴な例です。意外なことに脆弱性診断などで結構この例を見かけます。

NG例2:演算子として外部パラメータを埋め込み

@books = Book.where("price #{params[:op]} ?", params[:price])

NG例3:orderメソッドに外部パラメータを指定(最新のRailsでは対策されている模様)

@books = order ? Book.order(params[:order])

LaravelのEloquent / クエリビルダー は基本的に堅牢

Laravelにもwhereメソッドがあります。呼び出し方は Ruby on Rails と違い、列名、比較演算子、値の形になっており、これは非常に堅牢です。

$tasks = Task::where('kind', '=', $kind)->get();

▲プレースホルダでSQLインジェクション対策されている

$tasks = Task::where('kind = 1 or 1=1#', '=', $kind)->get();

▲列名を攻撃しようとしても、Column not found というエラーになる

$tasks = Task::where('kind', '=1 OR true# ', $kind)->get();

▲比較演算子を攻撃しようとしても、kind = ‘=1 OR true#’と解釈される

Laravel(Eloquent)のwhereRawメソッドの用途と注意点

Laravelは非常に堅いのですが(列名、比較演算子、値)で記述できないパターンもあります。その場合は、whereRawメソッドを使用しましょう。

Laravelを使っているのにSQLインジェクションがある場合

whereRaw等を用いる場合は、 Ruby on Rails と同様にプレイスホルダを用いましょう。

NG

$tasks = Task::whereRaw("kind = BINARY '$kind'")->get();

OK

$tasks = Task::whereRaw("kind = BINARY ?", [$kind])->get();

フレームワークとクロスサイトスクリプティング(XSS)

ここからは、やや上級者向けです。ぜひ動画をご覧ください。

XSSについてのまとめ

  • • XSS対策はとにかくややこしい
    • 「ややこしくない」と思っている貴方、危険かも?
    • 特にHTMLの中にJavaScriptが入っている場合、エスケープ処理を二重に行う必要がある
    • いまだに盛大に脆弱性が入る
  • SPAは、HTML、JavaScript、データ(JSON)が明確に分離されるので安全性を担保しやすい…はず
  • とにかくinnerHTMLを避けること
  • HTMLタグを有効にして表示する処理は難易度が高いので、慎重に設計すること

フレームワークと認可制御 / CSRF

総まとめ

アプリケーションフレームワーク

セキュリティ機能が組み込まれている

SQLインジェクション

単純なケースでは「なにもしなくても」対応される物が多い。一方、複雑なクエリについてはSQLインジェクションが入る余地があり、実際混入するケースが見られる

クロスサイトスクリプティング(XSS)

最近のフレームワークは自動エスケープが多いが手動(CakePHP等)もある

CSRF

フレームワークの機能を正しく設定するだけ

その他

フレームワークが全てのケースで対応してくれるわけではない

開発者が自覚的に対応し、テストで確認することが重要

EGセキュアソリューションズ株式会社

ゆりかごから運ぶ墓場まで、Webセキュリティ全般に対応しています。

最重要の企画段階のコンサルティングや開発の段階のレビュー、開発ガイドライン作成、トレーニング、開発終了のテスト試験など幅広くサービスを提供しています。最近は脆弱性診断を自分で実施したいという要望にもお答えしております。こちらのWebサイトで導入事例を公開しているので、ぜひご覧ください。

security-study1-09

講習サービスの特徴:柔軟なカスタマイズ

security-study1-10

本日はフレームワークを使ったアプリのセキュリティがテーマでしたが、やはり開発者が自覚的にセキュリティを考えないといけません。EGセキュアソリューションズ株式会社では、詳細なヒアリングを基に、受講者の理解度に合わせた講習を実施可能です。そのため、講習の成果をよりその後の実務に活かしていただけます。

イベント動画の視聴はこちら

徳丸浩のウェブセキュリティ講座はこちら

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ForlkwellPress ロゴ画像

編集部

Follow

エンジニアに役立つ情報を定期的にお届けします。

エンジニアに役立つ情報を定期的にお届けします。

SHARE

目次

目次