Snort rule for ESP packets - security

I'm wondering whether it's possible to write a snort rule matching ESP packet with spoofed SPI value.
Packets I want to alert:
00:00:00.000000 IP x.x.x.x > x.x.x.x: ESP(spi=0x00000000,seq=0x29)
Raw packet would look something like this:
4500 XXXX XXXX XXXX XXXX -> 20 bytes of IP header
0000 0000 XXXX XXXX XXXX -> ESP header starting with 4 bytes of zeroes
XXXX...
That's why my best guess is trying to match by:
1) IP Proto equals ESP
2) raw bytes at the start of ESP header equals 0x00000000
So far I came up with this:
alert ip any any -> any any \
(ip_proto:esp; content: "|00 00 00 00|"; offset:0; depth: 4;)
Unfortunately, that doesn't work. I believe it's because Snort starts looking at 'content:' in the payload. I tried using pkt_data option to reset detection cursor to the start of transport layer. Per manual:
"pkt_data: This option sets the cursor used for detection to the raw transport payload"
I assumed it would fool snort to start 'content:' checking right after IP header. Unfortunately, no result.
Am I making a mistake here somewhere? Or is it just not possible for Snort to match by raw bytes in the ESP header? Any help/opinion would be greatly appreciated!

There is no good way to do this except to write your own preprocessor. Snort does not currently have anything that exposes the ESP spi value to the rules configuration language.
While it is true that there is support to decode ESP data, this still only exposes the decrypted payload to your rules.
To save you some trouble, byte_test might seem like a possibility, but it very specifically allows you to manipulate the payload only. For example, the following will not allow you to examine the UDP destination port in the header for 2049:
...byte_test:2,=,2049,-2,big;

Related

Why might Wireshark and NodeJS disagree about a packet's contents?

I'm working with raw-socket (a node module for sending raw data out on the network) and playing with their Ping example.
I have Wireshark set up to monitor traffic. I can see my ICMP packet go out, and a response comes back.
Here's where things get strange.
Wireshark shows the following packet:
IP: 4500003c69ea00004001e2fec0a85647c0a85640
ICMP: 00004b5200010a096162636465666768696a6b6c6d6e6f7071727374757677616263646566676869
However, the node event handler that fires when data comes in is showing:
IP: 4500280069ea00004001e2fec0a85647c0a85640
ICMP: 00004b5200010a096162636465666768696a6b6c6d6e6f7071727374757677616263646566676869
The ICMP components match. However, bytes 0x02 and 0x03 (the Length bytes) differ.
Wireshark shows 0x003c or 60 bytes (as expected).
Node shows 0x2800 or 10kB... which is not what is expected.
Notably, the checksum (bytes 0x18 and 0x19) are the same in each case, although it's only valid for the Wireshark packet.
So, here's the question: what might lead to this discrepancy? I'm inclined to believe Wireshark is correct since 60 bytes is the right size for an ICMP reply, but why is Node wrong here?
OSX note
The docs for this module point out that, on OSX, it will try to use SOCK_DGRAM if SOCK_RAW is not permitted. I have tried this with that function disabled and using sudo and got the same responses as before.
Github issue
It looks like https://github.com/nospaceships/node-raw-socket/issues/60 is open for this very issue, but it remains unclear if this is a code bug or a usage problem...
This is due to a FreeBSD bug (feature?) which subtracts the length of the IP header from the IP length header field and also flips it to host byte order.
https://cseweb.ucsd.edu//~braghava/notes/freebsd-sockets.txt

Send Modbus RTU request via TCP with Netcat and catch the response

Let's say I have a Modbus RTU temperature controller connected to a device that reads TCP packets from a network and sends the payload from said packets to the temperature controller over RS485. If I wanted to test such a setup by sending a Modbus RTU [Read Input Registers] request over TCP/IP using netcat on a Linux command line, what would be the full command for that, assuming that it is possible?
nc 192.168.0.5 2000 # ...what now?
Suppose that the following details apply:
device address: 1
function code: 3 (read input register)
memory address: 1000H
no. of registers: 1
server IP address: 192.168.0.5
client IP address: 192.168.0.4
Port on server: 2000
I feel like I can listen for the response using netcat, also. Could I just do that with:
nc -l 3456
Would that be right? To send a request and log the response like this, I guess I would have to specify the port to send the request on as 3456 (or whatever). Is there a way to do that?
Especially, I'm confused as to how to turn a Modbus message like [01][03][1000H][01][CRC] into its bytes equivalent.
Many thanks in advance.
You can send raw bytes with:
echo -e '\x04\x03...' | nc host port
Especially, I'm confused as to how to turn a Modbus message like [01][03][1000H][CNC] into its bytes equivalent.
That would be:
echo -e '\x01\x03\x10\x00...' | nc host port
I'm not going to calculate if for you because I see no point in doing something like this other than for fun.
You'll have to put all parts of the Modbus frame together, just google it. The most difficult part is to calculate the CRC at the end of the frame. I guess that's what you mean by CNC?
If you struggle I would suggest you try something like QModMaster. Look at the raw data with menu view► Raw Data and use those bytes.
Note that other than building the frames, QModMaster would be able to send them too and even listen for and receive responses. That should be your one-stop-shop for Modbus. You can also find many other tools like pymodbus, libmodbus, minimalmodbus and even command line tools for Windows and Linux.
If you edit your question to present a fair reason why you need to use nc (obviously other than for fun) maybe I can try to offer some more help.
I could not find any references on using netcat to send and/or receive Modbus frames. I'm not sure if that's because I did not search long enough or because it is pointless... Maybe it's both.
Should it be of use to anyone, the answer to this question is:
sudo echo -e -n '\x01\x03\x10\x00\x00\x01\x80\xCA' | nc 192.168.0.5 2000
-e allows the conversion of escaped chars
-n prevents a newline character being appended
Listening for incoming messages using Netcat doesn't work, apparently because the individual Netcat process wants to make the TCP connection itself, otherwise it isn't interested in anything arriving at the specified port. Still, I am able to see the reply coming back from the slave using Wireshark, and have also written to registers and successfully controlled the device.

Specify MTU value

I'm trying to pentest some IPSEC implementation for a uni project, and following this guide I'm stuck at:
Step 1 (common): Forging an ICMP PTB packet from the untrusted network The attacker first has to forge an appropriate ICMP PTB packet (a single packet is sufficient). This is done by eavesdropping a valid packet from the IPsec tunnel on the untrusted network. Then the attacker forges an ICMP PTB packet, specifying a very small MTU value equal or smaller than 576 with IPv4 (resp. 1280 with IPv6). The attacker can use 0 for instance. This packet spoofs the IP address of a router of the untrusted network (in case the source IP address is checked), and in order to bypass the IPsec protection mechanism against blind attacks, it includes as a payload a part of the outer IP packet that has just been eavesdropped. This is the only packet an attacker needs to send. None of the following steps involve the attacker.
I know what MTU is, but what does the bold statement mean?
How do I set the MTU size of a packet with scapy?
It means that I have to set the size of a IP packet less than 576 bytes?
It's already set to 140 B,at least it shows this with len command.
There's something that I didn't get right, maybe I have to set the fragmentation?
I know nothing about the subject, but some quick searching seems to indicate that it's referring to an IPv6 ICMP packet with a type of 2 ("packet too big").
Then from some poking around scapy, this appears to be how you'd create one:
from scapy.layers.inet6 import ICMPv6PacketTooBig
icmp_ptb = ICMPv6PacketTooBig(mtu=0)
Of course though, you'll need to do some testing to verify this.

Does Linux IPSEC support AH Transport with AES GMAC?

Could not figure out if linux kernel 4.4 supports IPSEC AH transport with AES GMAC.
Trying various combination of "ip xfrm state" command but no luck. Is this implemented ?
Try 1 sudo ip xfrm state add src 192.168.0.1 dst 192.168.0.2 proto ah spi 100 mode transport auth "rfc4106(gcm(aes))" 0x010203047aeaca3f87d060a12f4a4487d5a5c335 RTNETLINK answers: Function not implemented
Try 2 sudo ip xfrm state add src 192.168.0.1 dst 192.168.0.2 proto ah spi 100 reqid 100 mode transport aead "rfc4543(gcm(aes))" 0x010203047aeaca3f87d060a12f4a4487d5a5c335 128 ALGO-TYPE values "enc", "aead", and "comp" are invalid with XFRM-PROTO value "ah"
Based on the code, it does support the algorithm under the cipher name rfc4543(gcm(aes)) for ESP, but I'm not sure if it does for AH. I guess technically this is considered an AEAD, meaning it is an encryption cipher (for ESP, not AH which is only authentication without encryption) even though it is NULL encryption.

Purpose of the selector in ip xfrm state add [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 2 years ago.
Improve this question
What does the selector (parameter sel) in the "ip xfrm state add" command achieve?
The source and destination addresses (and additional parameters like ports and protocol) are set in the ID section, but the selector contains a supplementary set of these. Example:
ip xfrm state add src 10.0.0.1 dst 10.0.0.2 proto esp spi 123456 sel src 10.0.0.3 dst 10.0.0.4 enc blowfish 0xaabbccddee
This leads to the following result:
src 10.0.0.1 dst 10.0.0.2
proto esp spi 0x0001e240 reqid 0 mode transport
replay-window 0
enc cbc(blowfish) 0xaabbccddee
sel src 10.0.0.3/32 dst 10.0.0.4/32
Setkey seemingly does not have the opportunity to add such a selector value. It also does not show selectors in the output. The xfrm command from above produces the following "setkey -D" output:
10.0.0.1 10.0.0.2
esp mode=transport spi=123456(0x0001e240) reqid=0(0x00000000)
E: blowfish-cbc aabbccdd ee
seq=0x00000000 replay=0 flags=0x00000000 state=mature
created: Nov 26 01:25:39 2013 current: Nov 26 01:26:07 2013
diff: 28(s) hard: 0(s) soft: 0(s)
last: hard: 0(s) soft: 0(s)
current: 0(bytes) hard: 0(bytes) soft: 0(bytes)
allocated: 0 hard: 0 soft: 0
sadb_seq=0 pid=6959 refcnt=0
So what does the IPsec subsystem eventually do with this selector?
It is probably straight from the IPsec standard (RFC 4301: Security Architecture for the Internet Protocol).
Probably is because the standard describes "nominal model" i.e. implementations do not have to be exactly as described.
In Section 4.4.2. Security Association Database (SAD):
For each of the selectors defined in Section 4.4.1.1, the entry for an inbound SA in the SAD MUST be initially populated with the value or values negotiated at the time the SA was created. ... For a receiver, these values are used to check that the header fields of an inbound packet (after IPsec processing) match the elector values negotiated for the SA. Thus, the SAD acts as a cache for checking the selectors of inbound traffic arriving on SAs. For the receiver, this is part of verifying that a packet arriving on an SA is consistent with the policy for the SA.
In Section 5.2. Processing Inbound IP Traffic (unprotected-to-protected):
IPsec MUST perform the following steps:
...
3a. If the packet is addressed to the IPsec device and AH or ESP is specified as the protocol, the packet is looked up in the SAD. ... If the packet is found in the SAD, process it accordingly (see step 4).
4. Apply AH or ESP processing as specified, using the SAD entry selected in step 3a above. Then match the packet against the inbound selectors identified by the SAD entry to verify that the received packet is appropriate for the SA via which it was received.
5. If an IPsec system receives an inbound packet on an SA and the packet's header fields are not consistent with the selectors for the SA, it MUST discard the packet.
In short for your example
ip xfrm state add src 10.0.0.1 dst 10.0.0.2 proto esp spi 123456 sel src 10.0.0.3 dst 10.0.0.4 enc blowfish 0xaabbccddee
when IPsec (ESP in this case) packet arrives at the server, then probably the following happens:
the part src 10.0.0.1 dst 10.0.0.2 proto esp spi 123456 is used to find the corresponding SA.
The SA is used to decrypt the packet's payload.
Payload in transport mode IPsec is another IP packet.
the part sel src 10.0.0.3 dst 10.0.0.4 is the selector from the SP which was used to create our SA.
This selector is applied to the inner IP packet to verify that it is consistent with the SP.
Selector is used in tunnel mode. i.e. networks that are (inter)connected by tunnel.

Resources