During the past year we had several projects where our target application used Jasper Reports in some way. In a few of the cases we found an API that offered to render a template along with some arguments into a PDF file. This was done with the help of the Jasper Reports Java library. Due to the way the library and the expression mechanism works, this endpoint gave us the possibility to inject Java code and gain remote code execution on the target systems.
In this blog post we want to provide an overview over the Jasper Reports Java library in terms of security especially with regard to expression injection attacks.
TL;DR; If you come across an API that lets you freely define a Jasper Report template you very likely have code execution. Or to put it differently: Never let Jasper Report templates be user or attacker controlled.
During code reviews we often see developers using weak RNGs like math.random() to generate cryptographic secrets. We think it is commonly known that weak random number generators (RNG) must not be used for any kind of secret and recommend using secure alternatives. I explicitly did not state a specific language yet, because basically every language offers both weak and strong RNGs.
So I asked myself: What if I use a weak RNG to generate a secret? Is it possible to recover the secret from some derived value, like a hash?
Jenkins is a continuous integration server, widely used in Java environments for building automation and deployment. The project recently disclosed an unauthenticated remote code execution vulnerability discovered by Moritz Bechler. Depending on the development environment, a Jenkins server can be a critical part of the infrastructure: It often creates the application packages that later will be deployed on production application servers. If an attacker can execute arbitrary code, s/he can easily manipulate those packages and inject additional code. Another scenario would be that the attacker stealing credentials, like passwords, private keys that are used for authentication in the deployment process or similar.
The HITBSecConf or “Hack In The Box” in Amsterdam is a well known security conference in Europe. We also attended this year too, and there were quite some interesting talks at the HITBSecConf16 conference. One of the talks was about “New Methods for Exploiting ORM Injections in Java Applications” by the security researchers Mikhail Egorov and Sergey Soldatov.
During one of our pentests in some corporate environment we were to analyze an application-server called Liferay. Liferay comes with a lot of functionalities, runs on top of Apache Tomcat and includes a nice API that makes it very easy to add components or further functionality that are not part of the core. These (potentially selfmade) “addons” are called “portlets” and they can be inserted in any place in the frontend.
We quickly found an active default-account (firstname.lastname@example.org : test) which immediately led to the question: how to get access on the system-layer through the account on the application. Because we were not aware of any portlet which provided the desired functionality, we decided to write it on our own and created a straight-forward portlet for system level command execution.
As mentioned above, Liferay offers an API for adding portlets to the core. This can be done by creating a standard war-file which contains java-classes, including the desired functionality and some – in this case – Liferay-specific xml-based configuration files. War files are often used to expand the functionality of java-servers (e.g. Tomcat can also be extended via war-files) – it just needs to contain the application-specific xml-files.
Our java-class includes a html-form consisting of an input-field and a button, which sends commands (via GET) to the server. On the server the input gets executed in a shell – a new java HTTP-Shell is born. After some adjustments regarding to the operating system and the java compiler (1) we had a GET-Parameter-based HTTP-Shell.
The following steps are necessary to deploy the shell portlet:
3.) Execute create.bat / create.sh [Note: javac and jar must be installed in the PATH.]
4.) Have fun with the ShellPortlet.war
How to deploy the war-file?
1.) Login to your Liferay-System with a privileged user-account and open http://yourdomain.com/group/control_panel/manage
2.) You should find a category called “Server” on the left side in the navigation. Click “Install Plugin” and on the next site click “Install more plugins” followed by “Fileupload”
3.) Upload the war-file and use “tail -f $CATALINA_HOME/logs/catalina.out” or (on Windows) the Tomcat-console to observe the logs for any error/exception. When everything worked you’ll find an entry like “1 Portlet for ShellPortlet is available for use”
4.) Now go back to your mainpage via the link in the upper area “Back to Liferay”. Then click “Add” -> “More” and you will see all categories in which the portlets are sorted.
5.) If everything went right you will find a category named “Ownage” in this list. Click on it and drag&drop the shellportlet anywhere on your website.
6.) Have fun playing! 🙂
This shows – once again – that it’s not that hard to gain system-access over a (web-) application. Everyone who uses web-applications should secure the higher-privileged accounts by strong passwords or better deactivate them in case they are not needed. It also shows that – once again – comprehensive and reasonable hardening would have prevented the compromise of yet another system.
(1): The java-class must be compiled by the same compiler-version which the tomcat-server is using. (E.g.: If the tomcat uses jre1.6, the java-class in the war-file must be compiled by a javac which is out of the jdk1.6)