Bug 1531135 (CVE-2017-18017) - CVE-2017-18017 kernel: netfilter: use-after-free in tcpmss_mangle_packet function in net/netfilter/xt_TCPMSS.c
Summary: CVE-2017-18017 kernel: netfilter: use-after-free in tcpmss_mangle_packet func...
Keywords:
Status: CLOSED ERRATA
Alias: CVE-2017-18017
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard:
: 1542309 (view as bug list)
Depends On: 1531136 1543088 1543089 1543090 1543091 1543092 1543093 1543094 1568854
Blocks: 1531138
TreeView+ depends on / blocked
 
Reported: 2018-01-04 16:15 UTC by Pedro Sampaio
Modified: 2022-03-13 14:37 UTC (History)
56 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
The tcpmss_mangle_packet function in net/netfilter/xt_TCPMSS.c in the Linux kernel before 4.11, and 4.9.x before 4.9.36, allows remote attackers to cause a denial of service (use-after-free and memory corruption) or possibly have unspecified other impact by leveraging the presence of xt_TCPMSS in an iptables action. Due to the nature of the flaw, privilege escalation cannot be fully ruled out, although we believe it is unlikely.
Clone Of:
Environment:
Last Closed: 2018-05-29 12:47:53 UTC
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2018:0676 0 None None None 2018-04-10 08:16:55 UTC
Red Hat Product Errata RHSA-2018:1062 0 None None None 2018-04-10 09:40:46 UTC
Red Hat Product Errata RHSA-2018:1130 0 None None None 2018-04-17 16:23:35 UTC
Red Hat Product Errata RHSA-2018:1170 0 None None None 2018-04-17 15:32:57 UTC
Red Hat Product Errata RHSA-2018:1319 0 None None None 2018-05-08 19:00:15 UTC
Red Hat Product Errata RHSA-2018:1737 0 None None None 2018-05-29 18:51:02 UTC

Description Pedro Sampaio 2018-01-04 16:15:31 UTC
The tcpmss_mangle_packet function in net/netfilter/xt_TCPMSS.c in the Linux kernel before 4.11, and 4.9.x before 4.9.36, allows remote attackers to cause a denial of service (use-after-free and memory corruption) or possibly have unspecified other impact by leveraging the presence of xt_TCPMSS in an iptables action. Due to the nature of the flaw, privilege escalation cannot be fully ruled out, although we believe it is unlikely.

References:

https://lkml.org/lkml/2017/4/2/13

https://marc.info/?t=149111917600001&r=1&w=2

http://patchwork.ozlabs.org/patch/746618/

An upsteam patch:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2638fd0f92d4397884fd991d8f4925cb3f081901

Comment 1 Pedro Sampaio 2018-01-04 16:16:35 UTC
Created kernel tracking bugs for this issue:

Affects: fedora-all [bug 1531136]

Comment 2 Justin M. Forbes 2018-01-05 12:52:52 UTC
This was fixed for all Fedora releases with the 4.11 kernel series.

Comment 3 Marcelo Ricardo Leitner 2018-02-06 23:58:05 UTC
*** Bug 1542309 has been marked as a duplicate of this bug. ***

Comment 14 Vladis Dronov 2018-02-07 17:40:19 UTC
Statement:

This issue affects the Linux kernel packages as shipped with Red Hat Enterprise Linux 5. This is not currently planned to be addressed in future updates of the product due to its life cycle. For additional information, refer to the Red Hat Enterprise Linux Life Cycle: https://access.redhat.com/support/policy/updates/errata/.

This issue affects the versions of the Linux kernel as shipped with Red Hat Enterprise Linux 6, 7, its real-time kernel, Red Hat Enterprise MRG 2, Red Hat Enterprise Linux 7 for ARM 64 and Red Hat Enterprise Linux 7 for Power 9 LE. Future Linux kernel updates for the respective releases may address this issue.

Comment 18 errata-xmlrpc 2018-04-10 08:16:35 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 7

Via RHSA-2018:0676 https://access.redhat.com/errata/RHSA-2018:0676

Comment 19 errata-xmlrpc 2018-04-10 09:40:27 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 7

Via RHSA-2018:1062 https://access.redhat.com/errata/RHSA-2018:1062

Comment 20 errata-xmlrpc 2018-04-17 15:32:34 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise MRG 2

Via RHSA-2018:1170 https://access.redhat.com/errata/RHSA-2018:1170

Comment 21 errata-xmlrpc 2018-04-17 16:23:12 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 7.4 Extended Update Support

Via RHSA-2018:1130 https://access.redhat.com/errata/RHSA-2018:1130

Comment 23 errata-xmlrpc 2018-05-08 18:59:53 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 6

Via RHSA-2018:1319 https://access.redhat.com/errata/RHSA-2018:1319

Comment 26 Vladis Dronov 2018-05-15 11:13:10 UTC
the detailed security impact analysis of the flaw

a packet from a network can get to net/netfilter/xt_TCPMSS.c:tcpmss_mangle_packet() which contains this flaw. the simple way to do this is to set an iptables rule like this:

# iptables -t mangle -A PREROUTING -i <intf> -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1380

doff is a 4-bit field in the tcp header, is measured in quad-words (4 bytes) and stands for the "data offset":

struct tcphdr {
        __be16  source;
        ...
        __u16   res1:4,
                doff:4,
                ...

tcphdr->doff*4 points to an end of TCP options i.e. beginning of the packet data. the data offset is counted from the beginning of a tcp header, so normally it should be >= 5, as the size of a mandatory tcp header is 20 bytes.

a packet from a network forged by an attacker can have the doff field set to zero, and this is the reason of the flaw. exactly this case is handled by the first change in the patch: it is checked that tcp_hdrlen (which is set to tcph->doff*4) is more or equal than a size of a mandatory tcp header:

-       if (len < tcp_hdrlen)
+       if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr))
                return -1;

without this patch the flaw itself is a use-after-free due to an out-of-bound-access due to a missing input validation (i.e. without the tcp_hdrlen check above) and erroneous signed/unsigned compare. it happens in the following code when a forged packet with doff=0 gets to the tcpmss_mangle_packet():

static int tcpmss_mangle_packet(struct sk_buff *skb, ...
{       ...
        int len, tcp_hdrlen;
        unsigned int i;
        ...
        tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); // this is a tcp header
        tcp_hdrlen = tcph->doff * 4; // forged tcp_hdrlen may be 0 here
        ...
        opt = (u_int8_t *)tcph; // opt also points to a tcp header
        for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) {
                if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) { ... }

in this loop i starts with 20, sizeof(struct tcphdr). in case forged tcph->doff is 0, tcp_hdrlen is also zero and so signed subtraction "tcp_hdrlen - TCPOLEN_MSS" is -4 (32 bits 0xfffffffc). but i is unsigned, and so i is less than (2^32-4). thus the loop keeps looping until i reaches (2^32-4) or until it finds a 0x02/0x04 (TCPOPT_MSS/TCPOLEN_MSS) byte sequence. in the unlucky case depending on memory content i can overflow and the loop can run forever.

after i exceeds size of a socket buffer (tcp header + data), opt[i] and opt[i+1] will start to access out-of-bound data beyond a socket buffer. these reads would lead to use-after-free errors detected by KASAN in case there were kernel memory which was freed previously. also this loop can corrupt a memory content outside of a socket buffer by writing a new MSS value to a place considered as TCPOPT_MSS tcp option:

                        oldmss = (opt[i+2] << 8) | opt[i+3];
                        if (oldmss <= newmss)
                                return 0;
                        opt[i+2] = (newmss & 0xff00) >> 8;
                        opt[i+3] = newmss & 0x00ff;

this corruption is quite restricted:
- there should be bytes 0x02/0x04 (TCPOPT_MSS/TCPOLEN_MSS) in a memory after a socket buffer
- 2 bytes after them are set to the newmss which is not controlled by an attacker, but is set by a system administration in the iptables rule
- this newmss should be less than oldmss (previous value of these 2 bytes)

while theoretically this overwrite may lead to some significant security impact, the overwrite is not controlled by the attacker and conditions for it are quite restricted and so we assume that privileges escalation is unlikely. a system denial-of-service is very likely due to a system crash or a kernel execution thread stuck on looping for 4G of memory for tens of seconds. also a silent memory corruption is likely and we consider this as a biggest real security impact.

it also can be that tcph->doff is 15 in a forged or normal tcp packet processed by tcpmss_mangle_packet(). in this case doff can wrap and become zero by:

        tcph->doff += TCPOLEN_MSS/4;

the later case is handled by the second change in the patch:

+	/* tcph->doff has 4 bits, do not wrap it to 0 */
+	if (tcp_hdrlen >= 15 * 4)
+		return 0;

without this patch a packet with wrapped doff=0 or a forged packet with doff=0 from the previous case can get further down the execution path. this condition is checked on the entry to the tcp part of the network stack in net/ipv4/tcp_ipv4.c:tcp_v4_rcv() or in net/ipv6/tcp_ipv6.c:tcp_v6_rcv():

int tcp_v4_rcv(struct sk_buff *skb)
{       ...
        if (th->doff < sizeof(struct tcphdr) / 4)
                goto bad_packet;

static int tcp_v6_rcv(struct sk_buff *skb)
{       ...
        if (th->doff < sizeof(struct tcphdr)/4)
                goto bad_packet;

such erroneous packets are dropped and so cannot cause a security impact.

Comment 27 errata-xmlrpc 2018-05-29 18:50:38 UTC
This issue has been addressed in the following products:

  Red Hat Enterprise Linux 7.3 Extended Update Support

Via RHSA-2018:1737 https://access.redhat.com/errata/RHSA-2018:1737


Note You need to log in before you can comment on or make changes to this bug.