Tags: web easy php sql-injection 

Rating: 5.0

The "Dumb Admin" challenge description states:

> The Admin coded his dashboard by himself. He's sure to be a pro coder and he's so satisfied about it. Can you make him rethink that?

Let's see what we are tasked with here.

![A simple login form](https://vollkorntomate.de/ctf-writeups/dantectf-2023/dumb-admin/login-form.png)

# Login OR 1=1

The Admin dashboard only consists of a simple login form, there's nothing more to discover here. As always, we started with the basics and the credentials `admin:admin`, but the only thing we get is an error telling us "Invalid password format". Other default credentials don't seem to work either, so let's see if there is any luck with SQL injection.

We choose the following SQL snippet as the username, together with some arbitrary password.
```sql
' OR 1=1; --
```

Success! We have logged in without knowing any valid credentials.

> We also discovered that there is some kind of check to the password, if it fits certain password rules. Apparently, all passwords shorter than six characters is discarded as an "invalid password format". Wrong credentials with a longer password are rejected as "invalid credentials".

# File upload

![The dashboard with the ability to upload JPEG files](https://vollkorntomate.de/ctf-writeups/dantectf-2023/dumb-admin/dashboard.png)

The dashboard looks quite empty. The only thing that we're able to do is to upload files. According to the text on the page, it only accepts JPEG images with up to 2 KB. Let's quickly explore how the page works if we use it as intended.

Since 2 KB is not very large for a JPEG image, we needed to be creative with which picture to choose. I decided to simply cut out a tiny piece from a photo that I had laying around and made sure it is small enough. I named the file `img.jpg` and uploaded it. As expected, this process works and we are presented with this sucess message:

> The image 704073e3b13582dd38ecbed0d6af8859.jpg has been uploaded!
You can view it here: [Click here]()

Seemingly, the file is being renamed to a harmless name in the process.

Now let's explore if the upload form really only accepts JPEG images. We first tried to upload a PHP file, but it the site tells us that the extension ".php" doesn't indicate an image file. Next, we checked whether the page only looks at the file extension, so we created a regular text file and named it `img.jpg`. Again, the file is not accepted, as it "seems to be not a real image". This indicates that the backend code checks for the file extension as well as its content and really only accepts valid JPEG files. Too bad for us, but as we'll see later, that's not the end of the story.

But first, let's go further with our successfully uploaded file. Clicking the link from the success message brings us to a page that renders the picture. We made a few observations on that page:
1. The URL for this particular image is `/imageViewer.php?filename=704073e3b13582dd38ecbed0d6af8859.jpg`
2. The page tells us that the image exists
3. The server is capable of executing PHP scripts

Our first thought here was: "Can we maybe access other files on this server?" – the `?filename=` parameter looks suspicious. A simple choice for a file to look for is the `flag.txt` file, which is – according to the CTF's rules – always found in the server's root directory, i.e. `/flag.txt`.

After some failed attempts, we found the correct number of directories to go up and the page confirmed that the file exists: `?filename=../../../../flag.txt`

However, we can't simply print out the contents of the file, since the only thing that the page does in order to render the image is to put the filename in the `src` attribute of an `img` tag and let the browser interpret it. Manually accessing the path, for example, via `curl` doesn't seem to work. So, we have to find another way.

# Connecting the dots

Until now, we know a few things:
1. The upload only accepts images that are valid JPEG files
2. There site provides us no native way to read the contents of a file on the server
3. If not configured otherwise, PHP only ever executes files that have the extension `.php`

This means that we would somehow need to upload a file that looks like a valid JPEG file to the upload code, but looks like PHP to the server. Suddenly, a thought came up in my mind:

> Does the upload form really look for the file extension? Or does it just enforce that the filename contains `.jpg` somewhere?

To answer this question, I took the (valid) `img.jpg` file from earlier and simply renamed it to `img.jpg.txt`, uploaded it and – success!

# The magic of JPEG and PHP

It's time to craft a script that finally outputs our flag. The PHP part of it is rather straightforward:
```php

```

Now we only need to modify the file such that it is identified as a JPEG image. Most programs use so-called [magic bytes](https://en.wikipedia.org/wiki/Magic_number_(programming)#In_files) in order to identify a file type. A JPEG image file always begins with `FF D8` and ends with `FF D9`. We use a simple [hex editor](https://github.com/HexFiend/HexFiend) to insert these bytes before our PHP script and save it as `img.jpg.php`.

![The entire PHP script to output the flag](https://vollkorntomate.de/ctf-writeups/dantectf-2023/dumb-admin/hex.png)

Since PHP ignores anything that comes before `` (or more specifically: treats it as plain HTML), these bytes don't interfere with any of PHP's execution.

We can finally upload our file and click the link in the success message to view the "image" on the `imageViewer.php` page. Of course, the browser can't render our fake image, so we need to manually visit the `img` tag's source, and there is our flag!

Original writeup (https://vollkorntomate.de/ctf-writeups/dantectf-2023/dumb-admin/).