Top 20 Secure PLC Coding Practices

If you work in cybersecurity, you have probably heard of the OWASP TOP 10: a standard awareness document that represents a broad consensus about the most critical security risks to web applications.

However, in Industrial Control Systems, we never talk about the security of the code that controls the process, why? This is the gap the TOP 20 project is trying to close.


Project genesis


The project started with Jake Browdsky’s presentation at the S4 conference in 2019:


In this talk, the concept of securing the industrial process by applying secure coding practices in the PLC code is discussed and several examples are mentioned.

This idea was then transformed into a collaborative project by Sarah Fluchs and Vivek Ponnada, on which more than 900 people contributed with their ideas!


Programmable Logic Controllers


Programmable Logic Controllers (PLCs) are located at the core of automation, at the level 1 of the Purdue model.

ISA representation of the Purdue model
Is The Purdue Model Dead? – Dale Peterson: ICS Security Catalyst (


PLC are embedded, real-time computers that interact directly with the sensors and the actuators to monitor and control a part of the industrial process.

They run an infinite loop, composed of 4 steps :


The “logic”, or code of the PLC, can be written in different languages, as defined in the IEC 61131-3 standard:

  • Ladder diagram (LD)
  • Function block diagram (FBD)
  • Structured text (ST)
  • Instruction list (IL) [now deprecated]
  • Sequential function chart (SFC)


The TOP20 document

The TOP20 document is the result of the online discussions to identify the 20 most important coding practices and can be downloaded from the project website.

Like the OWASP TOP10, it doesn’t aim at describing each and every possible secure coding practice, at least for now.

Each of the TOP20 practice is detailed with the same information:


The 20 practices can be organized in three main categories:


A few examples

Let’s have a look at one example from each category. For this we’ll use an entry-level PLC from our lab, a traffic light as well as a SCADA supervision.

Unfortunately, each PLC vendor -even each PLC family- uses its own specific programming software; examples showcased here cannot be copy-pasted in another PLC brand code and will require a different implementation.

The PLC code as well as the SCADA project used for the demonstration can be downloaded from our github page.


Rule #13: Disable unneeded / unused communication ports and protocols

This practice consists of hardening the PLC. Most PLCs today offer support for several ICS protocols, as well as a variety of additional services like FTP, a web server and many more.

Disabling the services not used and reinforcing the security of the ones enabled (changing default credentials, etc) is a necessary step to reduce the attack surface, and consequently limit the number of security patches to apply in the future (the less features enabled, the more vulnerabilities will be applicable and will have to be patched).

Let’s take a look at the video:


Rules #6 and #8 : Checking inputs at the PLC level

These two rules can be demonstrated in the same example as they follow the same principle : do not blindly trust external input! For someone like me who has done his fair share of web application pentesting, I couldn’t agree more!

Valid ranges for input values are oftentimes implemented at the SCADA level, leaving room for an attacker to directly write an out-of-range value to the right PLC register.

This is especially true for counters and timers, which should be checked to ensure they’re superior or equal to zero, and that the value is inferior to a high limit that makes sense for the process.

Let’s take a look at the video:


Monitoring the PLC rules #2 and #5

We can leverage operational data from the PLC to try to detect abnormal situations that could be cybersecurity incidents.


PLC state

Making sure the PLC is in “RUN” mode is critical for the safety and security of operations. A stopped PLC could prevent the SCADA HMI from displaying the right information to the operator, leading to bad decisions.

Likewise, features like input and output “forcing” could result in the SCADA HMI not displaying the real state of the process, and should be detected and clearly displayed to the operator.

Let’s take a look at the video:

This technique can also be used to detect PLCs in “PROGRAM” mode, which allows the PLC to be remotely programed.


PLC firmware and code version

Wouldn’t it be great to be able to query the firmware version of your PLC directly from a Modbus register? Well, you can!

In addition, on our PLC, we can also get a checksum of the PLC code, meaning we can detect if somebody has tampered with the PLC code, raise an alarm, and investigate if we cannot match that to an entry in the change management register.

Let’s take a look at the video:


So what can you do?

The top 20 document is readily available, but how can you use it?


If you want to learn more about PLC code security, you can also check the content we showcased during our workshops at DEFCON and BruCON on our Github page.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top