リクエストに関する規約
2008年2月3日
$_GET, $_POST, $_COOKIE 使用時の規約を定めることにした。こうすることで、少ないリソース量で有効なセキュリティ対策が行える。
1)キー名が『binary』で終わる場合以外は、ヌルバイトは使用禁止。
2)キー名が『id』で終わる場合は、数値のみを利用。
3)キー名が『path』で終わる場合、URLもしくはファイルなどのパスを指定できる。ただし、日本語使用不可。
4)キー名が『text』で終わる場合、ヌルバイト以外なら何でも使用可。
5)上のどれにも当てはまらない場合、英数字、ピリオド、ハイフン、アンダースコア、スラッシュおよび日本語のみが使用可能。
6)URIに『#』および2つ以上の『?』を含むものを禁止。
(080208 改定)
キー名が『binary』で終わる場合に、ヌルバイトを受け付けるようにした。また、6)の条件を追加した。
coreクラスにおける、該当部分のコードは以下のとおり。
1)キー名が『binary』で終わる場合以外は、ヌルバイトは使用禁止。
2)キー名が『id』で終わる場合は、数値のみを利用。
3)キー名が『path』で終わる場合、URLもしくはファイルなどのパスを指定できる。ただし、日本語使用不可。
4)キー名が『text』で終わる場合、ヌルバイト以外なら何でも使用可。
5)上のどれにも当てはまらない場合、英数字、ピリオド、ハイフン、アンダースコア、スラッシュおよび日本語のみが使用可能。
6)URIに『#』および2つ以上の『?』を含むものを禁止。
(080208 改定)
キー名が『binary』で終わる場合に、ヌルバイトを受け付けるようにした。また、6)の条件を追加した。
coreクラスにおける、該当部分のコードは以下のとおり。
private function forSecurity(){
// Remove unnecessary cookie settings
foreach($_COOKIE as $key=>$value) {
if (strpos($key,_CONF_COOKIEPREFIX)===0) continue;
unset($_COOKIE[$key]);
unset($_REQUEST[$key]);
}
// Check NULL byte in string.
self::checkRequest($_REQUEST);
// Remove $_COOKIE keys in $_REQUEST
// This is for avoiding bugs due to cookie keys.
foreach($_COOKIE as $key=>$value) unset($_REQUEST[$key]);
// Send content-type with character set anyway, to avoid XSS by invalid character like UTF-7.
@header('Content-Type: text/html; charset=iso-8859-1');
// MISC
if (!empty($_SERVER['HTTP_REFERER'])) {
if (!preg_match('!^(http|https|ftp)://!',$_SERVER['HTTP_REFERER'])) unset($_SERVER['HTTP_REFERER']);
}
if (preg_match('/(#|\?[^\?]*\?)/',$_SERVER['REQUEST_URI'])) {
exit("<html><body>URI shouldn't contain '#' and 2x'?'. Please check the browser/robot setting.</body></html>");
}
}
private function checkRequest(&$request,$requestkey=null){
if (is_array($request)) {
foreach($request as $key=>&$value) self::checkRequest($value,$requestkey===null?$key:$requestkey);
} else {
if (preg_match('/binary$/i',$requestkey)) return;
elseif (strpos($request,"\0")!==false) exit('Null byte cannot be used.');
switch(true){
case preg_match('/text$/i',$requestkey):
return;
case preg_match('/id$/i',$requestkey):
if (is_numeric($request)) return; else break;
case preg_match('/path$/i',$requestkey):
if (preg_match('/^([0-9a-zA-Z\x80-\xFF\-_\.:\/\\]*)$/',$request)) return; else break;
default:
if (preg_match('/^([0-9a-zA-Z\x80-\xFF\-_\.\/]*)$/',$request)) return; else break;
}
exit('Request type mismatch');
}
}