Stay hungry, Stay foolish

0%

PHP全局变量注册

Essential PHP Security的1.1.1. 全局变量注册:

当PHP的register_globals配置选项打开时,复杂的原始表单处理不复存在,公用变量会自动建立。它让PHP编程变得容易和方便,但同时也带来了安全隐患。

何为register_globals

register the EGPCS (Environment, GET, POST, Cookie, Server) variables as global variables.

如果php.ini里开启了这一项:

1
register_globals = on

那么,$_ENV、$_GET、$_POST,$_SERVER等变量就被注册成了全局变量。

危害:

1
2
3
4
5
if (isset($auth) && $auth){
echo 'Auth Passed!';
} else {
echo 'Auth Failed!';
}

当我们在当前文件的url后(http://localhost/test.php?auth=1)加个auth参数(POST也行),便会通过验证。
register_globals漏洞对于初始化的变量是没有效果的。即,在这段代码开始处加上如下代码:

1
$auth = false;

这样的话,虽然会走到’Auth Failed’分支,但是从url传入的auth参数就被忽略了。

1
var_dump($_GET['auth']);  // 输出为Null

防范

  • 配置中关闭
1
register_globals = off

php从4.2.0起就把这个参数设为了默认值,5.4.0开始已经移除了

  • 程序中关闭

假如php.ini里register_globals被设为了on,而程序员又无法修改设置。就只好在程序里写个函数来完成了。下面是wordpress里的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function wp_unregister_GLOBALS() {
if ( !ini_get( 'register_globals' ) )
return;

if ( isset( $_REQUEST['GLOBALS'] ) )
die( /*WP_I18N_GLOBALS_OVERWRITE*/'检测到 GLOBALS 的改写尝试'/*/WP_I18N_GLOBALS_OVERWRITE*/ );

// Variables that shouldn't be unset
$no_unset = array( 'GLOBALS', '_GET', '_POST', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES', 'table_prefix' );

$input = array_merge( $_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, $_FILES, isset( $_SESSION ) && is_array( $_SESSION ) ? $_SESSION : array() );
foreach ( $input as $k => $v )
if ( !in_array( $k, $no_unset ) && isset( $GLOBALS[$k] ) ) {
$GLOBALS[$k] = null;
unset( $GLOBALS[$k] );
}
}

参考资料

据说打赏我的人,代码没有BUG