Redes Sociales

sábado, 30 de junio de 2018

Snort rules for modbus and Unity traffic

Snort rules for industrial traffic are important to detect any strange behaviour. DigitalBond did already detect a number of rules which are included at the bottom of this post. However the number of snort rules detected here is much higher.

Taking a look at the Modbus specification and after my research in the Unity/UMAS protocol I have detected a total of 51 snort rules that detect anomalous Modbus and Unity traffic. This is the list of rules:

This is the whole listing:

Modbus protocol rules

RULE 1

Explanation: REQUEST MODBUS 0x01 --> BYTES 4-5 ==> Values should not be above 07D0h -->See Pag 12 modbus specification

alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|";
offset:2; depth:2; content:"|01|";offset:7; depth:1; byte_test: 2,>,0x07D0,10;
msg="Modbus TCP 0x01: Too many coils to read requested. Possible DoS";
classtype:attempted-dos; sid:987000001; rev:1; priority:1;)


RULE 2

Explanation: RESPONSE MODBUS 0x81 --> BYTE 2 (EXCEPTION CODE) ==> 0x01 o 0x02 o 0x03 o 0x04 --> See Pag 12 modbus specification

alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|81|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x01: Response exception code not allowed"; sid:987000002; rev:1; priority:1;)


RULE 3

Explanation: REQUEST MODBUS 0x02 --> BYTES 4-5 ==> Should not be higher than 07D0h -->See Pag 13 modbus specification

alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|02|"; offset:7; depth:1; byte_test: 2,>,0x07D0,10; msg="Modbus TCP 0x02: Too many inputs to read requested. Possible DoS"; classtype: attempted-dos; sid:987000003; rev:1; priority:1;)

RULE 4



Explanation --> RESPONSE MODBUS 0x82 --> BYTE 2 (EXCEPTION CODE) ==> 0x01 o 0x02 o 0x03 o 0x04 --> See Pag 13 modbus specification

alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|82|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x02: Response exception code not allowed"; sid:987000004; rev:1; priority:1;)



RULE 5

Explanation: REQUEST MODBUS 0x03 --> BYTES 4-5 ==> Should not be higher than 0x007D --> See Pag 15 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|03|"; offset:7; depth:1; -->  BYTE_test: 2,>,0x007D,10; msg="Modbus TCP 0x03: Too many holding registers to read requested. Possible DoS"; classtype: attempted-dos;sid:987000005; rev:1; priority:1;)




RULE 6

Explanation --> RESPONSE MODBUS 0x83 --> BYTE 2 (EXCEPTION CODE) ==> 0x01 o 0x02 o 0x03 o 0x04 --> See Pag 15 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|83|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x03: Response exception code not allowed"; sid:987000006; rev:1; priority:1;classtype: non-standard-protocol;)




RULE 7

Explanation: REQUEST MODBUS 0x04 --> BYTES 4-5 ==> Should not be higher than 0x007D --> See Pag 16 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|04|"; offset:7; depth:1; -->  BYTE_test: 2,>,0x007D,10; msg="Modbus TCP 0x04: Too many input registers to read requested. Possible DoS"; classtype: attempted-dos; sid:987000007; rev:1; priority:1;)




RULE 8

Explanation --> RESPONSE MODBUS 0x84 --> BYTE 2 (EXCEPTION CODE) ==> 0x01 o 0x02 o 0x03 o 0x04 --> See Pag 16 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|84|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x04: Response exception code not allowed"; classtype: non-standard-protocol; sid:987000008; rev:1; priority:3;)




RULE 9

Explanation: REQUEST MODBUS 0x05 --> BYTES 4-5 ==> Allowed values 0x0000 or 0xFF00 --> See Pag 17 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|05|"; offset:7; depth:1; content:"!|00 00|FF 00|"; offset:10, depth:2;  msg="Modbus TCP 0x05: Coil output value not allowed"; sid:987000009; rev:1; priority:1;)




RULE 10

Explanation --> RESPONSE MODBUS 0x05 --> BYTE 4-5 ==> Allowed values: 0x0000 or 0xFF00 --> See Pag 18 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|05|"; offset:7; depth:1; content:"!|00 00|FF 00|"; offset:10, depth:2;  msg="Modbus TCP 0x05: Coil value incorrect"; sid:987000010; rev:1; priority:1;)




RULE 11

Explanation --> RESPONSE MODBUS 0x85 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values 0x01 or 0x02 or 0x03 or 0x04 --> See Pag 18 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|85|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x05: Response exception code not allowed"; sid:987000011; rev:1; priority:3;classtype: non-standard-protocol;)




RULE 12

Explanation --> RESPONSE MODBUS 0x86 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 1 to 4 --> See Pag 19 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|86|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x06: Response exception code not allowed"; sid:987000012; rev:1; priority:3;classtype: non-standard-protocol;)




RULE 13

Explanation --> RESPONSE MODBUS 0x87 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 01 or 04 --> See Pag 20 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|87|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x07: Response exception code not allowed"; sid:987000013; rev:1; priority:3;classtype: non-standard-protocol;)




RULE 14

Explanation --> RESPONSE MODBUS 0x88 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 01 or 03 or 04 --> See Pag 22 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|88|"; offset:7; depth:1; content:!"|01|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x08: Response exception code not allowed"; sid:987000014; rev:1; priority:3;classtype: non-standard-protocol;)




RULE 15

Explanation --> RESPONSE MODBUS 0x8B --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 01 or 04 --> See Pag 25 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|8B|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x0B: Response exception code not allowed"; sid:987000015; rev:1; priority:1;)




RULE 16

Explanation --> RESPONSE MODBUS 0x8C --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 01 or 04 --> See Pag 27 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|8C|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x0C: Response exception code not allowed"; sid:987000016; rev:1; priority:3;classtype: non-standard-protocol;)




RULE 17

Explanation: REQUEST MODBUS 0x0F --> BYTES 4-5 ==> Should not be higher than 0x07B0 --> See Pag 29 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|0F|"; offset:7; depth:1; -->  BYTE_test: 2,>,0x07B0,10; msg="Modbus TCP 0x0F: Too many coils to write requested"; sid:987000017; rev:1; priority:1;)




RULE 18

Explanation --> RESPONSE MODBUS 0x0F --> BYTES 4-5 ==> Should not be higher than 0x07B0 --> See Pag 29 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|0F|"; offset:7; depth:1; -->  BYTE_test: 2,>,0x07B0,10; msg="Modbus TCP 0x0F: Too many coils responded"; sid:987000018; rev:1; priority:1;)




RULE 19

Explanation --> RESPONSE MODBUS 0x8F --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x04 --> See Pag 29 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|8F|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x0F: Response exception code not allowed"; sid:987000019; rev:1; priority:3;classtype: non-standard-protocol;)




RULE 20

Explanation: REQUEST MODBUS 0x10 --> BYTES 4-5 ==> Should not be over 0x007B --> See Pag 29 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|10|"; offset:7; depth:1; -->  BYTE_test: 2,>,0x007B,10; msg="Modbus TCP 0x10: Too many registers to write requested"; sid:987000020; rev:1; priority:1;)




RULE 21

Explanation --> RESPONSE MODBUS 0x10 --> BYTE 4-5 ==> Should not be higher than 0x007B --> See Pag 31 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|0F|"; offset:7; depth:1; -->  BYTE_test: 2,>,0x007B,10; msg="Modbus TCP 0x10: Too many registers responded"; sid:987000021; rev:1; priority:1;)




RULE 22

Explanation --> RESPONSE MODBUS 0x90 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x04 --> See Pag 31 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|90|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x10: Response exception code not allowed"; sid:987000022; rev:1; priority:3;classtype: non-standard-protocol;)




RULE 23

Explanation --> RESPONSE MODBUS 0x91 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 0x01 or 0x04 --> See Pag 32 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|91|"; offset:7; depth:1; content:!"|01|04|"; offset:8, depth:1;  msg="Modbus TCP 0x11: Response exception code not allowed"; sid:987000023; rev:1; priority:1;)




RULE 24

Explanation: REQUEST MODBUS 0x14 --> BYTE 2 ==> Allowed values: From 0x07 to 0xF5 --> See Pag 33 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|14|"; offset:7; depth:1; -->  BYTE_test: 1,>,0xF5,8; msg="Modbus TCP Request 0x14: message -->  BYTE count incorrect"; sid:987000124; rev:1; priority:1;)
alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|14|"; offset:7; depth:1; -->  BYTE_test: 1,<,0x07,8; msg="Modbus TCP Request 0x14: message -->  BYTE cunt incorrect"; sid:987000224; rev:1; priority:1;)




RULE 28

Explanation --> RESPONSE MODBUS 0x14 --> BYTE 2 ==> Allowed values: 0x07 to 0xF5 --> See Pag 33 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|14|"; offset:7; depth:1; -->  BYTE_test: 1,>,0xF5,8; msg="Modbus TCP Response 0x14: message -->  BYTE count incorrect"; sid:987000128; rev:1; priority:1;)
alert tcp $ $MODBUS_PLC 502 -> EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|14|"; offset:7; depth:1; -->  BYTE_test: 1,<,0x07,8; msg="Modbus TCP Response 0x14: message -->  BYTE cunt incorrect"; sid:987000228; rev:1; priority:1;)




RULE 31

Explanation --> RESPONSE MODBUS 0x94 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x04 or 0x08 --> See Pag 33 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|94|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x14: Response exception code not allowed"; sid:987000031; rev:1; priority:3;classtype: non-standard-protocol;)




RULE 32

Explanation: REQUEST MODBUS 0x15 --> BYTE 2 ==> Allowed values: 0x09 to 0xFB --> See Pag 34 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|15|"; offset:7; depth:1; -->  BYTE_test: 1,>,0xFB,8; msg="Modbus TCP Request 0x15: message -->  BYTE count incorrect"; sid:987000132; rev:1; priority:1;)
alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|15|"; offset:7; depth:1; -->  BYTE_test: 1,<,0x09,8; msg="Modbus TCP Request 0x15: message -->  BYTE cunt incorrect"; sid:987000232; rev:1; priority:1;)




RULE 36

Explanation --> RESPONSE MODBUS 0x15 --> BYTE 2 ==> Allowed values: 0x09 to 0xFB --> See Pag 35 modbus specification

 alert tcp $MODBUS_PLC 502 -> EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|15|"; offset:7; depth:1; -->  BYTE_test: 1,>,0xFB,8; msg="Modbus TCP Response 0x15: message -->  BYTE count incorrect"; sid:987000132; rev:1; priority:1;)
alert tcp $ $MODBUS_PLC 502 -> EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|15|"; offset:7; depth:1; -->  BYTE_test: 1,<,0x09,8; msg="Modbus TCP Response 0x15: message -->  BYTE cunt incorrect"; sid:987000232; rev:1; priority:1;)



RULE 40

Explanation --> RESPONSE MODBUS 0x95 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x04 or 0x08 --> See Pag 35 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|95|"; offset:7; depth:1; content:!"|01|02|03|04|08|"; offset:8, depth:1;  msg="Modbus TCP 0x15: Response exception code not allowed"; sid:987000040; rev:1; priority:3;classtype: non-standard-protocol;)




RULE 41

Explanation --> RESPONSE MODBUS 0x96 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x04 --> See Pag 37 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|96|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x16: Response exception code not allowed"; sid:987000041; rev:1; priority:3; classtype: non-standard-protocol;)




RULE 42

Explanation: REQUEST MODBUS 0x17 --> BYTES 4 and 5 ==> Allowed values: 0x0001 to 0x007D --> See Pag 38 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|17|"; offset:7; depth:1; -->  BYTE_test: 1,>,0x7D,10; msg="Modbus TCP Request 0x17: incorrect register count to read"; sid:987000142; rev:1; priority:1;)
alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|17|"; offset:7; depth:1; -->  BYTE_test: 1,<,0x01,10; msg="Modbus TCP Request 0x17: incorrect register count to read"; sid:987000242; rev:1; priority:1;)



RULE 43

Explanation: REQUEST MODBUS 0x17 --> BYTES 8 and 9 ==> Allowed values: 0x0001 a 0x0079 --> See Pag 38 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|17|"; offset:7; depth:1; -->  BYTE_test: 1,>,0x79,14; msg="Modbus TCP Request 0x17: incorrect register count to write"; sid:987000143; rev:1; priority:1;)
 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|17|"; offset:7; depth:1; -->  BYTE_test: 1,<,0x01,14; msg="Modbus TCP Request 0x17: incorrect register count to write"; sid:987000243; rev:1; priority:1;)




RULE 44

Explanation --> RESPONSE MODBUS 0x97 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x04 --> See Pag 39 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|97|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x17: Response exception code not allowed"; sid:987000044; rev:1; priority:3; classtype: non-standard-protocol;)




RULE 45

Explanation --> RESPONSE MODBUS 0x18 --> BYTES 2y3 ==> Allowed values: Should be lower than 0x0041 --> See Pag 41 modbus specification

 alert tcp $MODBUS_PLC 502 -> EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|18|"; offset:7; depth:1; -->  BYTE_test: 1,>,0x41,8; msg="Modbus TCP Response 0x18: message -->  BYTE count incorrect"; sid:987000145; rev:1; priority:1;)




RULE 46

Explanation --> RESPONSE MODBUS 0x18 --> BYTES 4y5 ==> Allowed values: 0x0001 to 0x001F --> See Pag 41 modbus specification

 alert tcp $MODBUS_PLC 502 -> EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|18|"; offset:7; depth:1; -->  BYTE_test: 1,>,0x1F,10; msg="Modbus TCP Response 0x18: message FIFO count incorrect"; sid:987000146; rev:1; priority:1;)
 alert tcp $ $MODBUS_PLC 502 -> EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|18|"; offset:7; depth:1; -->  BYTE_test: 1,<,0x01,10; msg="Modbus TCP Response 0x15: message FIFO count incorrect"; sid:987000246; rev:1; priority:1;)




RULE 47

Explanation --> RESPONSE MODBUS 0x98 --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x04 --> See Pag 41 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|98|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x18: Response exception code not allowed"; sid:987000047; rev:1; priority:3; classtype: non-standard-protocol;)




RULE 48

Explanation: REQUEST MODBUS 0x2B --> BYTE 2 ==> Allowed values: 0x0D or 0x0B --> See Pag 43 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|2B|"; offset:7; depth:1; content:"!|0D|0B|"; offset:8, depth:1;  msg="Modbus TCP Request 0x2B: Incorrect MEI Type"; sid:987000048; rev:1; priority:3; classtype: non-standard-protocol;)




RULE 49

Explanation --> RESPONSE MODBUS 0x2B --> BYTE 2 ==> Allowed values: 0x0D or 0x0B --> See Pag 43 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|2B|"; offset:7; depth:1; content:"!|0D|0B|"; offset:8, depth:1;  msg="Modbus TCP Response 0x2B: Incorrect MEI Type"; sid:987000049; rev:1; priority:3; classtype: non-standard-protocol;)




RULE 50

Explanation --> RESPONSE MODBUS 0xAB --> BYTE 2 (EXCEPTION CODE) ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x04 --> See Pag 44 modbus specification

 alert tcp $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|AB|"; offset:7; depth:1; content:!"|01|02|03|04|"; offset:8, depth:1;  msg="Modbus TCP 0x2B: Response exception code not allowed"; sid:987000050; rev:1; priority:3; classtype: non-standard-protocol;)




RULE 51

Explanation: REQUEST MODBUS 0x2B. --> BYTE 2=0x0E --> BYTE 3 ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x04 --> See Pag 44 modbus specification

 alert tcp $EXTERNAL any -> $MODBUS_PLC 502 (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|2B|"; offset:7; depth:1; content:"|0E|"; offset:8; depth:1; content:"!|01|02|03|04|"; offset:9, depth:1;  msg="Modbus TCP Request 0x2B: Incorrect Read Device ID Code"; sid:987000051; rev:1; priority:3; classtype: non-standard-protocol;)




RULE 52

Explanation --> RESPONSE MODBUS 0x2B. --> BYTE 2=0x0E --> BYTE 3 ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x04 --> See Pag 44 modbus specification

 alert tcp  $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|2B|"; offset:7; depth:1; content:"|0E|"; offset:8; depth:1; content:"!|01|02|03|04|"; offset:9, depth:1;  msg="Modbus TCP Response 0x2B: Incorrect Read Device ID Code"; sid:987000052; rev:1; priority:3; classtype: non-standard-protocol;)




RULE 53

Explanation --> RESPONSE MODBUS 0x2B. --> BYTE 2=0x0E --> BYTE 4 ==> Allowed values: 0x01 or 0x02 or 0x03 or 0x81 or 0x82 or 0x83 --> See Pag 44 modbus specification

 alert tcp  $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|2B|"; offset:7; depth:1; content:"|0E|"; offset:8; depth:1; content:"!|01|02|03|81|82|83|"; offset:10, depth:1;  msg="Modbus TCP Response 0x2B: Incorrect Conformity Level"; sid:987000053; rev:1; priority:3; classtype: non-standard-protocol;)


 


RULE 54

Explanation --> RESPONSE MODBUS 0x2B. --> BYTE 2=0x0E --> BYTE 5 ==> Allowed values: 0x00 o 0xFF --> See Pag 44 modbus specification

 alert tcp  $MODBUS_PLC 502 -> $EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; content:"|2B|"; offset:7; depth:1; content:"|0E|"; offset:8; depth:1; content:"!|00|FF|"; offset:11, depth:1;  msg="Modbus TCP Response 0x2B: Incorrect Conformity Level"; sid:987000054; rev:1; priority:3; classtype: non-standard-protocol;)




RULE 55

Explanation --> RESPONSE MODBUS MAYOR QUE 0x80 --> BYTE 2 ==> Allowed values: Should be lower than 0x0B --> See Pag 49 modbus specification

 alert tcp $MODBUS_PLC 502 -> EXTERNAL any (flow:from_client, established; content:"|00 00|"; offset:2; depth:2; -->  BYTE_test: 1,>,0x80,7; -->  BYTE_test: 1,<,0x0B,8; msg="Modbus TCP: Incorrect exception code"; sid:987000155; rev:1; priority:1;)

Unity protocol rules

RULE 56

Explanation: REQUEST MODBUS 0x5A --> BYTE 3=0x23 --> System Bit or Word Modification

 alert tcp any any -> any 502 (msg:"Schneider PLC UMAS Write System bit/word request";content:"|00 00|";offset:2;depth:2;content:"|5a|";offset:7;depth:1;content:"|23|";offset:9;depth:1;sid:987000110;)



RULE 57

Explanation: REQUEST MODBUS 0x5A --> BYTE 3=0x30 --> Strategy upload request

 alert tcp any any -> any 502 (msg:"Schneider PLC UMAS Initialize strategy upload request";content:"|00 00|";offset:2;depth:2;content:"|5a|";offset:7;depth:1;content:"|30|";offset:9;depth:1;sid:987000111;)



RULE 58

Explanation: REQUEST MODBUS 0x5A --> BYTE 3=0x33 --> Strategy upload start

 alert tcp any any -> any 502 (msg:"Schneider PLC UMAS Initialize strategy download request";content:"|00 00|";offset:2;depth:2;content:"|5a|";offset:7;depth:1;content:"|33|";offset:9;depth:1;sid:987000112;)



RULE 59

Explanation: REQUEST MODBUS 0x5A --> BYTE 3=0x36 --> BYTE4=0x02 --> Restore from backup request

 alert tcp any any -> any 502 (msg:"Schneider PLC UMAS strategy restore backup request";content:"|00 00|";offset:2;depth:2;content:"|5a|";offset:7;depth:1;content:"|36 02|";offset:9;depth:2;sid:987000113;)



RULE 60

Explanation: REQUEST MODBUS 0x5A --> BYTE 3=0x36 --> BYTE4=0x04 --> Remove backup request

 alert tcp any any -> any 502 (msg:"Schneider PLC UMAS strategy remove backup request";content:"|00 00|";offset:2;depth:2;content:"|5a|";offset:7;depth:1;content:"|36 04|";offset:9;depth:2;sid:987000114;)



RULE 61

Explanation: REQUEST MODBUS 0x5A. --> BYTE 3=0x40 --> PLC Start request

 alert tcp any any -> any 502 (msg:"Schneider PLC(Quantumn) uses function code 90 for communications the Unity pro software/Set PLC CPU STOP";content:"|00 00|";offset:2;depth:2;content:"|5a|";offset:7;depth:1;content:"|40|";offset:9;depth:1;sid:114;)



RULE 62

Explanation: REQUEST MODBUS 0x5A. --> BYTE 3=0x41 --> PLC Stop request

 alert tcp any any -> any 502 (msg:"Schneider PLC(Quantumn) uses function code 90 for communications the Unity pro software/Set PLC CPU Restart";content:"|00 00|";offset:2;depth:2;content:"|5a|";offset:7;depth:1;content:"|41|";offset:9;depth:1;sid:115;)

miércoles, 27 de junio de 2018

Story of a Linux server malware infection

On May 2016 I was asked to check a Linux Server that seemed to be functioning slowly and because of an alert from the communication services of the University that warned that the server could be serving malware and/or SPAM. This a report of what I found.

FORENSIC ANALYSIS REPORT

  • Date: 27th of May 2016
  • System name: SXXXXXXXa
  • Operative System: Ubuntu 14.04 LTS
  • Installation date: 12th of April, 2016
  • Usage of the System: Server used at the XXXXXXXXX department of the University of XXXXX for their daily operation. It's connected to the internal network of the University and at the same time it's directly accessible from internet through university's subdomain. XXXX.XXXXX.es (IP=193.XXX.XXX.X9). The system has, at the moment of the incident a SSH server accesible from internet. It does not offer any web site nor other available services.
  • Event:The department was informed from the communication services of the University that this server has been detected as the origin of malicious traffic and that probably it has a trojan running. To avoid further problem, the traffic was cut off from and to internet for the server.


Timeline of the problem

After accessing physically to the server the following facts were detected:

  1. The command 'ps' did not show any strange process running. The command netstat did not show any strange connection.
  2. In /root directory of the system, I found a file named XXXX.nano modified on April 21st, 2016 approximately at 12:00 AM in which I could see the line “PermitRootLogin yes”. This is a line for the SSH config file that allows SSH server to be accessed with root user. Checking the SSH config file, I can see it has the same date and time than the .nano file and therefore with that date, the system was allowed to be accessed by root. From my point of view this was not actually part of the attack but a very bad practice used by administrator some days after the system installation and days before the sttack started.
  3. That same day, and approximately same hour, it appears an SSH connection with a normal user (I'll use the fake username 'chris' to refer to it), and 5 minutes later an SSH connection with root user.
  4. Four days later we find that on April 25th, 09:03, an SSH connection with user 'chris' is started, but this time the connection comes from IP 183.3.202.187 (located in China).
  5. In command history of root user we find a total of 13 commands (From 71 to 83 in next image), where we can see that a file is downloaded from a server in China (IP 117.18.4.133), and it's give execution permissions and it's eventually executed... Finally on line 83 the root password is changed.

Unfortunately we cannot know the exact date and time of these commands, but we know that they happened before an SSH connection found on history line 86 (not shown) that happened on April 25th at 12:00 AM. So it seems the attack occurred on April 25th 9:03 and the server was owned a few minutes later.



Post Infection

The system was installed on April 12th, from the day after installation (April 13th, 2016) we can see SSH root Access attempts (which is normal as it had its own public IP address). Actually until the real attack, 42893 SSH connection attempts were found and in the whole life of the server more tan 131000 SSH Access attempts were found:

From IP 183.3.202.187 we can see five failed SSH connection attempts on April 25th at 09:03. The fifth attempt was the access with user 'chris' reported previously on point 3. From that moment on hundreds of connections from that IP were done (As seen in previous image). When asked user 'chris', he/she told me that the password was identical to the username. So the attacker simply tried a number of users with the same passwords and finally he could Access the system. Apparently user chris had sudo permissions and the attacked could easily Access the system as root.

After being owned the server was accessed successfully 61 times from 7 different IP addresses. This is a summary of the connections:

  • April 25th, 09:03. With user root from IP 183.3.202.187. This same day another 16 SSH connections were done with user root from IPs: 183.3.202.187, 185.103.252.14, 110.10.129.201 and 89.248.167.131.
  • The next day, April 26th a total of 15 connections are found from IPs 183.3.202.187 and 110.10.129.201, in these connections the history shows that a package named FakeRoot is installed.
  • The next day, April 27th, another 16 root connections are done from IPs 183.3.202.187, 222.186.21.100 and 110.10.129.201.
  • The next day, April 28th, another 12 root connections from IPs: 183.3.202.187 and 100.43.129.140.

From that day no root connections are done. Actually no new connections are performed from strange IPs.



Location of these IPs

  • 183.3.202.187 ==> Guangzhou, Guangdong, China.
  • 185.103.252.14 ==> Moscu, Russia. .
  • 110.10.129.201 ==> Seoul, South Korea.
  • 89.248.167.131 ==> ¿?, The netherlands.
  • 222.186.21.100 ==> Nanjing, Jiangsu Sheng, China.
  • 100.43.129.140 ==> Orange, California, USA.

All but the last one had been previously reported as malicious IPs.



Actions performed by attacker in the system

  1. In the directory /root the following malicious files were found:
    • 2016ttfacai, ELF executable, 1223123 bytes, with date April, 2nd.
    • heifacai, ELF executable, 1223123 bytes. With date April 3rd, but with the same MD5 hash, so it seems a copy of the former file.
    • conf.n, 73 bytes. Apparently a config file for the previous executables, although it's a binary file.

    All three files were sent to virustotal. The report of the two first executablescan be seen in this link.

  2. In /etc/init.d a script file named DbSecuritySpt was found that actually executed /root/heifacai previously mentioned. This script was executed at every system restart therefore ensuring its presence in memory.
  3. In /etc/init.d another two files kzgbqvo and mowepretrf were found with similar contents.
  4. In /bin at least three different commands 'ps', 'ss' and 'netstat' were found with modification dates between 25th and 28th of April. When running 'ps' no strange process where found and when running 'netstat' no strange connections where found, so it seems that the have the been substituted by a modified copy of the executable. When removed these files, they automatically appeared again:

    After downloading the 'ps' and 'netstat' executables from internet, the malicious heifacai process appeared.

  5. Other malicious files were also found in the /bin directory (ovqbbgzk, kzgbbqvo, kzgbbqvo.sh)


Measures taken

Although eventually the system seemed to be cleaned, a recommendation of formatting and reinstalling the system was given to the owner. A speech of cybersecurity concientization was given to the users and in the newly installed system secure password policies were included.

martes, 26 de junio de 2018

Making softflowd plugin to send correct netflow input_snmp values in a pfsense 2.4.2

As stated in this Netgate fórum post (https://forum.netgate.com/topic/66214/softflowd-source-and-destination-interface-id-as-0/3), the softflowd plugin for pfsense sends netflow packets always in-snmp and out_snmp field with value 0.

Therefore one cannot determine if a flow comes from an interface or the other.

As explained in that post, you should modify the source code of softflowd to fix the problem. As we were working in a production environment, we decided to test this solution and found that it's not exactly how it's explained in that post.

In this post we'll explain how did we prepare a test environment, how did we test the solution given in netgate's forum and how did we apply our solution to our production environment.

1.- Preparing the test environment

I needed a test environment of our pfsense firewall with capabilities to modify source code from the softflowd plugin. I first installed the pfsense in a virtual machine and started trying to install development packages (gcc, make and so on). Soon I realized that it was not so simple to install all necessary development packages to a pfsense environment and decided to start again. Removed this VM and created two different VMs. A first one that had a pfsense environment which had the same OS and plugin versions as in the production environment. A second VM was used to install BSD 11.1-RELEASE-p4, the same version used by our pfsense v2.4.2 (see table in https://www.netgate.com/docs/pfsense/releases/versions-of-pfsense-and-freebsd.html).

After that, the necessary packages for development were installed in this freebsd VM (roughly autoconf, automake, gcc, libtool and m4 packages).

Next step comprised to find out which softflowd version was installed in our production firewall. The pfsense plugin manager showed versión 1.1:

However I could not find version 1.1 anywhere, the last version which I could find the source code was 0.99 ( https://code.google.com/archive/p/softflowd/downloads), so I had to settle for this v0.99, so I downloaded it, compiled it in the freebsd VM and copied it (only the executables softflowd and softflowctl) in my testing environment. They worked fine... still sending netflow packets with the 'in_snmp' field set to zero (as expected).

So it was true, It worked and I had to fix the source code. After barely one hour Reading the code I could understand how does it work. Mainly the problem comes with the plugin expecting a network interface with names like eth:1 or enscp:0 and the number sent in the in_snmp value is that "0" or "1" that goes after the semicolon. This is the original source code that makes it:

OK, but, what if the network interface's name does not include a semicolon?. What if the interface's name does not include a number at all?. The solution given in that fórum Works fine. It calculates a number by adding up the ascii values of network interface name. This is how I left the same source code snipplet:

As it can be seen, al the strsep/strtok staff is out and simply the for loop that calculates a 5 digit number is included. With that done, and after compiling (./configure, make and make install) we tested that the netflow messages sent from the testing envionment included both in_snmp and out_snmp (normal as later an out_snmp=in_snmp is done) with a five digit value:

The final step was to copy the executables (only softflowd and softflowctl) to the production pfsense. It worked fine at the first try.