CodeIgniter1.7.3に合わせてSeezooもFIXしました

連日の記事となりますが、ご報告まで。

今日の朝来たら、CodeIgniter1.7.3がリリースされてました。
早速DL、Change Log — CodeIgniter 3.1.10 documentationを見てみると、

Version 1.7.3 is a security maintenance release, including a previously patched file Upload class, and a new security fix to prevent possible directory traversal in certain circumstances. There are no other significant changes.


ということらしいです。どうやらRouterのセキュリティFIXがあったようですね。
$config['enable_query_strings']がTRUEの時のディレクトリトラバーサル問題の解決らしいです。

というわけで、早速Diffをとって中身を見ると、



310c310< $this->class = str_replace(array('/', '.'), '', $class);

    • -

> $this->class = $class;
369c369< $this->directory = str_replace(array('/', '.'), '', $dir).'/';

    • -

> $this->directory = $dir.'/';


ふむふむ、Router::set_class()とRouter::set_directory()のコードが変わってるみたいですね。
これくらいならパパッと修正して〜…と思ってよく考えたらマズイことに気が付きました。

これだとディレクトリにパス(/)が含められない

早速Seezooに導入してみると、予想通り、3階層まで掘るルーティングができなくなってしまってます;;
Seezooはディレクトリを掘り進めて、その都度のディレクトリパスを「/」でつないでるので、2回目にset_directory()が
呼ばれると、それまであった「/」がstr_replace()によって消されてしまう、という状態でした。

解決策の模索

あ〜でもないこ〜でもないとうんうんうなりながら昼食していたら閃きました。


つまるところ、Directory Traversalの危険性のある文字を削除してる訳だよね


つまり、「/」と「.」が含まれるのがマズイ。でも階層を掘るなら「/」は付けないといけない。
ということなら、


格納する時点では付けず、最後にまとめてつければいいよね?


というわけで、ルーティング中はディレクトリデータ階層をstr_replace()した上で配列に格納、
最後にfetch_directroy()を呼び出す時にimplode()というやや強引な方法で解決しました。
具体的には、SZ_Router::fetch_directroy()をOverRideして処理変更。

コード

以下のように変更しました。

system/application/libraries/SZ_Router.php


var $directory = array() // override
var $directory_reg = array() // 拡張ルーティング用パス

.
.
.
// override CI_Router::set_directory
function set_directroy($dir)
{
// パスが含まれた最後のディレクトリ名を取得
$exp = explode('/', $dir);
$dir = str_replace(array('/', '.'), '', end($exp));

$this->directory[] = $dir;
}

.
.
.
// override CI_Router::fetch_directory
function fetch_directory()
{
$prefix = '';
if ($this->is_packaged_directory === TRUE) // 拡張ルーティング用
{
$prefix = '../../../' . SZ_EXT_DIR . 'controllers/';
}
return (count($this->directory) === 0)
? $prefix
: $prefix . (implode('/', $this->directory) . '/');
}

これで3階層+拡張パッケージからのルーティングを確認しました。
やや強引な方法だけど、Directory Traversalは怖いですからね><

感想

ルーティング部分の変更って意外とキツイ。
Seezooではquery_stringは使わないので影響はないだろうけど、コアのメソッドが変わってるのには影響を受けてしまいます。
でも拡張してOverrideで解決できるのもCodeIgniterの素晴らしいところですね。

1.7.3パッケージ導入後のSeezooは次のバージョンからです。
もし現行のSeezooをCI1.7.3にする場合は、上記のような修正をお願いします。



でもこれってコアでは「コントローラは2階層まで!」って事実上決められてしまったような気がします…