Multiple vulnerabilities in Concrete CMS – part2 (PrivEsc/SSRF/etc)

Intro

We have previously wrote about Concrete CMS here. In that post we described how we managed to exploit a double race condition vulnerability in the file upload functionality in order to obtain remote command execution. In this blog post we will present multiple vulnerabilities in Concrete CMS that we have found at the end of last year during a pentest for one of our customers. All these vulnerabilities have been fixed and we would like to thank their team for cooperation on these issues. For more info please see the “Mitigations” section regarding security tips for fixing the password poisoning issue and other tips on improving security of this CMS.

Privilege escalation

Let’s start with the privilege escalation issue that we have found when we started our testing. User groups have an hierarchical structure and they inherit permissions from one another. We had a user with limited privileges “Editor”, thus we have asked ourselves what would happen if we try to move our “Editors” group under “Administrators”, would we inherit their privileges too?

First attempt to move Editors under Admin group
First attempt to move Editors under Admin group
Attempt failed

Attempt failed

Well damn, it looks like our attempt failed and the developer actually thought of this and he’s checking our permissions in the backend. But this is not all, we discovered another endpoint where we could try the same operation, so let’s try again and see if permission checks are consistent on all endpoints 😉

Second attempt to move Editors under Administrators Group
Second attempt to move Editors under Administrators Group
Editors group now under Administrators, inheriting their privileges
Editors group now under Administrators, inheriting their privileges

Well, look at this, it seems that they forgot to implement the permission checks on this endpoint and we’ve managed to move the “Editors” group under “Administrators” using a user with very limited permissions (“Editor” role). We had to logout and login again in order to refresh our session and our permissions. And voila, we’re now an “Administrator” with access to the entire control panel 😉

PrivEsc  succeeded, we're now Admin
PrivEsc succeeded, we’re now Admin

SSRF

As discussed in part1, the control panel contains a SSRF by design feature. We showed how we got RCE in the previous post, however the first thing that we actually exploited was this SSRF. It was obvious that this SSRF was exploited previously and now they had some mitigations in place. The purpose of this feature is to allow editors to download a file from a remote server and save it locally.

SSRF by design
SSRF by design

We used a Collaborator payload from Burp Suite and we instantly get a callback:

Callback received
Callback received

AWS Instance metadata is blocked, oh no! As mentioned, it was clear to us that this has been exploited previously and some fixes were in place. Can we bypass these fixes?

Instance Metadata is not allowed
Instance Metadata is not allowed

Certain file extensions are blocked(.php & others) and you can’t use redirects either. What else can we do?

Redirects are not allowed/Blacklists are also used for extensions
Redirects are not allowed/Blacklists are also used for extensions

We discovered that we can bypass the extensions black lists with a well known php trick ( /info.php/test.html still requests info.php but the CMS now considers .html to be the requested extension which is whitelisted, while the server will actually execute a .php extension) and then pivot in the local network, accessing internal web-servers. Pivoting from the internet to the intranet:

Pivoting inside the LAN
Pivoting inside the LAN

You can use this to enumerate and fingerprint internal web applications. Here we’re reading the output of a typical phpinfo file stored on an internal webserver.

Accessing internal web servers
Accessing internal web servers

Pivoting in the LAN was nice, you can chain this with various one shot GET exploits, but this was not enough for us. The wholly grail in a cloud environments is accessing the Instance Metadata server and stealing the IAM credentials. We’ve managed to achieve this using our good old friend DNS rebinding. Thanks to emil_lerner for providing this very useful service. We tried a few of them, but this one worked best, with 0 setup on our side! As a tip, you might have to send 2-3 requests in order to succeed, because essentially you’re trying to win a race condition here (time of check, time of use), due to the multiple validations that the Concrete CMS team have put in place previously.

Fetching the AWS IAM role using DNS rebinding
Fetching the AWS IAM role using DNS rebinding

We got the AWS IAM role the instance is using:

AWS IAM role
AWS IAM role
AWS IAM keys from instance metadata
AWS IAM keys from instance metadata

The moral of this story is that there’s always one more trick to try, you just have to be persistent enough.

Password reset poisoning

We wrote previously about this type of attack on Drupal and Joomla. We thought of giving it a try here as well and it looks like we were right. Poisoning the host header below:

Malicious request to reset password
Malicious request to reset password

Will result in poisoning the password reset link.

Poisoned password reset link
Poisoned password reset link

And this is the email that will be sent to the user:

Email with poisoned link
Email with poisoned link

Mitigations

The SSRF and PrivEsc vulnerabilities have been fixed in versions 8.5.7 and 9.0.1 at the end of last year. You should upgrade to the latest version. For the password poisoning issue please set the canonical url in the Concrete CMS admin panel. For more tips on Concrete CMS security please see the following page for best practices on configuration: https://documentation.concretecms.org/developers/introduction/configuration-best-practices. Once again we would like to thank their team for their support and cooperation on addressing these issues in a prompt manner.