プログラミング初心者がアーキテクトっぽく語る

見苦しい記事も多数あるとは思いますが訂正しつつブログと共に成長していければと思います

OWASP Top 10

システム開発の現場には自分が書いているコードの脆弱性を気にしない人が結構いる。

「パブリックに公開されないシステムだから」ということだ。気持ちはわからないでもない。確かに非公開サービスが攻撃される可能性は低い。

しかしこれからのセキュリティの基本は「ゼロトラスト」だ。企業内に攻撃者が潜んでいる前提で可能な限り攻撃を防ぎ、最悪の状況でも被害を最小化する努力をすることがスタンダードとなりつつある。非公開サービスだからといってセキュリティを考慮しないことは許されない時代なのだ。

では開発者はどんなことに気をつければいいのだろう?

そんなとき指針になるがOWASPがまとめたOWASP Top 10だ。


OWASP

Open Web Application Security ProjectとはWebアプリケーションのセキュリティを高めるための情報や技術を共有することを目的として活動している非営利団体


活動

  • OWASP Top10

    • 優先して対処すべき脆弱性の共有
  • OWASP ZAP

    • 安全性を分析できるWebアプリスキャナーの開発
  • OWASP ASVS

    • Webアプリのセキュリティにおいて検証すべき事項の共有
  • OWASP OWTF

    • 効率的にセキュリティ検査するためのツールの開発
  • OWASP Testing Guide

    • 既知の脆弱性について内容・検査する方法の共有

OWASP Top 10

OWASPが世界中のSecurity Incidentを調査してまとめた脆弱性のトレンドガイドだ。

数年に1回程度のペースで更新される。今日現在の最新版は2017年版。その前の更新は2013年だったので時期的にはそろそろ次が版がリリースされてもおかしくない。

「防いで当たり前の既知脆弱性リスト」という訳ではない。検出の難しさは項目によって異なる。なにより、みんな防ぐのに苦労してるからTop 10に登場しているのだ。

ツールで簡単に検出できる脆弱性は確実に検出して対策しよう。ツールで検出できないものはコードレビューなどのチェック項目とするしかない。最も難しいのは継続的な運用努力が必要なもので体制作りが課題になる。

まずはどのような脆弱性があるかメンバー全員が理解することだ。そうすれば設計やコードのレビュー段階で新しい観点の指摘が生まれ、製品のセキュリティ品質もメンバーのセキュリティスキルも向上していくだろう。


ランキング方法

脆弱性はOWASPが計算したRiskのScoreによってランキングされている。

脆弱性はExploitability、Prevalence、Detectability、Technical Impactを1〜3の3段階で評価される。Riskはこれらの指標を下記に式に当てはめることで計算される。

Risk = AVG(Exploitability, Prevalence, Detectability) x Technical Impact

このRiskはあくまで一般論である。実際に自分のシステムにどの程度のRiskがあるかは上記計算結果にシステム固有の仕様やビジネス固有の事情を加味して検討する必要がある。


Top 10

以下に2017年度版のTop 10を簡単にまとめる。

1. インジェクション

攻撃者がWebアプリケーションに任意の文字列を注入して実行させること。Front Endから受け取ったデータをそのまま使うような実装になっていると悪用されてしまう。

SQLインジェクションが有名だが、NoSQL、OSコマンド、ORM、LDAP、EL式などのインジェクションもある。

SQLインジェクションには3種類ある。

In-band SQL Injection

  • 最も一般的なSQL Injection
  • クエリを送ってレスポンスを確認する
    • Error-based
      • エラーを発生させてエラーメッセージを確認してDB構造を調査する攻撃
    • Union-based
      • DBのSELECT文の結果を結合してより多くのデータを得る攻撃

Inferential SQL injection

  • データを盗むのではなく挙動を観察してDBの管理ユーザ名や構造などの情報を盗む攻撃
  • 攻撃者には盗みたいデータ自体(ユーザ名)が見えないのでBlind SQL Injectionとも呼ばれる
    • 「user()の1文字目はAか?」などのSQL文を繰り返して管理ユーザ名を特定したりする
  • 時間がかかるが脅威の度合いはIn-band SQL Injectionと同等
  • Boolean-based
    • レスポンスの内容からクエリの成否を識別する
  • Time-based
    • 実行に時間がかかるSQL文を実行してレスポンスに要する時間でクエリの成否を識別する

Out-of-band SQL injection

対策

  • 検出自体はツールで簡単にできるが対策は大変
  • SQL文はそもそも動的に生成するものなので根本原因であるユーザ入力自体をなくすことはできない
  • 1つの対策では不十分なので複数の対策を実施し多段階でデータを守ることが基本
  • まずユーザ入力の検証、フィルタリング、サニタイズをしっかり行う。
  • Parameterized Query / Prepared Statementを使用する。
  • Sensitiveな情報(SQLエラー等)をResponseに含めない
  • 大きな権限を与えない(DROP等)
  • IPS/FWで検知する

Parameterized Query / Prepared Statement

  • SQL文の中にプレースホルダー(例:「?」)を埋め込む
  • 実行時にプレースホルーダ部分にユーザ入力が代入されるが強制的にリテラルとして扱う
    • キーワード(SELECT FROM WHERE)、演算子(=)、識別子(カラム名、テーブル名)とは見なさない
    • よってユーザ入力文によってSQL文の意味自体を変更することができない
  • SQLインジェクション対策と性能向上に効果がある

2. 認証の不備

攻撃者がアカウント、パスワードを盗んで侵入すること。

辞書攻撃やリスト攻撃が成功しやすいシステム、脆弱な初期設定パスワードを発行するシステム、平文や脆弱なハッシュでパスワードを保管しているシステムなどはパスワードが盗まれる危険性が高い。

またURLにセッションIDが露出していたり、ログイン後もセッションIDが変わらないシステムはセッションIDが盗まれる危険性が高い。

実績のあるフレームワークを利用することで認証やセッション管理の不備を防止できる。


3. 機微な情報の露出

機密情報が第3者に見える形で通信、保存されていること。

対策として保護すべきデータを整理して必要に応じて通信やファイルを暗号化する。


4. XML External Entities (XXE)

XMLの参照機能を利用して外部プログラムを実行させること。

古いXMLプロセッサを使っていると危ない。

対策としてInput ValidationでXML文書内の不正なものを排除する。


5. アクセス制御の不備

攻撃者が本来、権限がないはずの処理を実行できること。

たとえばURLを直接入力すると管理者ページにアクセスできるケースなど。

対策として公開しているリソース以外はデフォルトでDenyする。


6. 不適切なセキュリティ設定

設定ミスにより攻撃者に攻撃の糸口を与えてしまうこと。

必要のない機能やデフォルトのアカウント・パスワードが有効なままだったり、本番環境では不適切な初期値が適切な値に変更されていない場合に起こりうる。

対策としてセキュリティ設定はちゃんと設定する。パッチや更新は素早く実施する。ツールで発見できるものもある。


7. Cross-Site Scripting (XSS)

Cross-site scripting (XSS)。攻撃者がJavaScriptのプログラムを被害者のWebブラウザに表示させて情報を盗んだりフィッシングしたりする。XSSには3種類ある。

1. Reflected XSS attacks

  • 攻撃者がJavaScriptのコードを掲示板に記載する。
  • 被害者が掲示板を閲覧して表示された攻撃者のJavaScriptをクリックして、攻撃者のサーバに転送されてしまう。

掲示板のように攻撃者のRequestの一部を被害者へのResponseに含めるサーバで利用される。

2. Stored XSS attacks

  • 攻撃者がDatabaseを攻撃して悪意のあるコードを埋め込む。
  • WebアプリケーションがDatabaseからコードを読み込み、検証なしで被害者に表示する。
  • 被害者がアクセスするとブラウザに読み込まれて実行される。

Databaseから取得した情報を検証なしでユーザへ表示するようなサーバで利用される。

3. DOM based attack

JavaScriptフレームワーク、シングルページアプリケーションが攻撃者のコードを動的に取り込んでWebページに出力してしまう。

対策

  • HTTPS TRACEを無効化する
  • Webページに含まれる変な情報は拒否する
  • 入力値を制限する
  • ユーザ入力をサニタイズする
    • コードに関わる下記の文字ををエスケープする
& < > ” ’
  • コンテンツとユーザ入力データを分離する。

8. 安全でないデシリアライゼーション

攻撃者がシリアル化されたデータにプログラムを混入させて、デシリイアライゼーションされたときに実行させること。

リアライゼーションをマイクロサービス間の通信に利用しているときなどに悪用されやすいと言われる。悪用することも発見することも難しく、実際に発生した報告はない

対策としてシリアル化されたオブジェクトにデジタル署名をつけるか、プリミティブなデータに限定することでリスクを低減できる。


9. 既知の脆弱性のあるコンポーネントの使用

公開された脆弱性にちゃんと対応していないこと。

対策として使用しているComponentを把握して脆弱性の確認と対処をする。


10. 不十分なロギングとモニタリング

攻撃された事実を検知できないこと。

breach発覚までに200日以上かかり、第3者からの指摘で発覚することが多い。検知が遅れると被害が拡大する。

対策としてPenetration Testingとログのレビューを行う。


番外編:CSRF/SSRF

CSRF/SSRFは2013年度版ではTop 10に入っていた攻撃だ。2017年度版ではランク外になっているものの引き続き注意が必要と言われている。

Server-side Request Forgery

外部公開されているサーバを介して非公開の内部サーバを攻撃する手法。

Webサーバから非公開サーバへリモートコマンドを実行させて機密情報を盗んだりする。Webサーバがアクセスしていもよい内部サーバの範囲をホワイトリスト形式のAccess Listなどで狭めることでリスクを低減できる。

Cross-side Request Forgery (CSRF)

正規のユーザを介して攻撃する手法。

ネット銀行のユーザにフィッシングのリンクをクリックさせて自分に送金させたりする。ネット銀行側が攻撃者に予測されにくい要素を(Token、Session ID、キャプチャ)を送金手続きに取り入れることでリスクを低減できる。

予測されにくいTokenをCSRF Tokenといい、CSRF Tokenに対応しているWeb Frameworkが多く存在する。PythonではFlask-WTF、Flask-SeaSurf、DjangoなどがCSRF tokenに対応している