We are given a link to a website with no other resource.
Upon opening, I see this:
I modify the request to include a "Referer" request header:
*You can use other request modifying tools too
I got:
Next, i included a "secret" parameter with the url.
And then I got:
I analysed the website source and found a hint:
Which means that the answer is http
.
Next, I got:
So I change the request method.
Lastly, I got the flag:
We are given a docker environment which contains a flask application.
The structure is as follows:
In the flask app:
We can see that a readFile function is present, this might be the gateway to obtaining a flag from a file. This prompted me to use a directory traversal attack.
The only checking done to the path is that it must start with 'public/'.
Therefore, I tried:
However, this didnt work as it gave me a 404 not found error.
This is because there script had a function that decoded the url passed in:
I encoded the url and tried again, but it still gave me a 404 not found error.
This told me that nginx was decoding the urls before it reached the api endpoint.
The solution was to use double encoding so that it bypasses both nginx and the unquote function.
And I got the flag:
Continuing from novel reader 1:
By scanning the private directory in the docker environment, we can see that the file private/A-Secret-Tale.txt
contains a flag at the second last word in the file.
In the main.py file, looking at the line in /api/read api endpoint:
We can see that buf[0:session['words_balance']]
is getting the first n characters of the string in buf, where n is words_balance.
Therefore, we can exploit Python's negative indexing to allow us to read all characters of buf if we can set session['words_balance']
to -1.
This is important because buf contains the whole contents of a file.
This prompted me to look for a way to set session['words_balance']
to -1.
Upon looking at the /api/read api endpoint, I see:
I noticed that price wasnt being checked for negative, and that i could input a negative number through the request parameter.
First, I got the current credits and words_balance through /api/stats
Since I currently have 1 word balance, so i pass in -2 to make nwords -1.
Then, I tried accessing the file:
However, I got this response:
By double encoding the filepath again, I got the flag:
We are given two files, output.txt
and what_next.py
.
Output.txt
what_next.py
I see that the encrypt function is used to encrypt the flag with the key, and that it performs an XOR operation in the line:
Since the decryption method for XOR cipher is the same operation as encryption, I wrote this function:
And then passed in the values:
To get the key:
We are given a .pcap file as follows:
Upon inspecting the packets, I noticed there were padded trailers in some of the Ethernet frames.
I filtered the packets by including only those with trailers:
And then extracted the parts of the flag from the trailers
By rearranging the parts according to the numbers, we get the flag:
For this one, the file provided (MAPNA.XXG) is a file
Running a program that checks the data of MAPNA.XXG pngcheck
This suggest a hidden image within the PNG
By hexdump
ing the png file, i was able to find the following data
This isnt important, the important one are below at around 0x200080 - 0x2001780
Which are some broken headers, as well as Gimp Metadata
Which is odd, as Gimp Metadata is found in a png file
Heres how a normal Gimp File looks like:
So i gambled and
and then i ran the gimp file
ggwp
In this level, we are given a 64 bit excecutable, where it has these security features
The decompiled source looks something like this
It basically will ask the user for three things in order
The program will then iterate through the text buffer and encrypt each character of the text with each character for the key.
There are 2 vulnerabilities in the code; A format string vuln at line 31 and a stack buffer overflow from read(0,&key,10)
at line 29 which will lead to another buffer overflow from char buf_store [264];
at line 18. The reason is because when we read 10 characters to store at key
which is meant to only store 8 characters, some of that data will overflow to the text_length
variable.
The enctypt
function will read from text_length
and apply xor
operations on text_length
bytes starting from the address at text_input
, which is only meant to hold 264 bytes, however text_length
is not garenteed to be < 264 anymore.
We also noticed that the key buffer is stored in BSS, so we cant read its contents when trying to do format string exploit, however, we can read the canary value to leak it, which is at address 0x7fffffffde78
here.
After some trials, we determined that that we needed to offset 312 bytes to read the canary value, as shown here
Now that we know what the canary value is, we can prepare our payload to overwrite the EIP wtih the win()
function.
I used this site to determine the offset to the EIP, turrns out it was 280 bytes.
With this information, we can develop our payload like so
As we can see, we are able to run the exploit locally.
However, this wont work in remote because of the PIE attribute of the application, which means the address of win
function is different every load.
I got stuck here until the challenge ended, however, after knwoing that PIE does not randomize every byte of the address, only bytes 1 - 7 in this case, made these few changes, I was able to get it to work on remote
The solution is quite straightforward, copy and paste the source in a editor, but you need to remove the new line, compile and run the flag
gcc main.c ; cat main.c |./a.out
The enumeration below shows us that the file is an executable and it is stripped and position independent, this information is important in reversing it.
The objdump below also shows us that there are also sound library functions being called like snd_pcm_close
, snd_pcm_write
etc. These function are from the ALSA C Library interface
Once we run the program, it plays a series of inconsistent beeping sounds, so that gave me a clue that the key is presented in a morse-code like format. I tried timing the beeps below but it seeme inconsistent and inaccurate.
So, I decide to get more information about the timing via the binary itself. Upon launching the binary, we can run r
run the program and interrupt it with Ctrl - c
. On pwndbg, we can run stack
to see its contents and I noticed morse code at address 0x7fffffffdb32
Using x/10c 0x7fffffffdb32 - 0x10
, we are able to view the original morse code contents
The code is then put to a morse code translator and we will receive our flag