Writeup: Really Awesome Hidden Service

Brief

Difficulty: Easy

Ahoy, matey! Some dirty scallywags seem to not be respectin' th' pirate code! Teach them a lesson by findin' out who they be.

ractfysfo3ncuhk5nwzou5mpwmwqrc6ll6ubogd4eotvuhrbr4hcpsid.onion

Writeup

This challenge was all about de-anonymising a Tor hidden service. If we go to the .onion address provided, we see it's a very legitimate and upstanding website for honest sharing of media.

Intended Solution

Most methods of de-anonymising a Tor hidden service depend on finding something which is present on both the hidden service and the plaintext service. This could be as simple as the content (for example, Facebook is available as a hidden service, and is identifiably Facebook from the content) or something more obscure like a HTTP header. You can even look for points of functionality in the site and use those to get callback (email being a frequent choice for this), however the site has none of these. There's no functionality, the content seems to be unique, and the headers look normal.

$ curl -s --socks5-hostname localhost:9050 ractfysfo3ncuhk5nwzou5mpwmwqrc6ll6ubogd4eotvuhrbr4hcpsid.onion -v 1>/dev/null
*   Trying 127.0.0.1:9050...
* SOCKS5 connect to ractfysfo3ncuhk5nwzou5mpwmwqrc6ll6ubogd4eotvuhrbr4hcpsid.onion:80 (remotely resolved)
* SOCKS5 request granted.
* Connected to localhost (127.0.0.1) port 9050 (#0)
> GET / HTTP/1.1
> Host: ractfysfo3ncuhk5nwzou5mpwmwqrc6ll6ubogd4eotvuhrbr4hcpsid.onion
> User-Agent: curl/7.76.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.14.1
< Date: Sun, 15 Aug 2021 17:24:36 GMT
< Content-Type: text/html
< Content-Length: 2632
< Last-Modified: Sat, 03 Jul 2021 17:04:58 GMT
< Connection: keep-alive
< ETag: "60e098ba-a48"
< Accept-Ranges: bytes

Well, when I said the content was unique, that wasn't entirely true. There is one often overlooked part of the website that was reused, the favicon. So, let's download the favicon as a starting point.

curl --socks5-hostname localhost:9050 ractfysfo3ncuhk5nwzou5mpwmwqrc6ll6ubogd4eotvuhrbr4hcpsid.onion/favicon.ico --output favicon.ico

And at this point, whilst we could go to the effort of getting the mmh3 hash of this favicon and searching for that on Shodan, there's already a great blog post about that from SANS.

Hunting phishing websites with favicon hashes
SANS Internet Storm Center - A global cooperative cyber threat / internet security monitor and alert system. Featuring daily handler diaries with summarizing and analyzing new threats to networks and internet security events.

Instead, we're going to use a tool called fav-up which automates this process for us.

$ python3 favUp.py --favicon-file favicon.ico -sc                
--> favhash    :: -915494641
--> file       :: ../favicon.ico
--> found_ips  :: 178.62.4.214|178.62.15.164

And now all we need to do is go to one of those IPs and find the flag.

Unintended Solution

It was however brought to my attention during the event that there is actually a much easier solution to this challenge. All you need to do is send the server an invalid host header, which will cause it to fail back to its default vhost which reveals the flag.

$ curl -s --socks5-hostname localhost:9050 -H "Host: asd.com" ractfysfo3ncuhk5nwzou5mpwmwqrc6ll6ubogd4eotvuhrbr4hcpsid.onion | grep "ractf"
    <center><h2 class="bounce rainbowText">ractf{DreadingPirates}</h2></center>

In retrospect, the solution to this would have been to make the flag only visible on a specific vhost, rather than the default.

How it Worked

The setup for this challenge was actually very simple. Whilst it couldn't just use a container on one of our usual challenge hosts, automating the process of deploying this challenge onto Digital Ocean was easy. This script would deploy a Tor hidden service and configure Nginx on a blank CentOS 8 machine and get the challenge ready to go.