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

(Last Updated On: 2019/02/03)

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

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

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

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

CWE-20の解説 – CWE/SANS Top 25 Monster Mitigation M1

実は態々私が解説しなくてもCWEの本家本元のMITREがCWE/SANS Top 25で解説しています。

Monster Mitigations(怪物的セキュリティ対策)で一番目のセキュリティ対策として以下のように記述しています。 ※ Mitigation(緩和策)もISO 27000のリスク対応定義により”セキュリティ対策”です。

「一番目の対策」というと大袈裟に感じるかも知れません。しかし、実際に多くのWebアプリケーション/IoTの脆弱性は適切な入力バリデーションで脆弱性を排除または緩和できます。コンピュータプログラムは妥当なデータでないと正しく動作せず、論理的にも一番目に対策しないとソフトウェアセキュリティ対策として出鱈目な対策になります。コンピューターサイエンティストはこの事実を理解しているので半世紀/四半世紀以上前から必須の前提条件としています

日本語訳した適当なページが無いようなので訳しました。2011年に作られた解説ですが、現在でも十分に通用する解説です。

前置きが長くなりましたが、CWE-20の解説です。意訳した方が良さそうな部分も直訳調にしています。

M1: 全体的に入力データに対して制御を確立し維持する
対象者: プログラマー
関連CWE:   CWE-20 不適切な入力バリデーション

不適切な入力バリデーションは健康なソフトウェアの一番の殺し屋です。もし開発者が入力データが期待している物でないか確認していないなら、問題を起こしてくれ、と頼む事と同じである。例えば、開発者が数値であることが期待している識別子は絶対に文字を含んでいてはならない。新車価格がたったの1ドルであるはずがありません、たとえ現在の経済状況でも。勿論、アプリケーションはこれらの単純な例より複雑なバリデーションが要求される。攻撃者が予期しない方法で入力を変更できる場合、不正確な入力バリデーションは複数の脆弱性の原因となる。適切な入力バリデーションにり、現在最もよく見られる多くの脆弱性は排除、または少なくとも削減できる。

全ての入力に対して標準的な入力バリデーションを使わなければならない。

・ 長さ
・ 入力種別(訳注: 期待される形式)
・ 少すぎる又は多すぎる入力
・ 関連するフィールドとの整合性
・ ビジネスルール

ビジネスルールロジックの例として、”boat”は構文的には正しいかもしれない。しかし、開発者が”red”や”blue”などの色の名前を期待している場合、”boat”は妥当ではない。

可能な限り、リクエストのパラメーターに期待する値に基き、利用する文字セットを制限するホワイトリストを使わなければならない。これは製品の何処かに存在するかも知れない脆弱性を削減または排除する間接的なメリットがある。

これらのルールを破るどのような入力も受け入れてはいけない。安全な値に変換してもいけない。

あなたのソフトウェアに対する全ての信頼できない入力が入り込む可能性がある箇所を全て理解しなければならない。例: パラメーターまたは引数、クッキー、ネットワークから読み込み全てのデータ、環境変数、DNSの逆引き、クエリ結果、リクエストヘッダー、URLやその一部、Eメール、ファイル、データベース、アプリケーションにデータを提供するあらゆる外部システム。 これらの入力はAPI呼び出しによって間接的に取得されることがあることを忘れてはならない。(訳注: 要するに「全ての外部入力データはバリデーションし、全ての入力データの妥当性を保証しなければならない

入力バリデーションを実施する前に、適切に入力のデータコード/アプリケーション内部データ形式への変換するよう、注意しなければならない。

対応するトップ25のCWE:
CWE-120CWE-129CWE-131CWE-134CWE-190CWE-209CWE-22CWE-285CWE-306CWE-311CWE-327CWE-352CWE-362CWE-434CWE-494,CWE-601CWE-676CWE-732CWE-754CWE-770CWE-78CWE-79CWE-798CWE-805CWE-807CWE-829CWE-862CWE-89CWE-98

少しだけ解説した方が良い文があります。(より詳しい説明は文中のリンク先にあります)

不適切な入力バリデーションは健康なソフトウェアの一番の殺し屋です。

MITRE(≒米国政府)は、入力バリデーションの不備が最悪の脆弱性だ、としている事が解ります。これはコンピューターサイエンスに於ける形式的検証の研究(ざっくり分けて、論理的検証と総当たり的検証の2種類がある)からも明らかです。プログラムにとって妥当でない入力からは絶対に妥当な結果は得られません。これは”動作原理”であり不変です。(原理=考え方の問題ではない)

入力データをざっくり分類すると3種類のデータ(妥当なデータ/入力ミスデータ/それ以外の無効なデータ)しかありません。 もっとざっくり分類すると2種類です。

  • 妥当なデータ (入力ミスを含む、処理可能な妥当なデータ)
  • ゴミデータ (≒ 処理不可能な攻撃データ/ゴミ)

ゴミデータ(≒攻撃データ)は組み合わせ爆発を誘発し、総当たり的検証を不可能にし、不正な動作の原因(=脆弱性)にしかならないゴミである、とコンピューターサイエンティストは何十年も前から知っています。この為、次の文のように表現しています。

もし開発者が入力データが期待している物でないか確認していないなら、問題を起こしてくれ、と頼む事と同じである

訳注: 要するに自殺行為

入力バリデーションは「セキュリティ対策ではない」「セキュリティ対策として重要ではない」「セキュリティ対策というより仕様である」「脆弱性を隠す対策で良くない」といった意見は全て、ソフトウェアセキュリティを理解していない場当たり的(=非論理的)な考え方と言えます。それぞれを解説をすると長くなりすぎるので、説明が必要な場合はコメントを下さい。

CVEとCWE-20

CVE DetailsではCWE-20かつCVSS 8.0以上といった検索も可能です。CWE-20無視は危険すぎる、と一目瞭然です。

アプリが入力バリデーション無しにライブラリ/フレームワーク/自分のコードに出鱈目なデータを渡す、これだと攻撃者が大喜びする脆弱性を残すことが解ります。

CWE-20と7PK

7PK(7つの悪質な領域)と呼ばれる論文の紹介文では不適切/不十分な入力バリデーションによるソフトウェア脆弱性は

basically all the low-hanging fruit the script kiddies love so much.

スクリプトキディ(攻撃ツールを使えるだけの低レベルな攻撃者/攻撃ツールを実行するだけのセキュリティ業者)が愛してやまない、基本的に全ての、攻撃しやすいターゲットである。

としています。 よくある勘違いに、出力さえ無害化していれば大丈夫、があります。しかし、コンピュータは妥当なデータでしか正しく動作しないので、出力の無害化だけでは全く不十分です。 ※参考1参考2参考3 詳しくは7PKの「APIの乱用」を参考にしてください。 7PKはCWE-700としてCWEのビューにもなっています。

出力対策しかないのに、あなたのアプリは出力する前に何らかのAPIにデータを渡していないでしょうか?渡しているなら「CVEとCWE-20」からも理解るように、スクリプトキディ(攻撃ツールを使えるだけの低レベルな攻撃者/攻撃ツールを実行するだけのセキュリティ業者)が愛してやまない脆弱性を持つ可能性が高くなります。

7PKはセキュリティ機能も悪質な領域の一つだとし、以下のように紹介を切り出しています。

Software security isn’t security software.

ソフトウェアセキュリティはセキュリティソフトウェアではない。

HTTPSを例にセキュリティ用のソフトウェア(≒他人のード)を使う事は、ソフトウェアセキュリティではないとしています。より噛み砕くなら、他人の書いたセキュリティ用コード(機能やAPI)を使うことがセキュリティ対策ではない、と言えます。独立したセキュリティ機能に限らず、他人が書いたセキュリティ用APIを使うだけ、ではソフトウェアセキュリティは維持できない、自分のコードでソフトウェアセキュリティは作る/維持する物です。「機能/APIだけ使えば安全になる」は、ソフトウェアの構造/仕組みから限られた条件下以外ではあり得ません。安全なソフトウェア構造は自分が書いてるソフトウェア/コードで作る必要があります。 ※ 参考

CWE-20とISO 27000/ISMS

現在のISO 27000/ISMSはセキュアプログラミング技術が体系的にまとめられ広く普及したとして「セキュアプログラミング技術を導入する」と簡潔な記述を要求事項としています。

ISO 27000/ISMSのいう”体系的にまとめられたセキュアプログラミング技術”はMITREのCWEやCERTのSecure Coding等を指しています。(重要: IPAの旧セキュアプログラミング講座は指していない。検索して出てくる旧版は修正後でも不十分すぎてセキュアプログラミングできません。)

健康なソフトウェアの一番の殺し屋」とするCWE-20(不適切な入力バリデーション)が明示してバリデーションせよ、とする入力データ

パラメーターまたは引数、クッキー、ネットワークから読み込み全てのデータ、環境変数、DNSの逆引き、クエリ結果、リクエストヘッダー、URLやその一部、Eメール、ファイル、データベース、アプリケーションにデータを提供するあらゆる外部システム

に対してバリデーションしていないアプリケーションはISO 27000(ISMS)の要求事項を満たしません。ISO 27000(ISMS)はCWE-20と同等の入力バリデーションを要求しているからです。米国が政府関連機関に要求するNIST SP800-171にも適合しません。CWE-20を定義しているMITREは米国政府の外郭機関だからです。

我が国、日本でもISO 27000(ISMS)、NIST SP800-171は無視できません。日本はISMS認証を受ける組織が最も多い国の一つです。NIST SP800-171は日本でも要求される規格になるからです。

CWE-20は理解されているか?

残念ながら多くの開発者は正しくCWE-20を理解していません。その証拠にCWE-20が

これらのルールを破るどのような入力も受け入れてはいけない。安全な値に変換してもいけない。

と入力データに対する”サニタイズ”(安全な値への変換)を禁止しているにも関わず、Rails セキュリティガイドは入力バリデーションの解説がなく、SQLインジェクション対策としてサニタイズだけ実施/解説しています。

7.2.4 対応策
Ruby on Railsには、特殊なSQL文字をフィルタする仕組みがビルトインで備わっています。「’」「”」NULL、改行がエスケープされます。Model.find(id)Model.find_by_なんちゃら(かんちゃら) に対しては自動的にこの対応策が適用されます。ただし、SQLフラグメント、特に 条件フラグメント (where("..."))、connection.execute()またはModel.find_by_sql()メソッド については手動でエスケープする必要があります。
条件オプションには文字列を直接渡す代りに、以下のように配列を渡すことで、汚染された文字列をサニタイズすることもできます。
Model.where("login = ? AND password = ?", entered_user_name, entered_password).first
上に示したように、配列の最初の部分がSQLフラグメントになっており、その中に疑問符「?」が含まれています。サニタイズされた変数は、配列の後半に置かれており、フラグメント内の疑問符を置き換えます。ハッシュを渡して同じ結果を得ることもできます。
Model.where(login: entered_user_name, password: entered_password).first
モデルのインスタンスでは、配列またはハッシュのみが使用できます。他の場所でsanitize_sql()を使ってみることもできます。SQLで外部の文字列を、サニタイズせずに使用するとセキュリティ上重大な結果がもたらされる可能性があることを普段から考える習慣をつけましょう 。

セキュリティ専門家でさえ理解できていません。その代表例がIPAです。”入力対策で出力対策を解説する”といった出鱈目な解説が行われていました。

証拠1:

証拠2:

※ IPAは恐らく2017年に出鱈目だったセキュアプログラミング講座を改訂し、CERT Top 10 Secure Coding Practicesを紹介する内容に改訂しました。 因みに、CWE/SANS Top 25の編集者にはIPAの方の名前もあります。IPAの方全てがCWE-20を理解していない訳ではないでしょう。 しかし、「安全なウェブサイトの作り方」は相変わらず出鱈目なままです。

  • ダメなデータには何をしてもダメ。そもそも受け入れない/処理しない。

これが正しく動作するソフトウェアの1番目の原理/原則です。

セキュリティ専門家がセキュアコーディングでは無い物をセキュアコーディングとして解説している物もあります。

CWE-20対策の実施状況

CWE-20が明示的にバリデーションすべし、としている物は以下です。

パラメーターまたは引数、クッキー、ネットワークから読み込み全てのデータ、環境変数、DNSの逆引き、クエリ結果、リクエストヘッダー、URLやその一部、Eメール、ファイル、データベース、アプリケーションにデータを提供するあらゆる外部システム

これら全てに対して入力バリデーションを実施しているアプリケーションはあまり在りません。残念ながら、多くの人の目に触れるはずのOSSのアプリケーションでさえ完全に実施している物はほぼありません。Webアプリケーションフレームワークも、上記データの入力バリデーションを実施する為に必要な機能を実装していない物がほとんどです。

世の中のほぼ全てのWebアプリはCWE-20対策が全く無いか、不十分な状態です。

OWASP TOP 10 A10:2017はこういった状況を変えることも意図して追加されています。A10:2017 Insufficient logging & monitoringを実装するには、全ての入力に対する厳格な入力バリデーションが不可欠です。

なぜ一番の脆弱性とされるCWE-20が無視される状況になったのか?

開発フレームワークのセキュリティガイドが入力バリデーションを解説していなかったり、開発フレームワークに適切な入力バリデーション機能を提供していなかったり、公的機関のセキュアプログラミング解説でさえ出鱈目であったり、セキュリティ専門家と言われていても重要でない/セキュリティ対策ではないと解説したりしていた事も大きな理由でしょう。

しかし、最も根源的な原因は「ボタンの掛け違え」(基礎の基礎の理解不足)だと思っています。

これはプログラミングの基本中の基本です。

例えば、「整数を0で割り算しようとすると処理できずエラーとなる」(ゼロ除算エラー)はプログラミングを習った方なら誰でも知っていると思います。

ゼロ除算エラー(これが低レベル言語で発生するとプログラムは強制停止される)を回避するには

  • 割り算を実行する前に分母が0でないことを確認する

を実行します。”ライブラリ”などではゼロ除算エラーでプログラムが停止すると困るので必ずチェックしゼロ除算エラーが発生しないようにするよう習います。ライブラリは送られてくる入力が妥当な入力であることを利用するコードに強制できないからです。

同時に”アプリケーション”では、そもそもゼロ除算エラーになるような値は出来るだけ早くエラーにするよう習うはずです。ゼロ除算エラーになる値を幾ら処理しても無意味であり、ライブラリに不備またはライブラリ仕様としてゼロ除算が無い事が前提であると、プログラムが強制停止するからです。

例外があればゼロ除算エラーを例外として処理してある程度綺麗に処理可能ですが、例外がない場合はエラーフラグを設定しチェックする、といった複雑な処理が発生します。不正な値の処理をライブラリなどの例外に任せても、エラーに任せても、良いことはありません。ライブラリなどの例外/エラーでは不正な値の処理が遅すぎるからです。(参考:契約プログラミング

このように正しくないデータを適当(=アプリケーションとして問題が無いよう)に処理するには「遅い段階で処理すると正しく処理するのが面倒かつ致命的問題の原因である」と習うと思います。

こういった「エラー処理」は基本的な事であり、プログラミング学習の”初期段階”で習う事です。

しかし、忘れてしまっていたり、ライブラリなどでエラーになればOK、と考えてしまっているアプリケーション開発者も少くないです。実際、「ライブラリ/API/出力先などでエラー/無害になればOK」と考えて書かれたアプリケーションは多く在ります。

しかし、原則は変わらず

  • コンピュータプログラムは不正な入力データを正しく処理できない

であり

  • ライブラリ/API/出力先などでエラー/無害になればOK、ではない

のですが、開発者の周囲にあるコードは

  • ライブラリ/API/出力先などでエラー/無害になればOK

とするコードだらけの状態(=常識)になっています。

この為、”基本的なボタンの掛け違え”に気が付かない、指摘されても掛け違えが正しい、と思ってしまい修正できなくなっていると考えられます。(身近な情報による誤謬と言われるよくある間違いです)

それでも”原理”は変わりません。コンピュータは”不正なデータ”では絶対に正しく動作しません。一見、動作しているように見えても、不正な結果を返している、不正なデータを保存/出力してしまっている、だけです。

セキュリティ標準や法規制は「ボタンの掛け違え」が”常識”であっても許さない

ISO 27000/ISMS では「セキュアプログラミング技術の導入」が要求されており、その一番の対策はCWE-20、つまり入力バリデーションです。ISO 27000はその前身であるISO 17799(2000年)からソフトウェアの基本セキュリティ対策として入力バリデーション”だけ”は具体的に解説していました。

コンピューターサイエンティストなら誰でも、正しく動作する(=セキュリティ問題がない)ソフトウエアには妥当な入力が欠かせない、と知っています。ソフトウェアセキュリティ対策でCWE-20対策をまず第一にすべきこと、とするのは当然です。

GDPRではISO 27000/ISMSで要求されるようなセキュリティ対策が要求されます。EUはこういった規格化が大好きな組織です。GDPRでISO 27000/ISMSの一番の対策であるCWE-20対策が無い/不十分であればほぼ間違いなく問題とされるでしょう。

EU諸国では「形式的検証」も盛んでした。「形式的検証」の基本中の基本も入力バリデーションです。入力バリデーションが不十分、まして無い状態で「十分なセキュリティ対策」とは認められるはずがありません。

米政府関連機関ではNIST SP800-171の実施が要求されます。ISO 27000/ISMSとは異なりますが、NISTの資料でISO 27000との対応表を載せてISMS認証を取得した組織がどこを補強すればNIST SP800-171に準拠できるか解説しています。ざっくり言うとISO 27000/ISMSに準拠した上で対応することができます。当然、NIST SP800-171でもCWE-20対策をしていないと問題になります。

米国CERT(米カーネギーメロン大学に設置された世界最古のITセキュリティ専門機関)もセキュアコーディング原則の第一番目として入力バリデーションを挙げています。そもそもCWE-20を管理するMITREは米国政府の外郭機関です。入力バリデーションが不十分、まして無い状態で「十分なセキュリティ対策」と認められるはずがありません。

まとめ

結局の所、情報セキュリティが重要と言いつつ基礎を蔑ろにし、専門家を含めて非論理的な情報セキュリティ対策を啓蒙し、「本当の情報セキュリティ対策」を知らずにボタンを掛け違えたままになっているのだと思います。

セキュアコーディングは、正しく動作するソフトウェア開発の概念と作法、で基本的にホワイトリスト型の対策です。”◯◯攻撃を防止する”といったブラックリスト型の対策ではありません。コンピュータプログラムの基本動作原理は、コンピュータプログラムは妥当な入力でしか正しく動作できない、です。原理的に真っ先に「入力データのバリデーション」をしなければ始まりません。このため、コンピュータサイエンティスト/ソフトウェアセキュリティ専門家は口を揃えてCWE-20が一番重要であると解説しています。

  • CWE-20を知らない = ソフトウェアセキュリティを知らない

と言える勘違いです。 これを理解しないと始まりません。コンピュータープログラムは「妥当なデータ」でしか正しく動作しないので。

例: パラメーターまたは引数、クッキー、ネットワークから読み込み全てのデータ、環境変数、DNSの逆引き、クエリ結果、リクエストヘッダー、URLやその一部、Eメール、ファイル、データベース、アプリケーションにデータを提供するあらゆる外部システム。 これらの入力はAPI呼び出しによって間接的に取得されることがあることを忘れてはならない。

上記の”要求事項”を全て満たしているWebアプリケーションはどのくらい在るでしょうか?周りのWebアプリケーションを見てみれば明きらかでしょう。ほとんど無い、それが現状です。 ※ これを満すことを可能にするPHP用のバリデーションフレームワークを公開しています。

OWASP TOP 10 A10:2017は更に踏み込んで、不正入力のログと対応対策がないアプリケーションは脆弱だ、としています。PCI DSS準拠を求められるアプリケーションでは致命的問題です。今のところ、ほぼ全てのWebアプリケーションが十分に入力データバリデーションを行わず、その為に不正な入力の検知ができず、ログもせず、対応もしない脆弱性な状態であるとしています。

PCI DSS認証が必要なクレジットカード決済を直接取り扱うサービスでなくても、ISMS準拠、NIST SP800-171準拠が求められる企業では、同様に致命的な問題として扱われるでしょう。例えば、開発会社がISMS準拠の開発を契約し、基本的な入力バリデーションが無い為にアプリケーションが脆弱になった場合、たとえ利用したライブラリなどにフェイルセーフ対策が無かったとしても、入力バリデーションで攻撃を回避できた場合、アプリケーション開発会社の責任が問われる可能性が高いです。

世界の情報セキュリティから遅れる日本とその証拠

時々耳にする「日本の情報セキュリティは10年単位で遅れている」と言葉は正解であり、不正解でもあります。

IPAのセキュアプログラミングガイドが支離滅裂であったりしました。この意味では正解です。しかし、CWE/SANS Top 25の編集者にIPAの方の名前があったり、ISO 27000の策定にIPAも関わっていたりします。この意味では不正解です。

世界的に見てもソフトウェア開発者の大半がCWE-20を正しく理解している、とは言い難い状況です。これは数あるオープンソースプロジェクトの現状から判ります。マトモに入力バリデーションを実装しているアプリがほとんどありません。日本だけが遅れている、とは言えません。

しかし、1つだけ確実に「遅れている」と言える事は「IPAは組織としては理解っているハズ」であるにも関わらず、マトモなセキュアプログラミングガイドやWebアプリセキュリティガイドが無かったりする(した)のは事実です。

世界的にも開発者の理解が及ばない/誤解が解けないのはどうしようもない部分もあります。

しかし、日本に於ては旗振り役のIPAが

不適切な入力バリデーションは健康なソフトウェアの一番の殺し屋です。もし開発者が入力データが期待している物でないか確認していないなら、問題を起こしてくれ、と頼む事と同じである

を正しく啓蒙できていない、これでは「日本の情報セキュリティは世界から遅れている」と言われても仕方ないでしょう。

CWE/SANS Top 25 Monster Mitigations M1の原文

原文はこちらです。

M1: Establish and maintain control over all of your inputs.
Target Audience: Programmers
Associated CWEs:   CWE-20 Improper Input Validation

Improper input validation is the number one killer of healthy software, so you’re just asking for trouble if you don’t ensure that your input conforms to expectations. For example, an identifier that you expect to be numeric shouldn’t ever contain letters. Nor should the price of a new car be allowed to be a dollar, not even in today’s economy. Of course, applications often have more complex validation requirements than these simple examples. Incorrect input validation can lead to vulnerabilities when attackers can modify their inputs in unexpected ways. Many of today’s most common vulnerabilities can be eliminated, or at least reduced, using proper input validation.

Use a standard input validation mechanism to validate all input for:

・ length
・ type of input
syntax
missing or extra inputs
consistency across related fields
business rules

As an example of business rule logic, “boat” may be syntactically valid because it only contains alphanumeric characters, but it is not valid if you are expecting color names such as “red” or “blue.”

Where possible, use stringent whitelists that limit the character set based on the expected value of the parameter in the request. This can have indirect benefits, such as reducing or eliminating weaknesses that may exist elsewhere in the product.

Do not accept any inputs that violate these rules, or convert the inputs to safe values.

Understand all the potential areas where untrusted inputs can enter your software: parameters or arguments, cookies, anything read from the network, environment variables, reverse DNS lookups, query results, request headers, URL components, e-mail, files, databases, and any external systems that provide data to the application. Remember that such inputs may be obtained indirectly through API calls.

Be careful to properly decode the inputs and convert them to your internal representation before performing validation.


Applicable Top 25 CWEs:
CWE-120CWE-129CWE-131CWE-134CWE-190CWE-209CWE-22CWE-285CWE-306CWE-311CWE-327CWE-352CWE-362CWE-434CWE-494CWE-601CWE-676CWE-732CWE-754CWE-770CWE-78CWE-79CWE-798CWE-805CWE-807CWE-829CWE-862CWE-89CWE-98

null

CWE/SANS Top 25 Monster Mitigations M1: Establish and maintain control over all of your inputs.
Facebook Comments
Pocket