タグ: セキュアコーディング技術

JavaScriptでインジェクションリスクがある関数/機能など

Webブラウザに対するJavaScriptコードのインジェクションは

  • サーバー側のコードが原因(サーバー側のPHP、Ruby、Python、JavaScriptが原因)
  • クライアント側のコードが原因(クライアント側のJavaScriptが原因)
  • サーバーとクライアント(上記の両方)

で起きる可能性があります。ここでは主にクライアント側が関係するケースで注意しなければならない箇所を紹介します。

もっと読む

X-Content-Type-Options: nosniff はIE以外にも必要

往年のWeb開発者であれば X-Content-Type-Options: nosniff はIE専用のオプションHTTPヘッダーだと理解している方が多いと思います。

この理解は正しかったのですが、現在は正しくありません。nosniffはChromeやFirefoxの動作にも影響与えます。このため、IEをサポートしないサイトであっても X-Content-Type-Options: nosniff は必要なHTTPヘッダーです。

もっと読む

SQLクエリと識別子エスケープの話

Facebookでこんなやり取りをしました。元々公開設定で投稿した物で、議論させて頂いた浅川さんにも「ブログOK」と許可も頂いたので、そのやり取りの部分だけを紹介します。

テーマは「SQLクエリと識別子エスケープ」です。

とあるブログの結論として

“「安全な静的SQLの発行方法」を開発者に啓蒙すればいいだけだ。つまり

  • プリペアドクエリでSQL発行は行うこと
    この場合変数のバインドは必ずプレースホルダを用いること。

SQL文の文字列操作は禁止であり、これほどシンプルなことも無いだろう”

と書かれていました。しかし、私はこの意見に対して

実践的なSQLクエリを書いたことが全くない開発者なのでしょう??
ソートカラム、抽出カラムを指定するSQLクエリでは「識別子(カラム名)が変数」になります。
初歩的なSQLクエリですが”自分が書いたことないから”といって一般的ではないと勘違いしています。行のソート順、抽出カラムを指定するSQLクエリは業務アプリでは”一般的”です。当たり前ですが。

こうやってベストプラクティスもどきのアンチプラクティスが使われて、喜ぶのはサイバー犯罪者とセキュリティ業者だけですよ。

とコメントしました。SQLのテーブルやジョイン結果を「表」として表示した際に、任意のカラムのソート順を指定するUIは、自分で作ったことが無かったとしても、ごく一般的だと分かると思うのですが・・・

もっと読む

エンジニアなら理解る文字エンコーディングバリデーションの必要性

入力バリデーションで文字列の妥当性を検証(保証)しないと、不正文字問題の解決はできません。

よく「文字エンコーディングバリデーションは入力バリデーションしなければならない」と紹介はするのですが、その理由を詳しく解説していませんでした。これは文字エンコーディング攻撃の仕組みを理解してれば分かる事なのでしていませんでした。

しかし、文字エンコーディング攻撃の仕組みを理解していても必要なし、とする意見があるので理解り易く説明します。(理解りづらかったら教えてください)UTF-8のみですが、他の文字エンコーディングでも基本は同じです。

もっと読む

バリデーションですべきこと

このブログは、IPAは基礎的誤りを明示し、正しい原則を開発者に啓蒙すべき、の「追加の情報」として書いた物を別エントリとしてまとめた物です。

CERTセキュアコーディング

  • 入力バリデーション(原則1)
  • ”セキュアコーディング標準”による安全なロジック処理(+具体的な入力/出力処理)※ 原則10 「セキュアコーディング標準を採用する」=自ら作るモノ
  • 出力の無害化(原則7)※ IPA版は原則2

の3つが1つのセットとして成り立ちます。これ以外はセキュアコーディングではありません。

入力、ロジック、出力、これら全てにバリデーションが必要です。

参考: コンピュータは数値さえ正確に扱えない

もっと読む

出力対策の3原則 + 1原則

ソフトウェアの不具合/脆弱性を無くすためには、出力先に対して無害であることを保障する出力対策が重要です。どんな出力でも3つの方法で無害化できます。

このブログでは基本として、セキュアコーディングの概念に基き説明しています。先ずはよくある入力対策と出力対策の区別がついていない誤りから紹介します。

参考:IPAは基礎的誤りを明示し、正しい原則を開発者に啓蒙すべき

もっと読む

バリデーションには3種類のバリデーションがある 〜 セキュアなアプリケーションの構造 〜

バリデーション、と一言で言っても一種類/一箇所だけではありません。バリデーションには3種類のバリデーションがあります。

バリデーションは重要であるにも関わらず誤解が多い機能の筆頭だと思います。日本に限らず世界中でよくある議論に

  • バリデーションはモデルで集中的に行うべきだ!
  • なのでコントローラー(入力)でバリデーションなんて必要ない!
  • モデル集中型バリデーション以外の方法/場所でバリデーションするのは非効率で馬鹿馬鹿しい考えだ!

があります。どこかで見た事があるような議論ですが、世界的にこのような考えの開発者が多いことは、この入力バリデーション用のPHP拡張モジュールを書いた時の議論で分かりました。1PHP開発者MLで議論したのですが、紹介したような議論をした方が少なからず居ました。少し続くとすかさず「そもそもActiveRecordパターンでないモデルも多数あるし、ActiveRecordパターンのモデルだけのバリデーションだと遅すぎ、その間に実行させる機能が悪用されるケースは山程あって、しかもそれが奥深いライブラリのどこで起きるか分らんだろ」的なツッコミがあるところは日本での議論とは異なった点です。

実際、多くのWebアプリケーションフレームワークは入力バリデーション機能をデフォルトでは持たず、アプリケーションレベルでの入力バリデーションを必須化していません。開発者が上記のような考えになっても当然と言えるかも知れません。しかし、必要な物は必要です。何故?と思った方はぜひ読み進めてください。

流石にこの時の議論ではありませんでしたが、以下の様な議論も見かけます(ました)

  • 入力データはバリデーションはできない!
  • どんな入力でもWebアプリは受け付けて”適切”に処理しなければならない!
  • 入力バリデーションにホワイトリスト型は無理、適用できない!
  • ブラックリスト型とホワイトリスト型のバリデーションは等しいセキュリティ対策!
  • 入力バリデーションはソフトウェアの仕様でセキュリティ対策ではない!
  • 脆弱性発生箇所を直接または近い個所で対策するのが本物のセキュリティ対策である!

全てセキュアなソフトウェア構造を作るには問題がある考え方です。最後の「入力バリデーションはソフトウェアの仕様でセキュリティ対策ではない!」とする考え方の問題点は”セキュリティ対策の定義” 2セキュリティ対策=リスク管理、にはリスクを増加させる施策も含め、定期的にレビューしなければならないです。(ISO 27000/ISMSの要求事項)リスクを増加させる施策、例えば認証にパスワードを利用など、は定期的にレビューしその時々の状況に合ったリスク廃除/軽減策をタイムリーに導入しなければならない。リスク増加要因を管理しないセキュリティ対策=リスク管理は”欠陥のある管理方法”です。 を理解していないと問題点は見えないかも知れません。

  • セキュリティ対策(=リスク管理)とはリスクを変化させる全ての施策で、多くの場合はリスクを廃除/軽減させる施策だが、それに限らない。

このセキュリティ対策の定義はISO 27000/ISMSの定義をまとめたモノです。

TL;DR;

何事も原理と基本が大切です。基礎的な事ですがプログラムの基本構造と動作原理を正しく理解しておく必要があります。

セキュアコーディングの構造/原理/原則

入力対策と出力対策は両方必要でバリデーションはセキュアなソフトウェア構築には欠かせません。

  • 原理1: コンピュータープログラムは「妥当なデータ」以外では正しく動作できない
  • 原理2: 何処かでエラーになるから、ではセキュアにならない遅すぎるエラーはNG

アプリケーションの入り口で入力バリデーション(入力検証)をしていないアプリはセキュアでない構造です。

入り口以外に入力検証がないアプリもセキュアではない構造です。セキュアなアプリには最低限、入り口でのデータ検証と出口でのデータ無害化(エスケープ/無害化API/バリデーション)が必須です。

  • プログラムは妥当なデータでしか正しく動作できない入力バリデーションは原理的に必須
  • 出力対策は必須の物とフェイルセーフ対策の物があるフェイルセーフ対策の場合は下層の多層防御です。そもそも”データが妥当でない場合”(=フェイルセーフ対策)のエラーは起きてはならない。当然ですが出鱈目なデータを処理するのもNG。

多層防御 3ソフトウェアに限らずセキュリティは多層で防御します。必ず必要な対策と無くても大丈夫なハズの対策(フェイルセーフ対策)の2種類がある。フェイルセーフ対策は万が一の対策であり、本来フェイルセーフ対策は動作してはならない。動作した場合はプログラムに問題がある。「動作してはならない」は「必要ない」ではない。実用的なプログラムは複雑であり失敗してしまうケースは十分にある。入力バリデーションが甘い/無いプログラムだとフェイルセーフ対策が機能してしまうことは当たり前に起きる。 は重要なのに勘違いされているソフトウェアセキュリティ要素の1つです。

バリデーションには3つの種類があります。

  • 入力バリデーション正しく動作する為に必須(主に形式検証)
  • ロジックバリデーション正しく動作する為に必須(主に論理検証)
  • 出力バリデーション –  大半が上の2つに失敗した場合のフェイルセーフ対策(追加の対策 – 安全な特定形式のみ許可の場合)

※ 出力時のエスケープ/エスケープが不必要なAPIの利用によるデータの無害化は、必須の対策が半分、フェイルセーフ対策が半分です。

※ “入力ミスの確認”を”バリデーション”と考えたり、言ったりすると混乱の元です。”入力ミス/論理的整合性の確認エラー”は処理の継続、”あり得ないデータによるバリデーションエラー”では処理の中止、が必要なので区別する方が良いです。

※ ソフトウェア基本構造の入力処理では”あり得ないデータによるバリデーションエラー”、ロジック処理では”入力ミス/論理的整合性の確認エラー”、になります。

※ リスク分析の経験があれば自然にセキュアな構造を思い付くことも可能だと思います。

リスク分析とリスク対応をしよう

イメージ図:

参考:データもコードも一文字でも間違い/不正があるのはNG

常識?非常識?プログラムは1文字でも間違えると正しく動作しない

もっと読む

  • 1
    PHP開発者MLで議論したのですが、紹介したような議論をした方が少なからず居ました。少し続くとすかさず「そもそもActiveRecordパターンでないモデルも多数あるし、ActiveRecordパターンのモデルだけのバリデーションだと遅すぎ、その間に実行させる機能が悪用されるケースは山程あって、しかもそれが奥深いライブラリのどこで起きるか分らんだろ」的なツッコミがあるところは日本での議論とは異なった点です。
  • 2
    セキュリティ対策=リスク管理、にはリスクを増加させる施策も含め、定期的にレビューしなければならないです。(ISO 27000/ISMSの要求事項)リスクを増加させる施策、例えば認証にパスワードを利用など、は定期的にレビューしその時々の状況に合ったリスク廃除/軽減策をタイムリーに導入しなければならない。リスク増加要因を管理しないセキュリティ対策=リスク管理は”欠陥のある管理方法”です。
  • 3
    ソフトウェアに限らずセキュリティは多層で防御します。必ず必要な対策と無くても大丈夫なハズの対策(フェイルセーフ対策)の2種類がある。フェイルセーフ対策は万が一の対策であり、本来フェイルセーフ対策は動作してはならない。動作した場合はプログラムに問題がある。「動作してはならない」は「必要ない」ではない。実用的なプログラムは複雑であり失敗してしまうケースは十分にある。入力バリデーションが甘い/無いプログラムだとフェイルセーフ対策が機能してしまうことは当たり前に起きる。

PHPのHTMLエスケープ

いろいろなコンテクスト用のエスケープ方法を書いてきましたが、HTMLコンテクスト用のエスケープ方法エントリは古いままでした。今のPHPのHTMLエスケープを紹介します。

参考:他のエスケープ方法は以下のエントリを参照してください。

PHP文字列のエスケープ

もっと読む

暗号学的ハッシュを安全に使うには?

2017年2月にGoogleがSHA1ハッシュの衝突に成功した、とアナウンスしました。1

暗号学的に安全なハッシュ関数な場合、SHA2-256を使っていると思います。SHA3が利用可能になのでSHA3を利用している場合も多いと思います。SHA2もSHA3も暗号学的ハッシュ関数です。ざっくりとこれらのハッシュ関数を安全に使う方法を紹介します。

もっと読む

HKDF, HMACなどのハッシュ関数を使う場合に知っておくべきFS/PFS

PHPにHKDF関数、hash_hkdf()が追加されましたが、そのシグニチャは褒められるモノではありません。

出鱈目なシグニチャのhash_hkdf関数を安全に使う方法

hash_hkdf()が脆弱なAPI仕様になってしまった主な原因は、開発者がハッシュ関数を利用して鍵を導出する場合に知っておくべきFS/PFSの概念を知らなかったことにあります。(秘密鍵のセキュリティ維持にSaltが必須であるとの理解が足りなかったことも原因)

FS/PFSはハッシュ関数を利用した安全な鍵導出に必須の知識です。簡単な概念なので直ぐに理解できると思います。

もっと読む

PHPとXML eXternal Entity(XXE)対策

2017年版OWASP TOP 10がリリースされました。新しくA4としてXXE、A10としてInsufficient Logging & Monitoringが入りました。今回はXXE対策を紹介ます。XXE対策は簡単です。

XXEは「リクエストのインジェクション」と考えると解りやすく、「リクエストのインジェクション」と理解すれば他の類似攻撃パターンにも応用できます。

自分で直接XMLモジュールのクラス/関数を使ってXML処理している場合は問題箇所は判り易いですが、ライブラリなどを使う場合は知らずにXXEに脆弱になりえます。外部XML文書を処理する場合、XML処理ライブラリは盲信するのではなく、XXEに脆弱でないか検証してから使わないとなりません。

もっと読む

PHP用入力バリデーションモジュール – validate

ブログで紹介するのを忘れていました。PHP用の入力バリデーションモジュール validateを作りました。

https://github.com/yohgaki/validate-php

PHP開発MLでの議論用に作ったので、作りかけと言える状態ですが、一応動作し使えます。

関数名はvalidate()の方が良いのでは?という意見があったので、名前は変更する予定です。valid()にしていた理由は”validate”だとあまりに一般的過ぎて、同じ名前の関数を定義しているユーザーがいるだろう、と予想したからです。自分のアプリやライブラリには名前空間を使うべきなので、モジュール関数はvalidate()にします。

いろいろ意見があったのですが、やはり入力処理における入力バリデーションとロジック処理の混同がありました。

入力処理における「形式的バリデーション」とロジック処理における「論理的/仕様的バリデーション」は別処理とした方が、構造的に優れています。この理由はまたの機会に書きます。