カテゴリー: Programming

プログラミングの「世界観」

rustcを通らないコードは間違っているに以下のような記述があります。

「そのコードがRust wayではない」という点で「間違っている」。microなスタイルからmacroな設計まで、ありとあらゆる点でRust的なコードであることを暗黙的ではあるが極めて強く要求する。それがRustというプログラミング言語だ。

Rustはコンパイル時点で可能な限りの正しく実行できないコードが生成されないような言語になっていることは比較的良く知られていると思います。このブログはこの違いを「世界観」が異なるという視点でまとめています。

Rustの場合、マルチスレッドプログラミングでデータ競合が起きないような書き方をしなければならない制約があり、従来のプログラミング言語とは異なる考え方(=世界観)が要求されている。自分のコードは正しくても「Rustの世界観では間違っている」としています。

「世界観」の違いで言語やプログラミング方式を捉える考え方は面白いと思います。

もっと読む

覚えるパスワードの作り方

覚えなくて構わないパスワード(ブラウザなどのパスワードマネージャーに記憶させる最強のパスワード)の作り方は、

覚えないパスワードは生成する物 〜 余計な文字数制限などは有害 〜

で紹介しました。最強のパスワードを自分で作るのが面倒な方はこのページのランダム文字列から90文字くらいをコピー&ペーストして使ってください。

今回は覚えられる最強のパスワードの作り方です。

備考:あるニュース記事で”ブラウザのパスワード機能は使わない”とする記事がありました。その理由は、離席した場合などにパスワードが表示できる物もあるから、でした。しかし、PCをログインしたままロックもせずに離席すると、ログイン済みならアクセス仕放題、サードパーティー製のパスワードマネージャーを使っていても利用するサービスにはログイン仕放題、です。デバイスの物理セキュリティは何をしていてもある程度は使い方で保証しなければセキュリティは維持できません。

もっと読む

”形式的検証”と”組み合わせ爆発”から学ぶ入力バリデーション

形式的検証とは

形式的検証(けいしきてきけんしょう)とは、ハードウェアおよびソフトウェアのシステムにおいて形式手法数学を利用し、何らかの形式仕様記述やプロパティに照らしてシステムが正しいことを証明したり、逆に正しくないことを証明することである

英語ではFormal Verificationとされ

formal verification is the act of proving or disproving the correctness of intended algorithms underlying a system with respect to a certain formal specification or property, using formal methods of mathematics.

と説明されています。形式手法として紹介されることも多いです。

参考: 形式検証入門 (PDF)

形式的検証は、記述として検証する方法から数学的にプログラムが正しく実行されることを検証する仕組みまで含みます。数学的な形式的検証では、可能な限り、全ての状態を検証できるようにしてプログラムが正しく実行できることの証明を試みます。

参考:ソフトウエアは硬い (日経XTECHの記事)

契約プログラミング(契約による設計 – Design by Contract, DbC)も形式的検証の1つの方法です。

形式検証の仕組みを知ると、厳格な入力バリデーションが無いと”組み合わせ爆発”により、誤作動(≒ セキュリティ問題)の確率も爆発的に増えることが解ります。

もっと読む

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

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

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

もっと読む

覚えないパスワードは生成する物 〜 余計な文字数制限などは有害 〜

Webサイトにはパスワードの登録に余計な制限をかけているサイトが少なからずあります。特に最悪なのはたった20文字程度のパスワードしか許可しないサイトです。

Webサイトのパスワードは基本的には覚える必要がありません。安全性を第一に考えると十分過ぎるくらいの長さのランダムパスワードを設定する/設定できるようにすると良いです。

参考:覚える場合のパスワードの作り方

TL;DR;

パスワード用のランダム文字列が必要でアクセスした方は以下のURLを参照してください。生成されたランダム文字列の一部、90文字くらい、をパスワードとして使うと安全です。

パスワード用のランダム文字列生成ページ (ランダム文字列を表示します)

もっと読む

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

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

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

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

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

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

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

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

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

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

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

もっと読む

hash_hkdf()でわざわざバイナリキー/バイナリSaltを使うことに意味はない

PHP 7.1で追加された hash_hkdf() は出鱈目なシグニチャを持っています。バイナリキーを使うことを想定して、わざわざ既存のハッシュ関数とは異なり、バイナリハッシュ値だけを返せるようになっています。

暗号化がプログラム内で完結する、といった極一部の例外を除きhash_hkdf()でわざわざバイナリキーを使う意味はありません。

CSRFキーを守るURLを守るAPIキーを守る、といったWebアプリケーションで最も頻繁に使われる鍵導出ではバイナリキー/バイナリSaltは、遅いのでむしろ有害と言えます。わざわざバイナリを使う必要はありません。

参考: HMACハッシュの使い方のまとめ – HAMCですが、HKDFはHMAC based Key Derivation Functionです。多くがHKDFで置き換えられます。HKDFが使える場合、hash_hkdf()を使った方が速くなるでしょう。これはPHPの関数呼び出しのオーバーヘッドが比較的大きいことに起因します。

もっと読む

「脆弱性を局所的に潰す」はアンチプラクティス

本物の「セキュアコーディング」(セキュアプログラミング)を知ればもう議論など必要ない、と思っています。本物の「セキュアコーディング」を「知ろうとしない」と幾らでもアンチプラクティスを作ってしまいます。

議論は終り、と思っていたのですがそうも行かないようなので紹介します。セキュアコーディングの概念を全く知ろうとしないで、セキュリティを作るのは「ただの無駄」です。多数のアンチプラクティス/間違いが含まれるスライドの中から(一々指摘するとキリがない)

  • 「脆弱性を局所的に潰す」

これ”だけ”だとアンチプラクティスです。

※ 契約プログラミングが流行らない理由はこいうアンチプラクティスも原因でしょう。特定の良いこと”だけ”を積み重ねても良い結果にならない、ことは合成の誤謬として知られています。

もっと読む

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

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

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

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

もっと読む

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

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

CERTセキュアコーディング

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

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

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

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

もっと読む

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

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

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

セキュアプログラミング/セキュアコーディングを要求するセキュリティ認証:

  • ISMS – 国際情報セキュリティ標準 ISO 27000 の認証規格
  • PCI DSS – クレジットカード情報を取り扱う場合の認証規格

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

しかし、残念ながらセキュアコーディングの第1原則の「入力バリデーション」は普及しているとは全く言えません。この状況には理由があります。

この状況に責任があるIPAは、IPAのセキュアプログラミング講座 1に基礎的な誤りがあったことを明示し、開発者に与えた誤解が正されるよう、最大限の努力をすべきでしょう。

IPAのあり得ないような基礎的誤りがどのような物だったか、ご覧ください。

追記: IPAは問題のページを更新/削除したようです。

もっと読む

ベストプラクティスもどきのアンチプラクティス TOP 10

ここ十数年で見聞きした、脆弱なアプリを作ってきたベストプラクティスもどきのアンチプラクティス、をリストアップしてみます。

限定された条件ではベストプラクティスと言える物でも、一般化するとアンチプラクティスになる物は多いです。

コード検査をしていると良く分るのですが、アンチプラクティスは強力な破壊力を持っています。ここに書いているアンチプラクティスを無くすだけでも、致命的な問題/脆弱なコードを多数無くすことができるでしょう。

特徴として原理や原則、適切な構造に合致しない物がアンチプラクティスになっています。

  • 原理:コンピュータープログラムは妥当な入力でしか、正しく動作しない
  • 原則:Fail Fast原則、失敗するモノはできる限り早く失敗させる、が守られていない
  • 構造:セキュリティ対策では境界防御、それも最外周の防御、が欠かせないがアプリケーション境界の防御が不十分・不適切

TOP 10と題しましたが、アンチプラクティスの順序と重要性(悪影響)にはあまり関連性はありません。

もっと読む

プログラムから「想定外」を無くす方法

ほとんどセキュリティ問題は「想定外の動作」が原因です。例えば、インジェクション攻撃は開発者にとって「想定外の動作」でしょう。ソフトウェア開発者が意図しない想定外の動作のほとんどは「想定外のデータ」が原因です。

この事実をから簡単に分かる「想定外」を無くす方法があります。たった2つの方法を”両方”行うだけで、現在あるアプリの9割程度の脆弱性が無くなります。

今まで出来る限り正確に「どうすれば想定外をなくせるか?」を紹介してきましたが、今回は出来る限り簡潔にどうすると良いのか、ダメなのか紹介したいと思います。 もっと読む

セキュリティを論理的に構築する方法

セキュリティの原理、原則、ベストプラクティスに自分でコメントを追加しました。以前、論理的にセキュリティ対策を検証する方法論理的なセキュリティ対策の評価方法は書いたのですが、論理的にセキュリティを構築する方法は書いていないことを思い出しました。追加したコメント欠陥だらけのソフトウェアセキュリティ構造を紹介したブログをベースにセキュリティを論理的に構築する方法を紹介します。

このエントリの解説はCERT、つまり米カーネギーメロン大学、の資料をベースにしています。

もっと読む