Blog: How-Tos
Quick wins with Adobe Experience Manager
Introduction
Adobe Experience Manager (AEM), is a comprehensive content management solution for building websites, mobile apps and forms. And it makes it easy to manage your marketing content and assets.
If you’ve ever looked into AEM you may have heard of Mikhail Egorov (@0ang3el). He has done some excellent security research on the AEM framework, and created a bunch of tools available from his GitHub repo. It was his work that inspired me to share my experience.
When testing AEM it makes sense to follow the same methodology as for any other web app. However, it’s one of those frameworks that seems to baffle people, e.g. it’s common to find misconfiguration issues.
Over time I have developed a specific methodology for testing AEM, and it leverages those misconfiguration problems. For example a very minor issue can allow PII leaking, or even complete compromise.
Also, it doesn’t take much to find AEM instances, some simple Google dorks will do the job e.g:
intext:/content/usergenerated
intext:/content/dam
intext:/jcr:content
Poor implementation
I have yet to do a test where I have found a secure AEM instance. It’s usually possible to write files or nodes to the server leading to XSS or finding PII with little effort.
The issue’s seem to lie with rules made during development. These rules tend to be trivial to bypass if the framework has not been thoroughly tested. A good example is JSON rendering at the base URL. If this is possible you know the test is going to produce a whole load of vulnerabilities through developer misconfiguration.
As with many other things, if they’ve missed the easy stuff you can bet that the harder things haven’t been touched.
Testing AEM
Go for the easy wins first:
- Is it possible to incorrectly render content?
- Can view anything sensitive by abusing the DefaultGetServlet?
If the above is achievable I will collect what I can about the instance. Even at this starter stage of testing if I can view the “content” directory the chances are that I’ll be able to read PII.
I recently took part in a bug bounty where I managed to dump a whole bunch of user PII from the server- phone numbers, names, postal and email addresses, even the content posted in form submissions.
From this point I’ll then attempt to abuse AEM’s querybuilder functionality. It can be possible to search for files using wildcards or even find places I have permission to write to.
Unsurprisingly AEM has plenty of CVEs. They include (but are not limited to) cross-site scripting, server-side request forgery and the most recent, an authentication bypass that can lead to remote code execution. There are fixes out there for these issues but they’re just being done.
AEM has what is known as Dispatcher rules. These rules allow or deny certain extensions throughout the application. Bypassing this, if mis configured, is usually trivial. It may be as simple as appending a “.css” to the end of a file that would otherwise return a 403 forbidden error. This then opens up the doors to an attacker to use functionality what was never intended to be used by anyone other than the developer or leak sensitive information.
Exploitation
JSON
As mentioned the initial stages of testing can produce some interesting results. Here’s an example of json rendering:
Because AEM uses only basic authorisation it can be easy to compromise accounts using username enumeration. This is an ideal foothold from which to gain further access.
querybuilder
This second example shows how querybuilder can be abused.
Here we use querybuilder to look at the “/home” directory. This contains usernames and often contain passwords as well!
In the above case “/bin/querybuilder.json” was unavailable without using a “.css” dispatcher bypass.
We can also use it to enumerate writable directories. This can sometimes be achieved using POST requests alone. In some case’s the directory “/content” will have world writeable paths that can lead to reflected XSS.
This is the response received when a post request was made to “/content/usergenerated/PentestPartners.html”:
This did not exist before, and with a simple POST request we have created a node or a file in which we can place whatever content we want!
Dispatcher bypass
It only takes a few small steps to achieve a bypass of the dispatcher rules, but it means that an attacker can leak PII or cause other mayhem.
This is a normal request using querybuilder. This the majority of the time will return a 403 forbidden error or a 404 not found. its then possible to use a “dispatcher bypass”:
GET /bin/querybuilder.json?path=/home HTTP/1.1
A request using a dispatcher bypass might look like this:
GET /bin/querybuilder.json;%0aa.css?path=/home HTTP/1.1
As the “.css” extension has been allowed as an exception in the dispatcher rules we find it will be possible to return the results of the query!
Dispatcher bypasses are can also be used when trying to render content.
https://example.com/content.json
404 not allowed!
https://example.com/content.json/a.css
200 OK!
This is a perfect example of a misconfigured AEM instance. A dispatcher bypass allowing access to what is otherwise a restricted page, alongside XSS:
AEM security top tips
- Ensure dispatcher rules can’t be bypassed
- Ensure directories are not writable by anonymous
- Patch for the latest vulnerabilities
- Functionality such as querybuilder should return a 404 error and not be accessible
- Don’t allow for JSON rendering of any directories other than used by the application to populate fields used by the application
- Any default credentials should be changed such as “admin:admin” or “author:author”
- Don’t store PII on a public facing server
- Administrative interfaces should never be public facing
- Directories such as /home or /bin should only be accessible to authenticated users