CSWorks: web-based industrial automation

Of CSWorks and software development

CSWorks user authorization using third-party access management system - Lab 04

clock October 22, 2010 13:38 by author Sergey Sorokin

Introduction

In CSWorks 1.4.3900.0 we have added a possibility to restrict user access to specific data sources, alarm groups and historical data points. Inquiring users will find compelling answers awaiting them in CSWorks documentation that explains new security model in detail. In this article, I will focus on CSWorks integration with a third-party access rights management system. For the purpose of demonstration, I will be using SecureAccess 4.2 by PortSight - .NET security component for user management and application access rights management. This product meets all of the requirements to be used as an underlying access management system:

  • it can be accessed from .NET applications
  • it allows custom privileges like LiveData Read, LiveData Write etc.
  • it allows storing of resource identifiers: strings (data sources) and guids (alarm groups, historical data points)
  • it allows retrieval of all resource identifiers of a specific type (data sources, alarm groups, historical data points) available to a specific user for specific action (read, write, acknowledge)

I will walk through the process of creating a custom authorization provider for CSWorks and using it with Secure Demo application that comes as part of the CSWorks setup.

Setting up SecureAccess

Here are the steps:

  • install SecureAccess on a server computer;
  • provide it with database server access and create a new database using SecureAccess Catalog Manager, call this database "SecureAccess";
  • create the following application hierarchy: Applications->AlarmSecurity->Alarm Groups->Pipeline alarms;
  • create a role "PipelineAdmins", create a user "JohnDoe" and add him to the role;

The following screenshot of the SecureAccess administration panel shows what has been done so far:

Roles

Now make sure that Description field of the application part "PipelineAlarms" contains the id of the alarm group "All Pipes" used by CSWorks Alarm Service and defined in Alarms.xml:

...
<alarmGroup id="{4709B095-BBB6-4e48-97B8-AF15C5F19DD6}" description="All Pipes">
...

The following screenshot displays "PipelineAlarms" details:

Parts

At the level of "AlarmSecurity" application, create custom permission types ReadAlarms and AckAlarms and make sure they are available in "PipelineAlarms" application part:

Permission Types

Now the most important thing: on "PipelineAlarms" application part level, give ReadAlarms and AckAlarms permissions "PipelineAdmins" role. Permission matrix for "PipelineAlarms" will look as follows:

Permission Matrix

Now SecureAccess is ready to perform authorization for users who want to access CSWorks alarms in "All Pipes" alarm group.

Developing authorization provider

Using Microsoft Visual Studio, create a new .NET library CSWorks.Server.SecureAccessAuthorizationProvider.dll that references CSWorks.Server.WebSecurity.dll (it comes as part of the CSWorks setup) and the following SecureAccess libraries:

  • ARDataServices.dll
  • ARObjects.dll
  • ARWebSecurity.dll
  • SecureAccess.dll

Create a class SecureAccessAuthorizationProvider that implements IAuthorizationProvider interface defined in CSWorks.Server.WebSecurity:

using System;
using System.Collections.Generic;
using System.Linq;
using PortSight.SecureAccess.ARObjects;
using CSWorks.Server.Diagnostics;

namespace CSWorks.Server.WebSecurity
{
  public class SecureAccessAuthorizationProvider: IAuthorizationProvider
  {
    public void Open(string connectionString, string userName)
    {
      // Nothing to do
    }

    public void Close()
    {
      // Nothing to do
    }

    public IEnumerable GetPrivilegeGuids(string userName, Privilege privilege)
    {
      List ids = new List();
      if (privilege == Privilege.AlarmRead || privilege == Privilege.AlarmAck)
      {
        IEnumerable alarmGroupAppParts = ARHelper.GetARObjects(ARObjectTypesEnum.ARApplicationPart).OfType().Where(ap => ap.ObjectAlias.StartsWith("AlarmSecurity.AlarmGroups.", StringComparison.InvariantCultureIgnoreCase));
        string secureAccessPrivilegeName = (privilege == Privilege.AlarmRead ? "ReadAlarms" : "AckAlarms");

        // Build a list of all group ids this user is authorized to READ or ACK
        foreach (ARApplicationPart ap in alarmGroupAppParts)
        {
          if (ARHelper.IsAuthorized(userName, ap.ObjectAlias, secureAccessPrivilegeName))
          {
            // Take group id from the app part description
            ids.Add(new Guid(ap.ObjectDescription));
          }
        }
      }
      else
      {
        // Report error: privilege not supported
      }

      return ids;
    }

    public IEnumerable GetPrivilegeStrings(string userName, Privilege privilege)
    {
      throw new NotImplementedException();
    }
  }
}

The idea is very straightforward: when given a user name and alarm privilege, GetPrivilegeGuids() method should return all alarm group ids this user has correspondent access to. GetARObjects() returns all application parts under "AlarmGroups", and IsAuthorized() method filters out those alarm groups that are not accessible.

Using authorization provider with your application

Copy CSWorks.Server.SecureAccessAuthorizationProvider.dll together with all SecureAccess dependencies to the bin folder of SecurityDemo application (CSWorks\Demo\Web\bin) so secure CSWorks web services can access it. Add the following lines to the web.config of SecureAlarmWebService located at CSWorks\Demo\Web\SecureAlarmWebService (make sure you have specified proper SQL Server name or address, SQL Server user name and password, and a valid SecureAccess license key):

<configuration>
  <configSections>
    <sectionGroup name="authorizationProviderConfig">
      <section name="authorizationProviders" type="CSWorks.Server.WebSecurity.AuthorizationProviderConfigurationSection, CSWorks.Server.WebSecurity" />
    </sectionGroup>
    ...
  </configSections>
  <appSettings>
    <add key="SecureAccessConnectionString" value="data source=sqlserver;initial catalog=SecureAccess;user id=sqluser;password=sqlpassword;packet size=4096" />
    <add key="SecureAccessDefaultCulture" value="en-US" />
    <add key="SecureAccessParentFrameName" value="" />
    <add key="SecureAccessLicenseKey" value="XXXX-XXXX-XXXX-XXXX-XXXX" />
    <add key="SecureAccessVirtualPath" value="" />
    <add key="SecureAccessTopRecords" value="1000" />
    <add key="SecureAccessCacheExpiration" value="30" />
    <add key="SecureAccessApplicationAlias" value="SecureAccess" />
    <add key="SecureAccessLogonFormRedirectsTo" value="" />
  </appSettings>
  <authorizationProviderConfig>
    <authorizationProviders activeAuthorizationProvider="secureAccessAuthorizationProvider">
      ...
      <authorizationProvider name="secureAccessAuthorizationProvider" type="CSWorks.Server.WebSecurity.SecureAccessAuthorizationProvider, CSWorks.Server.SecureAccessAuthorizationProvider" connectionString="" allowCaching="true"/>
    </authorizationProviders>
  </authorizationProviderConfig>
  ...
</configuration>

SecureAlarmWebService is ready to use the provider you have just crafted. Now modify SecurityDemo.aspx.cs source file of the SecurityDemo sample application by replacing "demooperator@acme.com" with "johndoe" in the AllowAlarmPipes_Click() method as follows:

namespace CSWorks.Server.SecurityDemoWebApplication.WebApplication
{
  public partial class SecurityDemo : System.Web.UI.Page
  {
    ...

    protected void AllowAlarmPipes_Click(object sender, EventArgs e)
    {
      //System.Web.Security.FormsAuthentication.SetAuthCookie("demooperator@acme.com", true);
      System.Web.Security.FormsAuthentication.SetAuthCookie("johndoe", true);
      Response.Redirect("SecurityDemoAlarm.aspx");
    }

    ...
  }
}

From now on, when a user clicks the "Allow 'All Pipes' alarm group only (no acks)" he/she is impersonated as "John Doe" and gets read/ack access to all alarms in the group "All Pipes". All other alarm groups are not available to this user.

Running the demo

Build updated SecurityDemo application, run it and click the "Allow 'All Pipes' alarm group only (no acks)" button. Make sure that "JohnDoe" user name appears in the message on top of the page and you have read/ack access only to those alarms that belong to "All Pipes" alarm group. You can do that by running "Pipes and tanks" demo application and closing all valves that feed the mixing tank: this eventually will trigger an alarm called "Both lines are empty" in "All Pipes" group, and you will be able to see it and acknowledge it from the Security Demo.

The discussed example deals with CSWorks alarming only, but you can easily do the same for LiveData sources (use data source name for SecureAccess application part description, and implement provider's GetPrivilegeStrings() method) and historical data points (use data point id for SecureAccess application part description, and add some code to GetPrivilegeGuids() method).



CSWorks 1.4.3900.0 released

clock October 20, 2010 21:53 by author Sergey Sorokin

What's new:

  • Security: item-level authorization, XmlAuthorizationProvider, using User.Identity
  • Setup: better component granularity, friendly ASP.NET/IIS dialogs
  • Security Demo: now uses LiveData, Alarm and Historical Data


Post-Stuxnet industrial automation systems

clock October 5, 2010 13:44 by author Sergey Sorokin

Introduction

Recently, I came across an excellent paper by Symantec engineers that sheds some light on what infamous W32.Stuxnet virus looks like from inside. First off, I was impressed. To be honest, I haven't had such interest reading about a dissected and prepared virus since mid-nineties when I was infatuated with assembly languages, and when viruses, worms and trojans just started making top spots in the newspapers. And here is why.

1. The scale of the research and development effort behind this attack is enormous. Simatic PLC programming, Step 7 internals, WinCC database vulnerability, Windows vulnerabilities (including two unreported exploits!), virus control centers in the web that parasite on some soccer site, compromised Verisign certificates issued to Realtek and JMicron, early versions of the virus that (presumably) conducted reconnaissance and gathered information about target hardware and software infrastructure... I can easily imagine big money spent on hardware and to keep busy a team of developers for many months. I can even imagine some black-hat hacker selling unknown Windows exploits and stolen private keys for the compromised certificates to this group - this type of product is marketable.

2. The determination of the aforementioned team to hit a specific target (or a group of targets). The detail level of the PLC part of Stuxnet gives the impression that someone with inside knowledge of how particular Siemens SCADA deployments work was involved. The effective use of system vulnerabilities and user habits is a trait of a very carefully planned action.

Anyways, after Stuxnet, SCADA world will never be the same. Let me share some thoughts.


Scapegoats? Anyone?

Iranian authorities have already detained several individuals presumably connected to the Stuxnet attacks. Being a peaceful tech person, I am absolutely not intrigued by the opportunity to see heads on sticks. Instead, I would rather take a closer look at the technical aspect of the story.

Siemens

By no means I am an expert in Siemens SCADA software, but to me it looks like WinCC database hard-coded password is the only serious security hole provided by Siemens in the Stuxnet case. Yes, using a hard-coded password that has been available on the Internet for several years cannot be considered a secure practice. But, after all, this vulnerability was used by Stuxnet only as one of the replication vehicles. Without this exploit, infection would spread out at slower rate, and that's it. As for the fact that a whole piece of Step 7 (Siemens PLC programming software) was replaced by the virus and executed to perform some malicious actions like tweaking PLC programs... Well, there is not too much Siemens developers can do if a virus gets privileged access to the system and can patch executable files in the memory and on hard and removable drives. This takes us to the next candidate.

Microsoft

These charges are harder to beat. According to the report, Stuxnet "exploits a total of four unpatched Microsoft vulnerabilities, two of which are previously mentioned vulnerabilities for self-replication and the other two are escalation of privilege vulnerabilities that have yet to be disclosed." This is big. These two unreported exploits gave the virus carte blanche to perform any memory and file modifications on all versions of Windows. Being a long-time Microsoft camper, I was happy to see the patch coming out on September 15, 2010.

IT infrastructure

While googling Stuxnet, I have come across this posting. Although the whole article is definitely worth attention, I would like to quote a couple of excerpts.

Question: Is it enough to separate the process control network from the business LAN? Is this realistic?
Answer: It depends on what you mean by “separate.” Industrial security standards and guidelines do recommend the networks be segmented by firewalls or other technology to prevent unauthorized communications between enterprise and control system networks. If by “separate” you mean “completely disconnected,” this is what control system folks mean when you hear the term “air-gapped.” In the pre-wireless days, the term meant “no electrons can pass between control networks and enterprise networks.”
Nowadays, very few control systems networks are completely disconnected from enterprise networks. Most control systems can still be run safely without enterprise network communications, but many physical processes can no longer be run profitably without routine, real-time enterprise network communications. ...

Question: We have found that changing the plant engineer’s way of thinking has been the biggest challenge with regard to increasing security on the control side.
Answer: I agree. There are many barriers to get past on the awareness side. Many plant engineers are focused on safety and availability objectives and see security measures as impairing their ability to meet those objectives. Others don’t believe there is a threat, or don’t believe their systems are sufficiently exposed to that threat. Many engineers simply aren’t aware – they don’t realize that their “air gaps” disappeared years ago.


To summarize all of the above, Stuxnet self-reproduction abilities would be extremely limited (and we would probably never hear of this attack) if the following conditions were met:
- all involved Windows system must be patched for known vulnerabilities (BID 41732, BID 43073, BID 31874);
- no public network shares;
- no removable devices (USB flash drives, CD-Rs);
- no WinCC database hard-coded password (I am not sure if this is achievable though);
- Step 7 stations should not have access to the Internet (no possibility to communicate to virus control centers);
- process control network (with PLCs and Step 7 stations) must be separated from other local networks and Internet.

Moving towards more secure SCADA systems

In the post-Stuxnet world, the term "SCADA virus" was coined by journalists and bloggers. Now, when I am introduced to non-technical people, I may hear: "Oh, you work with SCADA systems? You must be a virus expert!"  I find the term "SCADA virus" confusing and misleading and I tend to avoid it, and here is why. Stuxnet affects only one type of SCADA system and it doesn't really use SCADA for propagation - infection through compromised WinCC database is performed using OLE Automation stored procedures, which is a Microsoft SQL Server feature not related to SCADA. Siemens SCADA system just happened to be the target of the malicious payload part of the virus, but in theory it could be anything - a document management system (to get access to sensitive corporate materials), a CRM system (to borrow competitor's contacts and leads), an online game (to steal other players passwords).

The fact that Stuxnet is actually a "regular" virus is good news. This means anti-virus companies don't need to invent some special kind of defense and we can keep taking usual precautions to avoid infection. Just take them seriously - the stakes are a bit higher than in the stolen game password scenario. We already have all tools, we are aware of all good practices - let's just apply them properly. No user software running under super-user accounts, no removable media, firewalls, no weak/default passwords, no security by obscurity, controlled network access, code signing, up-to-date operating systems - the list is long but well-known.

I would like to elaborate the process control network separation aspect. Process control and PLC programming tasks can be sand-boxed using a dedicated local network. But HMI (Human-Machine Interface) applications that read and write from/to the controlling device require direct access to the device in most cases, intermediate database is not an option due to excessive latency. I can see only one solution here: HMI/SCADA developers must explicitly enforce production data access restrictions using standard, well-known and proven security solutions and practices. Every data read or write request from HMI client stations to PLCs must be authorized. No home-made security algorithms. No backdoors. No plain passwords sent across the network.

Security in web-based solutions

Let's get straight to the big question: are web-based systems more prone to cyber-attacks? Provided the server is able to properly authenticate the user and client-server communication channel guarantees data privacy and integrity, the answer is "no". As an HMI/SCADA developer, do I need to come up with some sophisticated algorithms to ensure proper user authentication and channel security? No. Internet security industry is sufficiently mature to provide developers with correspondent technologies.

There is also a psychological aspect that influences developer's behavior. When working on a web-based solution, developers constantly keep in mind the fact that that every piece of data sent between client and server is (potentially) constantly being watched by people with bad intentions. This thought fuels their sense of alarm and, eventually, makes them produce secure design and code.

"...only real security is a pair of wire cutters…"

I took this quote from this posting and it makes sense to me. Together with the simple diagram on the right, it explains why we probably will never see a 100% secure industrial automation system. Stuxnet was a loud wake-up call for SCADA developers and users, hopefully it will create additional motivation to move towards the "Security" vertex of the pyramid remembering the closing line of the Symantec paper:

"...Despite the exciting challenge in reverse engineering Stuxnet and understanding its purpose, Stuxnet is the type of threat we hope to never see again.”

References

W32.Stuxnet Dossier, Nicolas Falliere, Liam O Murchu, and Eric Chien, Symantec, Sep 2010
http://www.symantec.com/content/en/us/enterprise/media/security_response/whitepapers/w32_stuxnet_dossier.pdf

SCADA Watch: Things You Probably Wish You Didn’t Know, Paul Ferguson, Trend Micro, Jan 2008
http://blog.trendmicro.com/scada-watch-things-you-probably-wished-you-didnt-know/

Stuxnet Webinar Attendee Questions, Andrew Ginter, Industrial Defender, Aug 2010
http://findingsfromthefield.com/?p=510