Get Off Of MyCloud

I bought a 4TB WDMyCloud NAS the other day, and dare I say, it’s a beautiful piece of kit.  Inside you’ll find a 1.2GHz dual-core ARM processor with 256M of RAM, running Linaro Ubuntu.  You can enable SSH via the web admin page and the default credentials are root:welc0me.  Props to WD for making this a great box for DIYers.

The web interface is implemented in PHP using the Orion framework.  It’s RESTful API supporting the full gamut of HTTP verbs including GET, POST, PUT and DELETE.  The overall quality of the web interface is not something you usually see on embedded consumer-grade devices.  Also, it looks pretty fantastic.

wdmycloud_admin

This device has a few interesting features, some of which I’m still exploring.  It uses UPnP to tunnel ports 80 and 443 through your home router automatically.  This means you can access it from the Internet.  Luckily, WD was smart enough not to allow access to the full RESTful API from the Internet though; they included code to check $_SERVER[‘REMOTE_ADDR’] and make sure it’s on the same subnet.  There is a WebDAV interface accessible however, so that mobile devices and their thick client can access it remotely.

You can check for these devices via Shodan by searching for the Etag header value of e1-4e533dd6020c0, which yields 27225 devices at last count.  With an average capacity of 2TB, this implies that if you can compromise these devices remotely you get a cool 54 Petabytes of cloud storage (and one hell of a botnet).

I did a quick scan of the source after I enabled SSH access and found an interesting flaw.  In order to configure features such as new shares, users and other Linux features, they call out to a system shell using an exec wrapper function named exec_runtime.  You can grep the source on the box with a quick “find /var/www -name *.php -exec egrep -Hn ‘exec_runtime’ {} \;”.  What’s interesting, is that variables are passed to shell scripts using string interpolation with no escaping.  This means that nearly every single call to this function is vulnerable to command injection.

This vulnerability gets worse for two reasons.  First, www-data is in the sudoers file:

www-data ALL=(ALL) NOPASSWD: ALL

That’s not great.  Second, this bug exists in the language selection API call, which is accessible before authentication.

In order to exploit the issue, you must use a PUT request to the vulnerable URL at /api/2.1/rest/language_configuration?language= and use backticks to inject a shell command.  We’ve already established that we cannot access this API from the Internet (at least not directly), and we cannot use a PUT request to trigger a CSRF without CORS cooperation.  This last point probably needs some explanation.

If you issue an XMLHTTPRequest with the PUT verb on a modern browser, it will issue an OPTIONS request with the header “Access-Control-Request-Method: PUT” before the PUT request is made.  This is specifically designed to prevent CSRF issues from occurring with PUT requests.  Most web frameworks provide a convenient way around this due to the fact that old browsers (IE mostly) cannot make PUT requests (XHR or not).  In this case, we can use a GET request with the extra parameter of rest_method=PUT in order to simulate a PUT request.

One thing that prevents CSRF from being widely exploited in general is that you must know the IP address or hostname of the CSRF target beforehand.  For internally hosted resources, this generally requires some insider knowledge.  The WDMyCloud is a NAS though, and as such it advertises it’s DNS name by default so that users can see it in Mac Finder and Windows Explorer.  So in our case, this is not an issue (unless the user has changed the name).

With all this in mind, I’ve written a Metasploit module to exploit this vulnerability via CSRF.

My research is still ongoing and there are likely other issues.  If we can find an SSRF, XXE or RFI vulnerability somewhere, it may be possible to trigger this issue remotely over the Internet.

Update: Western Digital fixed this issue in version 03.04.01-219. Great job WD, that was quick.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s