163 lines
10 KiB
Markdown
163 lines
10 KiB
Markdown
Instead of embedding static Java serialized objects, Metasploit offers ysoserial-generated binaries with built-in randomization. The benefits of using the Metasploit library include quicker module development, easier-to-read code, and future-proof Java serialized objects.
|
|
|
|
To use the ysoserial libraries, let's look at an example from the [`shiro_rememberme_v124_deserialize`][2] module:
|
|
|
|
### Example code
|
|
|
|
In this example:
|
|
1. (L78) The module calls `payload.encode` to generate the command payload.
|
|
1. (L80) Then it sets the modified type to either `bash` or `cmd` based on the target.
|
|
1. (L81) Finally, the `ysoserial` library is used to generate a `CommonsCollections2`-based serialized object.
|
|
|
|
```
|
|
78 cmd = payload.encoded
|
|
79 vprint_status("Execute CMD: #{cmd}")
|
|
80 type = (target.name == 'Unix Command payload' ? 'bash' : 'cmd')
|
|
81 java_payload = ::Msf::Util::JavaDeserialization.ysoserial_payload('CommonsCollections2', cmd, modified_type: type)
|
|
```
|
|
|
|
Once the serialized object is generated and stored as `java_payload`, it's then sent to the target in an exploit-specific manner.
|
|
|
|
### Calling `ysoserial_payload`
|
|
|
|
`#ysoserial_payload(payload_name, command=nil, modified_type: 'original')`
|
|
|
|
- **payload_name** - The payload name parameter must be one of the supported payloads stored in the `ysoserial` cache. As of this writing, the list includes: `BeanShelll1`, `Clogure`, `CommonBeanutils1`, `CommonsCollections2`, `CommonsCollections3`, `CommonsCollections4`, `CommonsCollections5`, `CommonsCollections6`, `Groovy1`, `Hibernate1`, `JBossInterceptors1`, `JRMPClient`, `JSON1`, `JavassistWeld1`, `Jdk7u21`, `MozillaRhino1`, `Myfaces1`, `ROME`, `Spring1`, `Spring2`, and `Vaadin1`. While `ysoserial` includes additional payloads that are not listed above, they are unsupported by the library due to the need for complex inputs. Should there be use cases for additional payloads, please consider opening an issue and submitting a pull request to add support.
|
|
|
|
- **command** - The command parameter will be executed by the remote system. The parameter is OS-agnostic, meaning that the module must determine the OS and architecture, if necessary, before generating a payload.
|
|
|
|
- **modified_type** - Use a modified version that invokes the specified shell (except in the case of `original`). For more information regarding the invocation, see [`CmdExecuteHelper.java`][1]. The value must be one of the following:
|
|
|
|
- **bash** - A modified version that will invoke the command using the `bash` executable
|
|
- **cmd** - A modified version that will invoke the command using the Windows `cmd.exe` executable.
|
|
- **original** - The original ysoserial invocation without an OS-specific shell. **Be careful when using this option** as some ysoserial payloads (as specified using the *payload_name* parameter are incompatible with commands that contain the `"` character. For this reason, it is recommended that an OS-specific version be used when available. Some ysoserial payloads pass the OS command to execute to `Runtime.getRuntime().exec` as a string instead of an array of strings, leading to execution errors.
|
|
- **powershell** - A modified version that will invoke the command using the Windows `powershell.exe` executable.
|
|
|
|
### Regenerating the ysoserial_payload JSON file (MAINTAINERS ONLY)
|
|
|
|
**Neither module developers nor users need to concern themselves with the following.**
|
|
|
|
<details>
|
|
<summary>Click to expand</summary>
|
|
|
|
On occasion, Metasploit maintainers may want to re-run the script generation to incorporate new Java serialized objects from the ysoserial tool.
|
|
|
|
To avoid invoking Java (and all its dependencies) at runtime, the serialized objects are generated and cached within a JSON file. The JSON file can be refreshed using a standalone Ruby script, which comes prepackaged with a Docker image that handles downloading `ysoserial` and necessary dependencies. The script, `Dockerimage` and a high-level `runme.sh` script is stored within `tools/payloads/ysoserial`. An example run looks like:
|
|
|
|
```
|
|
$ cd ~/git/r7/metasploit-framework/tools/payloads/ysoserial
|
|
$ ./runme.sh
|
|
Sending build context to Docker daemon 101.8MB
|
|
Step 1/8 : FROM ubuntu
|
|
---> cd6d8154f1e1
|
|
Step 2/8 : RUN apt update && apt -y upgrade
|
|
---> Using cache
|
|
---> ba7e5691ed5a
|
|
Step 3/8 : RUN apt install -y wget openjdk-8-jre-headless ruby-dev make gcc
|
|
---> Using cache
|
|
---> d38488663627
|
|
Step 4/8 : RUN wget -q https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar -O ysoserial-original.jar
|
|
---> Using cache
|
|
---> 284ff722464b
|
|
Step 5/8 : RUN wget -q https://github.com/pimps/ysoserial-modified/raw/master/target/ysoserial-modified.jar
|
|
---> Using cache
|
|
---> 334c1ccb6fab
|
|
Step 6/8 : RUN gem install --silent diff-lcs json pry
|
|
---> Using cache
|
|
---> 9d452be9d01f
|
|
Step 7/8 : COPY find_ysoserial_offsets.rb /
|
|
---> 61b6f339590c
|
|
Step 8/8 : CMD ruby /find_ysoserial_offsets.rb
|
|
---> Running in ba7b14646e56
|
|
Removing intermediate container ba7b14646e56
|
|
---> f4ca5ecb6848
|
|
Successfully built f4ca5ecb6848
|
|
Successfully tagged ysoserial-payloads:latest
|
|
Generating payloads for BeanShell1...
|
|
Generating payloads for C3P0...
|
|
Error while generating or serializing payload
|
|
java.lang.IllegalArgumentException: Command format is: <base_url>:<classname>
|
|
at ysoserial.payloads.C3P0.getObject(C3P0.java:48)
|
|
at ysoserial.GeneratePayload.main(GeneratePayload.java:34)
|
|
ERROR: Errored while generating 'C3P0' and it will not be supported
|
|
Generating payloads for Clojure...
|
|
Generating payloads for CommonsBeanutils1...
|
|
Generating payloads for CommonsCollections1...
|
|
Generating payloads for CommonsCollections2...
|
|
Generating payloads for CommonsCollections3...
|
|
Generating payloads for CommonsCollections4...
|
|
Generating payloads for CommonsCollections5...
|
|
Generating payloads for CommonsCollections6...
|
|
Generating payloads for FileUpload1...
|
|
Error while generating or serializing payload
|
|
java.lang.IllegalArgumentException: Unsupported command []
|
|
at ysoserial.payloads.FileUpload1.getObject(FileUpload1.java:71)
|
|
at ysoserial.payloads.FileUpload1.getObject(FileUpload1.java:40)
|
|
at ysoserial.GeneratePayload.main(GeneratePayload.java:34)
|
|
ERROR: Errored while generating 'FileUpload1' and it will not be supported
|
|
Generating payloads for Groovy1...
|
|
Generating payloads for Hibernate1...
|
|
Generating payloads for Hibernate2...
|
|
Error while generating or serializing payload
|
|
java.sql.SQLException: DataSource name cannot be empty string
|
|
at javax.sql.rowset.BaseRowSet.setDataSourceName(BaseRowSet.java:855)
|
|
at com.sun.rowset.JdbcRowSetImpl.setDataSourceName(JdbcRowSetImpl.java:4307)
|
|
at ysoserial.payloads.Hibernate2.getObject(Hibernate2.java:58)
|
|
at ysoserial.GeneratePayload.main(GeneratePayload.java:34)
|
|
ERROR: Errored while generating 'Hibernate2' and it will not be supported
|
|
Generating payloads for JBossInterceptors1...
|
|
Generating payloads for JRMPClient...
|
|
Generating payloads for JRMPListener...
|
|
Error while generating or serializing payload
|
|
java.lang.NumberFormatException: For input string: ""
|
|
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
|
|
at java.lang.Integer.parseInt(Integer.java:592)
|
|
at java.lang.Integer.parseInt(Integer.java:615)
|
|
at ysoserial.payloads.JRMPListener.getObject(JRMPListener.java:42)
|
|
at ysoserial.payloads.JRMPListener.getObject(JRMPListener.java:34)
|
|
at ysoserial.GeneratePayload.main(GeneratePayload.java:34)
|
|
ERROR: Errored while generating 'JRMPListener' and it will not be supported
|
|
Generating payloads for JSON1...
|
|
Generating payloads for JavassistWeld1...
|
|
Generating payloads for Jdk7u21...
|
|
Generating payloads for Jython1...
|
|
Error while generating or serializing payload
|
|
java.lang.IllegalArgumentException: Unsupported command []
|
|
at ysoserial.payloads.Jython1.getObject(Jython1.java:52)
|
|
at ysoserial.payloads.Jython1.getObject(Jython1.java:42)
|
|
at ysoserial.GeneratePayload.main(GeneratePayload.java:34)
|
|
ERROR: Errored while generating 'Jython1' and it will not be supported
|
|
Generating payloads for MozillaRhino1...
|
|
Generating payloads for Myfaces1...
|
|
Generating payloads for Myfaces2...
|
|
Error while generating or serializing payload
|
|
java.lang.IllegalArgumentException: Command format is: <base_url>:<classname>
|
|
at ysoserial.payloads.Myfaces2.getObject(Myfaces2.java:47)
|
|
at ysoserial.GeneratePayload.main(GeneratePayload.java:34)
|
|
ERROR: Errored while generating 'Myfaces2' and it will not be supported
|
|
Generating payloads for ROME...
|
|
Generating payloads for Spring1...
|
|
Generating payloads for Spring2...
|
|
Generating payloads for URLDNS...
|
|
Error while generating or serializing payload
|
|
java.net.MalformedURLException: no protocol:
|
|
at java.net.URL.<init>(URL.java:593)
|
|
at ysoserial.payloads.URLDNS.getObject(URLDNS.java:56)
|
|
at ysoserial.GeneratePayload.main(GeneratePayload.java:34)
|
|
ERROR: Errored while generating 'URLDNS' and it will not be supported
|
|
Generating payloads for Vaadin1...
|
|
Generating payloads for Wicket1...
|
|
Error while generating or serializing payload
|
|
java.lang.IllegalArgumentException: Bad command format.
|
|
at ysoserial.payloads.Wicket1.getObject(Wicket1.java:59)
|
|
at ysoserial.payloads.Wicket1.getObject(Wicket1.java:49)
|
|
at ysoserial.GeneratePayload.main(GeneratePayload.java:34)
|
|
ERROR: Errored while generating 'Wicket1' and it will not be supported
|
|
DONE! Successfully generated 0 static payloads and 22 dynamic payloads. Skipped 8 unsupported payloads.
|
|
```
|
|
|
|
At completion, the `data/ysoserial_payloads.json` file is overwritten and the 22 dynamic payloads are ready for use within the framework. Afterward, the developer should follow the standard `git` procedures to `add` and `commit` the new JSON file before generating a pull request and landing the updated JSON into the framework's `master` branch.
|
|
</details>
|
|
|
|
[1]: https://github.com/pimps/ysoserial-modified/blob/e71f70dbc5e8c27d72873014ac5cb7766f4b5b94/src/main/java/ysoserial/payloads/util/CmdExecuteHelper.java#L11-L30
|
|
[2]: https://github.com/rapid7/metasploit-framework/blob/7d0cb771a5265375eb4484a986e732d8f94c2441/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb#L78-L81 |