Siemens SIMATIC S7 Device Detection (COTP)
🗓️ 17 Jun 2016 00:00:00Reported by Copyright (C) 2016 Greenbone AGType
openvas🔗 plugins.openvas.org👁 1550 Views
# SPDX-FileCopyrightText: 2016 Greenbone AG
# Some text descriptions might be excerpted from (a) referenced
# source(s), and are Copyright (C) by the respective right holder(s).
#
# SPDX-License-Identifier: GPL-2.0-only
if(description)
{
script_oid("1.3.6.1.4.1.25623.1.0.106099");
script_version("2023-10-13T05:06:10+0000");
script_tag(name:"last_modification", value:"2023-10-13 05:06:10 +0000 (Fri, 13 Oct 2023)");
script_tag(name:"creation_date", value:"2016-06-17 17:08:52 +0700 (Fri, 17 Jun 2016)");
script_tag(name:"cvss_base", value:"0.0");
script_tag(name:"cvss_base_vector", value:"AV:N/AC:L/Au:N/C:N/I:N/A:N");
script_tag(name:"qod_type", value:"remote_banner");
script_name("Siemens SIMATIC S7 Device Detection (COTP)");
script_category(ACT_GATHER_INFO);
script_copyright("Copyright (C) 2016 Greenbone AG");
script_family("Product detection");
script_dependencies("find_service.nasl");
script_require_ports(102);
script_tag(name:"summary", value:"COTP (Connection-Oriented Transport Protocol) based detection
of Siemens SIMATIC S7 devices.");
exit(0);
}
include("byte_func.inc");
include("dump.inc");
include("host_details.inc");
include("http_func.inc");
include("misc_func.inc");
include("port_service_func.inc");
function cotp_send_recv(req, soc) {
local_var req, soc;
send(socket: soc, data:req);
recv = recv(socket: soc, length: 6, min: 6);
if (strlen(recv) < 6)
return;
len = (getword(blob: recv, pos: 2) - 6);
if (len < 1 || len > 65535)
return;
recv += recv(socket: soc, length: len);
if (strlen(recv) != (len + 6))
return;
return recv;
}
function cotp_extract_packet(data) {
local_var data;
cotpPacket = substr(data, 7);
if (hexstr(cotpPacket[1]) == "01" || hexstr(cotpPacket[1]) == "07")
header_length = 10;
else
header_length = 12;
param_length = getword(blob: cotpPacket, pos: 6);
return substr(cotpPacket, header_length + param_length);
}
port = 102;
if (!get_port_state(port))
exit(0);
soc = open_sock_tcp(port);
if (!soc)
exit(0);
# COTP connection request
connectionReq = raw_string(0x03, 0x00, # TPKT (version 3) "Emulate" ISO transport services COTP on top of TCP
0x00, 0x16, # length
0x11, # COTP: length
0xe0, # PDU Type (CR Connect Request)
0x00, 0x00, # Destination reference
0x00, 0x02, # Source reference (can be set by the client)
0x00, # Class/extended format/flow control
0xc1, # Parameter code (src-tsap)
0x02, # Parameter length
0x01, 0x00, # Source TSAP
0xc2, # Parameter code (dst-tsap)
0x02, # Parameter length
0x01, 0x02, # Destination TSAP
0xc0, # Parameter code (tpdu-size)
0x01, # Parameter length
0x0a); # TPDU size
recv = cotp_send_recv(req: connectionReq, soc: soc);
if (!recv || hexstr(recv[5]) != "d0") {
# we have to open a new socket
close(soc);
soc = open_sock_tcp(port);
if (!soc)
exit(0);
# nb: Try an alternative request
connectionReq = raw_string(0x03, 0x00, 0x00, 0x16, 0x11, 0xe0, 0x00, 0x00,
0x00, 0x05, 0x00, 0xc1, 0x02, 0x01, 0x00, 0xc2,
0x02, 0x02, 0x00, 0xc0, 0x01, 0x0a);
recv = cotp_send_recv(req: connectionReq, soc: soc);
if (!recv || hexstr(recv[5]) != "d0") {
close(soc);
exit(0);
}
}
negotiatePdu = raw_string(0x03, 0x00, 0x00, 0x19, # TPKT header
0x02, # COTP: length
0xf0, # PDU Type (DT Data)
0x80, # Flags
0x32, # S7 Communication: Protocol ID
0x01, # Header: ROSCTR: Job
0x00, 0x00, # Redundancy Identification (Reserved)
0x00, 0x00, # Protocol Data Unit Reference
0x00, 0x08, # Parameter length
0x00, 0x00, # Data length
0xf0, # Parameter: Setup communictation
0x00, # Reserved
0x00, 0x01, # Max AmQ calling
0x00, 0x01, # Max AmQ called
0x01, 0xe0); # PDU length
recv = cotp_send_recv(req: negotiatePdu, soc: soc);
# nb: S7 Comm response ACK
if (!recv || hexstr(recv[8] != "03")) {
close(soc);
exit(0);
}
readModuleID = raw_string(0x03, 0x00, 0x00, 0x21, # TPKT header
0x02, 0xf0, 0x80, # COTP
0x32, # S7 Communication
0x07, # Header: ROSCTR: Userdata
0x00, 0x00, # Redundancy ID
0x00, 0x00, # PDU Ref
0x00, 0x08, # Param length
0x00, 0x08, # Data Length
0x00, 0x01, 0x12, # Parameter: Parameter header
0x04, # length
0x11,
0x44, # Type: Request / Function Group: CPU functions
0x01, # Subfunction: Read SZL
0x00, # Sequence number
0xff, # Data: Return code: Success
0x09, # Transport size
0x00, 0x04, # length
0x00, 0x11, # SZL-ID (Module identification)
0x00, 0x01); # SZL-Index
recv = cotp_send_recv(req: readModuleID, soc: soc);
if (!recv) {
close(soc);
exit(0);
}
dataPacket = cotp_extract_packet(data: recv);
# Return code must be "Success"
if (hexstr(dataPacket[0]) != "ff") {
close(soc);
exit(0);
}
version = "unknown";
if (strlen(dataPacket) >= 96) {
# Version
ver = hexstr(substr(dataPacket, 93, 95));
v1 = ver[0] + ver[1];
v2 = ver[2] + ver[3];
v3 = ver[4] + ver[5];
version = hex2dec(xvalue: v1) + "." + hex2dec(xvalue: v2) + "." + hex2dec(xvalue: v3);
# Module
module = substr(dataPacket, 14, 32);
set_kb_item(name: "siemens/simatic_s7/cotp/module", value: module);
}
log_message(port: port, data: "A Siemens SIMATIC S7 service answering to COTP requests seems to be running on this port.");
# nb: Register the service since we can be quite sure that this talks COTP
service_register(port: port, proto: "cotp", ipproto: "tcp", message: "A Siemens SIMATIC S7 service answering to COTP requests seems to be running on this port.");
# Read the component identifications to extract the model
readComponentID = raw_string(0x03, 0x00, 0x00, 0x21, 0x02, 0xf0, 0x80, 0x32,
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x08, 0x00, 0x01, 0x12, 0x04, 0x11, 0x44, 0x01,
0x00, 0xff, 0x09, 0x00, 0x04, 0x00, 0x1c, 0x00,
0x01);
recv = cotp_send_recv(req: readComponentID, soc: soc);
close(soc);
model = "unknown";
if (recv) {
dataPacket = cotp_extract_packet(data: recv);
if (hexstr(dataPacket[0]) == "ff") {
dataPacket = substr(dataPacket, 4);
element_size = getword(blob: dataPacket, pos: 4);
dataPacket = substr(dataPacket, 8);
for (i=0; i<strlen(dataPacket); i=i+element_size) {
element = substr(dataPacket, i, i+element_size);
if (hexstr(element[1]) == "01") {
plcName = substr(element, 2);
mod = eregmatch(pattern: "simatic([ ,]+)?(.*)", string: plcName, icase: TRUE);
if (mod[2]) {
model = mod[2];
}
}
else
if (hexstr(element[1]) == "02") {
moduleName = substr(element, 2);
mod = eregmatch(pattern: "((CPU )||(S7-))(.*)", string: moduleName, icase: TRUE);
if (mod[4]) {
model = mod[4];
}
}
else if (hexstr(element[1]) == "07") {
moduleType = substr(element, 2);
model = moduleType;
set_kb_item(name: "siemens/simatic_s7/cotp/modtype", value: moduleType);
}
}
}
}
if (version != "unknown") {
set_kb_item(name: "siemens/simatic_s7/detected", value: TRUE);
if (model != "unknown") {
# The extracted model string might included some non-printable characters so normalize it first
model = bin2string(ddata: model, noprint_replacement: "");
if (egrep(string: model, pattern: "^(CPU )?3.."))
model = 300;
set_kb_item(name: "siemens/simatic_s7/cotp/model", value: model);
}
if (version != "unknown")
set_kb_item(name: "siemens/simatic_s7/cotp/" + port + "/version", value: version);
set_kb_item(name: "siemens/simatic_s7/cotp/port", value: port);
}
exit(0);
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation
13 Oct 2023 00:00Current
7.1High risk
Vulners AI Score7.1