データ型とセキュアコーディング

このブログではどのように”データ型”の概念とセキュアコーディングが関連しているのか、Webサーバーアプリを主体に説明します。

セキュアコーディングの基本を理解している必要がありますが、難しくはないです。原則を知っているだけで十分です。セキュアコーディングの10原則は次の通りです。

1番目の原則「入力をバリデーションする」がデータ型と関連します。

プログラミング言語の「基本データ型」

一般にプログラミング言語は基本データ型として

  •  文字列
  •  整数
  •  浮動小数点
  •  配列/リスト

を持っています。この他に

  •  クラス/オブジェクト/構造体など複合型

があります。これらは基本的には文字列/整数/浮動小数点/配列/リストを組み合わせ”ユーザーが定義するデータ型”で、文字列/整数などの基本的なデータ型とは異なります。

プログラミング言語は一般に”汎用”利用されることを前提に設計されています。この為、基本データ型は汎用データ型として、そのデータ型が許すデータなら何でも保存できます。

例えば、C言語の整数型に対してオーバーフローするような値を代入しても「許されている」ので、無効なデータであっても保存できます

クラス/オブジェクトをサポートする言語には、言語要素として予め定義されたクラス/オブジェクトが在る場合もあります。こういった場合も基本的には”汎用”データ型として定義され、そのクラス/オブジェクトが許すデータなら何でも保存できます。

アプリケーションの基本データ型とは?

アプリケーションの入力データは、プログラミング言語の「基本データ型」が許可しているデータを全て受け入る変数ばかりではありません。プログラミング言語の「基本データ型」がそのまま使えるケースの方が少ないです。

プログラミング言語の「基本データ型」は”汎用データ型”であり、アプリケーションのデータ型はのほとんどが”専用のデータ型”です。プログラミング言語の”汎用データ型”とは一致しません。

アプリケーションにとってオーバーフローする整数値は通常”不正なデータ”です。年齢に”999”は無効なデータです。都道府県名に”あいうえお”といった文字列データも無効なデータです。

Webアプリケーションのデータは基本的に”全てテキストデータ”として取り扱われます。HTTP/HTTP/XML/JSON/SMTP/IMAP/LDAP/SQLといったインターフェースはデータをテキストとしてやり取りしています。整数データであっても”アスキーテキストの数字文字”でデータをやり取りします。

HTTP/HTTP/XML/JSON/SMTP/IMAP/LDAP/SQLといったテキストインターフェースを持つ処理系の場合、整数データの”はず”のデータであっても、”アスキーテキストの数字文字”だけが送られてくる、とは限りません。アスキー英数字だけの”はず”のデータであっても”アスキーテキストの英数字文字”だけが送られてくる、とは限りません。

攻撃者は”整数であるはずの年齢や数量データ”に”プログラム”を当たり前に送ってきます。”英数字だけであるはずの商品コード”に”プログラム”を送ってきます。攻撃用データは”プログラム”に限りません。アプリケーションやライブラリにとって”特別な意味を持つ文字”(改行/ヌル文字などの制御文字や壊れた文字エンコーディングなど)を含めたデータを送り攻撃してきます。こういった攻撃はインジェクション攻撃として知られているWebアプリケーションの最大の脅威になっています。

無効なデータはどこまで行っても無効なデータのままです。誤作動の原因でしかありません

話が少しそれましたが、アプリケーションは”専用”ソフトウェアで、それぞれの入力に”専用のデータ型”を持っている、と言えます。

  •  ユーザーID(整数) – 1000以上、2^63未満の整数
  •  商品コード(ASCII文字列) – 10桁の英数字
  •  名前(Unicode文字列) – 制御コード/記号文字を除く、1文字以上、20文字以下のUTF-8文字データ
  •  ふりがな(Unicode文字列) – 1文字以上、40文字以下のUTF-8平仮名
  •  メールアドレス(Unicode文字列) – ”RFC2822で許可された一文字以上のユーザー名文字列@有効なドメイン名”の形式を持つ文字データ

このような形で”アプリケーションの入力データ”には”専用のデータ型”があると言えます。

「入力データをバリデーションする」とは

 言い換えると「”アプリケーション専用のデータ型”として、”アプリケーションビジネスロジック”として妥当であることを保証する」です。

特定目的に開発された専用ソフトウェアであるアプリケーションには”アプリケーション専用のデータ型”があります。通常、この”アプリケーション専用のデータ型”は”プログラミング言語の基本データ型”とは完全互換ではありません

一般に”プログラミング言語の基本データ型”は”アプリケーション専用のデータ型”とは完全互換ではなく上位互換であり、アプリケーションにとって”無効なデータ”でも処理してしまいます。そして、アプリケーションが入力データをバリデーションせず”アプリケーション専用のデータ型”であることを保証していないこと、がインジェクション攻撃に脆弱になる大きな原因になっています。

インジェクション攻撃は”誤作動”の一種で、その大きな原因が”無効なデータ”です。このため、知る限りではIPAの旧セキュアプログラミングガイドを除き、全ての真っ当なセキュリティガイドラインでは、無効なデータを排除する為にホワイトリスト型の入力データバリデーションを行うことを要求しています。バリデーションの役割は有効なデータであることを保証し、アプリケーションの正しい動作を保証すること、にあります。

重要なので繰り返します。無効なデータはどこまで行っても無効なデータのままです。”誤作動”の原因でしかありません

「入力データをバリデーションする」をデータ型を使って言い換えると「入力データが”アプリケーション専用のデータ型”として妥当であるあることを保証する」(第一段階のバリデーション)となります。

「入力データが”アプリケーション専用のデータ型”として妥当であるあることを保証する」だけではまだ不十分です。”データ形式”がアプリケーションにとって妥当であるかしか検証していません。

入力データがアプリケーションにとって妥当であるには、入力データがアプリケーションにとって”論理的”に妥当でなければなりません。

  • 購入する商品のオプションが選択可能である
  • グループに追加するユーザーが存在する

こういった情報に付与されるID情報は”アプリケーション専用のデータ型”として妥当な形式であるあるだけ、では不十分です。「入力データが”アプリケーションのビジネスロジック”に対して妥当であるあることを保証する」(第二段階のバリデーション)が必要です。

「入力データが”アプリケーションのビジネスロジック”に対して妥当であるあることを保証する」には認証(Authentication)と認可(Authorization)、真正性(Authenticity)も含まれます。これらはビジネスロジックとして論理的に検証&保証されていなければなりまねん。認証、認可、真正性は”データ形式”(アプリケーション専用のデータ型)の検証では保証できないことは説明不要でしょう。

どこで2種類の入力データの検証を行うか?

 入力データの検証には次の2種類があると理解りました。

  1. 「入力データが”アプリケーション専用のデータ型”として妥当であるあることを保証する」(第一段階のバリデーション
  2. 「入力データが”アプリケーションのビジネスロジック”に対して妥当であるあることを保証する」(第二段階のバリデーション

これらの入力データ検証をアプリケーションの何処で行うべきでしょうか?

 セキュアコーディング原則1の「入力をバリデーションする」では”全ての信頼できない入力データをバリデーションする”ことを求めています。

Webアプリケーションクライアント(ブラウザ/Webサービス利用アプリなど)からの入力データは基本的に全て信頼できません。従ってブラウザなどからの入力データは全てバリデーションする必要があります。

入力バリデーション実装の原則:

  •  フェイルファースト原則で実装する(フェイルファーストとは失敗するモノはできる限り早く失敗させるプログラミングの一般原則。ただし、CWE-20でも言及している通り”データの正規化”は先に行う)
  • ゼロトラスト原則で実装する(全てを信頼しない原則。検証されたモノである、と完全に保証できないモノは信頼しない。検証さえも信頼しない – ISO 27001:2012では検証コード/プロセスの検証も要求)

 セキュアコーディングのベストプラクティスでは”全てのコンポーネントが入力バリデーションを行うよう指揮すること”が求められます。言い替えると”多層防御(縦深防御)を実装する”(セキュアコーディング原則8)になります。

Webアプリケーションの入力データバリデーション

Webブラウザからの入力の場合、以下の様に検証します。

  1. WebブラウザのJavaScriptで入力データバリデーションを行う
  2. Webアプリ(サーバー)のプログラムで入力データバリデーションを行う
  3. Webアプリのデータストレージ(RDBMSなど)で入力データバリデーションを行う

例えば、”年齢”というアプリケーションのデータ型(0以上140以下)がある場合、以下のようにバリデーションします。

  1. WebブラウザのJavaScriptで”0以上、140以下”であることを保証する
  2. Webアプリ(サーバー)のプログラムで”0以上、140以下”のデータのみ受け入れる
  3. Webアプリのデータストレージ(RDBMSなど)で”0以上、140以下”のデータのみ受け入れる

この例は、ブラウザ/Webサーバー/データベースの異なる独立したソフトウェア間での多層防御ですが、同じソフトウェア内でもモジュール間で同様の多層防御を実装するとより安全になります。 ※ ソフトウェアの信頼境界を越えるデータのやり取りが発生する場合、そのデータは全て信頼できません (=Webブラウザからの入力は全て信頼できない)

Webアプリ(サーバー)の入力データバリデーションは以下のように行います。

  • ユーザー(上記の場合、Webブラウザ)が送ってこれるデータだけを受け入れる
  • ユーザーが送ってこれるデータに十分な制限を課せない場合、Webアプリ(サーバー)で妥当な制限を課し、その範囲内のデータだけ受け入れる

 1のユーザーによる入力エラーのチェックをWebブラウザで行っている場合、2のWebアプリ(サーバー)では単純にアプリケーション仕様で決まっている”アプリケーション専用のデータ型”として妥当かバリデーションを行います。フェイルファースト原則に従わないと無用なリスクを生むことに注意してください。

1の「WebブラウザのJavaScriptで”0以上、140以下”であることを保証する」が実装できない/していない場合はどうするのか?と思うかも知れません。

1がない状態はビジネスロジックバリデーション(第二段階のバリデーション)をクライアント側で実装していない状態です。2のWebアプリ(サーバー)で両方実装(第一と第二段階のバリデーション)する必要があります。

MVCアーキテクチャーの場合:

  • フェイルファースト原則に従い、”コントローラー”で
    •  入力データのデコード/正規化を行う(デコード/正規化エラーは無効 = 処理中止。バリデーションの前にデコード/正規化を行うのはCWE-20の要求事項)
    • 入力データが”アプリケーション仕様”として許可する適当な長さの文字列であることをバリデーションする(Webブラウザが送るはずがないUnicode制御コードや未割り当て領域コード以外の妥当なUTF-8文字列で100文字以下、など。バリデーションエラーは無効 = 処理中止)
    •  上記の処理はルーティングなどの処理の前、可能な限り早く実施する
  • ビジネスロジックとして、モデルで
    •  入力データが”アプリケーション専用のデータ型”として妥当であるかバリデーションを行う(入力ミスは”妥当な入力”、つまり通常のエラー処理を実施する = 処理の強制中止は行わない)

ソフトウェアの各コンポーネント(この場合、ブラウザ/Webサーバー)がそれぞれの責任を果さないとWebサーバー側のデータバリデーション処理が複雑化します。各コンポーネントが厳格に入力データバリデーションを行うと、ソフトウェアをより単純にすることが可能(セキュアコーディング原則4)です。

データ形式バリデーションとロジックバリデーション

CERT、MITRE(CWE/SANS)、OWASPのセキュリティガイドラインでは入力データのバリデーションをデータ形式バリデーションとロジックバリデーションの2種類に分けて解説しています。

”年齢”のように単純な”アプリケーション専用のデータ型”の場合、他のデータとの整合性をバリデーションする必要はありません。しかし、”PCを注文する場合に選択可能なオプション”などの場合、データベースを利用し選択したオプションがビジネスロジック(ビジネスルール)に適合したオプションであるか検証する必要があります。(ソフトウェアの信頼境界を越えるデータには、基本的に再検証が必須である点に注意)システム構成によって”どこで、どのようなバリデーションを行わないとならないか?”は変わります。

”認証”と”認可”、”真正性”もバリデーションの一種で、ロジックバリデーションの1つです。ロジックバリデーションの多くはビジネスロジックを記述する部分、MVCの場合はモデル、に記述します。しかし、”認証”と”認可”、”真正性”のバリデーションはコントローラーで実施すべきである場合が多いです。(フェイルファースト原則)

  • データ形式バリデーション – MVCなら基本はコントローラー
  • ロジックバリデーション – MVCなら基本はモデル

ですが、これらは”基本形”であり、必ずデータ形式バリデーションはコントローラー、必ずロジックバリデーションはモデルで行う、といった原則ではありません。(原則にも例外がある場合もあります。原則を盲目的に信用するのではなくゼロトラストで考えます)

強いデータ型を持つプログラミング言語がよりセキュアでメンテナンスし易い理由

強いデータ型を持つプログラミング言語でプログラミングしている開発者であれば、データ型が異なると正しく動作しない、異なるデータ型で互換性がある場合でもキャスト(データ型を変更)しないと動作しない、と知っていると思います。上位互換のデータ型でなければ暗黙キャストでコンパイラが警告またはエラー(セキュアプログラミング原則2)にしてくれます。

強いデータ型を持つプログラミング言語では「言語がデータ型に適合しているか保証」してくれます。

データ型に不整合がある場合、絶対にプログラムは正しく動作しません。誤作動します。強いデータ型を持つ言語では「基本データ型」であれば、ほぼ確実に「基本データ型」として整合性があることを保証してくれます。「基本データ型」に整合性があることを保証できるだけでも、プログラムの誤作動をかなり減らせます。これが強いデータ型を持つプログラミング言語が

  • よりセキュアである
  • よりメンテナンスし易い
  • 大規模プロジェクトに向いている

と言われる理由です。

強いデータ型を持つプログラミング言語でも不十分

 強いデータ型を持つプログラミング言語でも「基本データ型」の整合性保証だけでは不十分です。”年齢”を符号付き整数型の変数に保存するだけで”年齢”データとして完全に妥当である、と考える開発者はいないはずです。

データ型によるセキュリティを実現するには、型理論(Type Theory)によるデータ型検証が必要です。 例えば、Scalaはコバリアント(Covariant)とコントラバリアント(Contravariant)を言語としてサポートしています。型理論のLSP(Liskov Substitution Principle)を実装する場合、これらの機能が必要になります。バリアンスサポート機能がない言語でもassertionなどを使ってある程度保証できますが、多少手間が必要で、実行時チェックなので型論理として正しいこと完全に保証するのは困難です。

アプリケーション専用のデータ型をクラスとして実装した場合に、そのデータ型が持つ”形式的検証”をセッターメソッドに実装すると実行効率が悪くなり現実的でなくなることもあります。例えば、100万を超えないカウンタ型のデータ型を定義した場合にセッターメソッドで毎回、カウンタ値が100万を超ていないかバリデーションした、とするとカウンタ値を増やすだけでif文によるブランチが発生します。「if文ブランチの1つくらいは大したことでない」と思うかも知れませんが、塵も積もれば山となる、で万事が万事この調子で実行時にバリデーションしているとアプリケーションの実行速度が許容不可能なレベルにまで低下することがあります。

話がそれ気味でしたが、要するに強いデータ型を持つ言語の「データ型チェック機能」は非常に有用だが、それだけでは不十分であったり、現実のアプリケーションでは利用できなかったりする場合がある、という事です。

  •  強いデータ型を持つプログラミング言語だからといって、自動的に型安全が保証される訳ではない
  • そもそもアプリケーションプログラマが適切な”アプリケーション専用のデータ型”を定義していないと型安全も保証できないし、データ内容の安全性も保証できない
  • Scalaのようにバリアンスをサポートする言語でも適切に型制約を定義&利用しないと型安全を保証できない

関連: 契約プログラミング/契約による設計はコードが持つ契約(≒データ型)が妥当であるか、確実にバリデーションするプログラミング/設計手法でもあります。

おかしなCWE-20の読み解き方(CWE-20入門)

徳丸さんが独自のCWE-20(≒入力バリデーション)解説を行っているので、CERT(1989年に米カーネギーメロン大学に設置された世界最古のコンピューターセキュリティ専門機関)が30年くらい前から提唱し、ISO 27000/NIST SP-800-171/PCI DSS等で要求されているCWE-20の解説を改めて書きます。

CWE-20(入力バリデーション)がなぜ重要なのか?それはCERT/MITRE/ISOが入力バリデーションをどのように解説しているかを見れば解ります。いずれも最も重要/一番最初の対策としています。(※ MITREはCWEを管理する組織で、CWEの本家と言える組織です)

徳丸さんのブログより前に、このブログでもCWE-20について以下のブログで既に書いています。CERT(≒米カーネギーメロン大学のコンピューターサイエンス学科)が提唱するセキュアコーディング/コンピューターサイエンスの基盤となる基礎概念の紹介では十分ではなかったかも知れません。

“おかしなCWE-20の読み解き方(CWE-20入門)” の続きを読む

ソフトウェアに入力バリデーションは必要ない 〜 ただし条件付きで

「ソフトウェアには入力バリデーションは必要ない」そんな事がある訳けないだろう?!いつも言っている事と真逆でしょ?!と思うでしょう。

しかし、「入力バリデーションが必要ないソフトウェア(=コード)」は沢山あります、条件付きですが。

“ソフトウェアに入力バリデーションは必要ない 〜 ただし条件付きで” の続きを読む

セキュリティ機能の利用はソフトウェアセキュリティではない

7PK(7つの悪質な領域 – CWE-700として定義されている業界標準のソフトウェアセキュリティ分類)では「セキュリティ機能はソフトウェアセキュリティではない」としています。明白なのは「他のソフトウェアやデバイスのセキュリティ機能によるセキュリティ」です。7PKでは例としてHTTPSを挙げています。

HTTPSは必要なセキュリティ機能ですが、HTTPSの利用=ソフトウェアセキュリティ、ではありません。HTTPSを使って保護できる分野はありますが、HTTPSを使っても開発者が作っているソフトウェアのセキュリティを作る物ではないからです。

結局の所、他の”モノ”に頼らず開発者が作っているソフトウェアの中でセキュリティを作らないとソフトウェアは安全になりません。7PKの「セキュリティ機能はソフトウェアセキュリティではない」とは、「ソフトウェアセキュリティはそのソフトウェアを開発している開発者が実現する」ということです。

7PKソフトウェアセキュリティの基礎概念の一つと考えられています。 (CWE-700) セキュリティ機能を使うこと自体はセキュリティ対策になります。しかし、セキュリティ機能を使う=ソフトウェアセキュリティ対策、にはなりません。「セキュリティ機能を使う」は「必要なセキュリティ対策」のサブセット(一部、それも極一部)でしかないからです。「セキュリティ機能を使う」=「必要なセキュリティ対策」、こういった誤解が度々あるので7PKでは「セキュリティ機能」の解説として態々明示していると思われます。一言でいうなら「ソフトウェアセキュリティは”その”ソフトウェアを作っている開発者の責任に於て作るモノ」です。「◯◯、△△、を使えばOKではない」です。

“セキュリティ機能の利用はソフトウェアセキュリティではない” の続きを読む

7PK – APIの乱用とは?

7PKとは「Seven pernicious kingdoms: a taxonomy of software security errors」の略でソフトウェアセキュリティ領域の分類の一つです。CWEのビューのCWE-700としても利用されています。CWE-700となっているので、ISO 27000などのセキュリティ標準で要求される「セキュアコーディング」の基礎知識として知っておくべき分類方法/概念です。

入力バリデーションの次に重要な領域である「APIの乱用/誤用」を紹介します。

※ 入力バリデーションが第一番目である理由は、入力データの妥当性が保証されていなとプログラムは絶対に正しく動作しないからです。不正な入力で動作しているように見えても、誤った出鱈目な結果を返しているだけです。プログラムが脆弱性なく正しく動作する為には入力バリデーションが欠かせません。

“7PK – APIの乱用とは?” の続きを読む

7PK – セキュリティソフトウェア ≠ ソフトウェアセキュリティ

CWE-700としても知られる7PK(7つの悪質な領域/王国)IEEE Explorerの論文解説では、「セキュリティ機能(Security features)」はソフトウェアセキュリティではない、としています。

Software security isn’t security software. All the magic crypto fairy dust in the world won’t make your code secure, but it’s also true that you can drop the ball when it comes to essential security features. 

ソフトウェアセキュリティはセキュリティソフトウェアではない。全ての魔法のような暗号などはあなたのソフトウェアを魔法の様に安全にはしない、不可欠なセキュリティ機能の場合では削除/省略することが不可能であることは事実だが。

暗号を例に「HTTPSがソフトウェアをセキュアにはしない」としています。これは暗号だけには留まりません。

※ 7PKとはソフトウェアセキュリティ全体を包括する7つの脆弱性分類を定義する論文です。実際には7つの領域+1つ(環境)を定義しています。

“7PK – セキュリティソフトウェア ≠ ソフトウェアセキュリティ” の続きを読む

開発者必修の7PKとは?

7PKという用語を聞いた事がある開発者も多いと思います。7PKは業界標準のソフトウェアセキュリティ分類です。まだの方はこれを機会に是非覚えてください。CERT Top 10 Secure Coding Practicesと同じく開発者全員に必修の用語と概念と言えます。何故なら、CERT Top 10 Secure Coding Practicesも7PKも知らないのならISO 27000(ISMS)、NIST SP800-171に対応するアプリケーションは作れないからです。

※ 7PKやCERTセキュアコーディング原則を知らなくても、セキュアなソフトウェアを作ることも可能かも知れません。しかし、それはかなり遠回りになるでしょう。

“開発者必修の7PKとは?” の続きを読む

MITREがCWEを大幅更新 〜 セキュアコーディング対応を強化 〜

CWEはセキュアなソフトウェア開発を行う開発者にとっては欠かせない情報源です。2019年1月3日にCWE (Common Weakness Enumeration – 共通脆弱性タイプ) 3.2が公開されました。大幅更新と言える内容になっています。

この更新を一言で言うと「セキュアコーディング対応の強化」でしょう。

“MITREがCWEを大幅更新 〜 セキュアコーディング対応を強化 〜” の続きを読む

IPAの「安全なウェブサイトの作り方」は安全な作り方のガイドではない

IPAは「安全なウェブサイトの作り方」とする資料を長年公開しています。しかし、これが、重大な誤りにより、全く安全ではないWebサイトの作り方なっています。

重大な誤りとは以下です。

コンピューターサイエンス/システムエンジニアリングの観点から考える情報セキュリティはISO 27000で標準としてまとめられています。GDPRなどの法制度やNIST SP800-171の義務化などISO 27000の重要性は高まるばかりです。ISO 27000は2000年から、入力バリデーションだけは具体的な対策を記述し、セキュアコーディング/セキュアプログラミングの導入を要求しています。

ISO 27000の基礎的要求事項を無視したセキュリティ対策で情報漏洩問題などが発生した場合、契約で定めた上限以上の損害賠償を課されるリスクが高くなります。法的な意味からも現在のIPAの「安全なWebサイトの作り方」は危険であると言えます。

※ 開発者が「入力バリデーションはしている」と思っている場合でも、穴だらけで脆弱/非効率で問題あり、である場合がほとんどです。MVCモデルのモデルでバリデーションしている!といった場合、ほぼ100%不十分なバリデーションしかしていません。そんなドイツ人開発者と議論した事もあります。

“IPAの「安全なウェブサイトの作り方」は安全な作り方のガイドではない” の続きを読む

CWE-20は知られているか? 〜 開発者必修のNo.1脆弱性のハズが知られていない 〜

CWE-20とは何か?と聞かれて即答できる開発者は多くないと思います。そもそもCWEとは何か?もあまり知られていないかも知れません。

実はCWE-20 不適切な入力バリデーション はソフトウェアセキュリティで最も重要な脆弱性とされています、CWEのみでなく情報セキュリティ標準的に情報セキュリティ関連法的にも。

※ CWE: Common Weakness Enumeration (共通脆弱性タイプ)

CWEは脆弱性識別子のCVEで有名なMITRE(米国でのIPAの様な組織)が管理するソフトウエア脆弱性パターンを列挙したドキュメント/データベースです。日本語名の通り、よくある共通のソフトウェア脆弱性を集めた物がCWEです。

“CWE-20は知られているか? 〜 開発者必修のNo.1脆弱性のハズが知られていない 〜” の続きを読む

PHP 7.3

PHP 7.3が今月(2018/12)リリース予定です。新機能や機能変更は小振りですが、結構多くの追加/変更があります。ソースコード中のUPGRADINGに変更点は記載されています。ここでは独断と偏見で選んだ重要度が高い追加/変更を紹介します。 ※ PHP 7.3.0 RC6時点のUPGRADINGから紹介します。

記載していない変更の方が多いです。詳しくはリリース版のUPGRADINGを参照してください。

“PHP 7.3” の続きを読む

コードで学ぶセキュアコーディング 〜 SQLインジェクション編

セキュアコーディング原則において、インジェクション対策の為に重要な原則は

  • 原則1: 全ての入力をバリデーションする
  • 原則7: 全ての出力を無害化する

の2つです。これらに、一般的なプログラミング原則であるフェイルファースト原則とフェイルセーフ原則、ゼロトラストを適用するとセキュアコーディングになります。

簡単なSQLインジェクション対策コードを使ってセキュアコーディングの概念を紹介します。

セキュアコーディング/セキュアプログラミングの原則と技術は国際情報セキュリティ標準(ISO 27000)でも要求される技術です。しかし、根本から誤ったセキュリティ対策の概念が長年啓蒙されています。GDPR対策にもISO 27000は重要です。日本に於てもISO 27000が要求する基礎的対策ができていない場合、法的リスクが非常に高いと言わざるを得ません。

“コードで学ぶセキュアコーディング 〜 SQLインジェクション編” の続きを読む

遅すぎるサニタイズではダメな例

PostgreSQL 11がリリースされました。このリリースでto_number()、to_char()、to_date()、to_timestamp()関数の仕様が変更されました。これらは名前の通り入力を変換する関数です。その際に

  • サニタイズ – ダメな形式のデータを使える/安全なデータ形式に変換する

を行います。保存されるデータ形式は、保存可能な形に変換されます。しかし、これは十分ではないです。遅すぎるサニタイズがダメな例として紹介します。

※ エスケープやプリペアードクエリもサニタイズ(無害化)の一種です。

“遅すぎるサニタイズではダメな例” の続きを読む

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

情報セキュリティ対策 ≒ リスクの分析、対応と管理、としても構わないくらい情報セキュリティ対策にとってリスク分析は重要です。体系的にまとめられたセキュリティ対策ガイドラインなら、どれを見ても記載されています。

情報システムは「モノ」(物と人)、「ネットワーク」、「ソフトウェア」で出来ています。それぞれリスクを分析、対応、管理する必要があります。

当然、ソフトウェアのリスク分析も重要です。しかし、多くの場合は「脆弱性対策」という形でリスク分析をせずにいきなり対応する、といったショートカットが開発現場で日常的に行われています。目の前にある問題に直ぐ対応しなければならない!といった場合も多いので仕方ない側面もあります。

しかし、問題は開発工程の早い段階で対応すればするほど、少ないコストで対応できます。システム開発に関わる人なら誰でも認識している事です。できる限り早い段階で早く問題に対応する、は情報システム開発の要求仕様のみでなく、セキュリティ要求仕様にも当てはまります。

※ このブログの説明はWebシステムを前提にしています。STRIDE、DREAD、リスクマトリックスなどのリスク分析手法はISO 31000等を参照してください。このブログでは単純なアタックツリー形のリスク分析を紹介しています。

“リスク分析とリスク対応をしよう” の続きを読む

無視されているリスク分析

炎上プロジェクトの主な原因の1つに、システム要求定義が不明確であること、があります。何を作ったらよいのか、よく分らない状態で作って上手く行くのを願うのは、サイコロを振るのと変りありません。

これと同じことが情報セキュリティ対策でも起きています。

致命的な脆弱性が残っているシステムの主たる原因の1つに、セキュリティ要求定義が不明確、ならまだよいのですがセキュリティ要求定義なし、であることが少なくない数あります。IoTやスマートカーのセキュリティを見れば明らかです。セキュリティ要求定義が不明確か無い状態で作った、としか思えない事例が数えきれません。

漏れのないセキュリティ要求定義には漏れのないリスク分析が必要です。

  • ◯◯対策として△△を実施する

といったセキュリティ仕様をセキュリティ要求だと勘違いしているケースも数えきれません。

システム要求定義がないプロジェクトが簡単に炎上するように、セキュリティ要求定義がないシステムも簡単に無視することが不可能な脆弱性だらけのシステムになります。

特にソフトウェアの分野では「リスク分析」が不十分過ぎる、さらには全く無い、システムで溢れています。これでは十分な安全性を効率良く達成することは不可能です。

続きを読む

Railsのリモートコード実行脆弱性、今昔

去年、今年とStruts2、Drupalのリモートコード実行脆弱性が問題になりました。記憶に新しい方も多いと思います。Railsにもリモートコード実行脆弱性が複数レポートされており、Railsユーザーであればよくご存知だと思います。

ざっと思い付く昔の脆弱性から最近の脆弱性まで簡単にまとめてみます。

“Railsのリモートコード実行脆弱性、今昔” の続きを読む