Does Linux IPSEC support AH Transport with AES GMAC? - linux

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.

Related

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.

Kernel API to know up address of interface

Is there any kernel side/space API to know the ip address of an interface , given it's name?
I think you're looking for rtnetlink (man page)
Rtnetlink allows the kernel's routing tables to be read and altered.
It is used within the kernel to communicate between various
subsystems, though this usage is not documented here, and for
communication with user-space programs. Network routes, IP addresses,
link parameters, neighbor setups, queueing disciplines, traffic
classes and packet classifiers may all be controlled through
NETLINK_ROUTE sockets.
According to strace, tt's the api ip addr show dev XXX uses:
strace ip addr sh dev lo 2>&1 | grep sendmsg
sendmsg(4, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=48, type=RTM_GETLINK, flags=NLM_F_REQUEST, seq=1596838225, pid=0}, {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0}, [{{nla_len=8, nla_type=IFLA_EXT_MASK}, 9}, {{nla_len=7, nla_type=IFLA_IFNAME}, "lo"}]}, iov_len=48}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 48
sendmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=40, type=RTM_GETLINK, flags=NLM_F_REQUEST, seq=1596838225, pid=0}, {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=if_nametoindex("lo"), ifi_flags=0, ifi_change=0}, {{nla_len=8, nla_type=IFLA_EXT_MASK}, 9}}, iov_len=40}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 40
However, it looks like a non-trivial api so if you don't need it often, it might be easier to just run ip addr sh dev XXX and parse the response.
Edit:
Looks like it's also possible using netdevice (man page), specifically, the SIOCGIFADDR ioctl:
SIOCGIFADDR, SIOCSIFADDR
Get or set the address of the device using ifr_addr. Setting the interface address is a privileged operation. For compatibility, only
AF_INET addresses are accepted or returned.
There's example code here

Snort rule for ESP packets

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;

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.

Modify linux protocol table

For some reason I need to change linux protocol table. For example I want to linux recognize protocol 1 as ipv4 (protocol 4) or protocol 47 to l2tp .
Does anyone know how to change this inside linux kernel or preferably in /sys folder, So my client send protocol tcp as an icmp protocol and in other side it receive icmp and recognize it as tcp.
thanks,
Protocol numbers are defined in include/uapi/linux/in.h. Exercise great caution when changing stuff there, you will make your OS incompatible with practically everything else there is out there.
edit: Watch out for drivers that blatantly ignore the value of IPPROTO_TCP in favor of hardcoded values... I just found this 'gem' in drivers/infiniband/hw/nes/nes_cm.c:
451 iph->protocol = 0x06; /* IPPROTO_TCP */

Resources