カテゴリー: Secure Coding

ソフトウェアはセキュリティの原理・原則から間違っている「入り口ノーガード設計」のままで良いのか?

現在のWebアプリケーションのほとんどは「入り口対策」がない「入り口ノーガード設計」です。

※ アプリケーションの入力処理、つまりMVCアーキテクチャーならコントローラーレベルで「入り口対策」がない設計が「入り口ノーガード設計」です。

このような設計になっているので、本来は自然数だけのハズのHTTPヘッダーのContent-Length(やContent-Type/Content-Disposition)にプログラムが書けてしまったStruts2 Webアプリにより国内ではクレジットカード情報が何十万件も盗まれる、米国では1億4千万件以上の信用情報が漏洩する、といった事件が発生しています。

幸い、「入り口対策」がない「入り口ノーガード設計」でもこういった大規模インシデントになるような脆弱性の攻撃は多くありません。しかし、話題にならないだけで多数のインシデントが世界中で発生していると考えられます。

先の事例はStruts2/フレームワークのセキュリティ問題、と捉えられていることが多いと思います。しかし、これは本質的にセキュリティ原則を無視した「入り口ノーガード設計」の問題です。

コード検査していると「入り口対策」をしていて、本当に良かったですね!というケースに出会うことが少なくありません。

2018年5月からEUでGDPRが施行されます。GDPR違反となると2000万ユーロまたは全世界売上の4%のどちらか高い方が罰金(組織によっては1000万ユーロまたは全世界売上の2%)となります。GDPRには様々な要件が要求されていますが、国際情報セキュリティ標準であるISO 27000で”普及している”とされた”セキュアプログラミング技術”の原則さえ採用しないシステムで個人情報漏洩が起きた場合の被害は、簡単に会社を潰すレベルの損害になる可能性があります。

もっと読む

出力対策の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文字列のエスケープ

もっと読む

出力対策”のみ”のセキュリティはアンチプラクティス

「しっかり出力対策”だけ”するのがセキュリティ対策のベストプラクティス」とする考え方1があります。しかし、これはベストプラクティスどころかアンチプラクティスです。

アンチプラクティスをベストプラクティスと勘違いしている限り、満足のいくセキュリティ対策(=リスク管理)は不可能です。セキュリティ対策は総合的なリスク対策です。「これ”だけ”やれば良い」とするセキュリティ対策は大抵アンチプラクティス2です。

※ 今まで出力対策”だけ”がセキュリティ対策だと勘違いしていた方には確証バイアスが働きやすいようです。論理的/構造的にどうすればリスクを効果的に削減できるのか?を考えると理解るはずです。

もっと読む

第一のソフトウェアセキュリティ原則さえ普及しない最大の理由とは?

追記:書き直しました。新しい方をご覧ください。

セキュアコーディングの原則1は「入力バリデーション」です。セキュアコーディングの原則1はソフトウェアセキュリティの一丁目一番地と言えるセキュリティ対策です。

入力バリデーションを第一のセキュリティ対策としているガイドライン:

90年代初めからコンピューターサイエンティストのセキュリティ専門家は「入力バリデーション」を重要であるとしてきました。「入力バリデーション」は論理的にセキュアな構造のソフトウェアを作る為に欠かせない必須の要素だからです。防御的プログラミングから数えると四半世紀を越える月日が経っています。

もっと読む

実は知られていない?リスク対策の原則?

ISO 31000(リスクマネジメント標準規格)はa)からk)まで、11のリスク管理の原則を定めています。

ITエンジニアであればISO 27000(情報セキュリティマネジメント標準規格)を一度は読んだことがあると思います。少なくとも名前くらいは知っていると思います。リスク管理の基礎/基本を理解していればISO 27000だけでも十分ですが、ちょっと自信がない、体系的には学んだ事がない方はISO 31000も参考にすると良いです。

情報セキュリティマネジメントはリスクマネジメントの一分野です。一般論としてのリスク管理の基礎知識は役立ちます。

リスク対策の原則が知られていない?ことも、間違ったセキュアコーディング理解の原因かもしれません。間違いだらけのセキュアコーディング解説も紹介します。

もっと読む

ソフトウェアセキュリティのアンチパターン

アンチパターンを知ることにより失敗を防ぐ。これはデータベース設計やソフトウェア設計で多く利用されている手法です。今回はソフトウェアセキュリティのアンチパターンを紹介します。

このエントリは不定期にメンテナンスするつもりです。

もっと読む

ゼロトラストをより細かく分解する

セキュリティを維持する為にはゼロトラスト、何も信頼しない所から始めて信頼できることを検証する、作業が必要です。ゼロトラストは信頼できるモノと信頼できないモノに分ける作業ですが、より細かく考える必要があります。

※ より細かく考える、とはいっても「細かい事だけ」では合成の誤謬にハマります。全体と詳細、両方をバランスよく「ゼロトラスト」することが大切です。

もっと読む

セキュリティ対策が論理的に正しいか検証する方法

全てのセキュリティ対策は緩和策だと考えるべきです。これは個々の対策が完全であるか検証することが容易ではないからです。例えば、SQLインジェクション1つとっても本当に完全であるか?検証することは容易ではありません。プログラムが本当に思っているように動作するのか?検証する研究は、まだまだ研究段階です。

しかし、容易ではないからといって諦める訳にもいきません。不完全であっても形式的な論理検証は容易にできます。

もっと読む

知っておくべきITセキュリティ概念Top 10 〜ショート版〜

ITシステム開発者必修のセキュリティ概念 Top 10です。ここで紹介する概念はセキュリティ設計やセキュアコーディングを行う上で欠かせないモノばかりです。順序はその基礎知識性、重要性、分かり易さで付けています。

では開発者必修のセキュリティ概念 Top 10です。

※ 長くなったので短い版を作りました。ロング版はこちら

もっと読む

当たり前?非常識?開発者必修のセキュリティ概念 Top 10

ITシステム開発者必修のセキュリティ概念 Top 10です。さっと考えたので変更するかも知れません。これらの考え方や概念を理解していないと、ITセキュリティ標準やガイドラインなどで要求されているセキュアプログラミング/セキュアコーディングを効率的かつ効果的に利用することはできないでしょう。

ここで紹介する概念はセキュリティ設計やセキュアコーディングを行う上で欠かせないモノばかりです。

順序はその基礎知識性、重要性、分かり易さで付けています。では開発者必修のセキュリティ概念 Top 10です。

参考:思いの外、長くなったのでショート版を作りました。

もっと読む

本当にプリペアードクエリだけを使っていますか?

'SELECT '.pg_escape_idetifier($_GET['col']).' WHERE '.pg_escape_identifier('tbl').' ORDER BY '.pg_escape_idetifier($_GET['col'])

SQLクエリにはプリペアードクエリを使いましょう!と言われて久しいです。私もプリペアードクエリを積極的に使うべきだと考えています。

  • 多くの場合、速い
  • SQLパラメーターを分離して書くので「ついうっかり」が起こりにくい
    • 特に初心者は「ついうっかり」が多い

しかし、「プリペアードクエリだけを使っていれば良いので、エスケープは要らない」という意見には賛成できません。なぜ賛成できないのか?コードを見れば分かります。

何年か前に議論になった話題です。自分のエントリを検索して、たまたま見つけたのですが物がありました。

例えば、入力バリデーションなしで以下のようなクエリは絶対に安全に実行できません。

$result = pg_query_params('SELECT '.pg_escape_identifier($_GET['col]). ' FROM '.pg_escape_identifier($_GET['table']). ' WHERE id = $1', [$_GET['id']]);

こんなクエリをそのまま書く人は居ませんが、プリペアードクエリ”だけ”ではインジェクション対策にならない事はSQLを知っていれば学生でも理解ります。

特定カラムの抽出/ソート(これはエスケープでぼほOK)、テーブル指定をするクエリは当たり前に存在します。

もっと読む

セキュアコーディング/セキュアプログラミングが流行らない理由

ISO 27000(ISMS)をはじめ、セキュアコーディング/セキュアプログラミングを行いなさい、と推奨するセキュリティガイドラインが多くあります。2014年改訂のISO 27000に至っては、セキュアプログラミングが広く普及したのでセキュアプログラミングを行うとする記述に簡素化しています。1

しかし、広く使われているフレームワークでさえセキュアコーディング/セキュアプログラミングをサポートする機能が無かったり/不十分でだったり、現状は到底普及している、とは言えないです。辛うじて普及しているかも?と言えるのはセキュアコーディング/セキュアプログラミングでは枝葉末節にあたるコーディング技術(ああすべき/こうすべき)くらいではないでしょうか?

なぜセキュアコーディング/セキュアプログラミングが普及していないのか?考えられる理由を挙げます。

セキュアコーディング/セキュアプログラミングとは?という方は以下を参考にしてください。

もっと読む

5分で解るセキュアコーディング

セキュアコーディングで最も重要な部分を理解するのは簡単です。スライドを作ったので公開します。

出力対策だけのセキュリティ対策は”誤り”です。

「出力対策だけのセキュリティ設計」が誤りである理由

確証バイアスのせいか、”セキュリティ専門家”を含め、この基本原理が理解できないケースが多いです。