PHP安全性漫谈

澳门新葡亰娱乐在线 2

本文所讨论的安全性环境是在Linux+Apache+Mysql+PHP。超出此范围的安全性问题不在本文范畴之内

一、CGI模式安装安全

一、apache server安全性设置

二、以Apache模块安装安全

1、以Nobody用户运行

一般情况下,Apache是由Root 来安装和运行的。如果Apache
Server进程具有Root用户特权,那么它将给系统的安全构成很大的威胁,应确保Apache
Server进程以最可能低的权限用户来运行。通过修改httpd.conf文件中的下列选项,以Nobody用户运行Apache
达到相对安全的目的。

User nobody
Group# -1

当 PHP 以 Apache 模块方式安装时,它将继承 Apache
用户的权限。这对安全和认证有一些影响。比如,如果用 PHP
来访问数据库,除非数据库有自己的访问控制,否则就要使“nobody”用户可以访问数据库。这意味着恶意的脚本在不用提供用户名和密码时就可能访问和修改数据库。一个
web Spider
也完全有可能偶然发现数据库的管理页面,并且删除所有的数据库。可以通过
Apache 认证来避免此问题,或者用 LDAP、.htaccess
等技术来设计自己的防问模型,并把这些代码作为 PHP
脚本的一部份一个常犯的对安全性不利的错误就是让 Apache 拥有 root
权限,或者通过其它途径斌予 Apache 更强大的功能。把 Apache
用户的权限提升为 root
是极度危险的做法,而且可能会危及到整个系统的安全。所以除非是安全专家,否则决不要考虑使用
su,chroot 或者以 root
权限运行。除此之外还有一些比较简单的解决方案。比如说可以使用
open_basedir 来限制哪些目录可以被 PHP 使用。也可以设置 Apache
的专属区域,从而把所有的 web 活动都限制到非用户和非系统文件之中。

2、ServerRoot目录的权限

为了确保所有的配置是适当的和安全的,需要严格控制Apache
主目录的访问权限,使非超级用户不能修改该目录中的内容。Apache
的主目录对应于Apache Server配置文件httpd.conf的Server
Root控制项中,应为:

Server Root /usr/local/apache

三、文件系统安全

3、SSI的配置

在配置文件access.conf 或httpd.conf中的确Options指令处加入Includes NO
EXEC选项,用以禁用Apache Server 中的执行功能。避免用户直接执行Apache
服务器中的执行程序,而造成服务器系统的公开化。

Options Includes Noexec

PHP
遵从大多数服务器系统中关于文件和目录权限的安全机制。这就使管理员可以控制哪些文件在文件系统内是可读的。必须特别注意的是全局的可读文件,并确保每一个有权限的用户对这些文件的读取动作都是安全的。PHP
被设计为以用户级别来访问文件系统,所以完全有可能通过编写一段 PHP
代码来读取系统文件如
/etc/passwd,更改网络连接以及发送大量打印任务等等。因此必须确保 PHP
代码读取和写入的是合适的文件。

4、阻止用户修改系统设置

在Apache 服务器的配置文件中进行以下的设置,阻止用户建立、修改
.htaccess文件,防止用户超越能定义的系统安全特性。

AllowOveride None
Options None
Allow from all

然后再分别对特定的目录进行适当的配置。

两个重要措施来防止此类问题。

5、改变Apache 服务器的缺省访问特性

Apache
的默认设置只能保障一定程度的安全,如果服务器能够通过正常的映射规则找到文件,那么客户端便会获取该文件,如
host/~ root/ 将允许用户访问整个文件系统。在服务器文件中加入如下内容:

order deny,ellow
Deny from all

将禁止对文件系统的缺省访问。

# 只给 PHP 的 web 用户很有限的权限。# 检查所有提交上来的变量。

6、CGI脚本的安全考虑

CGI脚本是一系列可以通过Web服务器来运行的程序。为了保证系统的安全性,应确保CGI的作者是可信的。对CGI而言,最好将其限制在一个特定的目
录下,如cgi-bin之下,便于管理;另外应该保证CGI目录下的文件是不可写的,避免一些欺骗性的程序驻留或混迹其中;如果能够给用户提供一个安全性
良好的CGI程序的模块作为参考,也许会减少许多不必要的麻烦和安全隐患;除去CGI目录下的所有非业务应用的脚本,以防异常的信息泄漏。

$username = $_SERVER['REMOTE_USER']; // 使用认证机制$userfile = $_POST['user_submitted_filename'];$homedir = "/home/$username";$filepath = "$homedir/$userfile";if (!ctype_alnum || !preg_match('/^(?:[a-z0-9_-]|.+$/iD', $userfile)) { die("Bad username/filename");}

7、SSL链接加密

以上这些常用的举措可以给Apache Server
一个基本的安全运行环境,显然在具体实施上还要做进一步的细化分解,制定出符合实际应用的安全配置方案。

由于 PHP 的文件系统操作是基于 C
语言的函数的,所以它可能会以您意想不到的方式处理 Null 字符。 Null字符在
C 语言中用于标识字符串结束,一个完整的字符串是从其开头到遇见 Null
字符为止。

二、PHP安全性设置

服务器并不能阻止所有的安全问题,例如程序漏洞问题、用户输入表单问题、PHP文件权限问题等。
也可以通过一些手段来迷惑黑客或者别有用心者。

# 会被 Null 字符问题攻击的代码:

1、程序代码漏洞问题

很多 PHP 程序所存在的重大弱点并不是 PHP
语言本身的问题,而是编程者的安全意识不高而导致的。因此,必须时时注意每一段代码可能存在的问题,去发现非正确数据提交时可能造成的影响。

<?php 
    unlink ($evil_var); 
    fwrite ($fp, $evil_var); 
    system ($evil_var); 
    exec ($evil_var); 
?>

必须时常留意你的代码,以确保每一个从客户端提交的变量都经过适当的检查,然后问自己以下一些问题:

此脚本是否只能影响所预期的文件?

非正常的数据被提交后能否产生作用?

此脚本能用于计划外的用途吗?

此脚本能否和其它脚本结合起来做坏事?

是否所有的事务都被充分记录了?

在写代码的时候问自己这些问题,否则以后可能要为了增加安全性而重写代码了。注意了这些问题的话,也许还不完全能保证系统的安全,但是至少可以提高安全性。

还可以考虑关闭 register_globals,Magic_quotes
或者其它使编程更方便但会使某个变量的合法性,来源和其值被搞乱的设置。

$file = $_GET['file']; // "http://www.cnblogs.com/etc/passwd"if (file_exists('/home/wwwrun/'.$file.'.php')) { // file_exists will return true as the file /home/wwwrun/http://www.cnblogs.com/etc/passwd exists include '/home/wwwrun/'.$file.'.php'; // the file /etc/passwd will be included}

2、用户输入表单问题

验证用户输入的任何数据,保证PHP代码的安全。

注意1:JS只是为了提高来访用户的体验而产生的,而不是验证的工具。因为任何一个来访的用户都可能会,也有可能无意间就禁用了客户端脚本的执行,从而跳过这层验证。所以我们必须在PHP的服务器端程序上检验这些数据。

注意2:不要使用$_SERVER[‘HTTP_REFERER’]这个超级变量来检查数据的来源地址,一个很小的菜鸟黑客都会利用工具来伪造这个变量的数据,尽可能利用Md5,或者rand等函数来产生一个令牌,验证来源的时候,验证这个令牌是否匹配。

# 验证输入的正确做法

3、PHP文件权限问题

PHP 被设计为以用户级别来访问文件系统,所以完全有可能通过编写一段 PHP
代码来读取系统文件如
/etc/passwd,更改网络连接以及发送大量打印任务等等。因此必须确保 PHP
代码读取和写入的是合适的文件。
请看下面的代码,用户想要删除自己主目录中的一个文件。假设此情形是通过 web
界面来管理文件系统,因此 Apache 用户有权删除用户目录下的文件。

<?php 
    $username = $_POST['user_submitted_name']; 
    $homedir = "/home/$username"; 
    $file_to_delete = "$userfile"; 
    unlink ("$homedir/$userfile"); 
    echo "$file_to_delete has been deleted!"; 
?>

既然 username
变量可以通过用户表单来提交,那就可以提交别人的用户名和文件名,并删除该文件。这种情况下,就要考虑其它方式的认证:

只给 PHP 的 web 用户很有限的权限。 -检查所有提交上来的变量。
-以下是更加安全的文件名和变量的验证和检查:

<?php 
    $username = $_SERVER['REMOTE_USER']; 
    $homedir = "/home/$username"; 

    if (!ereg('^[^./][^/]*$', $userfile)) 
        die('bad filename'); 

    if (!ereg('^[^./][^/]*$', $username)) 
        die('bad username'); 
?>
$file = $_GET['file']; // 对字符串进行白名单检查switch  { case 'main': case 'foo': case 'bar': include '/home/wwwrun/include/'.$file.'.php'; break; default: include '/home/wwwrun/include/main.php';}

4、隐藏PHP扩展名

一般而言,通过隐藏的手段提高安全性被认为是作用不大的做法。但某些情况下,尽可能的多增加一份安全性都是值得的。

一些简单的方法可以帮助隐藏
PHP,这样做可以提高攻击者发现系统弱点的难度。在 php.ini 文件里设置
expose_php = off ,可以减少他们能获得的有用信息。

另一个策略就是让 web 服务器用 PHP 解析不同扩展名。无论是通过 .htaccess
文件还是 Apache 的配置文件,都可以设置能误导攻击者的文件扩展名:

# 使PHP看上去像其它的编程语言

AddType application/x-httpd-php .asp .py .pl

# 使 PHP 看上去像未知的文件类型

AddType application/x-httpd-php .bop .foo .133t

# 使 PHP 代码看上去像HTML页面

AddType application/x-httpd-php .htm .html

要让此方法生效,必须把 PHP
文件的扩展名改为以上的扩展名。这样就通过隐藏来提高了安全性,虽然防御能力很低而且有些缺点。

四、数据库安全

三、Mysql数据库安全性设置

PHP 本身并不能保护数据库的安全。下面的章节只是讲述怎样用 PHP
脚本对数据库进行基本的访问和操作。记住一条简单的原则:深入防御。保护数据库的措施越多,攻击者就越难获得和使用数据库内的信息。正确地设计和应用数据库可以减少被攻击的担忧。

第一步一般都是创建数据库,除非是使用第三方的数据库服务。当创建一个数据库的时候,会指定一个所有者来执行和新建语句。通常,只有所有者才有权对数据库中的对象进行任意操作。如果想让其他用户使用,就必须赋予他们权限。应用程序永远不要使用数据库所有者或超级用户帐号来连接数据库,因为这些帐号可以执行任意的操作,比如说修改数据库结构或者清空整个数据库的内容。应该为程序的每个方面创建不同的数据库帐号,并赋予对数据库对象的极有限的权限。仅分配给能完成其功能所需的权限,避免同一个用户可以完成另一个用户的事情。这样即使攻击者利用程序漏洞取得了数据库的访问权限,也最多只能做到和该程序一样的影响范围。鼓励用户不要把所有的事务逻辑都用
web
应用程序来实现。最好用视图或者规则在数据库层面完成。当系统升级的时候,需要为数据库开辟新的接口,这时就必须重做所有的数据库客户端。除此之外,触发器还可以透明和自动地处理字段,并在调试程序和跟踪事实时提供有用的信息。*
连接数据库

1、数据库设计问题

应用程序永远不要使用数据库所有者或超级用户帐号来连接数据库,因为这些帐号可以执行任意的操作,比如说修改数据库结构(例如删除一个表)或者清空整个数据库的内容。以下截图的用户设置是危险的。

澳门新葡亰娱乐在线 1

澳门新葡亰娱乐在线 2

应该为程序的每个方面创建不同的数据库帐号,并赋予对数据库对象的极有限的权限。仅分配给能完成其功能所需的权限,避免同一个用户可以完成另一个用户的事情。这样即使攻击者利用程序漏洞取得了数据库的访问权限,也最多只能做到和该程序一样的影响范围。

把连接建立在 SSL 加密技术上可以增加客户端和服务器端通信的安全性,或者
SSH
也可以用于加密客户端和数据库之间的连接。如果使用了这些技术的话,攻击者要监视服务器的通信或者得到数据库的信息是很困难的。

2.数据库连接问题

把连接建立在 SSL 加密技术上可以增加客户端和服务器端通信的安全性,或者
SSH
也可以用于加密客户端和数据库之间的连接。如果使用了这些技术的话,攻击者要监视服务器的通信或者得到数据库的信息是很困难的。

SSL/SSH 能保护客户端和服务器端交换的数据,但 SSL/SSH
并不能保护数据库中已有的数据。SSL
只是一个加密网络数据流的协议。如果攻击者取得了直接访问数据库的许可,敏感数据就可能暴露或者被滥用,除非数据库自己保护了这些信息。对数据库内的数据加密是减少这类风险的有效途径,但是只有很少的数据库提供这些加密功能。对于这个问题,有一个简单的解决办法,就是创建自己的加密机制,然后把它用在
PHP 程序内。PHP 有几个扩展库可以完成这个工作,比如说 Mcrypt 和 Mhash
等,它们包含多种加密运算法则。脚本在插入数据库之前先把数据加密,以后提取出来时再解密。对某些真正隐蔽的数据,如果不需要以明文的形式存在,可以考虑用散列算法。使用散列算法最常见的例子就是把密码经过
MD5 加密后的散列存进数据库来代替原来的明文密码。参见 crypt。* SQL注入

3.数据库数据的加密

SSL/SSH 能保护客户端和服务器端交换的数据,但 SSL/SSH
并不能保护数据库中已有的数据。SSL 只是一个加密网络数据流的协议。

如果攻击者取得了直接访问数据库的许可(绕过 web
服务器),敏感数据就可能暴露或者被滥用,除非数据库自己保护了这些信息。对数据库内的数据加密是减少这类风险的有效途径,但是只有很少的数据库提供这些加密功能。

对于这个问题,有一个简单的解决办法,就是创建自己的加密机制,然后把它用在
PHP 程序内,最常见的例子就是把密码经过 MD5
加密后的散列存进数据库来代替原来的明文密码。

<?php 
$query = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');", 
addslashes($username), md5($password)); 
$result = pg_query($connection, $query); 
$query = sprintf("SELECT 1 FROM users WHERE name='%s' AND pwd='%s';", 
addslashes($username), md5($password)); 
$result = pg_query($connection, $query); 
if (pg_num_rows($result) > 0) { 
echo 'Welcome, $username!'; 
} else { 
echo 'Authentication failed for $username.'; 
} 
?>

很多 web 开发者没有注意到 SQL 查询是可以被篡改的,因而把 SQL
查询当作可信任的命令。殊不知道,SQL
查询可以绕开访问控制,从而绕过身份验证和权限检查。更有甚者,有可能通过
SQL 查询去运行主机操作系统级的命令。直接 SQL
命令注入就是攻击者常用的一种创建或修改已有 SQL
语句的技术,从而达到取得隐藏数据,或覆盖关键的值,甚至执行数据库主机操作系统命令的目的。这是通过应用程序取得用户输入并与静态参数组合成
SQL
查询来实现的。下面将会给出一些真实的例子。由于在缺乏对输入的数据进行验证,并且使用了超级用户或其它有权创建新用户的数据库帐号来连接,攻击者可以在数据库中新建一个超级用户。

4、SQL注入问题

直接 SQL 命令注入就是攻击者常用的一种创建或修改已有 SQL
语句的技术,从而达到取得隐藏数据,或覆盖关键的值,甚至执行数据库主机操作系统命令的目的。这是通过应用程序取得用户输入并与静态参数组合成
SQL 查询来实现的。下面将会给出一些真实的例子。

<?php 
$query = "SELECT id, name, inserted, size FROM products 
WHERE size = '$size' 
ORDER BY $order LIMIT $limit, $offset;"; 
$result = odbc_exec($conn, $query); 
?>

可以在原来的查询的基础上添加另一个 SELECT 查询来获得密码: union select
’1′, concat(uname||’-’||passwd) as name, ’1971-01-01′, ’0′ from
usertable; 假如上述语句(使用 ‘ 和 –)被加入到 $query
中的任意一个变量的话,那么就麻烦了。

这些攻击总是建立在发掘安全意识不强的代码上的。所以,永远不要信任外界输入的数据,特别是来自于客户端的,包括选择框、表单隐藏域和
cookie。就如上面的第一个例子那样,就算是正常的查询也有可能造成灾难。

永远不要使用超级用户或所有者帐号去连接数据库。要用权限被严格限制的帐号。
检查输入的数据是否具有所期望的数据格式。PHP
有很多可以用于检查输入的函数,从简单的变量函数和字符类型函数(比如
is_numeric(),ctype_digit())到复杂的 Perl
兼容正则表达式函数都可以完成这个工作。

如果程序等待输入一个数字,可以考虑使用 is_numeric()
来检查,或者直接使用 settype() 来转换它的类型,也可以用 sprintf()
把它格式化为数字。

一个更安全的防止SQL注入的分页显示方法:

<?php 
settype($offset, 'integer'); 
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;"; 
$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;", 
$offset); 
?>

Example #1 一段实现数据分页显示的代码……也可以被用作创建一个超级用户。

一般的用户会点击
$offset已被斌值的“上一页”、“下一页”的链接。原本代码只会认为
$offset是一个数值。然而,如果有人尝试把以下语句先经过
urlencode()处理,然后加入URL中的话:

0;insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
select ‘crack’, usesysid, ‘t’,’t’,’crack’ from pg_shadow where
usename=’postgres’;–那么他就可以创建一个超级用户了。注意那个
0;只不过是为了提供一个正确的偏移量以便补充完整原来的查询,使它不要出错而已。

— 是 SQL 的注释标记,一般可以使用来它告诉 SQL 解释器忽略后面的语句。

澳门新葡亰娱乐在线,对显示搜索结果的页面下手是一个能得到密码的可行办法。攻击者所要做的只不过是找出哪些提交上去的变量是用于
SQL 语句并且处理不当的。而这类的变量通常都被用于
SELECT查询中的条件语句,如 WHERE, ORDER BY, LIMIT 和
OFFSET。如果数据库支持 UNION构造的话,攻击者还可能会把一个完整的 SQL
查询附加到原来的语句上以便从任意数据表中得到密码。因此,对密码字段加密是很重要的。

Example #2 显示文章……以及一些密码

复制代码 代码如下:

可以在原来的查询的基础上添加另一个 SELECT查询来获得密码:

‘union select ‘1’, concat as name, ‘1971-01-01’, ‘0’ from
usertable;–假如上述语句被加入到
$query中的任意一个变量的话,那么就麻烦了。

SQL 中的 UPDATE
也会受到攻击。这种查询也可能像上面的例子那样被插入或附加上另一个完整的请求。但是攻击者更愿意对
SET子句下手,这样他们就可以更改数据表中的一些数据。这种情况下必须要知道数据库的结构才能修改查询成功进行。可以通过表单上的变量名对字段进行猜测,或者进行暴力破解。对于存放用户名和密码的字段,命名的方法并不多。

Example #3 从重设密码……到获得更多权限

复制代码 代码如下:

但是恶意的用户会把 ‘ or uid like’%admin%’; –作为变量的值提交给 $uid
来改变 admin 的密码,或者把 $pwd 的值提交为 “hehehe’, admin=’yes’,
trusted=100 “去获得更多的权限。这样做的话,查询语句实际上就变成了:

复制代码 代码如下:

// $pwd == “hehehe’, admin=’yes’, trusted=100 “$query = “UPDATE
usertable SET pwd=’hehehe’, admin=’yes’, trusted=100 WHERE…;”;?>

下面这个可怕的例子将会演示如何在某些数据库上执行系统命令。

Example #4 攻击数据库所在主机的操作系统

复制代码 代码如下:

如果攻击提交 a%’ exec master..xp_cmdshell ‘net user test testpass /ADD’
–作为变量 $prod的值,那么 $query将会变成

复制代码 代码如下:

MSSQL 服务器会执行这条 SQL
语句,包括它后面那个用于向系统添加用户的命令。如果这个程序是以 sa运行而
MSSQLSERVER
服务又有足够的权限的话,攻击者就可以获得一个系统帐号来访问主机了。

虽然以上的例子是针对某一特定的数据库系统的,但是这并不代表不能对其它数据库系统实施类似的攻击。使用不同的方法,各种数据库都有可能遭殃。

预防措施

也许有人会自我安慰,说攻击者要知道数据库结构的信息才能实施上面的攻击。没错,确实如此。但没人能保证攻击者一定得不到这些信息,一但他们得到了,数据库有泄露的危险。如果你在用开放源代码的软件包来访问数据库,比如论坛程序,攻击者就很容得到到相关的代码。如果这些代码设计不良的话,风险就更大了。这些攻击总是建立在发掘安全意识不强的代码上的。所以,永远不要信任外界输入的数据,特别是来自于客户端的,包括选择框、表单隐藏域和
cookie。就如上面的第一个例子那样,就算是正常的查询也有可能造成灾难。•永远不要使用超级用户或所有者帐号去连接数据库。要用权限被严格限制的帐号。

•检查输入的数据是否具有所期望的数据格式。PHP
有很多可以用于检查输入的函数,从简单的变量函数和字符类型函数,ctype_digit到复杂的
Perl 兼容正则表达式函数都可以完成这个工作。
•如果程序等待输入一个数字,可以考虑使用 is_numeric
来转换它的类型,也可以用 sprintf() 把它格式化为数字。

Example #5 一个实现分页更安全的方法

复制代码 代码如下:

// 请注意格式字符串中的 %d,如果用 %s 就毫无意义了$query =
sprintf(“SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET
%d;”,$offset);?>

•使用数据库特定的敏感字符转义函数(比如 mysql_escape_string() 和
sql_escape_string把用户提交上来的非数字数据进行转义。如果数据库没有专门的敏感字符转义功能的话
addslashes可以代替完成这个工作。看看第一个例子,此例显示仅在查询的静态部分加上引号是不够的,查询很容易被攻破。
•要不择手段避免显示出任何有关数据库的信心,尤其是数据库结构。参见错误报告和错误处理函数。
•也可以选择使用数据库的存储过程和预定义指针等特性来抽象数库访问,使用户不能直接访问数据表和视图。但这个办法又有别的影响。
除此之外,在允许的情况下,使用代码或数据库系统保存查询日志也是一个好办法。显然,日志并不能防止任何攻击,但利用它可以跟踪到哪个程序曾经被尝试攻击过。日志本身没用,要查阅其中包含的信息才行。毕竟,更多的信息总比没有要好。

五、错误报告

对于 PHP
的安全性来说错误报告是一把双刃剑。一方面可以提高安全性,另一方面又有害。

攻击系统时经常使用的手法就是输入不正确的数据,然后查看错误提示的类型及上下文。这样做有利于攻击者收集服务器的信息以便寻找弱点。比如说,如果一个攻击者知道了一个页面所基于的表单信息,那么他就会尝试修改变量:

Example #1 用自定义的 HTML 页面攻击变量

复制代码 代码如下:

通常 PHP
所返回的错误提示都能帮助开发者调试程序,它会提出哪个文件的哪些函数或代码出错,并指出错误发生的在文件的第几行,这些就是
PHP 本身所能给出的信息。很多 PHP 开发者会使用 show_source或者
highlight_file()函数来调试代码,但是在正式运行的网站中,这种做法可能会暴露出隐藏的变量、未检查的语法和其它的可能危及系统安全的信息。在运行一些具有内部调试处理的程序,或者使用通用调试技术是很危险的。如果让攻击者确定了程序是使用了哪种具体的调试技术,他们会尝试发送变量来打开调试功能:

Example #2 利用变量打开调式功能

复制代码 代码如下:

不管错误处理机制如何,可以探测系统错误的能力会给攻击者提供更多信息。

比如说,PHP 的独有的错误提示风格可以说明系统在运行
PHP。如果攻击者在寻找一个 .html
为页面,想知道其后台的技术,他们就会把错误的数据提交上去,然后就有可以得知系统是基于
PHP
的了。一个函数错误就可能暴露系统正在使用的数据库,或者为攻击者提供有关网页、程序或设计方面的有用信息。攻击者往往会顺藤摸瓜地找到开放的数据库端口,以及页面上某些
bug
或弱点等。比如说,攻击者可以一些不正常的数据使程序出错,来探测脚本中认证的顺序以及脚本中其它位置可能泄露的信息。一个文件系统或者
PHP 的错误就会暴露 web
服务器具有什么权限,以及文件在服务器上的组织结构。开发者自己写的错误代码会加剧此问题,导致泄漏了原本隐藏的信息。有三个常用的办法处理这些问题。第一个是彻底地检查所有函数,并尝试弥补大多数错误。第二个是对在线系统彻底关闭错误报告。第三个是使用
PHP
自定义的错误处理函数创建自己的错误处理机制。根据不同的安全策略,三种方法可能都适用。一个能提前阻止这个问题发生的方法就是利用
error_reporting()
来帮助使代码更安全并发现变量使用的危险之处。在发布程序之前,先打开
E_ALL
测试代码,可以帮你很快找到变量使用不当的地方。一旦准备正式发布,就应该把
error_reporting() 的参数设为 0 来彻底关闭错误报告或者把 php.ini中的
display_errors 设为 off
来关闭所有的错误显示以将代码隔绝于探测。当然,如果要迟一些再这样做,就不要忘记打开
ini 文件内的 log_errors 选项,并通过 error_log
指定用于记录错误信息的文件。

Example #3 用 E_ALL 来查找危险的变量

复制代码 代码如下:

六、使用Register Globals可能 PHP 中最具争议的变化就是从 PHP »
4.2.0版开始配置文件中 register_globals的默认值从 on 改为 off
了。对此选项的依赖是如此普遍以至于很多人根本不知道它的存在而以为 PHP
本来就是这么工作的。本节会解释用这个指令如何写出不安全的代码,但要知道这个指令本身没有不安全的地方,误用才会。

当 register_globals 打开以后,各种变量都被注入代码,例如来自 HTML
表单的请求变量。再加上 PHP
在使用变量之前是无需进行初始化的,这就使得更容易写出不安全的代码。这是个很艰难的抉择,但
PHP
社区还是决定默认关闭此选项。当打开时,人们使用变量时确实不知道变量是哪里来的,只能想当然。但是
register_globals
的关闭改变了这种代码内部变量和客户端发送的变量混杂在一起的糟糕情况。下面举一个错误使用
register_globals 的例子:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图