PHP安全--使用 Register Globals (2)
采取相应的预防措施以便在伪造变量输入的时候给予警告是完全有可能的。如果事先确切知道变量是哪里来的,就可以检查所提交的数据是否是从不正当的表单提交而来。不过这不能保证变量未被伪造,这需要攻击者去猜测应该怎样去伪造。如果不在乎请求数据来源的话,可以使用 $_REQUEST 数组,它包括了 GET、POST 和 COOKIE 的所有数据。详情可参见本手册的来自 PHP 之外的变量。
Example#3 探测有害变量
<?php
if (isset($_COOKIE['MAGIC_COOKIE'])) {
// MAGIC_COOKIE 来自 cookie
// 这样做是确保是来自 cookie 的数据
} elseif (isset($_GET['MAGIC_COOKIE']) || isset($_POST['MAGIC_COOKIE'])) {
mail("admin@example.com", "Possible breakin attempt", $_SERVER['REMOTE_ADDR']);
echo "Security violation, admin has been alerted.";
exit;
} else {
// 这一次请求中并没有设置 MAGIC_COOKIE 变量
}
?>
当然,单纯地关闭 register_globals 并不代表所有的代码都安全了。对于每一段提交上来的数据,都要对其进行具体的检查。永远要验证用户数据和对变量进行初始化!把 error_reporting() 设为 E_NOTICE 级别可以检查未初始化的变量。
更多关于模拟 register_globals 为 on 或 off 的信息,请见此 FAQ。
Note: Superglobals 可用性说明 自 PHP 4.1.0 起,可以使用超全局数组变量例如 $_GET,$_POST 和 $_SERVER 等等。更多信息请阅读手册中的 superglobals。
While we all appreciate the many helpful posts to get rid of register_globals, maybe you're one of those who just loves it. More likely, your boss says you just have to live with it because he thinks it's a great feature.
No problem, just call (below defined):
<?php register_globals(); ?>
anywhere, as often as you want. Or update your scripts!
<?php
/**
* function to emulate the register_globals setting in PHP
* for all of those diehard fans of possibly harmful PHP settings :-)
* @author Ruquay K Calloway
* @param string $order order in which to register the globals, e.g. 'egpcs' for default
*/ function register_globals($order = 'egpcs')
{
// define a subroutine
if(!function_exists('register_global_array'))
{
function register_global_array(array $superglobal)
{
foreach($superglobal as $varname => $value)
{
global $$varname;
$$varname = $value;
}
}
}
$order = explode("\r\n", trim(chunk_split($order, 1)));
foreach($order as $k)
{
switch(strtolower($k))
{
case 'e': register_global_array($_ENV); break;
case 'g': register_global_array($_GET); break;
case 'p': register_global_array($_POST); break;
case 'c': register_global_array($_COOKIE); break;
case 's': register_global_array($_SERVER); break;
}
}
}
?>
Put this to the beginning of every file or to a functions.inc.php and call it every time before start working with user variables.
This will prevent problems with wrong initalized variables or users who try to break your application.
And this has an extra bonus: Applications which still work are also register_globasl = off enabled!
<?php
// // If register_globals is on, delete all variables exept the ones in the array
// if (ini_get('register_globals')) {
foreach ($GLOBALS as $int_temp_name => $int_temp_value) {
if (!in_array($int_temp_name, array (
'GLOBALS',
'_FILES',
'_REQUEST',
'_COOKIE',
'_SERVER',
'_ENV',
'_SESSION',
ini_get('session.name'),
'int_temp_name',
'int_temp_value'
))) {
unset ($GLOBALS[$int_temp_name]);
}
}
}
// // Now, (re)import the variables
// if (isset ($_REQUEST['pass']))
$ext_pass = $_REQUEST['pass'];
if (isset ($_REQUEST['user']))
$ext_user = $_REQUEST['user'];
if (isset ($_REQUEST['action']))
$ext_action = $_REQUEST['action'];
// // Cleanup entries
// $int_pass = (isset ($ext_pass) ? preg_replace("'[^A-Z]'", "", $ext_pass) : '');
$int_user = (isset ($ext_user) ? preg_replace("'[]A-Za-z0-9áäàâãëèéêïìîóöòôõúüùû \.^\$\!\_-()'", "", $ext_user) : '');
$int_action = (isset ($ext_action) ? intval($ext_action) : '');
// // Import Session variables
// if (isset ($_SESSION)) {
foreach ($_SESSION as $int_temp_key => $int_temp_value) {
if ($int_temp_value != '') {
$$int_temp_key = $int_temp_value;
}
}
}
// // Import Cookie variables
// if (isset ($_COOKIE)) {
foreach ($_COOKIE as $int_temp_key => $int_temp_value) {
if ($int_temp_value != '') {
$$int_temp_key = $int_temp_value;
}
}
}
// // From here on, work only with $int_ variables and you're safe!
// ?>
With this you can prevent a lot of different problems!
Alans code may get rid of globals but it is slow since it is doing regular expressions on each of the input items. Then to add on more time the code is being passed through eval.
Besides the slower performance, his code is not checking to see if the variable may have been changed at any state before this code is being done.
There might be auto_prepended files or include files that might need to run before it. He is also going through get and post and lastly request which is a little silly seeing as request will contain the get, post and cookie so he has run get and post twice.
Here is a more effective fix that will take all the keys in request which become variable names and checks to make sure that the variables match then unsets the element.
@ Mike Willbanks's post
This is an even cleaner version of your code:
<?php
if( ini_get(register_globals) ) {
/* genocide the damn registered globals if they are on */ foreach( $_REQUEST as $key => $var ){
if( $var === $$key ){
unset($$key);
}
}
}
?>
责任编辑:黑客基地
本文引用网址:








