Skip to content

software-engineering-and-security/gadgetbuilder

Repository files navigation

GadgetBuilder

Gadget Builder Logo image

A new Java Deserialization Gadget Chain payload generator. GadgetBuilder is an overhaul of Ysoserial with:

  • A new developer-friendly API
  • New gadget chains which have been discovered since Ysoserial's last update in 2020
  • A construction approach to create gadget chains from a Trampoline Gadget + Main Gadget Chain + Sink Method Adapters. This leads to more chain varieties and fosters code reuse for further gadget chain additions.

For more information, we refer to the reference publication.

Contents

  1. Usage
  2. Build Instructions
  3. Contributing
  4. Using GadgetBuilder as a gadget chain benchmark for gc detectors
  5. Referencing this Work
  6. Troubleshooting and FAQs

Usage

Get the latest gadgetbuilder version from the releases page.

Getting started

java -jar gadgetbuilder.jar --help

# list all available gadget chains and trampolines
java -jar gadgetbuilder.jar -l

# get detailed information about a single chain
java -jar gadgetbuilder.jar -g <chainName> --help

Simple Usage Example

If you are overwhelmed by the fragment construction (trampoline + chain + sinkadapter), do not worry! We set default values (here) for trampolines and adapters, so you can run without configuring those to start with.

java -jar gadgetbuilder.jar -g <chainName> -c <command>

java -jar gadgetbuilder.jar -g Clojure1 -c "touch proof.txt" --b64
# run with the --test option to see if the payload executes on your machine
java -jar gadgetbuilder.jar -g Clojure1 -c "touch proof.txt" --test

Output options

  • --b64: output serialized payload in base64
  • -o <fileName>: write binary output into file

Build Instructions

Make sure you are using JDK 8 for building. If you want to very sure - we used JDK8u381.

# set JAVA_HOME env variable if necessary. Points to the home dir, not the java binary.
export JAVA_HOME=/path/to/JDK_8
mvn clean package

# Build target: ./gadgetbuilder-client/target/<gadgetbuilder-version>-jar-with-dependencies.jar

# Don't worry if the build for the testapp fails - it was there for experimentation purposes. You can build it separately
export JAVA_HOME=/path/to/JDK_9
mvn clean package --projects testapp

Contributing

In general, same as Ysoserial:

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-gadgetchain)
  3. Commit your changes (git commit -am 'Add gadget chain')
  4. Push to the branch (git push origin my-new-gadgetchain)
  5. Create new Pull Request

Contributing new Gadget Chains

Create a new class extending GadgetChain<Trampoline>, MethodInvokeGadgetChain<Trampoline,MethodInvokeAdapter> or InstantiateGadgetChain<Trampoline,InitializeAdapter> in the main chains1 module if:

  1. it creates no dependency conflict with any of the other gadget chains in the module.
  2. it is a gadget chain to a more recent dependency version. In this case rotate the old gadget chains to the legacy module chains2 or if needed further down to chains3 (create modules as necessary).

Otherwise add it to the legacy modules. For implementation examples, check out the following gadget chains:

  • A gadget chain with no trampoline: C3P0 - notice the usage of GadgetBuilder<NoTrampoline>
  • A gadget chain using a trampoline: Beanshell1 - notice the return value TrampolineConnector. Supply parameters to the trampoline connector according to the trampoline method call, e.g.:
    • toString(): the trampoline only needs to know on which object toString needs to be invoked, so return new TrampolineConnector(payload)
    • Comparator.compare(Object a, Object b): return new TrampolineConnector(comparator, a, b).
  • A gadget chain with a MethodInvokeAdapter: CommonsBeanutils1 - use MethodInvokeGadgetChain<CompareTrampoline, GetterMethodInvokeAdapter> if the invocation target can only be an arbitrary getter, otherwise MethodInvokeGadgetChain<CompareTrampoline, MethodInvokeAdapter>
  • A gadget chain with an InstantiateAdapter (constructor sink): CommonsCollections3

Contributing Trampolines

In general, we would consider a trampoline any sub-gadget-chain leading to a highly polymorphic method call within the Java Class Library. For instance: Object.hashCode, Object.toString or Map.get. The main trampoline types are defined in the gadgetbuilder-api, here. If a trampoline you discovered does not relate to any of the trampoline types defined in the API, you can add the new trampoline type to the API as part of the pull request. E.g., you find a trampoline path to Runnable.run, first add the interface RunnableTrampoline in the noparam directory.

Then, add the trampoline implementation in the gadgetbuilder-impl module. Check out the examples in the packages. Try to write the trampolines such that upon wrapping the payload object for the main gadget chain, they do not invoke that chain. This is often achieved using Java Reflection after the trampoline gadget was constructed, to add the payload to the respective properties.

Contributing Sink Adapters

This is mostly analogous to contributing trampolines. If the adapter type does not exist in the API, add it there. Then place the new sink adapter implementation in the impl module in the adapters package

Using GadgetBuilder as a gadget chain benchmark for gc detectors

In line with Ysoserial, we list the dependencies for which the gadget chains are know to exist with the @Dependencies annotation. The respective gadget chains are in the chain release modules gadgetbuilder-chains<x>/src/main/java/org/ses/gadgetbuilder/chains<x>, for instance:

The chains come with a getStackTrace() method, showing the gadget chain one would to confirm from the gc detector output. You can also get all this information from the CLI with:

# Example gadget chain
java -jar gadgetbuilder.jar -g CommonsBeanutils1 -h

Name:   CommonsBeanutils1
Dependencies:   [commons-beanutils:commons-beanutils:1.11.0]
Authors:        [frohoff, k4n5ha0]
Impact: Method.invoke()
Trampoline Type:        CompareTrampoline
Available Trampolines:  CC4Compare,ConcurrentSkipListMapCompare,PriorityQueueCompare
Variation count:        12
Adapter:        GetterMethodInvokeAdapter
Available Adapters:     JdbcRowSetMethodInvokeAdapter,PostgresqlMethodInvokeAdapter,TemplatesImplMethodInvokeAdapter,URLMethodInvokeAdapter
Usage Example:  java -jar gadgetbuilder.jar -g CommonsBeanutils1 -c "Command format depends on sink adapter" -t CC4Compare -a JdbcRowSetMethodInvokeAdapter
Chain:
------------------
org.apache.commons.beanutils.BeanComparator.compare()
org.apache.commons.beanutils.PropertyUtils.getProperty()
org.apache.commons.beanutils.PropertyUtilsBean.getProperty()
org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty()
org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty()
org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod()
java.lang.reflect.Method.invoke()
------------------

Referencing this Work

Credit where credit is due: we insist on referencing this work in combination with the original Ysoserial repository.

Ysoserial Citation

@article{frohoffysoserial,
  title={ysoserial--A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization, 2016},
  author={Frohoff, Chris and Lawrence, G},
  url={URL: https://github.com/frohoff/ysoserial}
}

Frohoff, C., & Lawrence, G. ysoserial–A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization, 2016. URL: https://github.com/frohoff/ysoserial.

GadgetBuilder Citation

TODO

TODO

Further Sources and Contributions

Troubleshooting and FAQs

I am getting an Exception: module does not "opens ..." to unnamed module @6d13a606

This is because since JDK 16, Java strongly encapsulates its internals as a part of project JigSaw. You can either run gadgetbuilder with an older JDK (e.g., 8, 11) or refer to the original Ysoserial issue.

An easy workaround is to create an environment variable with all add-opens:

export ADDOPENS="--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.xml/com.sun.org.apache.xpath.internal.objects=ALL-UNNAMED --add-opens=java.sql.rowset/com.sun.rowset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/sun.reflect.annotation=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"

which you can then use in all further executions:

java $ADDOPENS -jar gadgetbuilder.jar <...>

About

A new Java Deserialization Gadget Chain payload generator as an overhaul to Ysoserial.

Resources

Stars

Watchers

Forks

Packages

No packages published