enip: improve probing parser

Strict length for register sessions
NOP command must have options=0
pull/6198/head
Philippe Antoine 5 years ago committed by Victor Julien
parent 8bf6530540
commit 0c948142b9

@ -359,7 +359,7 @@ static AppLayerResult ENIPParse(Flow *f, void *state, AppLayerParserState *pstat
SCReturnStruct(APP_LAYER_OK);
}
#define ENIP_LEN_REGISTER_SESSION 4 // protocol u16, options u16
static uint16_t ENIPProbingParser(Flow *f, uint8_t direction,
const uint8_t *input, uint32_t input_len, uint8_t *rdir)
@ -371,43 +371,90 @@ static uint16_t ENIPProbingParser(Flow *f, uint8_t direction,
return ALPROTO_UNKNOWN;
}
uint16_t cmd;
uint16_t enip_len;
uint32_t status;
int ret = ByteExtractUint16(&cmd, BYTE_LITTLE_ENDIAN, sizeof(uint16_t),
(const uint8_t *) (input));
uint32_t option;
uint16_t nbitems;
int ret = ByteExtractUint16(
&enip_len, BYTE_LITTLE_ENDIAN, sizeof(uint16_t), (const uint8_t *)(input + 2));
if (ret < 0) {
return ALPROTO_FAILED;
}
if (enip_len < sizeof(ENIPEncapHdr)) {
return ALPROTO_FAILED;
}
ret = ByteExtractUint32(
&status, BYTE_LITTLE_ENDIAN, sizeof(uint32_t), (const uint8_t *)(input + 8));
if (ret < 0) {
return ALPROTO_FAILED;
}
switch (status) {
case SUCCESS:
case INVALID_CMD:
case NO_RESOURCES:
case INCORRECT_DATA:
case INVALID_SESSION:
case INVALID_LENGTH:
case UNSUPPORTED_PROT_REV:
case ENCAP_HEADER_ERROR:
break;
default:
return ALPROTO_FAILED;
}
ret = ByteExtractUint16(&cmd, BYTE_LITTLE_ENDIAN, sizeof(uint16_t), (const uint8_t *)(input));
if(ret < 0) {
return ALPROTO_FAILED;
}
ret = ByteExtractUint32(
&option, BYTE_LITTLE_ENDIAN, sizeof(uint32_t), (const uint8_t *)(input + 20));
if (ret < 0) {
return ALPROTO_FAILED;
}
//ok for all the known commands
switch(cmd) {
case NOP:
case LIST_SERVICES:
case LIST_IDENTITY:
case LIST_INTERFACES:
if (option != 0) {
return ALPROTO_FAILED;
}
break;
case REGISTER_SESSION:
if (enip_len != ENIP_LEN_REGISTER_SESSION) {
return ALPROTO_FAILED;
}
break;
case UNREGISTER_SESSION:
if (enip_len != ENIP_LEN_REGISTER_SESSION && enip_len != 0) {
// 0 for request and 4 for response
return ALPROTO_FAILED;
}
break;
case LIST_SERVICES:
case LIST_IDENTITY:
case SEND_RR_DATA:
case SEND_UNIT_DATA:
case INDICATE_STATUS:
case CANCEL:
ret = ByteExtractUint32(&status, BYTE_LITTLE_ENDIAN,
sizeof(uint32_t),
(const uint8_t *) (input + 8));
break;
case LIST_INTERFACES:
if (input_len < sizeof(ENIPEncapHdr) + 2) {
SCLogDebug("length too small to be a ENIP LIST_INTERFACES");
return ALPROTO_UNKNOWN;
}
ret = ByteExtractUint16(
&nbitems, BYTE_LITTLE_ENDIAN, sizeof(uint16_t), (const uint8_t *)(input));
if(ret < 0) {
return ALPROTO_FAILED;
}
switch(status) {
case SUCCESS:
case INVALID_CMD:
case NO_RESOURCES:
case INCORRECT_DATA:
case INVALID_SESSION:
case INVALID_LENGTH:
case UNSUPPORTED_PROT_REV:
case ENCAP_HEADER_ERROR:
return ALPROTO_ENIP;
if (enip_len < sizeof(ENIPEncapHdr) + 2 * (size_t)nbitems) {
return ALPROTO_FAILED;
}
break;
default:
return ALPROTO_FAILED;
}
return ALPROTO_FAILED;
return ALPROTO_ENIP;
}
/**

Loading…
Cancel
Save