/jun 6, 2017

Anatomy of a Cross-Site Scripting Flaw in the Telerik Reporting Module

By Matt Runkle

One of the interesting aspects of working as a Veracode Application Security Consultant is seeing the wide range of code across many business sectors. On an average day, I could look at some COBOL code twice my age in the morning, and by lunch I’m exploring a large .NET MVC app, before transitioning to review a self-deploying microservices package comprised of Java, node.js, and a little PHP for good measure. Besides just helping Veracode customers to secure their apps, I really enjoy learning the new trends, frameworks, and creative ways people use software to solve problems.

Occasionally, during a consultation, I’ll see something suspicious in the static or dynamic scan results that sticks out more than I’d expect for the type of application evaluated. In one particularly interesting case, I was working recently with a client who was pursuing a Verified seal – a rigorous process that provides high assurances about the application security posture of an application.

The customer was building a web application on a .NET stack that, among other things, generated various printable reports. To accomplish that task, the developers were using the popular Telerik Reporting project, built by Progress. While I’ve seen many Telerik components used in other applications, this was my first time coming across the Reporting module in a web context, so I was surprised to discover a reflective cross-site scripting (XSS) vulnerability within the Reporting component.

I reported the vulnerability (tracked as CVE-2017-9140) via email to the Progress team, who created a patch during their next update cycle. Now that the vulnerability has been properly fixed, I can safely share details of what I discovered and how to prevent and mitigate flaws of this type.

Details of the XSS Vulnerability

Reflective XSS occurs when applications mix untrusted data provided in an HTTP request with HTTP response content that is rendered without proper encoding. Unlike stored XSS attacks, which can affect many users of a service, reflective XSS requires that an attacker manipulate data within a request through some means or trick a user into clicking a malicious link containing an XSS payload.

In this case, our exploitation vector leverages an exposed parameter within the WebForms ReportViewer component. The default use is sufficient in this case. The ReportViewer is a simple web control used to view generated reports by adding a one-line snippet to any .aspx page, as such:

<telerik:reportviewer height="590px" id="ReportViewer1" runat="server" showexportgroup="False" shownavigationgroup="False" showrefreshbutton="False" width="750px">
</telerik:reportviewer>

The library then takes care of the rest to render a report in a container with various controls. In order to get the necessary data within the container and communicate with the rest of the application, the viewer component creates its own endpoint at /Telerik.ReportViewer.axd.

Upon initialization, several Ajax calls are made using this endpoint to bootstrap the viewer, pass additional parameters, and fetch viewer resources.

For example:

http://localhost:12345/Telerik.ReportViewer.axd?instanceID=2bc238bd3b46432cb985c71112373983&optype=Report&PageIndex=0&RenderID=8e61a09251404440853136b2f3b801cf&RenderingFormat=HTML5Interactive

Performing static analysis on an application using the ReportViewer as described here, I found the viewer accepted a request parameter to control the background color of the report. After some experimentation with a test application, I determined the bgColor parameter, when added to an HTTP request like above, would be passed back within the DOM without proper encoding as part of the style attribute of the <body> tag. To avoid dealing with URL encoding, the hash (#) character is replaced by an underscore (_) by the application.

Therefore, to exploit the vulnerability, we could provide a simple proof-of-concept value to demonstrate script execution (in this case, causing a browser prompt alert):

http://localhost:12345/Telerik.ReportViewer.axd?optype=Parameters&bgColor=_000000%22onload=%22prompt(1)

The webpage would contain the following HTML snippet as a result:

<body style="background-color: #000000;" onload="prompt(1);">

With a little more poking, I determined the endpoint is directly accessible, making this a fairly straightforward reflective XSS attack, where I might trick a user to click a link to exploit this flaw directly on any site using a vulnerable ReportViewer control. Of course, once I can add arbitrary JavaScript to a page, all bets are off – I could potentially steal a user’s session, manipulate data, or compromise the host system through a browser exploit.

Patching, Prevention, and Mitigation

MITRE has rated this Telerik Reporting vulnerability as medium-severity (CVSS3: 6.1; CVSS2: 4.3), in part because an attacker would need to rely on some social engineering to exploit it. Nevertheless, organizations should make sure they are using a patched version of the component. If you are using the Telerik Reporting library, especially if you are using the viewer functionality, be sure to update your applications to version 11.0.17.406 (2017 SP2) or later. This particular vulnerability does not impact the newer HTML5 viewer, only the legacy WebForms Viewer (Telerik.ReportViewer.WebForms.dll).

As with most XSS flaws, the use of a contextual HTML encoder would prevent this vulnerability. In this case, since the data are output within a style attribute, we want to use an encoder targeted to that area of the DOM, like the HtmlAttributeEncode method provided by the .NET Security.AntiXSS namespace. I suspect this is what the Telerik Reporting team did when implementing their patch. Alternatively, using a client-side framework that handles output encoding automatically, like Angular, would also help avoid these issues.

This disclosure, as well as the thousands of others published each year, underscore the importance of pro-active and persistent application scanning. Be sure you regularly evaluate your application with static and dynamic analysis, and, where appropriate, augment automated scans with penetration tests. Additionally, update third-party components frequently to ensure vulnerabilities are patched in a timely manner.

Related Posts

By Matt Runkle

Matt Runkle is a member of Veracode's Security Consulting team. He holds a B.S. in Computer Science from Worcester Polytechnic Institute and a M.S. in Cybersecurity from New York University. Matt has experience in the defense and commercial spaces, conducting application and network security research for organizations including DARPA. Prior to that, Matt worked as a software developer, both freelance and for various defense contractors. Outside of security, he facilitates leadership conferences nationally for university student groups, and takes an embarrassing number of pictures of his three dogs, Arya, Xena, and Carolina.