Monday, March 23rd, 2015

Johnson Controls Metasys Vulnerabilities – Part I

Last week, ICS-CERT released an advisory on a set of Johnson Control MetaSys vulnerabilities I reported. You can find the advisory here:

It’s interesting to note that my initial email describing the vulnerabilities was sent on November 22nd, 2013. So, 1 year, 3 months, and 23 days later… we finally get a public advisory. The vulnerabilities are extremely simple to exploit (as we’ll see in the post below), but they are also extremely easy to defend/detect. If you are a owner of one of these devices, the facility for which this device supports has been exposed for over a year. If you find these timelines unacceptable, you should call or email your Johnson Controls representative. Let them know that this is unacceptable and their security engineering practices need to be more agile. They obviously don’t care about security researchers, but maybe they’ll listen to their customers.

The Johnson Control NAE is a typical embedded device that you’ll find supporting Building Automation Systems. Here’s a picture of a NAE55.


The NAE55 runs Microsoft embedded standard on an Intel x86 Atom processor. Typically there is a flashdisk which can be accessed at /flashdisk. On the flashdisk, there is a large amount of web related code. Given that web interfaces are almost always remotely accessible, this is an excellent place to find impactful security issues. Some components created by Johnson Controls are written in .NET. While I didn’t find much raw source code, MetaSys makes use of precompiled binaries (dlls) on the NAE55. We can find these precompiled binaries on the flashdisk at: /flashdisk/Storage/Metasys/wwwroot/metasysIII/WS/bin

A quick note to device vendors, shipping .NET code, even in precompiled dlls, is the same as shipping raw source. But your code is tight… so you have nothing to worry about… right?.

There are a large number of binaries here, so where should we start? We’ll break out .NET reflector and we’ll look into a DLL named, “WebServices.Common.dll”. A screenshot of the WebService.Common.dll metadata is shown below.


WebServices.common refers to a number of interesting namespaces. The screenshot below shows the various namespaces.


“Security” is always interesting, so looking at the JohnsonControls.MetasysIII.Security namespace, we see the following:


“AdministationService” exposes several methods including a public method called, “getUserProperty()” getUserProperty accepts an INT value representing the userID and returns a XmlNode.


The implementation of “getUserProperty” is located in the Subsystems.Common assembly:


The Subsystems.Common code can be found in the “Subsystems.Common.dll”. Inside Subsystems.Common is a variety of namespaces including another namespace reference of “JohnsonControls.MetasysIII.Security”


Inside the “JohnsonControls.MetasysIII.Security” namespace is a class named “PrincipalStore”. A screenshot for “PrincipalStore” is shown below:


Inside the “PrincipalStore” class is the actual code for “getUserProperty()”


As you can see, the “getUserProperty()” method exposes user passwords (password hashes). If we can call this method remotely, we should be able to retrieve the password hash for any user on the device (along with a bunch of other user data).

It turns out, we can call this method as an unauthenticated user by making the following web service request (in the example below, we retrieve the details for the all powerful METASYSAGENT account, which is always userID = 1):

POST /MetasysIII/WS/Security/AdminService.asmx HTTP/1.1

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="" xmlns:xsd="" xmlns:soap12="">
<GetUserProperty xmlns="">

This POST request should return something like this:
HTTP/1.1 200 OK

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="" xmlns:xsi="" xmlns:xsd=""><soap:Body><GetUserPropertyResponse xmlns=""><GetUserPropertyResult><Stuff><MetasysUser id="1"><userName>MetasysSysAgent</userName><password>MD5-PASSWORDHASH</password><fullName>Metasys System Agent</fullName><emailAddress /><description>Metasys System Administrator</description><singleAccessUser>false</singleAccessUser><temporaryUser>false</temporaryUser><userExpiresDate>2099-02-01</userExpiresDate><passwordExpiresDate>ExpirationDate</passwordExpiresDate><mustChangePassword>false</mustChangePassword><cannotChangePassword>false</cannotChangePassword><accountDisabled>false</accountDisabled><accountLockedOut>false</accountLockedOut><modifyOwnProfile>true</modifyOwnProfile><canViewNavTree>true</canViewNavTree><userDefined>false</userDefined><Roles><Role id="4" /><Role id="1" /></Roles></MetasysUser></Stuff></GetUserPropertyResult></GetUserPropertyResponse></soap:Body></soap:Envelope>

We can increment the “userID” value and retrieve the password hashes for all users on the device. It’s a good thing that integrators always use really strong passwords, otherwise these would be easily cracked :)

Here is an interesting exercise… if you have MetaSys in your facilities, ask your integrator if you have any devices that are affected by this bug. If you do have vulnerable devices, ask your integrator to install the latest patches. I would also suggest reviewing your web logs to see if anyone suspicious has called the “AdminService.asmx” web service. Given that this bug allows someone to capture password hashes, it’s a good idea to ask your integrator to reset all the user passwords on the device after you’ve installed the security patches… unless of course changing one of the device passwords breaks inter-operability your integrator setup with other devices, in which case your integrator will be stuck with a pretty major project on their hands… but that would never happen :)

Probably more relevant for the next post, but for those trying to do last mile supply chain verification or forensics on the NAE, I’ve uploaded my MetaSys bins to WhiteScope.


Posted by xssniper | Filed in ICS, Security

Please leave a Comment