Securing HL7

Alan Monnox
Integration
Healthcare
15 Dec 2018

If you’ve worked with IT in the healthcare industry you’ll likely be familiar with HL7. HL7 V2 is the de facto standard for systems to exchange health information messages. The standard defines the type of messages and their structure but has little to say about how the information is secured. In fact, the standard explicitly states that information security is outside of its scope.

HL7 Version 2 itself, does not provide for the enforcement of a provider organization’s security and access control policies. There are no messages specifically defined, at this time, that affect the movement of data based on an organization’s security and access control policies in conjunction with message content information that identifies the users of the message data and the organization’s policies for that user’s authorization to access that data

Consequently, for HL7 security you are left to your own devices.

Note that for the purposes of this post we are looking at HL7 V2. While an older specification to the current V3, V2 is the predominate standard due to its ubiquity and simple implementation. V3 is significantly more advanced and does encompass encryption and digital signatures.

The focus of this post is on V2 and we will explore some of the common methods for safeguarding the transmission of sensitive healthcare data between systems. However, before diving into the security, it is worth having a quick refresher on HL7.

HL7 In a Nutshell

Unlike many of the XML based integration protocols, the concepts behind HL7 are very simple to grasp. Here’s an example of a typical message used to indicate that a patient has been admitted into hospital.

MSH|^~\\&|SENDINGAPP|SENDINGFACILITY|RECAPP|RECFACILITY|20181213151922|SECURITY|ADT^A01^ADT_A01|SI971304|P|2.4|||AL|NE
EVN|A01|20181213151922|||USERNAME|20181213124700|EVENTFACILITY
PID|1||123ABC4^^^AA^NI||Zero^Patent^^^^^D||19540412000000|F|||10 Fantasy Street^Faraway^Town^^0000^NZL^H^^1480^^P^20181212090356|||||||||||12^European^NZHIS||||||||N|||20181212090356|G00005
PV1|1|I|AMC^RM-00^BED-00-4^12345^^^^^Acute Assessment Room 00|R|||1999^Smith^Badger^Bill|||MED||||9|||1999^Smith^Badger^Bill|IP|987754^^^^^12345|35^20181212000000||||||||||||||||||||||||20181213124700||||||186864

On first looks it may seem a little odd. Where are all the ‘</>’ and ‘{}‘ characters that we’ve come to know and love from the likes of XML and JSON? Instead, HL7 has each line as a segment, with each segment broken down into fields using ‘|’ as a delimiter.

The standard defines which segments comprise each message type. In this example, we are showing an A01. The standard also specifies the fields that make up each segment.

That’s pretty much it as far as HL7 goes. Yes, fields can be broken down into sub-fields and we can have optional segments, repeating segments, repeats within fields, required fields and conditional fields but the core elements are as outlined.

If that’s the message structure, the next question to cover is how do we go about sending it.

Sending the Message

The Minimal Level Layer Protocol (MLLP) standard defines how messages are sent over TCP/IP. To send an HL7 message all you need is an open port with someone listening at the other end. If your message is successfully received you’ll get either an ‘ACK’ or ‘NACK’ back from the recipient. Radio silence means you are to assume the message did not reach its destination.

Breaking Down the Message Header

Working low down network stack over a raw TCP/IP connection doesn’t give us much to work with. Likewise, the message payload is also sparse in terms of carrying security-related data.

Here’s the MSH segment, which provides a header for the message:

MSH|^~\\&|MYPAS|SENDINGFACILITY|RECAPP|RECFACILITY|20181213151922|mary.smith|ADT^A01^ADT_A01|SI971304|P|2.4|||AL|NE

The header provides some useful information for applying security rules. We have an identifier for the ‘Sending Application’ (MSH.3) and a ‘Security’ field (MSH.8), which may typically contain the name of the user.

In the example above, our Sending Application is set to ‘MYPAS’, while the Security field holds a user name ‘mary.smith’.

Neither the Sending Application or Security fields are mandatory. However, what the Security field holds is entirely at the discretion of the implementer.

Here’s what the HL7 specification (v2.4) has to say on the subject:

Definition: In some applications of HL7, this field is used to implement security features. Its use is not yet further specified.

In other words – go for your life!

The HL7 V2 specification makes no mention of fields for holding a security token or digital signature, so the loose wording around MSH.8 presents some options. However, one challenge is that version 2.4 of the HL7 specification, which is old but in widespread use, limits the Security field to only a ten character string.

The Threats

When sending data over the wire, as a minimum we should be assessing the risks based on the following threat categories:

  • Spoofing
  • Tampering
  • Information disclosure

Yes, other threat categories will apply but for the purposes of this discussion we’ll limit the scope to these three.

Let’s consider each of these threat types in turn with respect to our HL7 message:

Spoofing: The client doesn’t handshake with the server so we’ve no way of confirming we are sending the message to a legitimate receiver. Likewise, the receiving system has no way of confirming the true identity of the application defined in the ‘Sending Application’ field.
Tampering: If we’re sending the message over an unsecured IP connection then we are fully exposed to a ‘man in the middle’ attack.
Information Disclosure: Any intercepted transmissions are in the clear and this visible to the attacker.

To secure the message appropriately, we clearly need more tools than are provided out of the box by HL7. To reduce our threat surface we are going to need to move up the network stack.

The first option should come as no surprise:

Secure the Channel With TLS

By encrypting the connection between the two communicating systems the threats of tampering and information disclosure melt away. With the TLS handshake, the client can confirm the identity of the server through its certificate. This at least addresses half of our spoofing threat.

We could also establish the channel over an IPSec tunnel. This approach mitigates the risks of tampering and information disclosure but comes up short with spoofing. While a VPN does require authentication in order to establish the tunnel this is not under the control of the connecting systems. Hence, an explicit TLS connection is a given for most integration scenarios.

We’ve covered some of the threats but we still haven’t protected ourselves against a spoofing attack. Fortunately, with a little more work TLS can help us out here as well.

Client Certificates for Authentication

This approach is known as mutual authentication. It is also often referred to as two-way SSL and requires the client to present a certificate as part the TLS handshake. In this way, the server has the opportunity to confirm the identity of the client.

This option does require more setup at both the client and server ends but by having our clients each submit a certificates for identity enables the receiving system to trust the sender.

Having each client have their own certificate may seem like a high overhead in terms of administration. Indeed, if we have a multitude of clients then this will likely be the case. For most integration scenarios, it will be discrete systems that are communicating. Requiring each application that is identified in the MSH Sending Application field to have its own certificate is an acceptable security policy.

One of the challenges with implementing this approach is the ability of the receiving system to establish the two-way SSL connection. However, this limitation can be overcome with architectural patterns that employ either middle-ware or network appliances to offer a trusted endpoint for terminating the TLS connection.

Using TLS with a client certificate address our spoofing risk by enabling both parties in the communication to identify one another. It’s a great option, as we can mitigate a high percentage of our known security risks without having to make any changes to the HL7 message. However, we still do have risks, albeit a reduced set. If multiple relying parties are involved in the delivery of the message then the information is open to access at any of these relaying points. Securing from one end to the other over such a circuit is also problematic.

We can address this vulnerability introduced by the third party but again we have to move up the network stack.

HL7 Over Web Services

Delivering a HL7 message as the payload of a SOAP call is common practice and provides some great benefits from a security perspective.

First, Web Services frameworks are ubiquitous and highly mature. If you’re working in Java or .Net then you have full framework support for the protocol. Second, the Web Services security model is highly complex, or should that read comprehensive and sophisticated! Fortunately, the use of Web Service frameworks hides much of the complexity away from the developer.

Web Service security encompasses such standards as WS-Security, WS-SecurityPolicy and WS-Trust. Each of these standards builds on one another to provide ever increasing security capabilities. Collectively, these standards provide a comprehensive range of options, from simple user-name and password through to a full-blown federated solutions employing identity providers and security assertions.

The benefit of the SOAP security model is we can secure the content of the message independent of the underlying transport channel. By encrypting the message we can safely transmit messages through third parties with no risk of information tampering or information disclosure, as only the sender and receiver of the message have the necessary information to access the content of the call.

Why Web Services and not REST? Well, we do have a number of strategies we can employ when making REST-ful calls but that introduces the subject of FHIR, the next evolution of HL7 but using JSON for the message. FHIR is a sufficiently large topic to justify it’s own discussion, so we won’t cover it here.

Summary

Effective security design is all about addressing risks. Of the known risks we get the most coverage if we use Web Services (and WS-Security) to both digitally sign and encrypt our message.

The use of Web Services however, isn’t always practical. The downside to sending our HL7 messages in a SOAP payload is that we move beyond the HL7 specification and have to define custom interfaces for sending the messages. If we are trying to integrate two out-of-the-box systems together with HL7 then we need to introduce additional components to intercept and package the data in a SOAP envelope. The higher security doesn’t always justify the added complexity and cost of the integration solution.

The TLS connection represents the least effort and covers the major risks. Hence, this approach will likely be the standard for meeting any integration requirements between healthcare systems. If one-way TLS does not tick all the boxes then we can employ client certificates. The use of mutual authentication will reduce the attack surface but beware that client certificates introduce additional complexity to the solution that must be offset with the benefits they offer.

At the end of the day it’s good to have options.