100 points

can you hack /etc/passwd?

I initially thought it was some kind of path traversal vulnerability for nginx. However, it wouldn't work. The value of the path was getting reflected back so I decided to try server-side template injection and it worked. I pulled a random working payload from swisskeyrepo. That gave me remote code execution. The flag was in /etc/passwd.

100 points

Try to bypass my conditions ;)

Looking at the source, this was a php type juggling challenge. The source code looked like this:

As said in this article, PHP, for loose comparison, if PHP decides both operands look like numbers even if they are actually strings, it will convert them both and perform a numeric comparison. So, let's take passwd as 240610708, whose md5 is 0e462097431906509019562988736854. So it converts both 0e462097431906509019562988736854 and 0e514198421367523082276382979135. They get converted to int(0) and pass the check, giving us the flag.

200 points

We are opening our own service to recieve CVs, can you make sure that the server is secure, and the /etc/passwd is not accessible.

We are greeted with a form to submit our resume. Trying to upload a text file tell us that the server will only allow us to upload pdfs. That was easily taken care of by changing the content-type to application/pdf. Submitting it tells us they will review it and get back to us shortly. Well, I was confused for a bit. Where is our uploaded file? What am I supposed to do here? I tried looking for the file in /uploads but no luck. So I ran dirsearch on the url. That gave me the /upload endpoint with the uploaded files. Go figure. Now the original filename we give did not change on upload. Seeing as it was a PHP server, I uploaded a .htaccess with the lines AddType application/x-httpd-php .pdf. I think any extension would work, but heck, why not pdf? Then I uploaded a simple php webshell with a filename like shell.pdf. I got the flag from either /etc/passwd (or possibly /flag.txt, I don't remember clearly).

200 points

Try to reveal all rick's secrets, maybe you could try to get his password.

I saw a login page. Like any intellectual, I tried test:test as credentials and it worked, leading me to some kind of dashboard. (Turns out it was also in the html comments anyway, but pfft, who needs that?). We are greeted with a pickle guy image. Clearly, there was some sort of pickle deserialisation bug. The session cookie was not a pickled object. I looked around for a bit, and turns out setting remember me loads a cookie which looks very suspicious. Trying pickle.loads(value) gave an error AttributeError: Can't get attribute 'usr' . So I created an empty usr class. I used fickling, a python pickle decompiler to get more information about the pickle object. It dumped the following:

Fiddling around, I realised that the code for the class to generate such an ast would be as follows:

Now, we just have to have to make use of the _reduce _() method. This function should return a tuple containing a callable object and a tuple as its arguments. When we pickle an object, we are actually storing the current state of the object in a so-called 'universal' format. So we can store our own values but we cannot perform a function remotely. Without __reduce__() at least. Why this function exists is explained rather well here. However, what we care about is that we get to execute our own function on the remote server now.

This is my script which does the job. I am using a lambda function to import os and execute any command I want. A reverse shell in this case. That sql stuff was just me trying to get rick's password but all we needed to do was cat /etc/passwd to get the flag.

200 points

it's important to go to root path of the system

We have a login page and the credentials are, once again, in the html comments. Upon logging in, we come across a page which allows us to upload png,jpeg or some other images. The file name is preserved in this case too. So we can use the same trick as CV_pwner earlier. Only this time we use .png instead of .pdf.

200 points

only Admin can see the secret.

Off the bat, we notice links such as /home/1 and /home/2. I try entering /home/a and lucky lucky, we get an sqlite error claiming there is no such column as a. So obviously this is an sqlite injection challenge. I tried simple things such as 1 union select 1 -- for a while and it did not seem to be working. However I quickly realised that my encoding was the issue. + for some reason did not decode to ' '. Oh well, we still have %20 my precious. This great cheatsheet has everything we really need. The following payload can be used to find the length of any value from table table_name from column col_name:

The following payload can be used to find the character at index i of any value from table table_name from column col_name:

Here is my full exploit script, along with some helpers I wrote that I like to use:

300 points

My tool doesn't have any admin, but I don't know how hackers got my secrets

This is a server-side template injection filter bypass challenge. This is the filter we need to bypass:

num_check simply prevents any numbers. If our payload matches this search, it will not be executed. On the other hand, if it doesn't, it will do render_template_string(request.form['name']) with our payload. Since the admin function is always False, we can never see the result. That's okay though. For starters, I copied the source code and created a template for myself. Now I can test my exploit locally. I edited index.py so it will still execute my payload even if hacking is detected, it will just print out 'hacking' to let me know that though. This helps with debugging. So flask uses the jinja templating engine. Since we are not allowed to use {{ we can simply use {%. Look here. {{...}} statements in jinja print an output while {%...%} do not. An easy workaround is {% print(expression) %}. However, it won't work in our case since we do not get the rendered variable back. It does help with debugging though. So that is great. What I wanted to do was execute: {{request.application.__globals__.__getitem__("__builtins__").__getitem('__import__')('os').popen('ls').read()}} We already know what to do with {{ and }} so we will come back to it in a bit. First thing we need is request.application. But . is not allowed. We can just use built-in filters. An interesting one is attr. foo|attr("bar") works like foo.bar. So we can just do request|attr('application') (single quotes work just fine as double quotes are blocked). But wait, application is blocked too. Note that it is a case-sensitive match so we can simple use the lower filter to convert 'APPLICATION' to lowercase. So now we have: request|attr('APPLICATION'|lower) But what about __globals__? It has an _. I just passed it in as a pragma header. Pragma: _. Which we can now access with request|attr('pragma). I stored it as a variable for convenient use. This can be done as follows:

we can now use u for underscore. This is where the format filter comes in handy.

'%s%sglobals%s%s'|format(u,u,u,u) gives us __globals__.

Using these tricks we can get the payload I mentioned before as follows:

Now we could simply get a reverse shell at this point. However, forcing blind injection to give output seemed interesting so why not?

Here is my full payload:

And there we go. The flag was in /flag.txt or something.

100 points

I have written a C program that acts as a Demo for XOR encryption, check how cool it is!.

Opening it in ida shows a simple xor challenge. The key is given in plaintext Cyb3rTalents.

Here is my solve script:

200 points

I made this cool game using Python 3.9 then I compiled it to be an ELF file, I left you something in the source code let's see if you can get it!.

So running file on the given binary, its an ELF binary. I opened it in ida to see this:

Note the pyinstaller. I looked up writeups and found out we can just use pyinstaller_extracter. Running it on cool_pyc generated a directory with extracted contents. There was an actual pyc file in this one. I tried (unsuccessfully) using uncompyle6. python3.9 which the pyc was for was not supported. I tried running strings to see if could get anything useful:

RkxBR3tIZXJlSUFNX0hpZGluZ0hlcmUhfQ== gives the flag FLAG{HereIAM_HidingHere!} on base64 decoding.

300 points

Reverse the ASM function to calculate the flag.

We get an ASM file from this challenge. Okay, we simply need to reverse this to get the flag.

Note the pyinstaller. I looked up writeups and found out we can just use pyinstaller_extracter. Running it on cool_pyc generated a directory with extracted contents. There was an actual pyc file in this one. I tried (unsuccessfully) using uncompyle6. python3.9 which the pyc was for was not supported. I tried running strings to see if could get anything useful:

RkxBR3tIZXJlSUFNX0hpZGluZ0hlcmUhfQ== gives the flag FLAG{HereIAM_HidingHere!} on base64 decoding.