Tags: web

Rating:

# CTFSecurinets Quals 2019 Writeup
This repository serves as a writeup for CTFSecurinets Quals 2019

## Custom Location

**Category:** Web
**Points:** 964
**Author:** TheEmperors
**Description:**

>Try to find out the database credentials.

>The author changed the location of some files to protect the web application from script kiddies.

**Hint:**

> No hint.

### Write-up

Nothing intresting.

Let's try visiting https://web0.ctfsecurinets.com/test

Now we can see an error page. It looks like we have much details as an error page. And it seems that it's based on php Symfony framework.

We try to click on one of the listed files under the error "NotFoundHttpException" text.

We find out that this page show the source code of one of the Symfony project files from this link:

After some tests I changed the URL to:

And I was surprised that Symfony web profiler module was enabled. For persons that don't know what profiler is, it's a module that help developpers to debug code while development process. It's enabled on "dev" environnment.

Let's resume what we got, we have profiler enabled and we have to search about database credentials on web profiler configuration.

We go to configuration

And there we can find Symfony configuration

It looks like we should find database credentials without phpinfo.

Until now, this is the common solution. The purpose of the task was more difficult. There was only one solution until that the author found a non intending solution.

So I'm gonna start by explaining the non intending solution (easy one) before explaining the intendended solution.

#### Non intended solution (easy one)

This was very easy to find from Request/Response menu. Then, Server Parameters. And then DATABASE_URL variable

So the flag is Securinets{D4taB4se_P4sSw0Rd_My5qL_St0L3n}

#### Intended solution (real purpose the task and the hard one)

Because of the previous non intended solution, this intended solution will be very useless. But some teams managed to find this one and that was very smart.

So, I'm gonna explain it.

If we ignore the previous non intended solution, we will try to open the configuration file that contains the database password defined on Symfony project.

So if we return to the configuraion page from the profiler, we can find Symfony framework version

>Symfony 4.2.4

Now, after a quick search from Google, we find the configuration file that contains the database credentials for Symfony 4.2

Then, we try to open .env file from the profiler

But it looks like that file was not found. And that's when we remember that task name is Custom Location. So that we need to find database credentials from a file that was moved to another location.

So how should we find it if we can only read files ?

Since framework configuration files are always available anywhere on the project, our solution was to download a Symfony project (4.2.4) and find out where .env file is loaded. Then we open that file on the Web Profiler on this task. And so we can read the new path of the .env file.

As a requirement, we need to install php 7.1 at least. Otherwise Symfony 3.4 will be installed. But nevermind since starting from Symfony 3.4, the project files tree is the same.

Now, we start searching for the .env file from all Symfony files except Test files, vendor directory (third party directory of any external module), and cache files grep '\.env' * -R | grep -v Test | grep -v vendor | grep -v cache

So, after opening all these files, we find that the only possible file that could load .env file is config/bootstrap.php

And that's how we are going to find out the real .env file from the Web Profiler

So, the real .env file path is secret_ctf_location/env. We try to open it from the Web profiler

So the flag is Securinets{D4taB4se_P4sSw0Rd_My5qL_St0L3n}.
___

**Category:** Web
**Points:** 989
**Author:** TheEmperors
**Description:**

>N00B developers are an easy target. Try to exploit the application feature to get the hidden flag.

**Hint (pinned on Web channel from Discord):**

>Hint 2: Trading values: change request values as a hacker

>Hint 3: Trading values: For the last part of the task: try to find another one. You don't know it but it's known by everyone

### Write-up

Reading the source code will not give us anything intresting: [index.html](resources/web-989-trading_values/inedx.html). Maybe because of the Hint 1.

So by inspecting Network Tab from the Browser (chrome) development tools (Ctrl+Maj+I, then go to Network Tab)

We can see there that each second a HTTP request is sent somewhere.

We inspect one of these requests. For example this one:

We find the sent parameters request are


formula: KHYxLm1wayt2MS5kcmYqKHYxLm1way8wLjUpLXYxLmRyZikvKHYxLmF2ZyowLjEpKyh2Mi5hdmcqKHYyLm1kcyt2Mi5kbXEpKS0odjMucGRpK3YzLnBkaSszLzIqKHYzLnJhciktdjMuZ2RwKSswLjI1Kih2NC5tdW0qdjQuZGFkKSp2NC5hdmc=
values[v1]: STC
values[v2]: PLA
values[v3]: SDF
values[v4]: OCK


And the returned response is a random float number

The sent formula parameter was encoded using base64 base.

We decoded it and we got this result:




So the decoded request was


values[v1]: STC
values[v2]: PLA
values[v3]: SDF
values[v4]: OCK


It seems like formula is using v1 attributes (mpk, drf, avg), v2 attributes (avg, mds, dmq), v3 attributes (pdi, rar, gdp, avg) and v4 attributes (mum, dad, avg).

We analyzed different HTTP request parameters and we figured out that formula changes (from Javascript when generating the request) but the concept is the same, the variables v1, v2, v3 and v4 are the same with the same attributes.

The hint 2 change request values as a hacker say that we need to change the formula or the values. But everytime we change the values[] value (not the key) we get a HTTP 500 error.

When we remove a values[] parameter (like values[v4]=OCK, we get an error that v4 was missing: Variable "v4" is not valid around position 117 for expression (v1.mpk+v1.drf*(v1.mpk/0.5)-v1.drf)/(v1.avg*0.1)+(v2.avg*(v2.mds+v2.dmq))-(v3.pdi+v3.pdi+3/2*(v3.rar)-v3.gdp)+0.25*(v4.mum*v4.dad)*v4.avg. Did you mean "v1"?

We googled this error and we got an intresting result

It looks like this feature is based on ExpressionLanguage module from Symfony. So the backend project is a php one. And it's trying to compute that formula using those 4 values.

But how if we follow Hint 2 and remove some values[] parameters and we also remove those variables from the formula parameter and we only keep one variable ?

For example:


formula: (v1.mpk+v1.drf*(v1.mpk/0.5)-v1.drf)/(v1.avg*0.1)
values[v1]: STC


So the real parameters request will be (base64(formula parameter)):


formula: KHYxLm1wayt2MS5kcmYqKHYxLm1way8wLjUpLXYxLmRyZikvKHYxLmF2ZyowLjEp
values[v1]: STC


We also get a float result. This mean that the backend page is answering to this request correctly.

But how if if keep only v1 insteal of v.<attributes> ?

For example:


formula: v1
values[v1]: STC


So the real parameters request will be (base64(formula parameter)):


formula: djE=
values[v1]: STC


We get another intresting result

We get the same thing when we replace STC by OCK or SDF or PLA:

Results (resume):


For STC: object(App\Entity\STC)#233 (4) { ["id":"App\Entity\STC":private]=> NULL ["avg"]=> int(909) ["mpk"]=> int(100) ["drf"]=> int(48) }
For OCK: object(App\Entity\OCK)#253 (4) { ["id":"App\Entity\OCK":private]=> NULL ["avg"]=> int(43) ["mum"]=> int(96) ["dad"]=> int(39) }
For SDF: object(App\Entity\SDF)#252 (5) { ["id":"App\Entity\SDF":private]=> NULL ["avg"]=> int(328) ["pdi"]=> int(87) ["gdp"]=> int(11) ["rar"]=> int(85) }
For PLA: object(App\Entity\PLA)#232 (4) { ["id":"App\Entity\PLA":private]=> NULL ["avg"]=> int(556) ["mds"]=> int(17) ["dmq"]=> int(74) }


So what we talked about before (the v1, v2, v3 and v4 attributes) was correct. And we got a namespace path (App\Entity\CLASS_NAME which is related to Symfony (PHP).

But how this works ? We tried to substitute values[v1] value with many values but we always fail.

We read Hint 3 Trading values: For the last part of the task: try to find another one. You don't know it but it's known by everyone. This is the difficult part.

Because we don't know about WHAT the author is talking when he say it. Maybe is he talking about values[v1] value. Because this is what we can actuelly change.

We can't guess it whitout knowing what is OCK ? From the previous output, it's an object.

Is the backend page creating a new OCK object using this syntax ? variable=new <out_input>() and he is calling computing the formula using that variable ? or is it using $OCK variable like this $<our_input> ?

We followed the hint 3 and tested values[v1]=__CLASS__ (to check if the code is going to call new __CLASS() to check the first theory. But, we got a blank page (a get a blank page also when we use a random values[v1] value). So this is not working.

Let's try to check the second theory (using a variable name). But we don't know any variable from the backend project.

And since we know that the backend application is based on PHP (Symfony) which is a Framework using classes (this is trivial when we saw namespaces from the object dump App\Entity\CLASS_NAMES), we figured out what does mean Hint 3. We need to google it and find any well known variable namees that we migh forget it actually but eveyone know it on Internet. And that's how we find the trivial local variable name $this. So we try  formula: v1 values[v1]: this  So the real parameters request will be (base64(formula parameter)):  formula: djE= values[v1]: this  And that's how we dump $this local variable from which we find the flag

A quick search we find the flag

So, the flag is Securinets{T00_Ea5y_T0_U5e_This_Local_variable}.
___

**Category:** Web
**Points:** 1000
**Author:** TheEmperors
**Description:**

>Find out the Mysql credentials and search the flag from the database.

**Hint (pinned on Web channel from Discord):**

>Hint 1 for Unbreakable Uploader: try Action deny, target all on the begining

### Write-up

When we visit the task page we get this

We have two ways, trying to upload an Image file or trying to add or remove a restriction.

The second way seems useless actually.

So we tried to exploit an upload vulnerability but whatever my file, the application is very smart and detect my PHP files whatever my bypassing method even if I upload a PHP file renamed as a PNG file. Only JPEG and PNG files are allowed. And I think this is why the task was called Unbreakable Uploader.

So, maybe should we exploit another vulnerability from the second part of the task (Restrictions Form).

The first hint was to use Deny as an action and an all as a target. After that we opened an image

When, we opened an image, we get a Forbidden response

This means that our all IP address were denied.

It seems that there is an ACL feature to deny and allow targets.

Also, the web server is Apache/2.4.25. Maybe the ACLs are written on .htaccess file ?

We tried to write the target and then I added a new line to add another .htaccess entry. But I failed several time until I got the greatest idea:

>Keep it simple

If I need a new line, let me write simply a new line. So I edited the target <input> as a <textarea> (Ctrl+Maj+I from Chrome browser, then Ctrl+Shift+C and click on the target input)

I changed input to textarea

Then, I can write easily new lines.

The first test I did to check if new lines works and at the same time I can check if we can trigger an error inside .htaccess file

Target:


test
test2


And so we got only Allow test. The new created line test2 was not there.

And as we expected, we triggered a .htaccess error while opening an existing image

We understood why is there a button I screwed-up everything and I want to reset the task.

Because we really screwed-up the .htaccess file and we need to reset it.

But, if we only upload PNG and JPEG real files and we can modify .htaccess and bypass editing retrictions from it to add new entries, how can we solve this task and get access to the database ?

After a quick search on internet, we found some documents talking about hardcoding php code inside PNG files that we can execute system commands using HTTP parameters based on this injected code 

The creator of this technique was really a genious.

Then, we uploaded that PNG file and it was successfull since it was a real PNG file.

We figured out thatwe should change PNG file types using .htaccess so that PNG files will be executed as PHP files.

So, we will use this value as a target value


test


It looks great

And also the uploaded PNG image is not displayed as a PNG file

Now, we are going to exploit the RCE using this command




And we got a nice result

Now, let's find out the database credentials a step by step.

We get the current location




So this is a Symfony project. A quick search on google gives up where we can find the database credentials from configuration files.

If the .env file exists, if should be there. Otherwise it should be on app/config/parameters.yml.

So let's check the project document root




.env file exists. So let's cat it




So we got:


Mysql Database
Hostname: localhost


In this task, mysqldump will not work. Maybe because of the database that was very big or because of user privileges. So we need to searh the flag inside the database step by step.

Let's show database tables:




But this strangely will not work.

We tried to go back and retrieve database names maybe we did something wrong




Clear Output:


Database
big_database
information_schema


So the database name that we found on the configuration file symfony_task_3 was a fake name and instead we should use big_database.

Let's list its tables




Clear output:


Tables_in_big_database
user_details


And finally we search the flag on that user_details table


curl -X POST "https://web3.ctfsecurinets.com/uploads/9b3aa7a5c5cebd1318e79442144ffa63/18abe44ac4242278ad0e64d5.png?0=shell_exec" -d "1=mysql -usymfony_admin -pSecurinets_dB_P455W0Rd_369 -hlocalhost --database big_database -e 'select * from user_details' | grep Securinets"


Clear output:


69069 paul47 brown morris fl46 Securinets{T00_MuCh_W0rk} 1


So, the flag is Securinets{T00_MuCh_W0rk}.

___

# Scoreboard

This is the tasks list released on the CTF:

And, this is the scoreboard and the rankin for the 100/436 teams that they solved at least one task in this CTF :

If you need the Json file of the scoreboard, you can find it [here](scoreboard/score.json)

Original writeup (https://github.com/mohamedaymenkarmous/CTF/tree/master/CTFSecurinetsQuals2019#custom-location).