Grav CMS: Avatar Settings as a Door to Superadmin Privileges

Marcin Teodorczyk
Feb 5 · 4 min read

A continuation of the first article related to Grav CMS. This time a more serious privilege escalation related to avatar settings, also with more step by step details on how I’ve discovered it.

Discovering the Bug

I’ve started with the newest available release at the time, that is Grav v1.6.0-beta.6 — Admin v1.9.0-beta.6. During initial setup there is only a superadmin account created. Since I was going after privilege escalation bugs, I’ve also created a low privileged user named user1. After logging in as user1 we can see following, basic dashboard:

What instantly caught my attention after creating the user was that the following yaml file describing user’s settings has been created as well:

/var/www/html/grav/user/accounts/user1.yaml

One might first think that it’s nothing special, but after carefully reading the content, it becomes clear that there might be a potential for privilege escalation. Why? Because in the same file we have everything that is related to the user, from typical user attributes like email, name and title, to the most critical ones, like privileges (access section). Being quite sure the user can influence the content of this file, all I had to do was to find the request for that. After a brief browsing it came out to be a request of following form:

/admin/user/user1 request
/admin/user/user1 response

The above request is sent when no avatar is set (notice null value for the avatar payload). Next I’ve tried to set an avatar. When doing this, the null payload of Content-Disposition: form-data; name=”data[_json][avatar]” section gets replaced by following (or similar) json:

This in turn maps to the content of the avatar section in the user settings yaml file as follows:

/var/www/html/grav/user/accounts/user1.yaml

Next, I’ve tried a few different payloads for avatar section of the request, observing how they’ve mapped in the user settings yaml file. Following that I’ve changed the avatar section name to something arbitrary. This resulted in a new section created in the user settings yaml file, also reflecting my request. This finally gave me an idea to try to just replace avatar section name with access section name and put payload for superadmin access rights. The only question was what the correct payload is? It was easy to answer as I could find it in the user settings yaml file of the superadmin (admin.yaml):

Translated to json it looks like this:

Exploiting

Finally, it was time to put it all together — logged in as user1 I’ve tried to grant me superadmin privileges sending as user1 following request:

/admin/user/user1 request
/admin/user/user1 response

The result has been following content of user1.yaml configuration file:

/var/www/html/grav/user/accounts/user1.yaml

Notice the highlighted super: true value. Indeed user1 had superadmin privileges. After refreshing the session, user1 has seen the following administrator dashboard:

Summary

I’ve disclosed the bug to the Grav Team on 13th of December 2018, as confirmed to be present in the Grav 1.6.0-beta.6 version. The Grav Team response was again quick and professional describing that it has been already observed by them and fixing is in progress on DEV branch. The next release with a fix (Grav 1.6.0-beta.7) has been published the following day (14th of December 2018).

intive Developers

At intive we’re building great digital products for our customers. Day by day. We want to share with you our way of doing things, the challenges we face, the tricks and shortcuts we discover. A little peek behind the scenes — welcome to our intive_dev blog!

Thanks to Jaroslaw Porzucek.

Marcin Teodorczyk

Written by

intive Developers

At intive we’re building great digital products for our customers. Day by day. We want to share with you our way of doing things, the challenges we face, the tricks and shortcuts we discover. A little peek behind the scenes — welcome to our intive_dev blog!