CI / Check (push) Waiting to run
CI / Detect Changes (push) Waiting to run
CI / Deploy Agent (push) Blocked by required conditions
CI / Deploy Dashboard (push) Blocked by required conditions
CI / Deploy Docs (push) Blocked by required conditions
CI / Deploy MCP (push) Blocked by required conditions
164 lines
7.6 KiB
Markdown
164 lines
7.6 KiB
Markdown
# PLC / SPS Projects (CODESYS)
|
|
|
|
Certifai analyzes industrial control logic (IEC 61131-3) for PLC/SPS targets such
|
|
as CODESYS projects. A single PLC/SPS target is treated as a **composite device**:
|
|
the control application *and* the device it runs on.
|
|
|
|
| What you provide | What Certifai does |
|
|
| --- | --- |
|
|
| PLC project (PLCopen XML / ST, or a `.projectarchive`) | **Control-logic SAST** — semantic security rules over ST **and** graphical FBD/LD |
|
|
| A `.projectarchive` | **Control-app SBOM** — the referenced CODESYS libraries + the runtime version, matched against known CVEs |
|
|
| A device firmware image | Firmware SBOM / CVE (opt-in) |
|
|
| A reachable endpoint (WebVisu, OPC UA) | DAST / pentest (opt-in) |
|
|
|
|
## Anatomy: a soft PLC is a SoC + Linux + runtime
|
|
|
|
A CODESYS controller is **not** a monolithic appliance like a classic Siemens
|
|
S7. It is **PC-based ("soft") control** — commodity silicon running a
|
|
general-purpose Linux, with a **software PLC runtime** as just another process:
|
|
|
|
| Classic PLC (e.g. Siemens S7) | Soft PLC (CODESYS-on-Yocto, OpenPLC-on-Raspbian) |
|
|
| --- | --- |
|
|
| Proprietary hardware + firmware | Commodity SoC (x86 / ARM) |
|
|
| Proprietary OS | General-purpose Linux (a **Yocto** image, or Raspbian) |
|
|
| Proprietary runtime | Software runtime (**CODESYS Control**, or OpenPLC) |
|
|
| STEP7 / TIA project | IEC 61131-3 control app (ST / LD / FBD / SFC) |
|
|
|
|
Because of this, the device is built along **two independent tracks**, by
|
|
different people, on different timelines, and shipped separately. It also
|
|
inherits the **entire Linux / IT attack surface on top of** the OT / control
|
|
one — which is exactly why a PLC/SPS target is treated as a **composite**:
|
|
Certifai ingests one artifact per layer and scans each with the right pipeline.
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
subgraph TA["Track A · Device platform — built by the hardware OEM / vendor"]
|
|
direction LR
|
|
A1["Yocto / OpenEmbedded<br/>BSP + RT kernel"] --> A2["Bake in the CODESYS<br/>Control for Linux runtime"] --> A3["bitbake → device image<br/>.wic / .tar + manifest"]
|
|
end
|
|
subgraph TB2["Track B · Control application — built by the machine builder / customer"]
|
|
direction LR
|
|
B1["CODESYS IDE<br/>ST / LD / FBD / SFC + WebVisu"] --> B2["Reference CODESYS +<br/>vendor libraries"] --> B3["Compile → download<br/>to device (gateway 11740)"]
|
|
end
|
|
|
|
A3 --> DEV(["Running soft-PLC device<br/>SoC + Linux + runtime + control app<br/>Modbus · OPC UA · EtherNet/IP · WebVisu"])
|
|
B3 --> DEV
|
|
|
|
subgraph CERT["What Certifai scans — one layer per artifact"]
|
|
direction LR
|
|
S1["Firmware layer<br/>FirmwareStatic · SBOM · CVE"]
|
|
S2["Control-logic layer<br/>PLC SAST — ST + FBD/LD"]
|
|
S3["Control-app SBOM<br/>libraries + runtime → CVE"]
|
|
S4["Running layer<br/>ICS probe · DAST (WebVisu)"]
|
|
end
|
|
|
|
A3 -. firmware image .-> S1
|
|
B1 -. PLCopen XML / ST via git .-> S2
|
|
B2 -. projectarchive (zip) .-> S3
|
|
DEV -. live URL / provisioned .-> S4
|
|
|
|
classDef yocto fill:#fde68a,stroke:#b45309,color:#111
|
|
classDef codesys fill:#bfdbfe,stroke:#1d4ed8,color:#111
|
|
classDef dev fill:#e9d5ff,stroke:#7e22ce,color:#111
|
|
classDef cert fill:#bbf7d0,stroke:#15803d,color:#111
|
|
class A1,A2,A3 yocto
|
|
class B1,B2,B3 codesys
|
|
class DEV dev
|
|
class S1,S2,S3,S4 cert
|
|
```
|
|
|
|
::: tip Where Yocto fits
|
|
Yocto is **Track A** — the *build system* for the device platform. It produces
|
|
the Linux image and bakes in the CODESYS runtime, so it is the **firmware
|
|
layer**, entirely separate from the control application. Hand it to Certifai as
|
|
its own **firmware image** artifact (scanned by the firmware pipeline, not the
|
|
PLC pipeline). The device OS need not be Yocto — Raspbian/Debian/Buildroot, or
|
|
even an RTOS / bare-metal, are all possible — but Yocto is the common,
|
|
product-grade industrial choice.
|
|
:::
|
|
|
|
## Two ways to deliver the project
|
|
|
|
You can either **upload** the project when onboarding, or point Certifai at a
|
|
**git repository** (recommended — every scan is just a `git pull`, no re-upload).
|
|
|
|
### Option A — Upload
|
|
|
|
On the onboarding wizard, choose target type **PLC / SPS**, then attach a **PLC
|
|
project** artifact and pick its format:
|
|
|
|
- **PLCopen XML** (`.xml`) — export from CODESYS via *Project → Export PLCopenXML*.
|
|
- **Structured Text** (`.st`) — a raw ST file.
|
|
- **Project archive** (`.projectarchive`) — *File → Project Archive → Save/Send
|
|
Archive…* with **"Referenced libraries"** ticked. This is the only form that
|
|
also yields the **library + runtime SBOM**.
|
|
|
|
### Option B — Git repository (recommended)
|
|
|
|
Attach a **Git repository** artifact to the PLC/SPS target. Certifai clones it and
|
|
runs the control-logic scan over the exported source in the repo.
|
|
|
|
## Best-case git repository layout
|
|
|
|
Because the binary `.project` does not diff or merge in git, commit **textual
|
|
exports** for review-friendly SAST, and include the **`.projectarchive`** so the
|
|
library/runtime SBOM is available too:
|
|
|
|
```text
|
|
my-plc-project/
|
|
├── src/
|
|
│ ├── PLC_PRG.xml # PLCopen XML export (ST or FBD/LD) — one per POU
|
|
│ ├── PumpController.xml
|
|
│ ├── SafetyInterlock.xml
|
|
│ └── GVL.xml # global variable lists, also as PLCopen XML
|
|
├── PumpStation.projectarchive # optional but recommended → library + runtime SBOM
|
|
└── README.md
|
|
```
|
|
|
|
**Guidelines**
|
|
|
|
- **Export to PLCopen XML** (`Project → Export PLCopenXML`), one file per POU, and
|
|
commit those. ST, **and graphical FBD/LD**, are both analyzed.
|
|
- Alternatively commit raw `.st` / `.exp` / `.scl` files — also analyzed.
|
|
- **Do not** commit only the binary `.project` — it cannot be parsed (and does not
|
|
diff). If you want the library SBOM, commit the **`.projectarchive`** as well.
|
|
- CODESYS's built-in Git integration, which stores an exported representation,
|
|
works too — as long as the committed form is PLCopen XML / textual.
|
|
|
|
::: tip What unlocks what
|
|
- **Control-logic SAST** needs textual source in the repo (PLCopen XML or `.st`).
|
|
- **Library + runtime SBOM** needs a **`.projectarchive`** — PLCopen XML exports do
|
|
**not** carry the referenced libraries.
|
|
:::
|
|
|
|
## What the scanner finds
|
|
|
|
The control-logic rules are CWE-mapped and include: hardcoded credentials
|
|
(CWE-798), default/weak passwords (CWE-1393), safety interlock / watchdog bypass
|
|
(CWE-1384), unchecked array indexing (CWE-129), division-by-zero (CWE-369,
|
|
guard-aware), cleartext/insecure communication (CWE-319), insecure protocol ports
|
|
(CWE-319, e.g. Modbus 502, FTP 21, Telnet 23), and unstructured jumps (CWE-691).
|
|
|
|
The **SBOM** view lists the CODESYS libraries (`pkg:codesys/<name>@<version>`) and
|
|
the runtime; matching runtime components (e.g. the `Cmp*` / `3SLicense` libraries)
|
|
surface real CODESYS advisories as CVE alerts.
|
|
|
|
## Dynamic testing — ICS protocol probe
|
|
|
|
Beyond the static analysis, Certifai can **probe the running device** over
|
|
industrial protocols. Attach a **Live URL** artifact (the device host / WebVisu
|
|
URL) to the PLC/SPS target and enable the **ICS Probe** scan.
|
|
|
|
The probe is **read-only** — it never writes to the live process. It currently
|
|
speaks **Modbus/TCP** (port 502): it confirms whether the device answers
|
|
unauthenticated Modbus requests and reads its device identity (vendor / product /
|
|
revision). Because Modbus/TCP has no authentication or encryption in the protocol,
|
|
a reachable endpoint that answers is reported as an exposed control interface
|
|
(CWE-306). OPC UA and EtherNet/IP probes are planned.
|
|
|
|
::: warning
|
|
The ICS probe connects to the live device. It is **opt-in** (off by default) and
|
|
should only be run against targets you are authorized to test. It performs reads
|
|
only, never writes.
|
|
:::
|