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.
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.