PHP+PostgreSQLでのSQLインジェクション対策

某大手企業向けのCMSシステムでセキュリティ監査があって、弊社納入のシステムで、ちょっと指摘をいただきました。

実際には、SQLインジェクションが実行可能だったわけではなく、お客様に土下座なんて事態にも至らなかったのですが、知らないことがあったのは事実なので、素直に今後は気を付けようと思う今日この頃。

内容は、以下の通り。全て必須対策だそうです。

コンパイル済みSQLを使用する

$db = pg_connect('dbname=…');
$result = pg_prepare($db, 'query1',
'SELECT * FROM TABLE1 WHERE CITY = $1 AND AGE >= $2');
$result = pg_execute($db, 'query1', array($city, $age));

これは正直言って関数自体を知りませんでした。
最近の入門書には書いてあるのかもしれませんね。
「ベテランであること」と「スキル」は全く関係ないことを痛感しました。

header関数で文字コードを必ず指定する

header("Content-Type: text/html; charset=UTF-8");

こちらに解説がありました。
結果オーライでやっていましたが、XSS対策の一つになるとは知りませんでした。

文字列のエスケープ

pg_escape_string()

これは知ってましたが以下の内容は勉強不足でした。

「’」(シングルクオート)と「\」(バックスラッシュ)のエスケープを実
施している場合でも、文字コードの問題によってSQLインジェクションが発生するケースがあります。
処理系の日本語対応が不十分な場合、シフトJISで2バイト目が「\」(バックスラッシュ)のアスキーコードである「0x5C」になっている文字が入力されると「’」(シングルクオート)が「\(0x5C)」にエスケープされます。
これにより、SQLインジェクションを成立させることが可能となりますので、
対策の際には注意が必要です。
具体的には以下の方法があります。

  • 最新のデータベース接続ライブラリを使用した上で、データベースエンジンにて提供されたエスケープ機能を利用する
  • バインド機構を利用する
  • PostgreSQLの場合は、以下の設定を利用する。この場合円記号「\」のエスケープはしないことに注意。
    backslash_quote = off
    standard_conforming_strings = on

とても勉強になりました。

2009/06/25 追記
徳丸様のご指摘により、standard_conforming_strings = offの部分をonに修正しました。

デフォルトのパーミッション

Linuxには、umaskという密かに便利なコマンドがあって、これを使用するとデフォルトのパーミッションを確認したり、設定することが可能です。

同じグループのユーザー全員に書き込み権限を与えたいときなどは、いちいち「chmod g+w ./foo.txt」なんてことをするよりも、デフォルトのパーミッションを変更したほうが効率的です。

umask 0002

作業開始時に、以上のコマンドを入力すると、そのあと新規作成されるディレクトリやファイルは、グループ全員に対する書き込み権限が設定されます。

以下の例では、foo.txtを作成した際のパーミッションが664になっていることをご確認できるかと思います。

[miya@marlin test]$ umask 0002
[miya@marlin test]$ touch foo.txt
[miya@marlin test]$ ls -al
合計 12
drwxrwxr-x   2 miya group 4096 11月 30 02:56 .
drwxrwxr-x  10 miya group 4096 11月 30 02:56 ..
-rw-rw-r--   1 miya group    0 11月 30 02:56 foo.txt

umaskで指定する数値の意味は、0777(ファイルは0666)からいくつ引き算するかと言うことなのですが、「0022」(これがデフォルトです)か「0002」以外を使うシチュエーションは少ないので、あえて深くは説明しません。

グループに書き込み権限を与えたいときは、「0002」。
デフォルトに戻すときは、「0022」と覚えておきましょう。

ちなみに、umaskコマンドで指定しただけでは、次回ログイン時にはumask設定値が元に戻ってしまいます。
.bashrcなどに記述しておくと次回ログイン以降も自動的に有効になりますが、これは上司の了解を得た方がよいかも。(笑)

ホームページ制作・システム開発のシータネットワークス

mod_perlを使ってhttpd.confをPerlで動的に生成する

意外と資料が少ないのですが、mod_perlを使用するとhttpd.conf内にPerlスクリプトを記述して、Apacheの起動時に動的にバーチャルホストを定義することができます。

この方法を利用すると、データベースやXMLなどからDocumentRootなどの最小限の情報を取得して、全てのバーチャルホストをテンプレートをベースに構築できますので、効率的で安全なバーチャルホストの設定が行えます。

# 以下をhttpd.conf内等に記述する
<Perl>

use Encode;
use XML::DOM;

my $dom = new XML::DOM::Parser;
my $doc = $dom->parsefile('/home/www/vhost.xml');

my $nodes = $doc->getElementsByTagName ("vhost");
my $httpd_conf = '';

for(my $i=0; $i<$nodes->getLength; $i++){

 my $node = $nodes->item($i);
 my $port = $node->getAttribute('port');
 my $name = $node->getAttribute('name');
 my $path = $node->getAttribute('path');
 my $text = Encode::encode(
        'utf8',
        $node->getFirstChild->getNodeValue()
    );

 if($port && $port != 80){
  $httpd_conf .= "Listen $port\n";
 }else{
  $port = '80';
 }
 $httpd_conf .= "<VirtualHost *:$port>\n";
 $httpd_conf .= "DocumentRoot $path\n";
 $httpd_conf .= "ServerName $name\n";
 $httpd_conf .= "</VirtualHost>\n\n";

}

open(OUT, ">/etc/httpd/conf.d/httpd_conf.cache");
print OUT $httpd_conf;
close(OUT);

$PerlConfig = "Include \"/etc/httpd/conf.d/httpd_conf.cache\"\n";

</Perl>
# httpd.confここまで

上記の例は、弊社内の開発用サーバーで使用しているもので、ポートベース及びネームベースのバーチャルホストをXML(/home/www/vhost.xml)を元に生成しています。

ここで使用されているXMLは、PHPのアプリケーション側でも読み込んで、テストサーバーのリンク集を生成するのにも利用されています。

したがって、「おーい、例の○○向けのシステムってURLなんだっけ?」みたいなやりとりを減らす効果もあります。

XMLのサンプルは以下の通り。

<?xml version="1.0" encoding="UTF-8" ?>
<vhosts>
  <vhost name="10.0.0.5" port="8003" path="/home/www.example.com/html">
    www.example.com向けECサイト
  </vhost>
</vhosts>

ちなみに、Apacheの1.3系と2.x系では記述内容が違います。
今回紹介している例は2.x系でのサンプルですが、2.X系ではセキュリティ上の制限が加わっているらしく設定できる項目に制限があるようでした。(詳細は勉強不足で不明です。)

それを回避するために、httpd_conf.cacheというファイルに一度書き出して、それをincludeするという方法をとっています。

この例は外部に全く公開していないテストサーバーでの事例なので、セキュリティについては多少目をつぶっています。

というわけで、器用貧乏な弊社ではLinuxサーバー構築のお問い合せをお待ちしています。

rsyncは正しく使いましょう

某超大手のお客様のサーバーがつぶれたので、コールドスタンバイのマシンにrsyncで保存してあったデータを、さらに別のマシンに移動することになった。

リカバリーするのにブッツケ本番ではダメでしょうとうことで、うちのサーバーを使って念のためテストすることに。。。

まずは、rsyncを使ったバックアップからと思って以下のコマンドを実行。

rsync -avz --delete / root@10.0.0.6:/

安易でした。
本当に後悔。

しばらく順調だったのですが、/sysまで進んだところでエラーを出力。
あれ?と思ってlsコマンドを打ったら、「command not found」。

むむ?と思ってもう一度打ってみても「command not found」

というわけでコピー元、コピー先ともにお亡くなりになりました。

安易と言えばそうなんですけどね。
確かにコピー先は多少トラブルがあることを想定してたんですけど、コピー元もお亡くなりになるとは想像しないですよ。しかもバックアップ用のコマンドで。。。

よかったテストして。。。(泣)

結局、本番では/home、/var、/usr、/lib、/etcのみを対象にしてrsyncを実行したら平和に終わりましたが、これは正しかったんだろうか?
(あれから1週間たちましたが各デーモンは問題なく動いています。)

そもそも、この現象は何で?
後学のために心当たりのある方はコメント下さい。

というわけで、我が身を犠牲にしてでもテストをする弊社では、Linux関連のお仕事をお待ちしています。

JavaScriptでPHPのnumber_format()

http://www5c.biglobe.ne.jp/~horoau/js_library/comma.htmlで公開されているソースを元に、JavaScriptのクラスを作成したので、配布します。

ダウンロード

メソッド名を、PHPで同様の機能を提供する関数「number_format()」と合わせたのと、マイナスにも対応しています。(だから、ほとんどパクリじゃんって突っ込まないで下さい。)

使用方法

head要素内等で本スクリプトを読み込んでください。
あとは、以下のようなコードを記述すると、戻り値にコンマがつけられます。

 var str = 1111; // 値は数値型でも文字列型でも可
 alert( str.number_format() ); // 1,111

不明な点がありましたら、コメントに書き込んでいただければ、なるべく早くご回答します。

2010/08/24 追記
prototype.js が必要と記述していましたがいりませんでしたので、その記述を削除しました。
本スクリプトは単品で動作します。

ライセンス

MITライセンスとします。
ただし、気に入っていただけた方からの寄付は歓迎します。

BloggerのテンプレートにJavaScriptを挿入する

Amazonのアフィリエイトバナーをこのブログに挿入するために、Amazonアソシエイトで取得したJavaScriptソースを貼り付けたら、なぜかうまく動かなかった。

何でだろうと思ってブログのソースを見ると、JavaScriptのソース内の改行が消えている。

この問題は、以下のように記述することで解決。

変更前:

<script .....>
.....
.....
.....
</script>

変更後:

<script .....>//<![CDATA[
.....
.....
.....
//]]></script>

めんどくさ。

ちなみにやりたかったのはヘッダの真下にあるAmazonの広告。
Amazonのインスタントストアってやつを使って本屋さんを開店してみました。


JavaScriptやAjaxに関する開発のお仕事承ります。

linuxコマンドで添付ファイル付きメール送信

データセンターなんかで作業をしていると、ログなどを持ち帰って解析したいことがある。

mail -s "logs" foo@example.com < /var/log/httpd/error_log

などのようなコマンドを実行すれば、単純なテキストファイルなら送信可能だが、圧縮データなどのバイナリを添付ファイルとして送信したいことがある。

そのような場合は、以下のようなコマンドを実行する。

uuencode path2file filename | mail -s "attach file" foo@example।com

uuencodeコマンドが無い場合は、redhat系なら以下のコマンドを実行してインストールする。

yum install sharutils

ひとつひとつのコマンドだけ見ると存在価値が分からないけど、パイプでつなげるとなるほどと思う今日この頃。

ちなみにLinuxサーバー構築承ります。

とりあえず

Bloggerを試してみたかったので開設。
制作会社の人間なので、他社のものを使うのはプライドが許さないような気もするけど、ビル・ゲイツさんもMacファンらしいとの噂を聞いたので、うちみたいな小さな会社の人間のプライドなんか小さい小さい。

技術的な内容の覚え書きが主になると思います。