APIとエスケープ/バリデーションとセキュリティ

PHP Security 11月 26, 2013 #出力対策
(Last Updated On: 2018年8月8日)

今回はセキュリティ対策におけるAPIとエスケープ/バリデーションをどう考えるかの話です。

Cプログラマになろうとしているプログラマにメモリ管理を教えないことは考えられません。メモリ管理を考えなくても文字列の処理をしたりするライブラリなどもありますが、メモリ管理をあまり考えなくても良いAPIさえ使っていればOK、メモリリークもValgrindでチェックしてレポートされなければOK、と考えているプログラマが作ったプログラムが安全である可能性は低いでしょう。

言語やプラットフォームの基本中の基本を避けて通っては安全なプログラムの構築が難しくなるだけです。

安全なプログラムを作るために「プログラマに何を教えるべきか?」が今日のテーマです。

C言語でプログラムを作っているのに「メモリ管理が必要ないAPIをだけ使えば良い」を教えるセキュリティ教育・セキュリティ対策はあり得ません。同じ様にWebアプリセキュリティ対策の基本である「エスケープ処理を教えずにAPIを使えば良い」とするセキュリティ教育・セキュリティ対策もあり得ません。

Webアプリを構築する場合、テキスト型のインターフェース規格を持つ出力先へ出力します。テキスト型のインターフェース規格を持つ出力先には、HTML、CSS、XML、SQL、JavaScriptなどがあります。これらの規格にはAPIを持つものもありますが、規格自体にAPI無が無くフォーマットされた文字列を処理する物が殆どです。一文字でも特殊な意味を持つ文字があると、文字列の持つ意味が改ざんされ攻撃に利用される可能性があります。フォーマットされた安全な文字列を作るにはエスケープ処理とバリデーション処理が必須です。

テキストベースのインターフェースを持つ物にもAPIを作る事は可能ですが、全てのテキストベース型インターフェースがAPIを持っている訳ではありません。むしろ規格としてAPIを持っていない物ばかりです。APIを持っていても利用できない場合もあります。

例えば、HTMLテキストを生成する場合にDOMが利用できます。DOMのAPIを利用してHTML文書などを作れますが、DOMは非常に多くのメモリ・CPUリソースを利用します。HTML文書をテキストとして生成することに比べ非常に多くの手間もかかります。全てのHTML文書を生成する為にDOM APIを使うことは可能ですが現実的ではありません。仮にDOMを使ってHTMLを生成する様、プログラマに強制しても安全なHTML出力になりません。

フレームワークや特定のライブラリを利用してWebアプリを構築する場合、コーディングルールとして間違いを起こしづらい安全性の高いAPIの利用を推奨・強制する事は可能ですし、できる限りそうすべきです。しかし、「出力にAPIを利用する」というセキュリティ対策は「出力セキュリティ対策の基本中の基本」ではないことに留意すべきです。

WebアプリにはHTML文書、CSS、JavaScript/JSON、XPathクエリ、SQLクエリ、LDAPクエリ、メール(SMTPなど)、HTTPなど多くのテキストベースのインターフェースを持つ標準・仕組みを利用します。テキストベースのインターフェースを持つ処理系を安全に利用する為の「基本中の基本」は

  • 適切なエスケープ処理
  • 適切なバリデーション処理

です。セキュリティ対策教育として優先順位を付けるなら「APIの利用」はこれらの次です。

メモリ管理を理解していないプログラムが安全なCプログラムを作れない事とと同じ様に、テキストベースのインターフェースを多用するWebアプリ開発を行うプログラマがエスケープ・バリデーション処理を知らずに安全なプログラムを作ることは出来ません。

APIに制約された範囲内でプログラムを作っていれば、それなりに安全なプログラムを作ることは可能です。この外部システムを利用するには「このAPIを使ってさえいれば大丈夫!」というAPIもありますが、多くのAPIには制限や限界があります。例えば、プリペアードクエリはクエリへの変数埋め込みを制限することは出来ません。パラメータ埋め込みができないORMだけを使うという方法もあり得ますが、複雑な集計処理をORMだけで行うことはあまり現実的ではありません。

APIだけで何とかアプリが作れれば良いのですが、API範囲外の処理が必要になったり、API自体を作らなければならない場合「テキストベースのインターフェースを持つ処理系を安全に利用する為の”基本中の基本”」をしっかり理解しておく必要があります。

とは言っても、開発者になったばかりの人達やこれから開発者になろうとしている人達に「HTML、CSS、JavaScript、JSON、XPath、SQL、LDAP、SMTP、HTTPなどWebアプリで利用されるテキスト型インターフェースを全てきっちり理解してから作りなさい」と要求する事は不可能です。現実的には「中身をよく知らなくてもそれなりに安全に使えるAPIの利用を勧める」事になります。

「結局APIを勧める事になるなら、APIを勧めれば良いじゃないか?」と思うかも知れませんが、APIには制限がある事を忘れてはなりません。プログラマは好き勝手にテキストを出力できるのです。セキュアなプログラムを書くプログラマを育てるなら

  • 安全な出力には適切なエスケープ処理が必要
  • 安全な出力には適切なバリデーション処理が必要

と教えた上で「中身をよく知らなくても安全に利用できるAPIを利用する」を勧める必要があります。その際には「APIの制限」を明確に説明しなければなりません。

廻りくどい事をしなくても、と考える方も居るかも知れません。しかし、プログラムには1つでもセキュリティホールがあればセキュアなプログラムでなくなる事を考えれば必要であることが理解できると思います。

まとめ

「教育」も重要なセキュリティ対策の1つです。プログラミングのセキュリティ対策とは「安全なコードを書けるように教育すること」と言っても良いでしょう。こう考えると教育はプログラマにとって最も重要なセキュリティ対策であると解ります。

APIの利用をすれば良いと教える場合、エスケープ・バリデーションの必要性を理解した上でAPIを利用すれば良いと教える場合、どちらの教え方で育てられたプログラマの方が安全なコードを書くでしょうか?もう既に結論は出ています。

メモリに自由に書き込みができるC言語でのセキュアプログラミングに安全なメモリ管理が必須である事と同様に、テキストを自由に書き込めるPHPを含むLL系言語でセキュアWebプログラミングを実践するには安全なテキスト処理の知識が必須です。

参考

 

投稿者: yohgaki