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

SQL識別子のエスケープ

SQLのリテラルはエスケープが必要であることは広く認知されていると思います。しかし、識別子のエスケープはあまり広く認知されていないように思います。

PostgreSQLの場合、識別子のエスケープAPI(libpqのPQescapeIdentifier)が提供されておりPHPでもpg_escape_identifier()として利用できます。PostgreSQLの場合は”(ダブルクオート)で識別子を囲むことにより、ダブルクォート無しでは利用できない文字(例えば日本語)も識別子に利用できるようになります。
もっと読む

LDAPエスケープ – PHPのldap_escape関数

OWASP TOP10の1位のセキュリティ脅威はインジェクションです。

https://www.owasp.org/index.php/Top_10_2013-A1-Injection

SQLインジェクション、コマンドインジェクションはリファレンスとして掲載されていますが、何故かLDAPインジェクションは掲載されていません。しかし、OWASPの別の文書では簡単に解説されています。

もっと読む

セッションID管理は結局どうすれば良いのか?

脆弱性やセキュリティ対策について技術的な話ばかりしていたので「それで結局PHPのセッション管理どうすれば良いの?」と思われた方も多いと思います。簡単にまとめます。漏れや追記した方が良い事などがあったらご指摘ください。

もっと読む

プログラミングではホワイトリスティングが基本

ホワイトリスト方式の優位は神話」と題するエントリに私のブログホワイトリストはどう作る? が引用されている事を教えていただきました。

ホワイトリストの基本中の基本は”デフォルトで全て拒否する”であることに注意してください。全て拒否した上で、許可するモノ、を指定しないとホワイトリストになりません。

誤解されないように書こうとすると、どうしても長文になります。暇な方だけお付き合いください。

参考: セキュリティを論理的に構築する方法 (こちらは科学的なセキュリティの基本構造の作り方の話です。ぜひどうぞ) もっと読む

ホワイトリストはどう作る?

まずホワイトリストの基本中の基本は”デフォルトで全て拒否するであることに注意してください。全て拒否した上で許可するモノを指定しないとホワイトリストになりません

例えば、CSPはホワイトリストで不正なJavaScriptの実行を防止する仕組みです。2016年のGoolgeの調査によると95%のCSP定義が、実際にはJavaScriptインジェクション脆弱性の防止に役立っていない、との調査結果を発表しています。原因はホワイトリストの作り方の基本、全て拒否した上で許可するモノを指定する、を理解していないことにあると考えられます。1

私はいつも基本的に能動的なセキュリティ対策2を選択するようにお勧めしています。能動的なセキュリティ対策とは全ての入力値の厳格なバリデーション処理であり、出力時に過剰とも言えるエスケープ処理です。入力/出力の両方にホワイトリスティング対策をお勧めしています。3

もっと読む

SET NAMESは禁止

MySQLには文字エンコーディングを変更する「SET NAMES」SQL文が用意されています。(PostgreSQLも同様のSQL文、SET CLIENT_ENCODINGがあります)この機能はSQLコンソールからは使ってよい機能ですが、アプリケーションからは使ってはならない機能です。SQLインジェクションに脆弱になる場合があります。

Ruby on Railsの本を読んでいて、ActiveRecordを説明している部分にMySQLの文字エンコーディングを変更する場合の例としてSET NAMESが利用されていました。アプリケーションからはSET NAMESは使ってはならない事を周知させるのは結構時間が必要かなと思いました。

PHPも5.2の途中からMySQLモジュールにlibmysqlの文字エンコーディング設定APIのラッパー関数が追加されていたりするので、たまたま最近読んだRoRの本だけでなく、多くの開発向け情報ソースにSET NAMESを利用した例が載っていると思います。

ストアドプロシージャだけ使っていれば安全ですが、アプリケーションからDBMSの文字エンコーディングを設定する場合、SQL文ではなく必ず文字エンコーディング設定APIを利用するよう紹介しなければならないです。MySQL4はストアドプロシージャが使えないので、フレームワークなどではエミュレートしています。ストアドプロシージャだけ使って防御している「つもり」で防御になっていない場合もあります。これもフレームワークを使っていてもアプリケーションが脆弱になる良い例ですね。

脆弱性の説明は面倒ですが注意事項は簡単です。「DBMSをアプリケーションから利用する場合、文字エンコーディング設定は必ずAPIを利用する」つまり「SET NAMES(PostgreSQLのSET CLIENT_ENCODING等も)は禁止」です。

PHPのMySQL:

PHPのPostgreSQL:

PHPのPDO:

<?php
// MySQL
$pdo = new PDO(
    'mysql:host=yourhost;dbname=yourdb;charset=sjis',
    'user', 'password'
);

// PostgreSQL
$pdo = new PDO(
    "pgsql:host=yourhost;dbname=yourdb;options='--client_encoding=sjis'"
);

Rails:

config.encoding = 文字コード