Sep - 12th

MySQLのカラム複製脆弱性

Posted at 3:45 pm | Filed Under MySQL, PHP, PostgreSQL, Security, WordPress

昨日書いたMySQLの脆弱性ですが、手元の環境で見事に再現しました。MySQLのバージョンはCentOSでyumからインストールしたmysql-4.1.20-3.RHEL4.1.el4_6.1です。

手順は以下の通り。まずデータベース、テーブルを作成します。

mysql> create database sec_test;
Query OK, 1 row affected (0.02 sec)

mysql> use sec_test
Database changed
mysql> create table test (username char(16));
Query OK, 0 rows affected (0.01 sec)

ご覧の通り、char(16)でusernameというカラムを持つテーブルを作成します。

まず「admin」というusernameを持つ行を作ります。

mysql> insert into test (username) values ('admin');
Query OK, 1 row affected (0.00 sec)

mysql> select count(*) from test where username = 'admin';
+----------+
| count(*) |
+----------+
|        1 |
+----------+
1 row in set (0.00 sec)

出来ています。

次に、問い合わせの文字列部分の後ろに空白を追加してみます。全部で16文字になるようにしました。

mysql> select count(*) from test where username = 'admin           ';
+----------+
| count(*) |
+----------+
|        1 |
+----------+
1 row in set (0.00 sec)

後ろの空白が無視されているのがわかります。update:正確にいえば、char型なので指定された長さ未満の文字列は空白文字で埋められるみたいです。null文字とかじゃないんですね。

次に、char(16)の範囲を超えたところで「x」を追加して検索してみます。

mysql> select count(*) from test where username = 'admin           x';
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

さすがにヒットしませんでしたが、そもそもカラムの制限長を超えているのにエラーにはなりません。

では、この値をINSERTしてみます。

mysql> insert into test (username) values ('admin           x');
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> select count(*) from test where username = 'admin';
+----------+
| count(*) |
+----------+
|        2 |
+----------+
1 row in set (0.01 sec)

「admin」としてINSERT出来てしまいました

これで、(1)既存のデータに重複行があるかチェック(2)なければINSERT、という処理で重複登録を防ごうとしてもダメなことがわかります。

ちなみにPostgreSQL 7.4.19でテストすると

db_test=# create table security_test (username char(16));
CREATE TABLE
db_test=# INSERT INTO security_test (username) VALUES ('admin');
INSERT 0 1
db_test=# SELECT COUNT(*) FROM security_test WHERE username = 'admin';
 count
-------
     1
(1 row)

db_test=# SELECT COUNT(*) FROM security_test WHERE username = 'admin           ';
 count
-------
     1
(1 row)

db_test=# SELECT COUNT(*) FROM security_test WHERE username = 'admin           x';
 count
-------
     0
(1 row)

db_test=# SELECT COUNT(*) FROM security_test WHERE username = 'admin            ';
 count
-------
     1
(1 row)

db_test=# INSERT INTO security_test (username) VALUES ('admin           x');
ERROR:  value too long for type character(16)
db_test=# SELECT COUNT(*) FROM security_test WHERE username = 'admin';
 count
-------
     1
(1 row)

db_test=#

INSERTはできません。8.3.3でも。

db_test=# create table test (username char(16));
CREATE TABLE
db_test=# INSERT INTO test (username) VALUES ('admin');
INSERT 0 1
db_test=# SELECT count(*) FROM test WHERE username = 'admin';
 count
-------
     1
(1 row)

db_test=# SELECT count(*) FROM test WHERE username = 'admin           ';
 count
-------
     1
(1 row)

db_test=# SELECT count(*) FROM test WHERE username = 'admin           x';
 count
-------
     0
(1 row)

db_test=# SELECT count(*) FROM test WHERE username = 'admin            ';
 count
-------
     1
(1 row)

db_test=# INSERT INTO test (username) VALUES ('admin           x');
ERROR:  value too long for type character(16)

INSERT時にあふれた分が勝手にカットされることはありませんでした。

Read More>

Sep - 10th

WordPress 2.6.2はセキュリティ修正

Posted at 6:06 pm | Filed Under PHP, Security, WordPress

WordPress2.6.2が出たのでさっそく更新したが、今回のリリースにはセキュリティ関連の修正が入っていた。

1 推測されやすい乱数生成の問題

PHPのrand関数はlibcのrandのラッパで、mt_randはメルセンヌ・ツイスタ擬似乱数生成装置の実装なのだが、どちらも32ビット型符号なし整数をシードにしている。しかし、実装の問題により実際にはそれ以下の強度にしかならないそうだ。そのため、暗号化に際してこれらの関数を利用するのは不適切ということになる。それに対処したようだ。

2 MySQLのクエリの長さ制限の問題

MySQLではデフォルトでサーバとクライアント間で送信されるクエリとその応答の長さがmax_packet_sizeディレクティブ(っていうのかな?それはApacheだけ?)で1MBに制限されている。もし1MBを超えたクエリがクライアントから送信された場合、MySQLサーバ側でエラーとして処理してしまう。

たとえば、期限の切れたセッションデータをDBから削除するようなクエリがあり、意図的にこのクエリが長くなるようなデータをセッションに埋め込むことができれば、クエリはいつまでも実行されず、何かしら問題が起きることになる。

update: もっとすごい問題があった。

3 MySQLのダメダメな文字列比較ルール

MySQLにこんなクエリを投げる。

SELECT * FROM user WHERE username = 'admin';

たとえば、ユーザ登録の際に登録名の重複チェックをしているとしよう。WordPressのように、そのサイトにはadminという名のユーザが必ず存在するとして考える。新規のユーザが登録時に「admin」という名前を使おうとすると、上のようなクエリでチェックが行われ、すでに登録されている名前であるとしてアプリケーションによって登録がはじかれる。まあ、そういう仕組みのウェブアプリがあるものと思ってもらいたい。

このusernameというカラムが、たとえばchar(16)だったとする。MySQLではSELECTによる比較時にクエリ内の文字列の後ろの空白は無視されるようになっている。「admin           」だと、

SELECT * FROM user WHERE username = 'admin           ';

こうなるが、実際には最初のクエリと同じ扱いになる。

ところで、じゃあ「admin           x」という名前を使おうとしたらどうなるだろう。ここでは意図的に名前をchar(16)から外れるようにした。数えにくいかもしれないが、17文字ある。

SELECT * FROM user WHERE username = 'admin           x';

MySQLでは、比較の際にはカラムの型を無視してくれるので、上のSQLは何も返ってこない。つまり、新規登録可能なユーザ名として認識される。そこで、INSERET処理を実行すると、今度はカラムの型をみて余分なところはカットし、さらに後ろの空白を取り除くので、あれま、「admin」という名前でユーザ登録が完了してしまう。

これでadminアカウントの乗っ取りが完了する。ひええ。

もちろん、UNIQUE INDEXで対処することは可能だが、そうでないアプリケーションなら困ったことになる。

未検証なのでなんともいえないが、本当だったらこわい。

update:再現しますた

Read More>

Jun - 11th

アレックス

Posted at 10:16 pm | Filed Under Apple, Family, WordPress, life

息子の保育園の同級生に、アレックスという子がいた。太っちょで元気な、甘たれでやさしい子だった。かみさんにもよくなついていたし、息子とも仲良くしてくれていた。

次男が生まれて名前を考えていたとき、アレックスのことを思い出した。アレックスっていい名前だよな。王の名前だもん。しかもただの王じゃない。アレキサンダー大王は東欧からインドの手前までを版図とする大帝国を築き上げ、インドの手前で引き返したのが今でも謎といわれるくらいのとんでもない大王で、ずっと後世までその名を冠した都市アレクサンドリアはローマ帝国が燃やすまで巨大な図書館があったりしてずっと栄えていたし、家庭教師ときたらなんとアリストテレスだもん。

町山智浩の「ツォツィ」の映画評でずっと心に残っていた一言がある。

何の希望もないツォッツィはその赤ん坊に自分の本当の名前をつける。

 デイヴィッド。

 今はクズ同然の彼も、王の名を持って生まれてきたのだ。

こうして取り出してみると、本当になんでもないような言葉かもしれないが、これを読んだときから、なぜかずっと心に引っかかっていた。息子に王の名前をつけるって、どういうことなんだろう、とか。

アレックスも、日本人ばっかりの普通の小学校に進学したと思うから、きっと今頃は周囲の子たちと違うってことでいろいろ苦労しているんだろうな。でも、お前の名前は大王の名前だし、他にもアレックス・ラミレスとかアレックス・カブレラとかアレックス・ロドリゲスとか野球のスーパースターたちと同じ名前でもあるんだから、そんなのに負けないでがんばれといいたい。

だいたい、コスモポリタンって言葉もアレクサンダー大王時代に成立した概念だったはずだ。アレクサンダーの巨大な帝国が、当時、ヨーロッパと地中海沿岸地方と小アジア、西アジア、南アジアに至るまでの広い地域が突然ひとつの国となって交流が盛んになり、民族とか人種という小さな枠では収まりきらない新たな世界観を人間が手にする契機になったという話だったとはずだが、それを考えると、やっぱりまわりの連中とちょっとばかし違うなんてどうでもいいことは吹き飛ばして元気にやっていてくれたらいいなと切に思う。

Read More>

Jun - 1st

息子のブログ

Posted at 5:56 pm | Filed Under Family, WordPress

小学3年生の長男が自分でもサイトを作りたいというので、ドメインを取得してWordPressを設定した。

まだ操作方法はよくわかっていないので、一緒に画面を見ながら更新している。こういう文章を書いてくれと頼まれた内容を親が書き込んで、それを息子が読んで判断して掲載しているので、基本的には息子の意見が反映されている。

ちょびたんしんぶん

将来的にどうなるかわからないが、興味深く見守るべきだろう。

Read More>

Apr - 26th

WordPress 2.5.1

Posted at 7:17 pm | Filed Under Security, WordPress

公表されていないセキュリティ上の問題が修正されたWordPress2.5.1がリリースされている。

うちのサーバはみんな更新した。

Read More>

Apr - 8th

WordPress2.5の謎

Posted at 12:17 am | Filed Under WordPress

xmlrpc.phpを呼び出してもなぜかエラーが発生するので、ここをみてダウンロードし直したWordPress2.5のxmlrpc.phpと差し替えたら、なぜか動いた。

両方のファイルのdiffを取ってもmd5sumでも違いがないのが解せない。

Read More>

Feb - 7th

WordPress更新

Posted at 8:58 pm | Filed Under Security, WordPress

セキュリティ更新。xmlrpc.phpに問題があったらしい。詳細はまだ見ていないが、どうやら第三者に投稿権限が奪取されてしまうようだ。

Read More>

Dec - 30th

WordPress更新

Posted at 11:39 am | Filed Under WordPress

Bugtraqに上がっていた問題修正されていた。

Read More>

Oct - 27th

WordPress2.3.1に更新

Posted at 11:23 pm | Filed Under WordPress

このサーバでホストしているWordPressを2.3.1に更新。

Read More>

Sep - 27th

AirPress

Posted at 8:23 pm | Filed Under WordPress

AdobeのAIRを使ったWordPress管理クライアント、AirPress

まだ日本語は使えない。

Read More>

keep looking »