Skip to content

Pre-auth NULL-pointer dereference in S7 Upload handler — snap7 server #15

Description

@entropy1337

[CWE-476] Pre-auth NULL-pointer dereference in S7 Upload handler — snap7 server

Finding ID: SNAP7-06 Severity: High (unauthenticated remote DoS)
Component: snap7 S7 server — TS7Worker::PerformFunctionUpload()

Summary

The S7 Upload handler resolves a block-container from an attacker-controlled
block-type byte via FServer->getArea(BlkType) and immediately calls ->Find()
on the result without a NULL check. TSnap7Server::getArea(int) returns NULL
for any value that is not one of {srvAreaDB, srvAreaOB, srvAreaFB, srvAreaFC, srvAreaSDB}. An attacker who sends an upload request with any other block-type
byte causes a NULL-pointer dereference and crashes the server thread/process —
an unauthenticated remote denial of service.

Affected Version

SCADACS/snap7 at commit f6ff90317ca5d54250f4dcd29209689a74e26d82
(src/core/s7_server.cpp, PerformFunctionUpload, and TSnap7Server::getArea).

Reachability

REACHABLE, unauthenticated. Opcodes pduStartUpload (0x1D), pduUpload (0x1E)
and pduEndUpload (0x1F) all dispatch to PerformFunctionUpload()
(s7_server.cpp:343-345), which unconditionally parses the PDU as a start-upload
request and reads BlkType.

Technical Details

// PerformFunctionUpload()
ReqStartParams = PReqFunStartUploadParams(pbyte(PDUH_in) + sizeof(TS7ReqHeader));
BlkType = ReqStartParams->BlkType;                       // attacker-controlled
area = FServer->getArea(BlkType)->Find(BlkNum);          // line 1034: no NULL check

// TSnap7Server::getArea(int srvArea)
switch (srvArea) { case srvAreaDB: return DBArea; ... case srvAreaSDB: return SDB; }
return NULL;                                              // for any other BlkType

Find()IndexOf() dereferences the NULL container → SEGV.

Data flow: TCP bytes → upload BlkType byte → getArea()==NULLNULL->Find()
→ read at ~offset 0x10 of a NULL object → crash.

Proof of Concept

Discovered automatically by the AFL harness (poc/fuzz_s7_pdu) within seconds.
Minimized crashing input: poc/corpus/seed_upload_nullderef.bin. ASan
(poc/crash/SNAP7-06_upload_nullderef_asan.txt):

ERROR: AddressSanitizer: SEGV on unknown address 0x000000000010
  #0 PS7AreaContainer::IndexOf(unsigned short)  s7_server.cpp:79
  #1 PS7AreaContainer::Find(unsigned short)     s7_server.cpp:65
  #2 TS7Worker::PerformFunctionUpload()         s7_server.cpp:1034
  #3 TS7Worker::PerformPDURequest(int&)         s7_server.cpp:345

Impact

CVSS v3.1: 7.5AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. Unauthenticated
remote crash of an S7 server commonly deployed in OT/ICS environments.

Suggested Remediation

Check the container before use:

PS7AreaContainer* c = FServer->getArea(BlkType);
if (!c) return /* reply with an S7 error */ false;
area = c->Find(BlkNum);

The same getArea(...)->... pattern should be audited in the Download path.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions