Wednesday, May 2, 2018

AsisCTF 2018 - Trashy or Classy


Don’t be Trashy. Try being Classy!!

Downloaded the file and used de file command to check it’s signature:

$ file Trashy_Or_Classy_1afb5f5911a97860e181722b55dae50bb765285cd8dcbb38837d1a1094e53444
Trashy_Or_Classy_1afb5f5911a97860e181722b55dae50bb765285cd8dcbb38837d1a1094e53444: XZ compress data

Decompressed it using tar and got a file named Trashy_Or_Classy. Using file command again we get that it’s a tcpdump file (pcap). I’ll use wireshark for this search. At first glance, I noticed it has a lot of HTTP requests, so I filtered only this type of packet:

alt text

In a deeper analysis, I figured out HTTP requests brute-forcing a host’s ( directory. So, I’ve extracted all of these requests to understand what happened here (File > Export Objects > HTTP…):

alt text

Saved all of those files in new dir called trash. Let’s dig in!

$ cd trash
$ for i in $(ls); do echo -n "$i --> "; cat $i; echo ;done | less

alt text

There is a lot of 404 Not Found! That means this really is a directory brute-force attempt! Let’s check for HTTP responses that are not 404 (200, 403 etc.). Digging more, I found a 401 Unauthorized for a private dir:

alt text

Cool! There is a lot of of it. That means the attacker was throwing an authentication brute-force attack on this dir. Let’s see if he had success:

alt text

Yeah, he did it! I think these 2 items had been downloaded by him. Checking this out:

alt text

alt text

The download of the first file (flag.caidx) was successful, but the other one (flag.castr) was forbidden (it is a directory). I don’t know what kind of extension caidx is and, making a little Google (dumb’s father) research, I’ve found that the caidx extension belongs to casync - Content Addressable Data Synchronizer and this is the explanation what it is exactly for:

What is this?

  1. A combination of the rsync algorithm and content-addressable storage
  2. An efficient way to store and retrieve multiple related versions of large file systems or directory trees
  3. An efficient way to deliver and update OS, VM, IoT and container images over the Internet in an HTTP and CDN friendly way
  4. An efficient backup system

File Suffixes

  1. catar → archive containing a directory tree (like “tar”)
  2. caidx → index file referring to a directory tree (i.e. a .catar file)
  3. caibx → index file referring to a blob (i.e. any other file)
  4. castr → chunk store directory (where we store chunks under their hashes)
  5. cacnk → a compressed chunk in a chunk store (i.e. one of the files stored below a .castr directory)

Operation on archive index files

(…) # casync mount –store=/var/lib/backup.castr /home/lennart.caidx /home/lennart (…)

Therefore, I need a directory which the file points to, but I only have flag.caidx. I don’t have permission to access /private/flag.castr, only server has. Reading more about casync, there is an useful command:

Operations involving the web

(…) # casync mount –seed=/home/lennart /home/lennart2 (…)

The command above gives me access to mount the directory remotely, but I need the right credentials to do it. Going back to the pcap file, I’ll look for a succesful access to a private directory and, when I find it, I’ll use the wireshark’s Follow HTTP Stream...:

alt text

Holy shit! They’re using Digest Authentication! OK! How is it work? At Wikipedia:

(…) RFC 2069 was later replaced by RFC 2617 (HTTP Authentication: Basic and Digest Access Authentication). RFC 2617 introduced a number of optional security enhancements to digest authentication; “quality of protection” (qop), nonce counter incremented by client, and a client-generated random nonce. These enhancements are designed to protect against, for example, chosen-plaintext attack cryptanalysis.

If the algorithm directive’s value is “MD5” or unspecified, then HA1 is


If the algorithm directive’s value is “MD5-sess”, then HA1 is


If the qop directive’s value is “auth” or is unspecified, then HA2 is


If the qop directive’s value is “auth-int”, then HA2 is


If the qop directive’s value is “auth” or “auth-int”, then compute the response as follows:


If the qop directive is unspecified, then compute the response as follows:

response=MD5(HA1:nonce:HA2) (...)

In this case, HA1 is MD5 and HA2 is qop=auth. Made a brute-force code in python with Rockyou wordlist:

import hashlib

username = "admin"
password = open('rockyou.txt', 'r').read().split('\n')
nonce = "dUASPttqBQA=7f98746b6b66730448ee30eb2cd54d36d5b9ec0c"
realm = "Private Area"
uri = "/private/"
qop = "auth"
for i in password:
    print("Testing "+i+"...")
    hash1 = hashlib.md5(username+':'+realm+':'+i).hexdigest()
    hash2 = hashlib.md5("GET:"+uri).hexdigest()
    response = hashlib.md5(hash1+':'+nonce+':'+nc+':'+cnonce+':'+qop+':'+hash2).hexdigest()
    if response == "3823c96259b479bfa6737761e0f5f1ee":
        print("Password is "+i)

The credentials for private access is admin:rainbow. Installing casync:

# apt install sphinx-common libudev-dev libfuse-dev libzstd-dev libcurl4-openssl-dev liblzma-dev meson
$ git clone
$ cd casync
$ ./ #this command will try to install binaries, but it doesn't have sudo


# cd /usr/lib/casync/protocols/
# ln -sf /pathexample/casync/build/casync-http .
$ cd /pathexample/casync/build
$ sudo ./casync mount --store=http://admin:[email protected]/private/flag.castr http://admin:[email protected]/private/flag.caidx /mnt -v
Acquiring http://admin:[email protected]/private/flag.caidx...
HTTP server failure 401 while requesting http://admin:[email protected]/private/flag.caidx
Failed to run synchronizer: Bad message

WTF! Why is it happening? I’ve tried so many times… I had an idea: capturing packet using tcpdump and see what is going on.

alt text

Oh, boy, casync doesn’t support Digest Authentication! If I only had it’s source code, then I could try patching it! Casync has a binary file called casync-http, responsible to making every remote connection. Analyzing this code, I found out it uses libcurl and supports HTTP, HTTPS, FTP and SSH protocols, but no mention of the auth type. I had to read libcurl’s help and, with a big effort from Alisson Bezerra teaching me how to patch this source code, I’ve included this code below (after line 275) in src/casync-http.c:

if (arg_verbose) { //line 275
		curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); //added by me
		curl_easy_setopt(curl, CURLOPT_USERPWD, "admin:rainbow"); //added by me
                log_error("Acquiring %s...", url); //don't change this
	} //closing if statement

I deleted old build directory, changed the source code, built and ran it again:

$ cd ../build
$ sudo ./casync mount --store= /mnt -v

Now it works! I watched all of mounting process (it took so long!) and when it stopped, I looked in /mnt directory and there is a PNG file (flag.png). Opening this file, there was the flag:

alt text

Capture the Flag , Forensics , Writeup