Skip to content

Commit 4c90c3e

Browse files
authored
Fix heap-buffer-overflow in ModbusLayer on truncated packets (#2159)
Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
1 parent ec8a45c commit 4c90c3e

6 files changed

Lines changed: 24 additions & 1 deletion

File tree

Packet++/header/ModbusLayer.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ namespace pcpp
101101
return port == 502;
102102
}
103103

104+
/// A static method that checks whether the data is large enough to hold a MODBUS header
105+
/// @param[in] data A pointer to the raw data
106+
/// @param[in] dataSize The size of the data in bytes
107+
/// @return True if the data is large enough to be parsed as a MODBUS layer, false otherwise
108+
static bool isDataValid(const uint8_t* data, size_t dataSize)
109+
{
110+
return data != nullptr && dataSize >= sizeof(modbus_header);
111+
}
112+
104113
/// @return MODBUS message type
105114
uint16_t getTransactionId() const;
106115

Packet++/src/TcpLayer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ namespace pcpp
482482
{
483483
constructNextLayer<GtpV2Layer>(payload, payloadLen, getAttachedPacket());
484484
}
485-
else if (ModbusLayer::isModbusPort(portDst))
485+
else if (ModbusLayer::isModbusPort(portDst) && ModbusLayer::isDataValid(payload, payloadLen))
486486
{
487487
constructNextLayer<ModbusLayer>(payload, payloadLen, getAttachedPacket());
488488
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
000c29af7ffe109add4e060d080045000038c6e64000400658880a0101ea0a0a0555c8d301f6e072efbac405c33a8018ffffd5d900000101080a37c3fee900ba2a0f00110000

Tests/Packet++Test/TestDefinition.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ PTF_TEST_CASE(CiscoHdlcLayerEditTest);
329329
// Implemented in ModbusTests.cpp
330330
PTF_TEST_CASE(ModbusLayerCreationTest);
331331
PTF_TEST_CASE(ModbusLayerParsingTest);
332+
PTF_TEST_CASE(ModbusLayerTruncatedTest);
332333

333334
// Implemented in X509Tests.cpp
334335
PTF_TEST_CASE(X509ParsingTest);

Tests/Packet++Test/Tests/ModbusTests.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,14 @@ PTF_TEST_CASE(ModbusLayerParsingTest)
5151
PTF_ASSERT_EQUAL(modbusLayer->toString(),
5252
"Modbus Layer, Transaction ID: 17, Protocol ID: 0, Length: 6, Unit ID: 255, Function Code: 4");
5353
} // ModbusLayerParsingTest
54+
55+
PTF_TEST_CASE(ModbusLayerTruncatedTest)
56+
{
57+
// A packet to port 502 whose payload is shorter than a full modbus_header (8 bytes).
58+
// It must not be parsed as a Modbus layer, otherwise the header getters read out of bounds.
59+
auto rawPacket1 = createPacketFromHexResource("PacketExamples/ModbusTruncated.dat");
60+
61+
pcpp::Packet packet(rawPacket1.get());
62+
PTF_ASSERT_FALSE(packet.isPacketOfType(pcpp::Modbus));
63+
PTF_ASSERT_NULL(packet.getLayerOfType<pcpp::ModbusLayer>());
64+
} // ModbusLayerTruncatedTest

Tests/Packet++Test/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ int main(int argc, char* argv[])
401401

402402
PTF_RUN_TEST(ModbusLayerCreationTest, "modbus");
403403
PTF_RUN_TEST(ModbusLayerParsingTest, "modbus");
404+
PTF_RUN_TEST(ModbusLayerTruncatedTest, "modbus");
404405

405406
PTF_RUN_TEST(X509ParsingTest, "x509");
406407
PTF_RUN_TEST(X509VariantsParsingTest, "x509");

0 commit comments

Comments
 (0)