当前位置: 首页 > 图文教程 > 网络编程 > PHP > PHP泛安全

PHP
php调用mysql存储过程
PHP+.htaccess实现全站静态HTML文件GZIP压缩传输(一)
PHP中HTTP方式下的Gzip压缩传输方法举偶
隐藏X-Space个人空间下方版权方法隐藏X-Space个人空间标题隐藏X-Space个人空间管理版权方法
如何提高PHP速度
发布一个用PHP fsockopen写的HTTP下载的类
php公用函数列表[正则]
实现了一个PHP5的getter/setter基类的代码
php简单封装了一些常用JS操作
Smarty+QUICKFORM小小演示
给php新手谈谈我的学习心得
NOD32 v2.70.32 简体中文封装版 提供下载了
个人站长制做网页常用的php代码
收集的php编写大型网站问题集
如何从一个php文件向另一个地址post数据,不用表单和隐藏的变量的
php下实现农历日历的代码
php+dojo 的数据库保存拖动布局的一个方法dojo 这里下载
php网页后退不再出现过期
PHP实现用户认证及管理完全源码
用PHP制作的意见反馈表源码

PHP泛安全


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-11-03   浏览: 229 ::
收藏到网摘: n/a

/*---------------
*Author:xy7
*Data:2006/11/1
*---------------
*/


如今基于PHP的WEB程序是越来越安全了,php.ini默认时的 magic_quotes_gpc=on就在初始安全性上提高了一个档次.很多程序在接受到用户的输入时都会提前判断一下 get_magic_quotes_gpc() 即使这个开关没有开就马上addslashes()函数跟上进行转义,所以想在PHP程序中找到一个类似与以前ASP注入那样的漏洞是比较不容易的.
对于PHP的跨站其实也很好防范,用 htmlentities() 就可以了,不过当处理XML文件时采用这个函数可能会出现些问题,只需手工转换下那5个元字符就可以了。举个例子,以前写过篇文章关于XML文件隐患的,其实就是CDATA部件的问题,现在比较流行的说法是AJAX hacking,大概说下,看看以下代码:
if ($rssid == 0 OR $rssid == 7) {
} elseif (!empty($stmt)) {
    $dbinfo =& $db->getResultSet($stmt, array('pageSize'=>$pagesize));
    if ($dbinfo === false) {
        $msginfo = str_replace(']]>', ']]>', $lang['tpl.str0']);
        $TPL_items .= <<<EOT
        <item>
            <title>{$msginfo}</title>
            <link>{$fsetting['forumurl']}</link>
            <author>{$fsetting['forumname']}</author>
            <pubDate>{$datenow}</pubDate>
            <description><![CDATA[{$msginfo}]]></description>
        </item>
EOT;
$msginfo是用户提交的,然后被程序写进RSS里以用来聚合,如果$msginfo的值为<sciript>alert('loveshell')</script>时,RSS聚合解析后会原样输出,如果为]]><sciript>alert('loveshell')</script>时,就可以跨站了,看看他的过滤:
if ($dbinfo === false) {
        $msginfo = str_replace(']]>', ']]>', $lang['tpl.str0']);
很好意识到了这点,可是这句呢<title>{$msginfo}</title>,意识到问题所在很关键,重要的是要理解问题.

可是还是有很多会被程序员疏忽的地方,这是安全意识的问题,对于用户的任何输入,在写程序时脑子里都要提前做个思考:用户的输入是什么类型的?用户会有哪些输入方式?怎么处理用户的错误和非常规输入?
PHP的安全还体现在Safe Mode 和openbase-dir上.即使这样基于PHP底层的一些漏洞还是会直接影响到这两个非常重要的安全选项.举个例子:
比如error_log() Safe Mode Bypass
看他的语法:bool error_log ( string message [, int message_type [, string destination [, string extra_headers]]] )
输出错误信息到一个文件,可以这样写
<?
error_log("<? phpinfo();?>", 3, "test.php");
?>
运行在safe_mode关闭的情况下,直接访问test.php就可以看到phpinfo了,当safe_mode开的时候就会报错,再这样写:
<?
error_log("<? phpinfo();?>", 3, "prefix://../../test.php");
?>可以看到phpinfo又被执行了
看下漏洞代码:
PHPAPI int _php_error_log(int opt_err, char *message, char *opt, char *headers TSRMLS_DC)

{

php_stream *stream = NULL;

switch (opt_err) {

case 1: /*send an email */

{

#if HAVE_SENDMAIL

if (!php_mail(opt, "PHP error_log message", message, headers, NULL TSRMLS_CC)) {


return FAILURE;

}

php_error_docref(NULL TSRMLS_CC, E_WARNING, "Mail option not available!");

return FAILURE;

}

break;

case 2: /*send to an address */

php_error_docref(NULL TSRMLS_CC, E_WARNING, "TCP/IP option not available!");

return FAILURE;

break;

case 3: /*save to a file */

stream = php_stream_open_wrapper(opt, "a", IGNORE_URL | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);

if (!stream)

return FAILURE;

php_stream_write(stream, message, strlen(message));

php_stream_close(stream);

break;

default:

php_log_err(message TSRMLS_CC);

break;

}

return SUCCESS;

}
可以看到error_log函数的核心就是 php_stream_open_wrapper()函数,问题也就出在保存错误信息