The Backstory
I recently exchanged emails with APC support on their use of a self signed certificate for SSL access to the web management interface of Powerchute Network Shutdown (PCNS). Powerchute Network Shutdown is used in conjunction with APC Universal Power Supplies (UPS). The product is used to manage and shutdown servers during power issues and outages. The most recent release is version 2.2.4.
In previous releases, APC did not support SSL for remote access to the web interface of PCNS. Although the current version now defaults to https, it only supports the use of a self signed certificate provided by APC. The risks of self signed certificates are well recognized. Such configurations can make a Man-in-the-Middle attack on an https session trivial.
While using a firewall to limit access to the web application or disabling the web service are certainly viable options in some environments, it may not be in others. Since I have a lot of free time during my commute and I tend to obsess about such things, I decided the fix the issue myself.
Poking the Source Code
By default APC PCNS can be found in the C:\Program Files\APC\PowerChute\group1 directory of a Windows system. The software is also available for several *nix distros, so consult the documentation as needed. The web server runs on port 6547 and is hosted on Jetty (Version 6.0.0). By default, version 1.5.0.18 of the Java Runtime Environment (JRE) is installed in C:\Program Files\AP\jre\jre1.5.0_18 directory.
Although this version of JRE has had its share of vulnerabilities, that is not the focus of this post (although if your reading this APC you may want to consider updating your shit).
I began by decompiling the .jar files associated with the application with Java Decompiler by Emmanuel Dupuy. A nice feature of Java Decompiler is its search capabilities. This is very useful to find what you’re looking for quickly or in my case stumble through the source code awkwardly. I quickly located the WebServerSettings class in the webServer.jar file.
Yes that is the password to the Java keystore hardcoded. Convenient isn’t it?
Certificate Management Hell
So using this newly obtained password we can view the current self signed certificate within the Java keystore with keytool utility included with the runtime environment.
>keytool -list -v -keystore "C:\Program Files\APC\PowerChute\group1\keystore"
Once found, I removed the current keystore entry, generated a new one, and created a csr for submission to my CA.
>keytool -delete -alias securekey -keystore "C:\Program Files\APC\PowerChute\group1\keystore"Please note the following are the default values for the keytool -genkey option. You may want to change these to suit your requirements.
>keytool -genkey -alias securekey -keystore "C:\Program Files\APC\PowerChute\group1\keystore" -dname CN=win7.securitybraindump.com,OU=Infosec,O=SecurityBraindump,L=Boston,S=Massachusetts,C=US"
>keytool -certreq -alias securekey -keystore "C:\Program Files\APC\PowerChute\group1\keystore" -file securekey.csr
-keyalg "DSA"For the purposes of this post I used a Windows 2003 CA (yes that is as ugly as it sounds but it is what I had readily had available at the time). To submit the csr to the CA, obtain my certificate, and export the CA Root certificate (for the chain) I used certreq.
-keysize 1024
-validity 90
-sigalg (Depends on the key algorithm chosen.) If the private key is "DSA", -sigalg defaults to "SHA1withDSA" or if "RSA", the default is "MD5withRSA".
>certreq -Submit -attrib "CertificateTemplate: WebServer" securekey.csr securekey.cerThe base-64 certificates can then be imported into the keystore using the -import option.
>certutil -ca.cert rootca.cer
>keytool -import -trustcacerts -v -alias rootca -file rootca.cer -keystore "C:\Program Files\APC\PowerChute\group1\keystore"Once imported, verification can be accomplished by using the keytool -list option again.
>keytool -import -v -alias securekey -file securekey.cer -keystore "C:\Program Files\APC\PowerChute\group1\keystore"
After, installation, you must restart the PCNS1 service. Once restarted you can now enjoy your new, shiny, valid certificate. You may also want to consider changing the keystore password. While this is trivial to do using the keytool utility, the webserver.jar file will need to be altered to reflect the change and then recompiled using the JDK. For this reason, most of the Java development forums I read noted that hard coding the password is not practical. From a security perspective, no matter where the password is stored, you must trust the system storing it. Although I would suspect using the same static password across multiple independent systems is not ideal. If you have experience with the development and security of such systems I am interested in hearing your thoughts on this.
The "R" Word
So what is the Risk? As I mentioned earlier, using a self signed certificate is risky in regards to Man-In-The-Middle attacks. Users tend to ignore certificate warnings. Moreover, it is very feasible to pass a victim the legitimate self signed certificate during an attack. Consequently, the use of a self signed certificate is not providing much protection except against passive sniffing. If the web session to APC PCNS is hijacked, then the credentials to the application could become compromised. Once access is gained, one obvious scenario would be a Denial of Service (DOS) attack by shutting down the systems controlled by the application. I wanted to find something a bit more nefarious, however. It so happens that PCNS allows administrators to not only shutdown systems when events are triggered but also run command files.
Note that the command file does not need to be located on the server being attacked. It also should be noted that if running multiple executables from a command file, the following syntax needs to be followed due to a bug in the current release (thank you readme.txt). Note: quotes are only needed if the path contains spaces.
@START "some path\evil.exe" argumentsI'll let the output from my evil.cmd file containing the "whoami > whoami.txt" command speak for itself;
@START "some otherpath\pwn.exe" arguments
nt authority\systemNUM! Happy Hunting!