PEAK XOOPS - 記事一覧
| 発行日時 | 見出し |
|---|---|
| 2009-1-7 4:37 |
大きな傘のSQL Injection版
![]() ![]() XOOPSに限らず、いろいろなPHPアプリケーションで、今でもちょくちょくSQL Injection脆弱性が出てきます。それもケアレスミスです。 もちろん、ケアレスミスは人力では根絶不可能であり、SQLを文字列として生成すること自体をやめて、パラメータ方式で呼び出すべきだ、という方が本質的な議論でしょう。 ただ、オープンソースの世界では、自分の考えを他者に押しつけることはできませんし、SQL Injectionの可能性ある「誰か」の書いたコードを一切利用しない、というのも現実的ではありません。 事実として、SQL InjectionはXSSとは比べものにならないくらい恐い攻撃です。もし私がオープンソースアプリケーションで構築された特定のサイトを攻撃するとしたら、最初に狙うのはSQL Injectionでしょう。なぜならXSSやCSRF、セッション関連の攻撃と違い、即座に直接攻撃可能だからです。(さすがにコマンドインジェクションとかRFIはない、という前提で) そういうわけで、Protectorでは、SQL Injection対策っぽいものも入っているのですが、私自身、あまり役に立っている気がしません。攻撃者がProtectorの対策コードを読めば、明らかに抜け道だらけです。(本当に役に立ったとすれば「最後にidのつくリクエスト変数名について強制的にintval()をかける」くらいでしょうが、これも副作用が大きすぎます) 強力なSQL Injection対策ができない理由は簡単で、本当に必要なリクエストと区別がつかないからです。「UNIONをUNI-ONにする」なんてのも、本当はあってはならないことです。UNIONという単語を使ったまともな投稿が勝手に書き換わってしまいます。 入口であるリクエストだけで判断している以上は、ここが限界となりますが、大きな傘anti-XSSシステムと同様、入口と出口の両方を押さえれば、かなり有力な手段となるでしょう。 anti-XSSでは、出口はobフィルターでした。XSSになる可能性があるリクエストがある時のみob_start()をかけて、出力にリクエストがそのまま含まれるようならXSSとして停止する。 これをSQL Injectionにあてはめると、出口は当然クエリ関数(メソッド)となります。SQL Injectionになる可能性があるリクエストがある時のみ、DBレイヤーを乗っ取って、クエリ本文(クオーテーション外)にリクエストが含まれるようならSQL Injectionとして停止する。 …とまあ、文章として書くのは簡単なのですが、SQL Injection用の出口処理は結構面倒です。SQLをちゃんとパースする必要がありますから。 また、この仕掛けをXOOPS用Protectorとして採用する場合、もう一つ問題があります。それは、現状のDBレイヤーは、途中で乗っ取ることが不可能、ということです。この点は、コア側に対応してもらう必要があるため、別エントリにしたいと思います。 ちなみに、今回私が考え出した(と思っていた)方法ですが、元ネタがあったのを思い出しました。 「本質的なSQL Injection対策のためにはDBレイヤーを乗っ取るしかない」 と、もう4年も前にJM2さんが指摘していました。流石としか言いようがありません ![]() |
| 2008-12-28 18:02 |
dirnameのcase依存性
![]() ![]() 先日、gusagiさんより、bulletinHDについてのバグレポートとして、以下のURLを転送してもらいました。 http://ryus.co.jp/modules/d3blog/details.php?bid=107 先に結論から書くと、このエントリはMySQLの基本的なcase sensitiveルールを誤解していることによる、間違ったレポートです。 Quote:
この時点でバグでも何でもありません。まずはこっちを読んでください。 http://dev.mysql.com/doc/refman/4.1/ja/name-case-sensitivity.html Quote:
そういう「仕様外」のことをやりたければ、lower_case_table_names=1 を使うべきでしょうし、もしなんらかの理由でソースコードを改変するしかない場合でも、Database::prefix()の方にかければ一箇所で済みます。SQL生成部すべてにstrtolower()をかける、という方法はメンテナンス性という観点からも筋が悪すぎます。 # 個人的には、Case sensitiveな環境がターゲットなのに、Case insensitive環境で開発しているっていうのがあり得ない… ただ、このレポートのおかげで私も一つ勘違いしていたことに気付きました。 それは、caseしか違わないdirnameで、2つのモジュールが同時には動かせない、ということです。 当たり前ですが、case sensivie環境で動かすのなら、XOOPSにおけるdirnameも原則的にcase sensitiveです。例えば、XUGJのQandAフォーラムは、あくまで"QandA"であり"qanda"ではありません。(中身はd3forum) http://www.xugj.org/modules/QandA/ 上のリンクは生きてますが、 http://www.xugj.org/modules/qanda/ 下のリンクは死んでます。 「つまり、D3モジュールでありさえすれば、picoがインストールされている環境でも、PICOというdirnameで別のモジュールとしてインストールできるだろう」 ここに思い込みがありました。 実際にはcase sensitiveな環境でもインストールできません。 なぜならSQLとして以下のクエリで判断されるからです。 この 'PICO' はcase insensitiveに比較され、'pico'と一致します。 つまり、インストール済だよ、というメッセージで拒否されます。当たり前ですが、インストーラだけを無理矢理通過させても意味がありません。やはり同様のクエリによって、モジュールの分岐処理がなされるからです。 では、どうすれば良いのか。答えは簡単です。 としてあげれば良いのです。dirnameカラムにbinary属性を加えることによって、case sensitiveになりました。 これを実際に試してみると、picoとPICOが普通に共存できました。 まあ、そんな需要もほとんどないとは思いますが、ちょっとしたTipsくらいに覚えておくと、今後役に立つことがあるかもしれません。 なおこの場合、言語定数オーバーライド機能の一部が、picoとPICOでは独立して働きません。 それは、 というコードによるものです。 考えてみたら、定数名が大文字である必然性などどこにもなく、strtoupper() を$dirnameにかけることは、バグ以外の何物でもないでしょう。 今後のD3モジュールでは、$constprefへのstrtoupper()を外していきます。(各種言語ファイルに含まれてしまっているのがかなり面倒だったりしますが…) |
| 2008-12-14 6:04 |
altsysの大掃除 :-)
![]() ![]() 日本では年末に大掃除を行う習慣があります。 家中のガラス拭きをやった勢いで、altsysのmyblocksadmin機能について大掃除してみました。(半分嘘 )実際、myblocksadminは私が積極的にメンテしているコードの中では最悪クラスの汚さで、機能的にも、WYSIWYG対応もspawのみ、新コアについてもXOOPS2.2のみ、と半端でした。 どうやら本家はXOOPS2.2を切り捨てることを完全に決断したようで、2.3という番号を冠しながら、中身は2.0.18の改良版のようなので、XOOPS2.2対応はやめました。いろいろ問題のあるspawもやめてます。 その代わり、というわけではないのですが、ImpressCMSに正式に対応しました。これで、D3モジュール群がImpressCMSでストレスなく使えると思います。正直、本家版についてまで、動作確認している暇はないのですが、XOOPS_VERSIONを見て、2.3なら、ImpressCMSと同じ扱いにしています。もしブロックポジションなどの仕様が同じであれば、XOOPS2.3でもすんなり動くかもしれません。 もちろん、WYSIWYGはcommon/fckeditor(fckxoops)に対応しています。これが入っていなければ警告が出るという親切設計! ![]() XCL2.1コアの機能で、ブロック編集画面で表示対象グループが選べる、というのも、絶対にあった方が利便性が高そうなので、ついでに実装してます。ただ、これをまともにやると、group_permissionテーブルのgperm_idが異常に増大しそうなので、表示対象グループに変更がなければ同テーブルはいじらない、なんてあたりにも一応手間をかけました。 まるまる書き直した関係で、バグもいろいろありそうですが、ベータ版等と分けて管理する余裕もないので、一発勝負で0.70としてリリースしてます。 もし不具合があったらコメント等の方法で教えてください。 |
| 2008-11-29 4:45 |
ProtectorにLFIだそうです(笑)
![]() ![]() xoops.org (Mamba) がこんなニュースを出しました。 Security : Protector Security Fix for XOOPS 2.0.x and 2.2.x users 先に結論から言うと、無意味なレポートなので、無視して構いません。 XOOPS_TRUST_PATH内のファイルにアクセスされたらLFIだ、なんてトンデモなレポートですから ![]() この世の中には、DocumentRootの外に置く部分と中に置く部分が別れているアプリケーションはごまんとあります。 むしろそういうアプリケーションの方が正しい設計であり、全部をDocumentRoot内に置く古いXOOPSの構造こそある意味おかしいと言えます。 もし、前者のようなアプリケーションについて、DocumentRoot外に置かれるべきコードをDocumentRoot内に置いて、そこに直接アクセスされたとしたら、そりゃあゴロゴロと「脆弱性」が出てくるように見えるでしょう。 少なくとも、PathDisclosureくらいはいくらでもあります。 でも、誰もそんな馬鹿げたレポートはしません。 なぜなら、DocumentRootの内か外か、というのは非常に重要な違いであると言うことを誰もが知っているからです。 XOOPS_TRUST_PATH はDocumentRootの外に置く これは大原則です。 こんなニュースを出すという時点で、xoops.org は誰もセキュリティの基本を知らないことを露呈してしまっています。 (ニュースだけならサイト管理者であるMamba氏が無知なだけでしょうけど、ご丁寧にもphppp氏がメールで問い合わせまでしてきてます) 翻って、ImpressCMSを見てみると、彼らはちゃんとXOOPS_TRUST_PATHの意味を理解していることが判ります。例えば、mainfile.php 内のパスワード部分を、XOOPS_TRUST_PATH内に別ファイルとして保存しています。 (本当に必要かどうかはともかく) つまり、xoops.orgからリリースされるXOOPSという名前のCMSより、ImpressCMSの方がお勧めだと言えるでしょう。 |
| 2008-11-12 4:08 |
serialize()とvar_export()の比較 (2)
![]() ![]() serialize()/unserialize() var_export()/eval() A)安全性 この2つのペアを一見して判るのが、後者でeval()を使う怖さです。当たり前ですが、var_export()の出力であることが保証されているテキストでなければ、アンシリアライズしてはいけません。 もっとも、unserialize()についても、ちょっと古いPHPであれば、バッファオーバー脆弱性があったわけで、シリアライズテキストがリクエスト依存、という状況はいずれにせよあり得ないでしょう。 B)速度 結果から書いてしまうと、serialize()/unserialize() の方がだいぶ速いようです。 こんな感じのベンチプログラムで検証してみました。 あくまでCLI版での検証ですが、赤は青のだいたい3倍くらいかかってます。PHPバージョン依存も確認してみましたが、PHP4.4.xでも5.2.xでも、同じようなパターンです。 ただ、eval()だけが遅いのかと思いきや、var_export()単独でも、serialize()の3倍かかります。 もちろん、この検証で重要なのは絶対値です。具体的な数字は書けませんが、シリアライズ/アンシリアライズなんてもともと小さな処理です。そこが3倍かかったくらいで、全体の処理にはほとんど影響ないはずです。(もちろん、大量に処理するケースでは避けた方が無難かも知れません) C)使いやすさ var_export()の圧勝です。 エンコーディング変換によるトラブルがなくなるだけでなく、シリアライズ形式でデータをいじることも、serialize()によるものより、はるかに楽です。 D)結論 失われてもさほど問題にならないデータや、大量のデータなら serialize() 重要性の高いデータで、さほど量が大きくないなら var_export() という形で使い分けるのが良い気がします。 unserialize()で復元できなかった時の痛さと言ったら… E)余談 ここでいきなりXOOPSの話題になって恐縮ですが、拙作picoでは、追加フィールド機能やフォーム機能で、serialize()/unserialize()を使っていました。しかし、この結論から、今後は、var_export()/eval()に変更していきます。 |
| 2008-11-11 18:28 |
serialize()とvar_export()の比較 (1)
![]() ![]() PHPで配列やオブジェクトをシリアライズする際、一般に利用されているのはserialize()です。 しかし、serialize()されたテキスト形式が、結構やっかいです。 具体的には日本語などのマルチバイト処理と極めて相性が悪いのです。 もし、serialize()された状態で、テキストエンコーディングをEUC-JPからUTF-8に変更したりすると、もうunserialize()は効きません。フォーマットがバイト長に依存しているからです。 これだけなら、プログラミングレベルでカバーも出来るのですが、もっと厄介なのが、DBの自動エンコーディング変換とからむケースです。 たとえばXOOPSでは、セッションをDBに保存しています。そのセッションに日本語テキストをserialize()された状態で入れてしまうと、DBの自動エンコーディング変換で、テキストが元と別物になってしまうことがあります。MySQL4.1以上だと、内部的には常にUTF-8でデータを保持しています。EUC-JPのテキストに対しては、常にUTF-8への変換行われるので、EUC-JPとして取り出したとしても、実際には、 EUC-JP -> UTF-8 -> EUC-JP という変換がかかっているのと同じです。そして、その際にどこかでバイト長がずれれば、unserialize()が効かなくなり、セッションが失われるわけです。 ここでクローズアップされるのが、PHPビルトイン関数だけで可能な、もう一つのシリアライズ方法です。 var_export()であれば、 のようなテキストにシリアライズするので、eval() によってアンシリアライズ可能です。 そして、このテキストであれば、バイト長問題は発生しません。シリアライズしたテキストをエンコーディング変換しても、変換された状態でアンシリアライズ可能です。 …と、ここで時間切れなので、そのメリット・デメリット論は次回に。 |
| 2008-10-30 16:04 |
XOOPSにおけるSnoopy脆弱性の影響
![]() ![]() Snoopyにコマンド実行脆弱性が見つかっています。 http://jvn.jp/jp/JVN20502807/ 現実には、XOOPS各フォークのコアで、任意のURIをSnoopyに渡す、ということはありませんし、各モジュールについても、Snoopyで取得するURIについては、管理者以外は指定できないものがほとんどだと思うので、ほぼすべてのXOOPSサイトでそれほどの緊急性はないでしょう。慌てず騒がず、今後でてくる新バージョンにバージョンアップすれば十分です。 ただ、もし、ゲストが投稿したURIからRSSやサイトイメージを取得しようとするような使い方をしているのなら、緊急性があります。いますぐパッチを当ててください。 なお、Snoopyを自前で持っているモジュールには、xhldがあります。こちらについても、とりいそぎパッチを当てておきます。d3pipes は自前で持っていないので、コアの方だけパッチを当てれば十分です。 それにしても、$safer_URIなんてのが全然安全じゃなかったことに、1.2.3パッチの時点で気付けなかった自分が恥ずかしい… |
| 2008-10-15 16:28 |
XOOPSにおけるPHPエラーハンドリング問題
![]() ![]() XOOPS2.0.4から導入されて「しまった」XoopsErrorHandler。 私自身、ことある毎にこれについて批判してきましたが、その理由は明確です。 (1) phpの設定によらず、PHPエラーがHTTPボディとしてechoされてしまう (2) fatalエラーなどで止まる場合は、ハンドラの上書きが効かない (3) mainfile.phpを通過するケースとそうでないケースで、設定を一致させる術がない (1)は、実稼働サイトでエラーを確認する術がないことを意味します。XoopsErrorHandlerは一応XOOPS_URLを隠蔽してくれますが、PHPデバッグがONの間、すべての訪問者にエラー内容を送出してしまう、という根本的な問題が解決されていません。 (2)も大きな問題です。mainfile.phpなどの記述ミスで、fatalエラーとなる場合、error_reporting()やXoopsErrorHandlerの処理など実行されないのですから、必然的にphpの設定がそのまま生きます。 (3)は(2)と似ていますが、これはPathDisclosure問題と直結します。XOOPSの構造は古く、本来DocumentRoot外に置かれるべきPHPコードの断片ファイル群が、DocumentRoot内に多く存在します。それらに直アクセスされた時に、PathDisclosureとなるかどうかは、php設定によるのです。 つまり、どのようなエラーハンドラ設計を行おうと、php設定こそが重要である、という事実はひっくり返しようがないのです。 であれば、特定条件を満たした時だけ働くエラーハンドラなど無効にして、PHP設定だけですべてをコントロールできるようにするのが合理的な手段というものでしょう。 特に勝手にerror_reporting()レベルを変更してしまうXoopsErrorHandlerなんて、今すぐ捨てましょう! …と、ここで従来であれば、「その部分を潰すHackは〜」となるわけですが、XCL2.1なら、それさえもpreload一個で実現できることに、今になってようやく気付きました。 XCL2.1用のエラーハンドラ正常化preload http://www.peak.ne.jp/support/xoops/Preload_ErrorHandlerOriginal.zip (解凍で得られた ErrorHandlerOriginal.class.php を preloadフォルダにコピー) このpreloadを入れるだけで、php設定だけでエラー処理をすべてコントロール出来るようになります。 なお、ほとんどすべてのケースで都合が良いのは、エラーをログに記録する方法です。 「ログ記録方式だとリアルタイムなデバッグに使いづらいじゃないか」なんていう人には、良い方法を教えましょう。好きなターミナルを開いておいて、 $ tail -f error_log とするだけです。tailの-fオプションは様々な局面で役立つので、絶対に暗記しておくべきでしょう。 もしあなたがXCL-2.1を利用しているのなら、上述したpreloadを有効にした上で、php.iniや.htaccessで、エラーをロギングするようにしましょう(log_errorsをonにして、error_logに適切なファイルを指定)。もちろん、display_errorsはoffです。 それこそが、開発者にとって最も効率よい環境であり、同時に、サイト運営者にとって最も安全な環境ですから。 |
| 2008-10-9 17:45 |
CGIを使った強力なWebアプリケーションインストーラ
![]() ![]() ●アプリケーションインストーラの原理等 前の記事でも書いたのですが、rsync+sshやsshログインが出来ない環境で、大量のファイルを展開するWebアプリケーションのセットアップは、かなり辛いものがあります。FTPでアップロードするのにもとても時間がかかり、途中で切れることも珍しくありません。アップロードが不完全であることに気がつければまだ良い方で、成功したと思い込んで作業を進めてしまうと、後になってから面倒なトラブルが頻出することになります。 しかし、そういう環境(安価な共有型ホスティングサービス)であれば、おそらくCGIはsuExecです。であれば、アーカイブの展開をCGIでやってしまえば良いのです。ファイルオーナーはFTPでアップするのと一緒です。つまり、FTPで大量のファイルをアップロードする必要なんてなくなります。 ついでに、アーカイブもwgetで取得してしまえば、FTPでアップロードするのは、そのCGIのみとなります。そうなれば本当に楽ちんです。 ここで注意しなければならないのは、wgetのパラメータが任意ではいけません。そんなことをしたら、そのCGIが存在しているタイミングに、任意のアプリケーションをインストールされてしまいます。(もちろん、そうであってもなくても、そのCGIは実行後、即座に消すべきですが) とりあえず、サンプル的な意味で、ホダ塾ディストリビューションをインストールするためのCGIを書いてみました。 http://www.peak.ne.jp/support/xoops/hd_installer.zip ●bashCGI版インストーラ使い方 このファイルを解凍すると、hd_installer.cgi というファイルが出来ますので、これをサーバにFTPでアップロードします。アップロード先が重要で、XCLのルートフォルダとなるべきフォルダにアップロードしなければなりません。 例えば、サーバのDocumentRootが /home/foo/public_html で、そのルートにインストールしたいのであれば、そのまま /home/foo/public_html の下にアップします。 このファイルはCGIですから、実行パーミッションを与えます。755または705が一般的でしょう。また、サーバによっては、.htaccess に Options +ExecCGI の一行を追加する必要があるかもしれません。 あとは、ブラウザで、そのCGIにアクセスするだけです。例えば、 http://www.example.com/hd_installer.cgi など。 あとは画面に表示される手順に従うだけで、インストーラ画面が開きます。tar.gzアーカイブを、パーミッション保存したまま展開するので、cache, uploads, mainfile.php などのパーミッションをFTPで変更する必要すらありません。「5分でインストール」どころか2分を切れそうです ![]() 一度遊びで試してみれば、その簡単さに驚くはずです。 ただ、「遊び」とは言っても、ローカルでテストしたら、たいがいうまく行きません。xampp環境ではそもそもbashがないでしょうし、自宅サーバなどに*nixをインストールして開発に使っているケースでも、ちゃんとsuExecを有効にしていることはほとんどないでしょう。このCGIは、suExecを有効にしている共有型レンタルサーバでないと動かないし動かす意味もない、ということをお忘れなく。 ●余談 wgetで取得可能なアーカイブは、 http://downloads.sourceforge.net/hodajuku/ 直下のファイルに限定されます。ただ、サーバがファイルをリモートから取ってくる形ではなく、CGIと同一フォルダにアーカイブを用意しておけば、一部のモジュールのインストールにも利用可能です。少なくとも私のD3モジュールであれば、そのまま行けます。(もっとも、そのほとんどがHDに同梱されているのでほとんど意味はありませんが) なお、XCL2.1.xはなぜかzipしか用意がないので、この手が使えません。もちろん、unzipコマンドを使えば解凍できるので、そのようにCGIを改変すれば良いのですが、unzipはあまり一般的ではないので、そういうコードにしていません。さらにzipにはパーミッションの概念がないので、解凍したファイル群に対するパーミッション変更までCGIに記述する必要があります。 このタイプのインストーラに興味があるなら、ぜひhd_installer.cgiを改変してください。 スパゲッティになりやすいbashスクリプトにしては、そこそこ見やすく再利用しやすいコードとなるよう努力したつもりです。スクリプトの最初の方にある定数定義だけいじれば、ImpressCMSや本家版XOOPSにも利用できるでしょう。再利用しやすいように、ライセンスも修正BSDとしてあります。 今回はインストーラでしたが、このシステムが本当に効いてくるのは、むしろアップデータでしょう。大量のファイルをFTPで上書きアップロードするというのは、本当に面倒です。しかもインストール時よりもさらに、途中で切れたかどうかの判断が難しくなります。 さらに、アップデータであれば、インストールされた情報(XOOPSであればmainfile.php)を参考にすることが出来るので、インストーラのようにリクエストに依存する必要がなくなります。つまり、サーバに置きっぱなしでも良いようなCGIを作れる可能性はあります。 次回はそのアップデータを作ってみたいと思います。 |
| 2008-10-8 15:32 |
bashでWebアプリケーションを書く
![]() ![]() 私自身もともとPrimitiveな環境での実験が好きなのですが、今回、Webアプリケーション(というかちょっとしたCGI)をbashで書くことをいろいろと試してみました。(もちろん、Webサーバはapache) 結論を先に書くと、「そんな馬鹿なことはやめなさい」で終わりです。 perlがどれだけ素晴らしいツールであるか、身を持って知った気がします。 ただ、あえてbashで書く、というのにはそれなりの動機付けがあります。 perlだと、モジュールの有無でいろいろと動作環境問題が出がちですが、bashであれば、普通の*nixにはほぼ100%インストールされてますし、環境問題も出づらいでしょう。(もちろん、使うコマンドにもよりますが) 環境差によるハマリをさけるため、使って良いコマンドも極力、絞ります。 比較的高機能なコマンドはsedくらいでしょうか。 'perl -ne' などが使えたら相当に楽なのですが、あえてperlは一切使わずに頑張ります。 以下、bashでCGIを書くときの注意点と対策を列挙します。 ・必ずHTTPレスポンスを返す HTTPレスポンスを返さないと、500エラーとして扱われます。 ヘッダの各行は、基本的にechoで直書きします。 もちろん、ヘッダとボディは空行で区切ります。 ・echo -e オプションを忘れないこと これがないと、コードが書きづらいでしょう。 ・リクエスト受取方法 GET変数は$QUERY_STRINGを分解することで得られます。POST変数は標準入力をいったん変数に受け取ってから分解します。分解はbashのパターン照合を駆使します。 こんな感じで、$keyと$valueの対が得られます…が(続く) ・bashには連想配列がない! とにかくこれが辛いです。連想配列がないために、リクエストのkeyとvalueの対をスマートに保存する術がありません。私自身さんざん悩んだのですが、REQUEST_(key) という形の変数をリクエスト専用の文字空間として利用することで、擬似的に連想配列を実装(?)しています。 ・簡単にセキュリティホールが出来る PHPは穴を作りやすい開発言語と言われて久しいですが、bashに比べたら可愛いものだと言わざるを得ないでしょう。 なぜなら、bashのCGIでは、ちょっとミスしただけでも、簡単にコマンドインジェクション脆弱性が確定しますから。外部コマンドに対して、変数が展開されてから渡されるのか、それともクオーティングされたまま渡されるのか、ちゃんと把握しないと、それだけで即死です。 ・HTMLエスケープするスマートな手段がない これも相当に困ります。bashの関数は、戻り値を文字列とすることが難しいので、文字列を変換する関数が事実上作れません。 これについても、良い方法が思い浮かばなかったので、変数に '"&<> が含まれないようにする、という消極的な手段を取りました。 リクエストを受け取る時に、[a-zA-Z0-9._-] 以外のキャラクターを全部消す、という処理を共通にかけています。 逆に言えば、複雑なテキストを受け取る可能性があるWebアプリケーションはbashで作ってはいけない、ということでしょう。 …と、ここまで読む限りでは、すべてが無駄な努力のように思えますが、実はbashでCGIを作ることで、PHPアプリケーションのインストールやアップデートがとても簡単になるのです。sshの使えない共有型レンタルサーバで、大量のファイルをFTPでアップロードするのに四苦八苦していた人には朗報になるはずです。 次回を待て! |
| 2008-9-12 17:23 |
「Ajaxセキュリティ」を監訳しました
![]() ![]() 最近、こんな書籍を監訳しました。 ![]() HP SoftwareのBilly HoffmanとBryan Sullivan両氏による"Ajax Security" (Addison-Wesley) が原著です。 基本的には、渡邉さんの手による和訳文を読んで、日本語として判りづらいところや技術的におかしなところに突っ込みを入れる、という作業がほとんどでしたが、原著自体がなかなか面白く、楽しんで仕事ができました。 毎コミのぽち@さんに「宣伝しておきますね」と安請け合いしておきながらナニですが、ぶっちゃけ、この書籍高いです。 5,040円もします。(元が$49.99だということを考えれば、意外と安いとも言えます) 個人レベルではなかなか購入できないでしょう。 でも、職業としてWebプログラマーをやっている人なら、一度目を通しておいても損はしないだろう、と思えるレベルの書籍だと思います。 Web開発系会社の社長さん、ぜひ御社のプログラマーやテスタに買い与えてやってください ![]() この書籍は特にJavaScript系の攻撃に詳しく、そういう落とし穴を事前に知っておくだけでも、今後のキャリアに役立つはずです。 「オレオレ詐欺(振込め詐欺)」だって、その手口を知っているのと知らないのとでは、引っかかってしまう危険性は雲泥の差でしょう。 ついでに、これまた正直に書いておくと、原著には結構突っ込みどころが多く存在してました。 ただ、それらについては、極力、訳註という形でフォローしてますので、トータルではそれなりのレベルには仕上がっていると思います。 もちろん、私のつけた訳註そのものが間違っている可能性もありますが、万一その場合は正誤表を載せる方向でご容赦ください ![]() すでにAmazon様にも登録されていて、9/26発売だそうです。 (Amazonの方が監訳者よりよほど詳しい! )<姑息なアフィリエイトリンク> # ちなみに表紙は、アヤックス(AFC Ajax)のディフェンダーです ![]() # ちゃんと急所をおさえているとこに注目! |
| 2008-9-6 6:02 |
D3モジュール用のイベント通知ハンドラ
![]() ![]() D3モジュールの問題点として、イベント通知処理が面倒、というのがあります。 X2のNotificationHandlerは、triggerEvent()する時に、 ROOT/modules/(dirname)/language/(lang)/mail_template/(mail_template).tpl を読みに行きます。 そこにファイルが無かった時点で、イベント通知は無効だとして処理がスキップされてしまいます。 それを回避するために、d3forumやpicoでは、それぞれ独自のtrigger_event関数を作っていたのですが、それは明らかに工数の無駄です。 D3モジュール用に、イベント処理テンプレートファイルをTRUST_PATHの下からも検索してくれる共通のルーチンを書けば良いだけです。 D3モジュールを使うならaltsys必須 というのも事実上ルール化してますので、D3NotificationHandlerクラスをaltsysに追加しました。 使い方は簡単です。 従来は上の書き方だったところを、下のように変更するだけです。 モジュール指定を $mid ではなく $mydirname で渡すところが違いますが、D3モジュール的にはこの方が使いやすいでしょう。 あまりいろいろテストしてませんが、おそらくXCL2.1でもImpressCMSでも本家2.3でもこのコードで動くでしょう。 すでに手元のpicoやd3forumは、このコードを利用していますので、今後の私のD3モジュールはすべて altsys-0.61以上必須、という形になる予定です。(実際には、altsys本体のバージョンが低くても、class/D3NotificationHandler.class.php ファイルだけ用意すれば事足りますが) なお、このD3イベント通知ハンドラにおけるメールテンプレートの検索順序は以下の通りです。 |
| 2008-8-30 18:39 |
XUGJダウン中
![]() ![]() 8月29日深夜より、XUGJがアクセス過多でSWAPしまくり状態になり、ほぼダウンした状態になりました。 私が連絡を受けた時点ですでにSSHログイン効かない状態になっていて、かろうじて生きていたserver-statusで確認した限りでは、大量のクローラがW状態でした。明らかに大量のリクエストを処理しきれなかったのが原因でしょう。 # 大量のクローラーのうち、特に悪質だと思われるのは、baidu-jpとbecome。 # この2つは、iptablesレベルで弾いた方が良いかもしれません。 # XCLで運用しているみなさんもお気をつけください その後も状況は悪化する一方で、sshは完全に無反応、server-statusも効かなくなり、もはやハードウエアリセットしか手はない状態です。 しかし、その専用サーバをホスティングしている会社は、週末は一切連絡がつきません(個人的にはそれが一番信じられませんが)。つまり、月曜の朝に社員が出社してくるまで、XUGJがダウンし続けることはほぼ確定しました。XUGJの管理をお手伝いしているものとしては大変心苦しいのですが、月曜朝までお待ちください。 XUGJのサーバが復活し次第、fabiさんと相談して、同様の事態にならないような対策(ホスティングサービスの変更も含む)を講じたいと思います。 |
| 2008-8-30 6:31 |
D3モジュールの定義
![]() ![]() 「今さら定義?」という気もするのですが、ホダ塾メンバーでさえも、D3の重要な仕様を知らなかったことに驚き、あらためて"D3"を定義したいと思います。 もともと"Duplicatable"は、X2の制限をいかにして回避するか、ということを考えて積み上げられてきたテクニックの集大成です。 つまり、「X2で動くこと」というのがすべての"Duplicatable"の大前提となります。それはD1・D2・D3に共通します。 だから、「XCL専用」のモジュールは、複製可能でXOOPS_TRUST_PATHを使おうとも、それはD3ではないのです。 もちろん、「X2でも動作確認しなさい」などと偉そうに言うつもりはありません。ただ、D3の構造を素直に利用すれば、X2でも自動的に動くはずなのです。(この部分には多少誇張が含まれてますが) D3の構造を意図的に外して、XCL専用とするのも当然自由ですが、それがD3でないのは自明です。 D3の構造で作ったけど、できあがったものはX2互換がなかった、なんて可能性も当然考えられます。そしてX2での動作確認を必要条件にするつもりもありません。でも、そういうケースならX2互換にするのは簡単でしょう。 D3モジュールは、世界中のX2アーキテクチャーで動きます。ImpressCMSでも、JP版X2でも、もちろん本家版XOOPSでも(一部要修正)。だからこそ、XCL専用モジュールには"Duplicatable V3"という名前を冠して欲しくないのです。それはXCL以外の海外ユーザの誤解を招くからです。 前置きが長くなりましたが、D3モジュールの定義を書きます。 *必要条件(こうじゃなければD3モジュールとは呼べないもの) (1) 原則的にX2互換であること (2) dirnameが[0-9a-zA-Z_-]のキャラクター組み合わせで自由に決められること (3) ほとんどのロジックがXOOPS_TRUST_PATHの内側にあること (4) ROOT/modules/下にあるディレクトリをコピーするだけで複数動作すること(そこにソースコード書き換えは一切発生しないこと) (5) XOOPS_TRUST_PATHの内側(ロジックの記述されたファイル)は複製する必要がないこと *推奨条件(そうじゃなくても良いが、できれば対応して欲しいもの) - ROOT/modules/(dirname)/mytrustpath.php ファイルを用意すること - 利用する各テーブルは (prefix)_(dirname)_(table) という名前でCREATE TABLEされること - テンプレートは (dirname)_(tplfile) という形でDBに取り込まれること - blocks/(tplfile).html という階層を持ったテンプレートをブロックに利用しないこと(=ブロック用のテンプレートも他のmoduleテンプレートと同様に扱うこと) - 特に理由がなければ、ブロックも複製可能とすること(can_cloneのセット) - D3言語マネージャを利用すること - コメントにはd3コメント統合が利用できること 「推奨条件」はまだ増えるかもしれませんが、「必要条件」は最初の5つだけです。 なお、D3モジュールの構造については、Gnaviのkentaroさんが判りやすいドキュメントを作成してくれています。まだ途中ではありますが、非常に良くできたテキストで、これからD3モジュールを作ろうという人にも、すでに作ったことのある人にも役立つと思います。 http://xoops.iko-ze.net/modules/pukiwiki/ |
| 2008-1-10 4:53 |
resource.db.php をフックすることによるXoopsTpl動作改善
![]() ![]() 前回、resouce.db.php をフックできると操作性・開発性などで大きな改善が出来るよ、などと気を持たせておきながら、2ヶ月以上も放置してしまいました。 まず resource.db.php とは何か一応説明しておきます。これは、Smartyのリソースプラグインと呼ばれるものです。中身には「どこからテンプレートを持ってくるか」「更新状況をどうチェックするか」という処理が記述されています。 XOOPSの場合、特に指定しなければ、"db:"テンプレートが呼ばれるために、"db"リソースプラグインが重要なのです。 次に、標準のresource.db.phpによって実装されているDBテンプレートの問題点・要改善点を下に列挙してみます。 (1) テーマがdefaultだとDBテンプレートのリセット処理が入ってしまう (2) テーマ下テンプレートによってコンパイルキャッシュが作成されるとテーマを切り替えてもそのまま残ってしまう (3) テーマ下テンプレートのパス themes/(theme)/templates/(dirname)/(block/)? という階層構造は面倒なだけではないか? しかもDBテンプレートの実態を反映していないので余計な混乱を招く恐れがある (4) テーマ下テンプレートの置き場所がバラバラ 本家だと themes/(theme)/modules/(dirname)/(block/)? だったりする (5) テーマ下テンプレートが削除されても認識しない (6) テーマ下テンプレートが追加されてもコンパイルキャッシュより古いと認識しない このうち、(1)〜(4)について対応した resource.db.php を作ってみました(下リスト参照)。 もちろん、XoopsTplフックのおかげで、このresource.db.phpの置き場所は、XOOPS_TRUST_PATH/libs/smartyplugins/ で良く、Hackではなくなります。 残った(5)と(6)についても、なんとか対応したいと考えてます。 ホダ塾ディストリビューションでは、jidaikoboさんが、skel_flexテーマに対して積極的にテーマ下テンプレートを導入してくれていますが、このresource.db.phpによって、テーマとテンプレートがうまく連動することがお判りいただけるでしょう。(もちろん従来もテーマ下テンプレートは有効でしたが、連動はしなかった) 最新のNightlyアーカイブで試せるはずです。 |
| 2008-1-8 6:31 |
Project Honey Pot (1)
![]() ![]() http://projecthoneypot.org/ ここの提供するhttp:BLは、対コメント/トラックバックSPAMに特化したブラックリストのようです。 もともとは、スパマーをひっかけるためのHoneypotのプロジェクトであり、XOOPSサイト内にもpotを設置しましょう、というのが本来の流れですが、とりあえずはProtectorでhttp:BLを利用出来るようにしてみたので、使い方だけ説明しておきます。 まずは、http:BLを利用するための「キー」を取得する必要があります。(ユーザごとにキーが必要) http://www.projecthoneypot.org/create_account.php からアカウントを作ってログインし、Services → HTTP Blacklist からアルファベット12文字からなるキーを取得できます。 http:BLの利用は、Protectorのfilter機能として実装してますので、 XOOPS_TRUST_PATH/modules/protector/filters_disabled/ の中にある postcommon_post_deny_by_httpbl.php を、 XOOPS_TRUST_PATH/modules/protector/filters_enabled/ にコピーします。 その上で、このファイルをエディタで開き、最上部のこの行に、12文字のキーを書き入れます。(もちろん....の部分は消す) spamhausなどと比べて精度や更新頻度がどうなのかはテストしていないので不明です。 ただ、Honeypotの性格から、HTTP経由のSPAMしか取得していないでしょうから、他のBLよりはノイズが低いことは期待できそうです。 なお、このサイトは、ゲストコメントやトラックバックをONにしていないのでテストが出来ません。だれかテストしたらその結果を教えてください ![]() もし次があれば、今度は本来のHoneypot設置について書いてみたいと思います。 |
| 2007-11-1 6:03 |
XCL2.1でのXoopsTplフック方法
![]() ![]() XCDM#1でも発表したネタなのですが、XCL2.1ではpreload一発で、レンダラーのかなり大きな部分をフックすることができます。 preloadでフックするべきデリゲート名は、おなじみ 'XoopsTpl.New' です。 まずはソースコードを見てください。 フック処理が来た直後に、 XOOPS_TRUST_PATH/libs/smartyplugins を、Smartyプラグイン用ディレクトリとして挿入してます。 「これ、どこかで見たことあるな」と思った人は勘がいいです。まさに、 http://ryus.co.jp/modules/wordpress/index.php?p=57 と同じですから。 でも、ryusSmartyPluginsEx との違いは、追加ではなく挿入していることです。 ユーザディレクトリから先に探すことにより、デフォルトのSmartyプラグインを乗っ取ることができるのです。 そして、乗っ取って一番面白いのは、やはり resource.db.php でしょう。XOOPS_TRUST_PATH/libs/smartyplugins/resource.db.php にDBリソースの見つけ方を記述することで、テンプレートの動作を自由にコントロールできます。(その具体例は次回) このpreloadにおける hook()メソッドでは、それ以外に、コンパイルIDの指定を行っています。これによって、テーマ毎に異なるコンパイルキャッシュを生成するようになり、テーマを切り替えたけどテンプレートは切替前のテーマ付属のテンプレートのまま、というトラブルを避けることができます。 このあたりは、本家版コアのパクリですが、コアの構成ファイルを一切おきかえずとも、このような重要な仕様改善ができるというのは、まさにXCL2.1の真骨頂でしょう。 preload/HdXoopsTplHook.class.php |
| 2007-10-29 5:43 |
XoopsCube Developers Meeting #1
![]() ![]() XCDM#1 参加してきました。 技術よりの話かと思ったら、そんなのはまったくなくて、「自分はOSSに対して何ができるか」を確認する作業でした。密室の中でチームになって、プロジェクトに対して貢献できることをリストアップしていく作業……。これって、新興宗教のオルグ? とかちょっと思いました ![]() 確かに、XOOPSというOSSもどきを、ちゃんとしたOSSにするためには、なんらかの洗脳が必要なのかもしれません。 そんな中、なぜか私一人だけが技術話をしたのですが、それについては、おいおい書いていきます。 あと、Marijuanaさんから、「XOOPS Cube Legacy デベロッパーズバイブル」をいただきました! ありがとうございます。これから読みます。 |




)




)