# Injectics

## Navigation

We start by taking a look at the web page to understand how it is built and see if we can already gather some information.

This is what the `index.php` page looks like. All links are placeholders except the **Login** one, which redirects to `login.php`.

<figure><img src="/files/WBdPZ7W9B1Eg0IeDItvg" alt="index.php"><figcaption></figcaption></figure>

Looking at the page source, we can find a name, an email, and some interesting information in the footer:

```
<!-- Website developed by John Tim - dev@injectics.thm -->
<!-- Mails are stored in mail.log file -->
```

Let’s continue and navigate to the login page.

<figure><img src="/files/9xNl3rFaaOOHOIWjPZIj" alt="login.php"><figcaption></figcaption></figure>

We have a classic login form, and interestingly, a **“Login as Admin”** button.

By reviewing the source code, we can see that a JavaScript script is running on this page:

<figure><img src="/files/hfZtnRc7LSIeFnnavifg" alt="script.js SQL filtering"><figcaption></figcaption></figure>

There is some **front-end input sanitization** preventing us from entering certain SQL keywords. This suggests that the login form likely uses SQL for credential validation.

When submitting the form, the credentials are sent to `functions.php`, which handles authentication. On success, the user is redirected to `dashboard.php`.

Trying random credentials results in the error:

> “Invalid email or password”

Using the email found earlier also results in the same error.

When trying SQL keywords, an alert appears:

> “Invalid keyword detected”

Clicking on **“Login as Admin”** leads to `adminLogin007.php`. The same login form is present, but this time:

* No front-end validation
* No request sent to a backend script

This is quite unusual.

## Reconnaissance

We now know the application uses PHP, so we perform directory enumeration looking for:

* `.php`
* `.js`
* `.log` files (remember `mail.log`)

<figure><img src="/files/3xYPGvLT0YSNZpAruCYU" alt="root enumeration"><figcaption></figcaption></figure>

We discover a `/phpmyadmin` directory, which confirms that the application likely uses **MySQL**.

Accessing `/phpmyadmin` shows the standard login page.

Next, we access the `mail.log` file.

{% code overflow="wrap" %}

```
From: dev@injectics.thm
To: superadmin@injectics.thm
Subject: Update before holidays

Hey,

Before heading off on holidays, I wanted to update you on the latest changes to the website. 
I have implemented several enhancements and enabled a special service called Injectics. This service continuously monitors the database to ensure it remains in a stable state.

To add an extra layer of safety, I have configured the service to automatically insert default credentials into the `users` table if it is ever deleted or becomes corrupted. This ensures that we always have a way to access the system and perform necessary maintenance. I have scheduled the service to run every minute.

Here are the default credentials that will be added:

| Email                     | Password 	              |
|---------------------------|-------------------------|
| superadmin@injectics.thm  | superSecurePasswd101    |
| dev@injectics.thm         | devPasswd123            |

Please let me know if there are any further updates or changes needed.

Best regards,
Dev Team

dev@injectics.thm

```

{% endcode %}

This file contains:

* Default credentials
* A table name ('users')
* A service description (Injectics)

The developer mentions that a service will automatically restore default credentials if the `users` table is corrupted or deleted.

Our goal will be to make this service run!

**Note:**\
During my scan, I initially missed important information because I stopped it too early (forgot to remove `-x`, which slowed it down a lot).

Later, I found a `/vendor/twig` directory, indicating that **Twig** is used. This suggests a possible **SSTI vulnerability**. Thanks to Djalil Ayed (<https://www.youtube.com/watch?v=2ruk0rDNNEA>) for this.

<figure><img src="/files/34B6Y9gwvoRgiw9iTvz7" alt="vendor directory enumeration"><figcaption></figcaption></figure>

## Exploitation

### Login Bypass (SQL Injection)

Back on the login page, we know:

* SQL is likely used
* Input is filtered on the client side

This was a quick one for me, after some tries this worked: using **Burp Suite**, we intercept the request and can bypass the filtering easily.

By inserting a valid email (from `mail.log`) and commenting the rest of the query, we successfully log in.

<figure><img src="/files/fR69euUuRppdbZ89MxYB" alt="POST login request and response"><figcaption></figcaption></figure>

And we are redirected to dashboard.php.

{% hint style="info" %}
Note that the ‘redirect\_link’ in the response is “dashboard.php?isadmin=false”, Even when changing it to `true`, nothing changes. However, `is_admin` is set to `true`, so access control is likely handled server-side... Maybe logging in from adminLogin007.php gives us a special token/cookie that is checked on the back-end.
{% endhint %}

<figure><img src="/files/8ONuVMotVazuLr88Eosc" alt="dashboard.php"><figcaption></figcaption></figure>

The dashboard displays a leaderboard with medals per country.\
In the source code I didn’t find anything special except the following comment: `<!-- Leaderboard Table -->` which may indicate that this is the name of the table used in the database and from where this data comes from.

Clicking **Edit** on one of the rows sends a request to edit\_leaderboard.php:&#x20;

<figure><img src="/files/sjU5wNhPtJ6Oo0a0Ds81" alt="edit_leaderboard.php GET request"><figcaption></figcaption></figure>

<figure><img src="/files/GCI3SJsaafkserJK4LmJ" alt="edit_leaderboard.php"><figcaption></figcaption></figure>

We have here a form to update the number of medals. When pressing the Update button, the following data is sent:

<figure><img src="/files/enb2NTZ1kZvgHEFFSaBA" alt="edit_leaderboard.php POST request"><figcaption></figcaption></figure>

And it’s redirecting us to the dashboard.php page. Weirdly the country value is empty. I don’t know if this is voluntary.

After some testing I could confirm that this update form was using SQL. When putting ‘#’ or ‘;’ after a valid number on one of the medals fields, it would update the same field for all countries. Example:

<figure><img src="/files/uYX1LKvgSsPoZauL1P57" alt="Example of result after escaping the UPDATE statement"><figcaption></figcaption></figure>

So I assumed that the SQL statement was the following:

`UPDATE leaderboard SET gold = x, silver = x, bronze = x WHERE rank = x`

Observations:

* Input fields accept numbers
* Expressions like `5+5` are evaluated → result = `10`
* Adding `#` or `;` affects all rows
* Since country is empty, the condition relies only on rank

That’s one step ahead but we can’t do anything with the data of this table.

We really want to escape this UPDATE statement and write something else and interact with other tables. After some hours of testing, I concluded that there was some keyword filtering. If I would input in ‘gold’ ’10SELECT1’ and update, it would update the value to 101. So there is some stripping happening here too. I tried a lot of things like urlencode, playing with the GET parameters, trying to update the ‘country’ column etc... nothing worked.

But remember, our goal was to break the ‘users’ table.

### Breaking the Users Table

We want to trigger the recovery service.

After multiple failed attempts with the DELETE statement (which deletes data), I went for the DROP one (removes a selected table from the database):

<figure><img src="/files/S0M4aIOFkeDFndfVAagx" alt="DROP TABLE SQL Injection"><figcaption></figcaption></figure>

And this worked!!

<figure><img src="/files/gUQtoRvBTQSqVPSea43t" alt="Injectics service running"><figcaption></figcaption></figure>

This was a very hard and time consuming one as we couldn’t see which keywords were filtered and that we had 5 fields. I did try to run SQLMap on it but it didn’t find anything or maybe I did it wrong.

### Admin login - 1<sup>st</sup> flag

Using the default credentials from `mail.log`, we log in as admin on the adminLogin007.php.

We now have:

* First flag
* A new **Profile** section

<figure><img src="/files/9BXNCjQMlybeB3zbJhii" alt="Admin dashboard"><figcaption></figcaption></figure>

### SSTI - 2<sup>nd</sup> flag

Clicking on the Profile button leads us to the update\_profile.php page.&#x20;

In this page we have a from to update our profile:

<figure><img src="/files/rfbCmvgUC21026kkYNB5" alt="Update_profile.php form"><figcaption></figcaption></figure>

Only one of these field actually interests us, the ‘**First Name**’ field. As we can see on the dashboard.php page there’s the following message ‘Welcome, `<first name>` !’. We could display interesting content there if it’s injectable or even get a reverse shell.

Thanks again [Djalil ](#reconnaissance)for this one, like I mentioned in the reconnaissance phase, I didn’t scan well and that costed me hours of roundtripping. Ironically, I just finished the SSTI room before doing this one.

You can use the following payload for most SSTI vulnerabilities (most frameworks): **${{<%\[%'"}}%.**

<figure><img src="/files/1wkf3UsNePjaWRyt9K2S" alt="SSTI triggered error"><figcaption></figcaption></figure>

And here we go. This is the error we get when we enter this payload in the ‘**First Name**’ field and submit.

Unfortunately we’re not out of the woods yet… Twig is quiet well configured here and calling PHP functions like ‘**system()**’, ‘**exec()**’, ‘**shell\_exec()**’ and ‘**passthru()**’ to run shell commands don’t work. They’re all banned.

I did try to use SSTIMap here but weirdly I didn’t get any result, he didn’t even detect any injection vulnerability…

I tried the following commands without success (maybe they are wrong):

`python3 sstimap.py -X POST -u 'http://xxx/update_profile.php' -d 'fname=' --cookie 'PHPSESSID=xxx'`

`python3 sstimap.py -X POST -u 'http://xxx/update_profile.php' -d 'email=&fname=&lname=' --cookie 'PHPSESSID=xxx'`

So, I had to lookup for this one, thanks to 0xB0b. he crafted a payload that works:

<figure><img src="/files/tsBKvUZV0yOnTvRJEQlP" alt="SSTI payload using sort and passthru"><figcaption></figcaption></figure>

{% embed url="<https://0xb0b.gitbook.io/writeups/tryhackme/2024/injectics>" %}
Be sure to check his writeup out, lot of things to learn!
{% endembed %}

We set our listener on and submit the above command on **update\_profile.php** in the ‘**First Name**’ field and we get our reverse shell and we can grab our **2**<sup>**nd**</sup>**&#x20;flag**:

<figure><img src="/files/rgZ26LdArQypYij15aZd" alt="Reverse shell"><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mehdi-2.gitbook.io/writeups/writeups/tryhackme/paths/web-application-pentesting/injectics.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
