Breaking, Misc

Vulnerabilities in Sitefinity WCMS – A Success Story of a Responsible Disclosure Process

Preface

For those who never heard of Sitefinity before, it is an ASP.NET-based Web Content Management System (WCMS), which is used to deploy and manage applications as other CMS‘s do. A bitter quick glance at Sitefinity and its advantages can be found in this overview.

Delving into the core of this blog post, recently I had the opportunity to look at Sitefinity WCMS in which I found two reflected Cross Site Scripting (XSS) (CVE-2018-17053 and CVE-2018-17056), a stored XSS (CVE-2018-17054) and an arbitrary file upload (CVE-2018-17055) vulnerabilities.

I admit that the vulnerabilities mentioned in here are classical ones, but because of the huge spectrum of the platform versions affected, I thought it would be helpful to send a loud signal to whomever are using Sitefinity, so they can apply fixes and be safe 😉

Proof of Concept

The first reflected XSS was because of the missing validation for the GET URL parameter redirect_uri. The following excerpt of the HTTP GET request shows how the affected parameter was simply injected with client-side code:

GET /Sitefinity/Authenticate/OpenID/connect/authorize?client_id=sitefinity&redirect_uri=javascript%3Aalert(%27ERNW%27)&response_mode=form_post&response_type=[...]&scope=[...]&state=[...]&nonce=[...] HTTP/1.1
Host: localhost
Cookie:idsrv=[...]
Connection: close
Upgrade-Insecure-Requests: 1

Receiving the previous request resulted in reflecting the JavaScript URI as the value of the action parameter of the form HTML tag. The injection was not only limited to the JavaScript URI, but also escaping from the HTML context was possible using quotes and tags.

The second reflected XSS, was in the REST API service URL, where all the GET URL parameters were not validated and echoed back to the client. In fact, the only barrier to make this XSS fully exploitable is that the component at the server-side does not do URL decoding for the payload. Therefore attacking users with modern browsers that do URL encoding is not possible, because the payload will be reflected with URL-encoded values, which prevents the payload from being triggered. The following excerpt is an example of an injection point in one of the affected GET URL parameters:

GET /restapi/sitefinity/related-data/child-items?ParentItemId=cc42"onmouseover="alert(1)"any="[...]&ParentItemType=[...]&ParentProviderName=[...]&FieldName=[...]&skip=[...]&take=[...]&Status=[...]&ChildItemType=[...]&ChildProviderName=[...]&_=[...] HTTP/1.1
Host: localhost
[...]

The stored XSS on the other side is achieved by injecting a GET parameter called post_logout_redirect_uri, which is part of the URL that is sent after the Sitefinity user logs out. Upon receiving the request, a 302 Redirect to the logout URL will be sent back to the client and following the redirection will result in receiving the injected payload. The redirecting link contains a GET parameter called id, which has a value of 32 hexadecimal digits (probably MD5) and this value is a unique for each logout request. The injected payload will be used as the value for the content parameter of the meta HTML tag. The snippets shown below depict the aforementioned information:

GET /Sitefinity/Authenticate/OpenID/connect/endsession?post_logout_redirect_uri=javascript%3Aalert(%22ERNW%22)%27%3E%3Cscript%3Ealert(%22ERNW%22)%3C%2Fscript%3E%3C%27&id_token_hint=[...] HTTP/1.1
Host: localhost
[...]

HTTP/1.1 302 Found
Location: https://localhost/Sitefinity/Authenticate/OpenID/logout?id=dfc9e7d06d67b06e5791b7c1add2fb7e
[...]


GET /Sitefinity/Authenticate/OpenID/logout?id=dfc9e7d06d67b06e5791b7c1add2fb7e HTTP/1.1
Host: localhost
[...]


HTTP/1.1 200 OK
[...]

<!DOCTYPE html>
<html>
<head>
<meta http-equiv='refresh' content='javascript:alert("ERNW")'><script>alert("ERNW")</script><''>
</head>
<body></body>
</html>

The arbitrary file upload vulnerability was a result of the insufficient checks on the uploaded files e.g. the image of the user profile. Although the server-side component does really check the uploaded image header, however this turned out to be an incomplete measure, because the file was served back according to the extension, which was appended to the uploaded filename and this was not validated by the upload functionality. By abusing the unchecked filename extension, I could upload e.g. an HTML file, which started with a piece of a valid PNG image and appended some HTML at the end of that image. The link for the uploaded file can be sent to any user and directly opened by the browser by removing the GET URL parameter download or set it to false. The following image illustrates a successful upload of an HTML file:

Screenshot of a successful upload of an HTML file
Screenshot of a successful upload of an HTML file

Mitigation

All the vulnerabilities can now be mitigated by following the instructions in the base knowledge article, which was published on 25.09.2018 by Progress Sitefinity.

Timeline of the Disclosure Process

  • On 14.08.2018, Sitefinity Security team was first contacted.
  • On 23.08.2018, all the reported vulnerabilities were confirmed by the vendor.
  • On 25.09.2018, the vendor released the security fixes.

At the end, I would sincerely like to thank the security team of the Sitefinity for being very responsive and active to mitigate the reported vulnerabilities. This – in my humble experience – is a live example of a well cooperative vendor, which cares about making the world a safer place.

For you guys, who stepped by and read my post, thanks for your time and I hope you enjoyed it 🙂

Till the next blog post, be safe and good bye,

Ali Hardudi

Leave a Reply

Your email address will not be published. Required fields are marked *