JSONPathはCSSのセレクタやXPathのクエリのような形でJSON形式のデータを選択/クエリする仕様です。
JSONPathの説明はしないのでオンラインの評価環境で仕様は把握してください。

JSONPathクエリは上記のような”意味を持つ文字”を使ってクエリを実行します。インジェクション攻撃は一文字でも意味がある文字があると攻撃される、と思って構わないです。JSONPathクエリもインジェクション攻撃が可能です。
JSONPathはCSSのセレクタやXPathのクエリのような形でJSON形式のデータを選択/クエリする仕様です。
JSONPathの説明はしないのでオンラインの評価環境で仕様は把握してください。
JSONPathクエリは上記のような”意味を持つ文字”を使ってクエリを実行します。インジェクション攻撃は一文字でも意味がある文字があると攻撃される、と思って構わないです。JSONPathクエリもインジェクション攻撃が可能です。
IPAは”旧セキュアプログラミング講座は更新しない”とWebサイトに記載していましたが、次のブログで「IPAは旧セキュアプログラミングガイドの基礎的誤りを明示し、正しい原則を開発者に啓蒙すべき」と指摘したところ修正されたので第二弾です。
※ 2018年3月に指摘し、少なくとも秋頃には修正されていました。因みに現在セキュアプログラミング講座はCERTのセキュアコーディング習慣(原則)に則った科学的/エンジニアリング的に妥当な解説になっています。
第一弾では「入力処理セキュリティ対策の解説が出力処理のセキュリティ対策の解説になっており、出鱈目である」と指摘しました。修正後のページは改善はされていますが、まだ入力処理と出力処理のセキュリティ対策とを一緒に説明している点はダメなままです。 入力対策と出力対策は実施する場所が異ります。分けて説明すべきでしょう。CERT Top 10 Secure Coding PracticesもCWE/SANS Top 25 Monster MitigationもOWASP Secure Coding Quick Reference Guideも分けています。全て1番目が入力対策でが、IPAの旧セキュアプログラミング講座では入力対策の重要性が理解らないでしょう。
”入力対策”の解説としていた項目が”出力対策”の解説になっていたモノを無理矢理”入力・注入対策”にした、といった事情もあると思います。
しかし、なぜCERTがセキュアコーディング原則の第一番目としている入力対策が独立した項目ではないのでしょうか?OWASP TOP 10:2017を策定する際に「ほぼ全てのWebアプリが十分な入力対策を行っていない」と指摘されています。この現状に異論はないと思います。入力対策の不備がWebアプリにとって大きなリスクとなっています。これは今に始まったことではなく、昔からですが。入力対策解説の不備は第三弾としてブログを書くかも知れません。
今回はSQLインジェクション対策の問題点を指摘します。
セキュアコーディング原則において、インジェクション対策の為に重要な原則は
の2つです。これらに、一般的なプログラミング原則であるフェイルファースト原則とフェイルセーフ原則、ゼロトラストを適用するとセキュアコーディングになります。
簡単なSQLインジェクション対策コードを使ってセキュアコーディングの概念を紹介します。
セキュアコーディング/セキュアプログラミングの原則と技術は国際情報セキュリティ標準(ISO 27000)でも要求される技術です。しかし、根本から誤ったセキュリティ対策の概念が長年啓蒙されています。GDPR対策にもISO 27000は重要です。日本に於てもISO 27000が要求する基礎的対策ができていない場合、法的リスクが非常に高いと言わざるを得ません。
SQL文やコマンド実行には命令と引数を分離するAPIがあります。便利なAPIなのですが、安全性について根本的な勘違いが多いです。
これらは大きな勘違いです。
SQLのデータもコマンド実行のデータも、そのデータ出力の安全性は出力先(コンテクスト)でどのように処理されるかに依存します。
SQLインジェクションもコマンドインジェクションも1つでも間違いがあると大問題となる脆弱性ですが、大きな勘違いはかなり広く浸透しています。どこからこんな”とんでもない誤解”が生まれて、広まるのでしょうか?
Facebookでこんなやり取りをしました。元々公開設定で投稿した物で、議論させて頂いた浅川さんにも「ブログOK」と許可も頂いたので、そのやり取りの部分だけを紹介します。
テーマは「SQLクエリと識別子エスケープ」です。
とあるブログの結論として
“「安全な静的SQLの発行方法」を開発者に啓蒙すればいいだけだ。つまり
- プリペアドクエリでSQL発行は行うこと
この場合変数のバインドは必ずプレースホルダを用いること。SQL文の文字列操作は禁止であり、これほどシンプルなことも無いだろう”
と書かれていました。しかし、私はこの意見に対して
実践的なSQLクエリを書いたことが全くない開発者なのでしょう??
ソートカラム、抽出カラムを指定するSQLクエリでは「識別子(カラム名)が変数」になります。
初歩的なSQLクエリですが”自分が書いたことないから”といって一般的ではないと勘違いしています。行のソート順、抽出カラムを指定するSQLクエリは業務アプリでは”一般的”です。当たり前ですが。こうやってベストプラクティスもどきのアンチプラクティスが使われて、喜ぶのはサイバー犯罪者とセキュリティ業者だけですよ。
とコメントしました。SQLのテーブルやジョイン結果を「表」として表示した際に、任意のカラムのソート順を指定するUIは、自分で作ったことが無かったとしても、ごく一般的だと分かると思うのですが・・・
全てのセキュリティ対策は緩和策だと考えるべきです。これは個々の対策が完全であるか検証することが容易ではないからです。例えば、SQLインジェクション1つとっても本当に完全であるか?検証することは容易ではありません。プログラムが本当に思っているように動作するのか?検証する研究は、まだまだ研究段階です。
しかし、容易ではないからといって諦める訳にもいきません。不完全であっても形式的な論理検証は容易にできます。
'SELECT '.pg_escape_idetifier($_GET['col']).' WHERE '.pg_escape_identifier('tbl').' ORDER BY '.pg_escape_idetifier($_GET['col'])
SQLクエリにはプリペアードクエリを使いましょう!と言われて久しいです。私もプリペアードクエリを積極的に使うべきだと考えています。
しかし、「プリペアードクエリだけを使っていれば良いので、エスケープは要らない」という意見には賛成できません。なぜ賛成できないのか?コードを見れば分かります。
何年か前に議論になった話題です。自分のエントリを検索して、たまたま見つけたのですが物がありました。
例えば、入力バリデーションなしで以下のようなクエリは絶対に安全に実行できません。
$result = pg_query_params('SELECT '.pg_escape_identifier($_GET['col]). ' FROM '.pg_escape_identifier($_GET['table']). ' WHERE id = $1', [$_GET['id']]);
こんなクエリをそのまま書く人は居ませんが、プリペアードクエリ”だけ”ではインジェクション対策にならない事はSQLを知っていれば学生でも理解ります。
特定カラムの抽出/ソート(これはエスケープでぼほOK)、テーブル指定をするクエリは当たり前に存在します。