Game of Thrones CTF: 1 – Vulnhub Writeup

Source: https://www.vulnhub.com/entry/game-of-thrones-ctf-1,201/

I’m a sucker for a challenge (this one advertises itself as medium-high difficulty) and a good theme.  As per the vulnhub.com instructions for this CTF there are:

  • 1 flag for each of the 7 kingdoms
  • 3 secret flags
  • 1 final battle flag (root?)

So let’s get started.

Initial nmap scan to confirm target’s IP:

nmap 192.168.111.0/24 -sP

Now for the OS/Service discovery on all ports (I like doing this longer thorough scan initially now because it gives me an excuse to take a coffee break):

nmap 192.168.111.100 -O -sV -p- -T4

From this initial scan we have a lot of different directions to go.  There are 3 instances of web servers running alone!

Let’s start with the most obvious (port 80):

A simple page with the symbols of all seven kingdoms and the GoT theme music playing in the background.  But when we look at the source we get some instructions:

Goal:Goal: -Get the 7 kingdom flags and the 4 extra content flags (3 secret flags + final battle flag). There are 11 in total.Rules/guidelines to play: - Start your conquer of the seven kingdoms - You'll need hacking skills, no Game of Thrones knowledge is required. But if you play, it may contains spoilers of the TV series - Difficulty of the CTF: Medium-High - This is the start point, the base camp - You must travel to westeros. First stop: Dorne. Last stop: King's Landing - Don't forget to take your map (try to find it). It will guide you about the natural flag order to follow over the kingdoms - Listen CAREFULLY to the hints. If you are stuck, read the hints again! - Powerful fail2ban spells were cast everywhere. Bruteforce is not an option for this CTF (2 minutes ban penalty) - The flags are 32 chars strings. Keep'em all! you'll need them Good luck, the old gods and the new will protect you! The game already started!! A couple of hints as a present. 
"Everything can be TAGGED in this world, even the magic or the music" - Bronn of the Blackwater
"To enter in Dorne you'll need to be a kind face" - Ellaria Sand

Instead of loading the main picture via HTML, CSS + JS script is called so let’s take a look at both of those as well (~/js/game_of_thrones.js, cs):

Here we find 3 additional hints:

/*
“You’ll never enter into King’s Landing through the main gates. The queen ordered to close them permanently until the end of the war” – Tywin Lannister

“If you put a city under siege, after five attacks you’ll be banned two minutes” – Aegon the Conqueror and His Conquest of Westeros Book
*/

/*
“Music reaches where words can’t. It’s known even for the animals” – Catelyn Stark
*/

That last hint gives me an idea and I download both the MP3 and WAV file that are referenced on the page for the background music.  Using strings on both I was’t able to find anything decipherable with the WAV file, but I did find this right at the end of the MP3:

So that’s 1/3 secret flags acquired! – 8bf8854be

When we used binwalk on the two files something even more interesting appears:

After fiddling with both files trying to squeeze out any possible clues for a while I decided to move on.

I don’t see any reference to Dorne or a map yet so decide to dig deeper and do a nikto (maybe a dirbuster) scan of the site for hidden files/directories to explore.

Several interesting findings here…let’s take a look at the robots.txt first.

I can’t get to /the-tree/ without modifying my user agent string, but let’s try out the latter two.

/secret-island/ (the ever trustworthy Lord Baelish) gives a link to a map along with another possible hint:

“Take this map and use it wisely. I want to be your friend” – Petyr (Littlefinger) Baelish

So Dorne will be the FTP service (21).  Before moving on let’s check on the two other directories referenced in robots.txt.

/direct-access-to-kings-landing/ won’t be so easy.  We do get an additional hint about the secret flag we already acquired:

“I’ve heard the savages usually play music. They are not as wild as one can expect, are they?” – Sansa Stark

After installing a user agent switcher firefox add-on I customized the agent to be “Three-eyed-raven” and tried the /the-tree/ path again.

This time I’m let in and I get some hints from Bran:

“I will give you three hints, I can see the future so listen carefully” – The three-eyed raven Bran Stark

“To enter in Dorne you must identify as oberynmartell. You still should find the password”
“3487 64535 12345 . Remember these numbers, you’ll need to use them with POLITE people you’ll know when to use them”
“The savages never crossed the wall. So you must look for them before crossing it”

I lied, there’s one other thing from the nikto report I wanted to take a look at and it’s the sitemap.xml.

Index.php is of course the site we came in on, but raven.php is new.

You received a raven with this message:
“To pass through the wall, mcrypt spell will help you. It doesn’t matter who you are, only the key is needed to open the secret door” – Anonymous

We’ll file that hint away for later.  Now let’s see if we can get into Dorne.

My first thought was to use the first secret flag as the password, but that didn’t work.  Mcrypt is for file encryption so wasn’t quite sure what that would have to do with finding the password at this point.  I checked over my findings thus far, as well as the accumulated hints but was a little stuck at this point.  So time to dig even deeper.

Not much new here until I explore the “h” folder which leads to an “i”, a “d”…and so on.

So let’s navigate to the path and see what’s there.

“My little birds are everywhere. To enter in Dorne you must say: A_verySmallManCanCastAVeryLargeShad0w . Now, you owe me” – Lord (The Spider) Varys

“Powerful docker spells were cast over all kingdoms. We must be careful! You can’t travel directly from one to another… usually. That’s what the Lord of Light has shown me” – The Red Woman Melisandre

So it looks like we now have the password to enter Dorne, and a warning that states we can’t bypass sections but must travel in the order the map presents.

We have our first flag (first kingdom down!): fb8d98be1265dd88bac522e1b2182140

Let’s take quick look at the two files we pulled down from FTP.

The “md5(md5($s).$p)” clue I gather is referring to how the hash is created and $s =salt, $p = password.

The problem I ran to here was I couldn’t find any listed hash types that matched the format given in hashcat help.  I finally ran into it on the hashcat official wiki way down at the bottom under legacy hash types (#3610).  The legacy version of hashcat doesn’t support GPUs so hopefully this won’t be too hard to crack…

Found hashcat-legacy on github here: https://github.com/hashcat/hashcat-legacy/

Downloaded as a zip but it wouldn’t extract properly…thinking the file was corrupted I tried again and failed…again.  So I used GIT instead and that was fine (?).  I spent way too much time trying to get the source to compile using old libraries until I realized there was a binary included (duh!).  Anyway, now to try and crack the password/hash combo using legacy hashcat.

Looking through hashcat options I confirm the hash type option is 3610 here under “roll your own”:

I created “crackme.txt” containing:

6000e084bf18c302eae4559d48cb520c:2hY68a

Attack mode we will use 0 for “straight”.

Finally the wordlist we will use is the built-in Kali “rockyou”

Running for barely a second we get our password back of “stark”.  Now to go back to the other file and decrypt it using mcrypt (renamed to remove file extensions first).

So we’ll probably have to edit our hosts file to point to http://winterfell.7kingdoms.ctf/——W1nt3rf3ll—— or just the http://winterfell.7kingdoms.ctf instead of http://192.168.111.100.  Let’s try the latter.

Navigating to the above path I’m presented with a popup login window and punch in jonsnow & “Ha1lt0th3k1ng1nth3n0rth!!!” and come to this page.

In the source again we find:

Welcome to Winterfell
You conquered the Kingdom of the North. This is your second kingdom flag!
639bae9ac6b3e1a84cebb7b403297b79 (2/7 kingdom flags)

“We must do something here before travelling to Iron Islands, my lady” – Podrick Payne

“Yeah, I can feel the magic on that shield. Swords are no more use here” – Brienne Tarth

The Winterfell page’s css holds an additional clue:

“Old TeXTs are written about how to enter into the Iron Islands fortress” – Theon Greyjoy

“I can feel the magic on that shield…” leads me to take a  look at “stark_shield.jpg”.

Using strings there is some exif data and near the bottom I see this:

The map above says that the Iron Islands need to be accessed via DNS…so we will need to somehow use the text given (Timef0rconqu3rs TeXT) manually in a DNS request.

A quick google search leads us to “dig”, however trying Timef0rconqu3rs or “Timef0rconqu3rs.winterfell.7kingdoms.ctf” yielded no response for any dns query type (txt or any) whether I specified the port (53) or not.

I tried nslookup next but kept getting the same “connection timed out” message I was seeing above no matter how I formatted the request.

Then I thought I realized my mistake…it was using “winterfell.7kingdoms.ctf” in the hosts file instead of “7kingdoms.ctf”.

Except…it still didn’t work.

Some more googling later led me to modifying /etc/resolv.conf (adding line “nameserver 192.168.111.100”).  Tried dig again:

Finally success!

“You conquered Iron Islands kingdom flag: 5e93de3efa544e85dcd6311732d28f95 (3/7 kingdom flags). Now you should go to Stormlands at http://stormlands.7kingdoms.ctf:10000 . Enter using this user/pass combination: aryastark/N3ddl3_1s_a_g00d_sword#!”

Onward to the Stormlands.

Nothing immediately useful was found in the source so let’s go ahead and log in.

Nothing again in the source but we do have a search box now.  At first I thought the trick would be to do some sort of command injection, but playing around with search I was able to yield some interesting results just putting in single letters for the search query:

From here I launched the link to the File Manager module.

But something about the java execution was broken and nothing responded from here.  Filling data into the path also yielded nothing, and of course Chrome doesn’t allow execution at all.  I fiddled around troubleshooting possible icedtea-web/NPAPI issues for a while with no success.

I googled for browsers that specifically support NPAPI and came across palemoon which….after some hurdles was able to install.   I was then able to navigate around the directories and find the flag.txt.

Hopefully these issues are just particular to me (I just updated Kali so maybe that has something to do with it).   Anyway, I pulled down the flag and then cat’d out its contents:

So our new flag is 8fc42c6ddf9966db3b09e84365034357 (4/7 kingdom flags)  and for the Vale we’re also given a user ID, password, and db name.  Checking back on the map shown above the vale is postgresql which we found via nmap initially running on port 5432.

user/pass: robinarryn/cr0wn_f0r_a_King-_
db: mountainandthevale

Using psql (instructions here) seems to be the way to go so let’s form a query and see what shows up for “mountainandthevale”.

First I do a \list function to see all available databases.

\dt to list tables for the current database (mountainandthevale).

Now use SELECT to dump the contents of each table.

I also  tried to connect to the “braavos” db but the connection was rejected with my current user/pass.  So some things that stood out to me from the above tables were:

“Dro wkxi-pkmon qyn gkxdc iye dy mrkxqo iyeb pkmo. Ro gkxdc iye dy snoxdspi kc yxo yp iyeb usvv vscd. Covomd sd lkcon yx drsc lyyu’c vycd zkqo xewlob. Dro nkdklkco dy myxxomd gsvv lo lbkkfyc kxn iyeb zkccgybn gsvv lo: FkvkbWybqrevsc” – let’s find a way to try to decode this message

“I’m here to help as always… If you OWN your destiny you can do anything” – a hint about ownership…file ownership? Something DB-related?

“The High Garden citizens never were great warriors, they are POLITE people. If you want to enter to their fortress you only need to Knock at the gates but following their rules… they like order” – there’s a previous hint + code for polite people.

“The old arcane Docker magic is present over all the kingdoms. Usually you can’t use it to move between them but there is a secret tunnel from The Rock to King’s Landing, everybody knows that” – a good hint to keep for later.

Alright, so let’s start with the encoded message first.  My first instinct was rot13 and used  http://www.rot13.com/ to check.  That wasn’t it, but cycling through the options ROT16 ended up giving me the solution:

So that gives us 13 login ID options with the password of “ValarMorghulis”.  This wasn’t a huge list to attempt so I did so manually.

This was made faster by other IDs returning invalid immediately.  Now connected to braavos I repeated the same steps to show available tables.

There is only one table called “temple_of_the_faceless_men” and its contents are a new secret flag 3f82c41a70a8b0cfec9052252d9fd721 (2/3 secret flags)

Now I had to think for a bit about what the other “own” clue could mean.  I haven’t done much/any rights administration for databases before so I had to do some research first.

Looking at the “GRANT” usage examples to be found here it appears we can grant access to all tables in the schema (all are within “public”).  Not successful with attempts under database “braavos” I reconnected to “mountainandthevale”.

I thought it would maybe trigger a message or a new table to be spawned, but I couldn’t see anything new.  I checked through the table contents again to see if they changed…and they didn’t. \list didn’t show any new databases.  I was stumped here for a while.  Doing some googling for “postgresql enumerate all database contents” led me to the command  for showing all relations and THAT finally made everything clear.

SELECT * FROM flag; yielded this:

I recognize the telltale == at the end….this is likely base64.

Sure enough, and we now have our flag for the Vale: bb3aec0fdcdbc2974890f805c585d432 (5/7 kingdom flags).  We also have credentials for the Kingdom of the Reach.

[email protected]/H1gh.Gard3n.powah

There are 2 previous hints….a passcode of “3487 64535 12345” and the hint that we have to knock before opening the gates.  Looking back at the map it should be found via the IMAP service on port 143.

As expected trying to connect to IMAP via telnet initially without “knocking” first didn’t work and we receive no reply.

I tried connecting via netcat to port 3487, 64535, 12345 then telneting again over port 143 but that didn’t work.  I tried telnet for all connections.  I tried scripting them all together so the knocking and connection attempt would be very close together…nothing appeared to be happening so I opened up Wireshark to see if there was anything going on in the background that I was missing.

I get RST,ACK from the knocking, but nothing at all for the 143.  I wait a while and try again thinking there was maybe a lockout period…and it worked!

This IMAP cheat sheet got me started.  There is one unread message in the inbox.

But how to view or download the message?  This helped a bit more.

I conquered the Kingdom of the Reach…but no flag?  Aha, if we fetch the body we see the full unclipped version.

So we have the new flag of aee750c2009723355e2ac57564f9c3db (6/7 kingdom flags).

User: TywinLannister
Pass: LannisterN3verDie!

The map shows The Rock & King’s Landing as gitlist/mysql, nmap shows port 1337 as http (NGINX).  I couldn’t for the life of me connect to 1337 in any browsers and after banging my head on the wall for a while I started to think the VM was somehow broken.

Doing an nmap scan of the port yielded:

I rebooted and tried another nmap scan.  Still closed.

Keeping the original VM saved, I re-imported the OVA, booted it up, tried the path again….and WHEW, I got a log in box.  Not sure what I did but I messed up the other VM good.

After logging in I’m presented with a GitList site.

The other two sections I skimmed over but appear to only contain GoT lore and no further clues (probably).  After looking at for a second the “2f686f6d652f747972696f6e6c616e6e69737465722f636865636b706f696e742e747874” appears to be hex which translates to:

/home/tyrionlannister/checkpoint.txt

Well, that’d be useful if we were logged into a shell… I’m obviously missing something important here.  I looked at the other pictures and content again and couldn’t find anything interesting there.

The only other clue is that the map said gitlist AND mysql.  There’s a search box so let’s try some injection tests…didn’t have any success there.  The mysql service port is filtered so it’s unlikely we can access it directly.  Can we find an injectable URL?  Not that I can see.

I found this in the source for the “note under the bed” page.

Combinations of “../” just redirect me to main site directory.  As per above clue tried:

http://7kingdoms.ctf:1337/home

http://7kingdoms.ctf:1337/casterly-rock/home/

Note the different response this time…but “http://7kingdoms.ctf:1337/casterly-rock/home/tyrionlannister/checkpoint.txt/” returned the same message.

Using 7kingdoms.ctf:1337/casterly-rock/blob/ or /blob/master/ returned the same.

Utterly stuck I tried to go back and find any hints for this kingdom.

“The old arcane Docker magic is present over all the kingdoms. Usually you can’t use it to move between them but there is a secret tunnel from The Rock to King’s Landing, everybody knows that”

Not sure that helps.  Can’t really use dirbuster to enumerate paths.

With some hints from Reddit (search for GitList vulnerabilities!) I found I could use the following path to execute commands:

http://7kingdoms.ctf:1337/casterly-rock/blob/master/””`CMDHERE`

Note those are backticks, not single quotes!

The results of your command are embedded in the error.  ls on top dir works just fine!

Now we can finally make use of the path given to us and cat it out to the screen.

Oui…alright, we’ll need to find a way to connect to the DB via this cmd injection.  Maybe I’ll try to spawn a reverse shell to see if we can make things easier.  Unfortunately not much luck with the python/bash/perl/telnet shells I tried.

No shell feedback for mysql commands so …we’ll have to get his exactly right if we want any sort of output back.  Can’t have interactive password prompt and will need to dump tables.  Digging through MySQL command options is the execute option so we can piggy back a request for all tables.

mysql -h 192.168.111.100 -u cerseilannister -p_g0dsHaveNoMercy_ -D kingslanding –execute=”show tables;”

So we have the table name of “iron_throne” so let’s do a follow up command to dump the table contents.

mysql -h 192.168.111.100 -u cerseilannister -p_g0dsHaveNoMercy_ -D kingslanding –execute=”SELECT * FROM iron_throne;”

I went down the rabbit hole checking to see if the current user had sudo or some other sort of privileges I could exploit until I realized there was another clue here.  That’s not just broken ASCII art, it’s a code.  A little surprised that google didn’t recognize it (maybe it’s just the formatting), I instead found a Morse Code Translater and came up with this:

/ETC/MYSQL/FLAG

But when I try to cat the flag or check the parent directory…no flag.  Maybe the privileges they’re talking about in the above hint are for the database user?  Back to the MySQL documentation to find this.

So we have FILE/GRANT/SELECT/INSERT/CREATE rights to the DB, but how can we take advantage of that?  Can we use the mysql command (possibly has elevated rights?) to output the contents of /etc/mysql/flag?

I tried SELECT load_file(“/ETC/MYSQL/FLAG”); but couldn’t get that to work (but the thread I found talking about it did mention that mysql should be restricted to only opening files within its own directory.

I took a break to regroup and try and get more advice on where to go from here.  Got some good advice to try out commands in a test environment first to confirm they work – went over to https://virtualboximages.com to find a VM with MySQL preinstalled.

Also found this: https://dev.mysql.com/doc/refman/5.7/en/load-data.html (the LOAD function we saw above, I couldn’t get SELECT to work). The main example I’m trying to work out adapting is:

LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;

Now “iron_throne” is the only table that exists now and we know it displays out to the screen fine so let’s try loading/etc/mysql/flag into it.

That didn’t seem to work, and I didn’t get any sort of error message back.  When repeating the same command above to display back the contents of “iron_throne” the same contents as before remained.

So I decided to create a new table and ensure it was blocked out with a large enough space to store whatever might be in the “flag” file.

http://7kingdoms.ctf:1337/casterly-rock/blob/master/casterly-rock/tree/master/%22%22%60mysql%20-h%20192.168.111.100%20-u%20cerseilannister%20-p_g0dsHaveNoMercy_%20-D%20kingslanding%20–execute%20%22CREATE%20TABLE%20test%20%28toto%20VARCHAR%2810000%29%29;%22%20%60/

The key command here being:

–execute “CREATE TABLE test (toto VARCHAR(10000));”

Note the first time I tried I got the above error, but when doing it again I get confirmation back that it was successful (already created):

Now using LOAD DATA INFILE again:

–execute “LOAD data INFILE ‘/etc/mysql/flag’ INTO TABLE test;”

This time it says the same if you try it again, but let’s try to display the contents of the new table anyway.

–execute “SELECT * FROM test;”

Well as you can see from the duplicated output here LOAD DATA INFILE doesn’t overwrite but simply appends data to the end of the file.  But the main thing is it WORKED and we have the new flag of c8d46d341bea4fd5bff866a65ff8aea9 (7/7 kingdom flags) as well as user and password for SSH:

User: daenerystargaryen
Password: .Dracarys4thewin.

Logging in we see:

“Digger.txt” is a list of words I’m guessing to be used for brute forcing a service at the local address given.  But let’s try to fingerprint the service first to see what it is.  Before we can try to banner grab we need to know what port the service is running on so I did a simple netstat -l

I included the first section to note the docker instances running on the server.  The second picture shows 2 instances of SSH (22) running externally and another internal which I’m guessing is what the dragonglass service will be.

Confirmed.

So we will need to download the dictionary file and then pivot through external SSH to internal SSH with a Kali session so we can utilize hydra or other brute-forcing tools to determine the password.  We know the user account is “root” because of the pretty on-the-nose clue given above.

Now to create a tunnel to bind to local port 3333 in Kali.

With that forwarded we now use the word list to brute force the service using hydra:

So lets connect to the SSH service with the password we have now.

And we have our last secret flag now!  a8db1d82db78ed452ba0882fb9554fc9

I remember seeing branstark’s /home/ directory on the host the first time I looked so I’m assuming  “Th3_Thr33_Ey3d_Raven” is the password for it.  Let’s try to reconnect using the bran account.

Here we are!  The final battle!

uname -r gives us a Linux version: 4.9.0-3-amd64 (AKA Devian “Stretch”)

Tried these 2:

Both appeared to fail, but when I was checking group permissions for bran each time I saw:

So I searched docker priv-esc on exploit-db and found a Metasploit exploit:

  • https://www.exploit-db.com/exploits/40394/

So we have the session open…and after locating docker_daemon_privilege_escalation…

It didn’t work the first time but only because I didn’t set LHOST first.

We have a meterpreter session!

Oh boy, I was thinking we’d be done! 🙂

Jumping back our secret flags are as follows:

  1. 8bf8854be
  2. 3f82c41a70a8b0cfec9052252d9fd721
  3. a8db1d82db78ed452ba0882fb9554fc9

This feels like a flashback to some evil exam question from a computer science course.  Let’s break these down into their 3 parts first:

concat(substr(secret_flag1, strlen(secret_flag1) – 10, strlen(secret_flag1)),

substr(secret_flag2, strlen(secret_flag2) – 10, strlen(secret_flag2)),

substr(secret_flag3, strlen(secret_flag3) – 10, strlen(secret_flag3)))

// PART 1 //

substr(secret_flag1, strlen(secret_flag1) – 10, strlen(secret_flag1)

Except…that doesn’t make any sense.  I’ll have to go back and revisit “secret 1” because I have to assume something got cut off (can’t have negative values for start of substring).  I look at cat/strings again but it gives me the same info.

It’s only when I look at the audio properties of the file do I finally get the full flag without it being cut off.

CORRECTED SECRET 1 = 8bf8854bebe108183caeb845c7676ae4

// PART 1 //

substr(secret_flag1, strlen(secret_flag1) – 10, strlen(secret_flag1)

substr(8bf8854bebe108183caeb845c7676ae4, 22,  32)

So that is the last 10 chars of flag:

45c7676ae4

// PART 2 //

Same process repeated…last 10 chars =

252d9fd721

// Part 3 //

2fb9554fc9

Now add them together:

45c7676ae4252d9fd7212fb9554fc9

But what to do with this?  There’s another file called “final_battle”.  Let’s download and take a look.

It’s an encrypted zip file.

GOT IT!!!!

Whew, this was a GREAT VM put together by OscarAkaElvis.  Probably up there with The Necromancer as the more (most?) difficult ones I’ve worked on.  Really well done and took me over a week to finally crack.