当该配置项为ON时,会把用户通过GET、POST提交的参数自动注册成全局变量。当代码中存在有未初始化的变量时,可能会导致变量覆盖的问题;
(PS:其中参数覆盖的顺序受到配置文件中variables_order的参数影响,默认是EGPCS。按顺序,右边的参数来源会覆盖左边的的参数来源)
当该配置项为ON时,可以通过include、require等函数进行远程文件包含
其中有个类似的配置项是allow_url_fopen,这个参数配置为on的时候可以函数中例如file_get_contents中打开url。
当两个配置项都为ON的时候,可以直接使用url进行远程包含,当include为ON,fopen为OFF时,只能通过php伪协议进行包含
此配置项为ON的时候会对GET、POST、COOKIE变量中的单引号(')、双引号(")、反斜杠()、空字符(NULL)前添加反斜杠进行转义,注意:这个配置并不会对SERVER变量里的特殊字符进行转义,因此可能会导致referer、client-ip存在注入等漏洞
这个配置和magic_quato_gpc的区别就在于runtime是对从数据库或者文件中取出的数据进行转义,因此只对例如file()、fgets()、fread()、mysql_fetch_array()等很多对数据库查询和文件读取的函数产生影响
这个配置和magic_quato_gpc 的区别在于,sybase只会转义空字符,把单引号转为双引号,并且这个配置如果为ON会覆盖gpc的配置
这个配置用来设置限定php程序只能访问哪些目录。在windows下,多个目录用分号(;)分割,linux下用冒号(:)进行分割。注意的是配置的目录需要用斜杠(/)进行封尾,否则就变成了前缀匹配。例如,配置/var/test,那么/var/test和/var/test123都是可以进行访问的,如果指定一个确定的目录就要写成/var/test/
一般程序都是通过判断install文件下有没有安装过程中生成的以lock为后缀的文件或者config配置文件来判断有没有安装。
例如PHPSHE B2C商城1.6(wooyun 2014-062047)
例如frcms (wooyun 2014-073244)
foreach(Array('_GET','_POST','_COOKIE') as $_request){
foreach($$_request as $_k => $_v) ${$_k} = _runmagicquotes($_v);
}他会把你从GET、POST、COOKIE中的变量注册为全局变量,因此我们直接通过GET参数提交$insLockfile变量即可绕过
例如startbbs (wooyun-2013-045143)
class Install extends Install_Controller
{
function __construct ()
{
parent::__construct();
$this->load->library('myclass');
$file=FCPATH.'install.lock';
if (file_exists($file)){
$this->myclass->notice('alert("系统已安装过");window.location.href="'.site_url().'";');
}
}可以看到其中判断install.lock文件存在后直接使用js代码将用户进行重定向,但是并没有die程序,直接从前端删除返回的js代码即可重装
例如: 用thinkphp 改造的hdcms (wooyun-2015-092061)
我们先跟着框架走一遍,首先查看入口文件index.php
首先定义了一些基本的框架目录,然后就直接开始引入框架文件,我们进入框架初始化文件hdphp.php
可以看到module_path常量是通过将get形式提交的var_group参数进行拼接的,然后又将module_path拼接入module_config_path,最后使用require进行了文件包含。(PS:因为这里后面制定了config.php,所以需要用到%00进行截断)
但是我们分析到目前为止只能说是疑似存在文件包含漏洞,我们还要看GET参数接收时有没有进行过滤,于是我们进入之前的解析路由方法route::parseurl(),代码较长我就不贴图了,里面就是将url中的参数进行截取解析,没有进行任何的过滤和检测,因此可以确定此处存在文件包含漏洞。因此我们接下来需要确定输入点,可以发现变量是通过thinkphp中获取参数的C方法进行获取的,而C方法获取的变量在config.php中,于是我们查看文件中可以看到var_group对应的变量是g
之前的文件包含漏洞我们是通过index.php这个入口文件一步步搞懂cms框架然后进行审计。除了这种方法,我们还可以直接定位数据库查询语句或者功能附近,看看传入的数据有没有被进行清洗。
注入漏洞这里我们就用两个有意思的骚操作来分析一下
其实在ECshop中的init.php中对用户输入的参数进行了全局转义
$order_sn = str_replace($_GET['subject'], '', $_GET['out_trade_no']);其中代码对用户提交的out_trade_no参数中将subject替换为空,然后送入check_money函数中的sql查询语句.[\-->\\,"-->\","-->\",null-->\0]out_trade_no=%00' ————>经过全局gpc转义————> out_trade_no=\0\'————>送入str_replace函数处理,将0替换————>out_trade_no=\\' 也就是等于了',最终也就成功在sql语句中引入了一个单引号,从而可以进行注入再来分析一下前段时间出来的wordpress格式化字符导致的注入
具体的代码分析在这就不贴图了,我们直接来分析一下格式化字符串漏洞的核心原理,其中一个关键点就是sprintf的padding特性
printf()和sprintf()函数中可以通过使用%接一个字符来进行padding功能
例如%10s 字符串会默认在左侧填充空格至长度为10,还可以 %010s 会使用字符0进行填充,但是如果我们想要使用别的字符进行填充,需要使用 ‘ 单引号进行标识,例如 %’#10s 这个就是使用#进行填充(百分号不仅会吃掉’单引号,还会吃掉 斜杠)
同时sprintf()可以使用指定参数位置的写法
%后面的数字代表第几个参数,$后代表格式化类型
于是当我们输入的特殊字符被放到引号中进行转义时,但是又使用了sprintf函数进行拼接时,例如%1$’%s’ 中的 ‘%被当成使用%进行padding,导致后一个’逃逸了
还有一种情况就是’被转义成了’,例如输入%’ and 1=1#进入,存在SQL过滤,’被转成了\’
于是sql语句变成了select * from user where username = '%\' and 1=1#’;
如果这个语句被使用sprintf函数进行了拼接,%后的被吃掉了,导致了’逃逸
<?php
$sql = "select * from user where username = '%\' and 1=1#';";
$args = "admin";
echo sprintf( $sql, $args ) ;
//result: select * from user where username = '' and 1=1#'
?>不过这样容易遇到 PHP Warning: sprintf(): Too few arguments的报错
这个时候我们可以使用%1$来吃掉转移添加的\
<?php
$sql = "select * from user where username = '%1$\' and 1=1#' and password='%s';";
$args = "admin";
echo sprintf( $sql, $args) ;
//result: select * from user where username = '' and 1=1#' and password='admin';
?>