# php -r '$a=array("1"=>1);var_dump($a[1]);'
int(1)
# php -r '$a=array("1a"=>1);var_dump($a);'
array(1) {
["1a"]=>
int(1)
}
# php -r '$a=array("0x1a"=>1);var_dump($a);'
array(1) {
["0x1a"]=>
int(1)
}
# php -r '$a=array(0x1a=>1);var_dump($a);'
array(1) {
[26]=>
int(1)
}
# php -r '$a=array(""=>1);var_dump($a);'
array(1) {
[""]=>
int(1)
}
# php -r '$a=array(false=>1);var_dump($a);'
array(1) {
[0]=>
int(1)
}
# php -r '$a=array(true=>1);var_dump($a);'
array(1) {
[1]=>
int(1)
}
# php -r '$a=array(1.1=>1);var_dump($a);'
array(1) {
[1]=>
int(1)
}
# php -r '$a=array("1.1"=>1);var_dump($a);'
array(1) {
["1.1"]=>
int(1)
}
# php -r '$a=array("01"=>1);var_dump($a);'
array(1) {
["01"]=>
int(1)
}
# php -r '$a=array(-1=>1);var_dump($a);'
array(1) {
[-1]=>
int(1)
}
# php -r '$a=array("-1"=>1);var_dump($a);'
array(1) {
[-1]=>
int(1)
}
# php -r '$a=array("+1"=>1);var_dump($a);'
array(1) {
["+1"]=>
int(1)
}
$_cachedModule_mid[intval($module->getVar('mid'))] =& $module;
PEAK XOOPSのようなサイトまるごと引越でpagerankを引き継げるか。
まず、基本的なリダイレクトテクニックは、上鍵さんがどこかに書かれた記事を参考にしました。ForceType と Actionの組み合わせは、とっても便利です!
OSCでjidaikoboさんに、302ではなく301で返せば引き継がれるらしい、と聞いて調べてみたら、こんなのが見つかりました。
http://www.web-20.net/2006/05/seo301.html
なるほど。
と、telnetで確認してみたら、302を返してました。
PHPマニュアルを読み返してみると、
「header()でLocationヘッダを送ると、自動的に302を付与する」
そうだったのか!
というわけで、リダイレクトスクリプトを修正します。Pagerank7に戻るのは無理でも、6くらいには回復したいですね。
DocumentRoot
-- xoops_redirect.php
-- xoops/
---- .htaccess
---- index.html (dummy)
<?php
$uri = strtr( substr( $_SERVER['REQUEST_URI'] , 6 ) , array( "\n" => '' , "\r" => '' ) ) ;
header( "HTTP/1.0 301 Moved Permanently" ) ;
header( "Location: http://xoops.peak.ne.jp".$uri ) ;
?>
ForceType xoops_redirect
Action xoops_redirect /xoops_redirect.php
「大きな傘」(BigUmbrella)XSS対策システムの最終回。考察編です。
(3)に示したコードには、議論の余地が2つ残っています。
・疑うべきリクエストのパターンがそれで良いのか
(3)で示したチェックパターンはこうです。
preg_match( '/[<\'"].{15}/s' , $val , $regs )
「大きな傘」(BigUmbrella)XSS対策システムの第3回。最終回のつもりでしたが、まだひっぱります。
前回では、コンセプトだけの簡単なコードを示しましたが、それだと以下のような問題が考えられます。
(A) text/html 以外のContent-Typeに対しても、XSSチェック処理が入ってしまう。
例えば、POSTでリクエストされた通りに、text/plain で出力するアプリケーション。この場合、htmlspecialchars()をかける方がおかしいわけですが、正しいはずの処理が、"XSS Found" で潰されてしまいます。
(B) 巨大なファイル転送処理についても、出力フィルターがかかる
一見(A)に似ていますが、こちらはパフォーマンス上の問題点です。数百Mbyteのファイルを、phpで転送する、という場合、出力フィルターがかかると、その巨大なファイルをいったんすべてメモリに取り込んでからの処理となってしまうため、サーバ負荷が極端に上昇します。つまり、DoS攻撃に対して弱くなる、と言えます。
(C) text/html 出力で、GET/POSTされた文字列をそのまま表示したいケースはある
いわゆる「HTML許可」投稿におけるプレビューがそれに該当します。
このうち、(A)は比較的まっとうに対応が可能です。出力フィルター側で、headers_list()関数を使えば、Content-Typeが明示的に指定されているかどうかを確認できます。Content-Typeとしてtext/html が指定されているか、Content-Typeが指定されていない時に限れば、問題解決でしょう。ただし、headers_list()関数は、PHP5以降でしか利用できないため、PHP4でこれを実現することはほぼ不可能であり、(B)と同じ解決法を選択せざるを得ないでしょう。
一方、(B)の問題を、BigUmbrella側だけで対応するのは不可能です。というのも、出力フィルター関数に処理が移ってきた時点で、負荷が問題となる出力のメモリー取り込み処理は終了しているからです。
だから、ユーザスクリプト側で、巨大なファイルを転送する時などに、明示的に出力フィルターを切るしかないでしょう。
// remove output bufferings
while( ob_get_level() ) {
ob_end_clean() ;
}
define( 'BIGUMBRELLA_DISABLED' , true ) ;
昨日書いた「大きな傘」たりえるXSS対策のコード編です。
理屈はすでに述べた通りですが、これをどうコードに落とすかについては、実はまだ迷いがあります。
とりあえず、一番簡単なパターンだとこんな感じでしょうか。
(1) ファイルを作成
/usr/local/lib/php/bigumbrella.php
<?php
function bigumbrella_init() {
foreach( $_REQUEST as $key => $val ) {
if( preg_match( '/[<\'"].{15}/s' , $val , $regs ) ) {
$GLOBALS['bigumbrella_doubtfuls'][] = $regs[0] ;
}
}
if( ! empty( $GLOBALS['bigumbrella_doubtfuls'] ) ) {
ob_start( 'bigumbrella_outputcheck' ) ;
}
}
function bigumbrella_outputcheck( $s ) {
if( ! is_array( @$GLOBALS['bigumbrella_doubtfuls'] ) ) {
return "bigumbrella injection found." ;
}
foreach( $GLOBALS['bigumbrella_doubtfuls'] as $doubtful ) {
if( strstr( $s , $doubtful ) ) {
return "XSS found." ;
}
}
return $s ;
}
$GLOBALS['bigumbrella_doubtfuls'] = array() ;
bigumbrella_init() ;
?>
php_value auto_prepend_file /usr/local/lib/php/bigumbrella.php
auto_prepend_file = /usr/local/lib/php/bigumbrella.php