tcp: strict RFC 5961 RST sequence validation (contributes to #1132)#13165
Open
ibondarenko1 wants to merge 1 commit into
Open
tcp: strict RFC 5961 RST sequence validation (contributes to #1132)#13165ibondarenko1 wants to merge 1 commit into
ibondarenko1 wants to merge 1 commit into
Conversation
handleReset in pkg/tcpip/transport/tcp/connect.go accepted any RST whose sequence number was within the advertised receive window (rcv.go:70-81 acceptable). The source comment cited RFC 793 page 37. With a 4 MB advertised window the per-packet probability of a blind off-path RST hitting an in-window sequence is roughly window/2^32 (about 0.1 percent). An off-path attacker that knows the 4-tuple could terminate an established TCP connection in a small number of packets. CVE-2024-10603 (commit cbdb2c6, 2023-11-10) added source-port randomization, which raised the practical cost by a factor of about 2^16. With both source-port randomization AND the existing window- based RST check, the joint per-packet blind probability is around window/2^48. The remaining gap is the RST acceptance rule itself. Rewrite handleReset to implement RFC 5961 section 3.2: * Segment sequence number out of window: silent drop. (Unchanged.) * Segment sequence number in window but not exactly equal to RCV.NXT: send a challenge ACK via the existing rate-limited helper e.snd.maybeSendOutOfWindowAck(s) and drop the segment. (New. Previously such a RST aborted the connection.) * Segment sequence number exactly equals RCV.NXT: accept and reset the connection. (Unchanged for legitimate peers.) The challenge ACK path reuses the same helper used by the existing RFC 5961 section 4.1 implementation at connect.go:1290-1312 (SYN-in-window). The rate-limit is provided by maybeSendOutOfWindowAck which already defends against the CVE-2016-5696 class of challenge-ACK side channels on the Linux side. Linux net/ipv4/tcp_input.c tcp_validate_incoming has implemented RFC 5961 section 3.2 since version 3.6 (2012). gVisor partially implements RFC 5961: section 4.1 is present, this PR adds section 3.2. Tests at pkg/tcpip/transport/tcp/test/e2e/handle_reset_rfc5961_test.go: * TestRFC5961_RSTOutOfWindowIsDropped (silent drop, unchanged) * TestRFC5961_RSTInWindowNotExactSendsChallengeAck (new behavior, challenge ACK observed via sniffer) * TestRFC5961_RSTExactMatchAbortsConnection (legitimate RST still aborts) Tested: bazel build //pkg/tcpip/transport/tcp:tcp bazel test //pkg/tcpip/transport/tcp/test/e2e:handle_reset_rfc5961_test bazel test //pkg/tcpip/transport/tcp/test/e2e:rcv_test Contributes to issue google#1132 (open since 2019-08); does not close it. Hardening, not an advisory: class is denial of service (off-path blind RST termination); Google VRP does not bounty DoS, and gVisor's published threat model does not claim RFC 5961 compliance. References: RFC 5961 section 3.2 (RST acceptance) RFC 5961 section 4.1 (SYN-in-window challenge ACK, connect.go:1290) Linux net/ipv4/tcp_input.c tcp_validate_incoming CVE-2016-5696 (Off-Path TCP Exploits, Cao et al., USENIX Sec 2016) CVE-2024-10603 (TCP source-port randomization, gVisor cbdb2c6)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contribution to issue #1132 (open since 2019-08, "Validate segment handling in Netstack as per RFC 793 page 69"). That issue documents the gap explicitly: "We also need to verify which parts have been updated by RFC5961 to make TCP robust against attacks." This PR adds RFC 5961 section 3.2 strict-match RST acceptance.
Problem
pkg/tcpip/transport/tcp/connect.gohandleResetaccepts any RST whose sequence number is within the advertised receive window (pkg/tcpip/transport/tcp/rcv.go:70-81acceptable). The source comment cites RFC 793 page 37.With a 4 MB advertised window the per-packet probability of a blind off-path RST hitting an in-window sequence is roughly
window / 2^32(~0.1 percent). An off-path attacker that knows the 4-tuple can terminate an established TCP connection in a small number of packets.CVE-2024-10603 (commit
cbdb2c61b1"Randomize TCP source port selection", 2023-11-10) already added source-port randomization, which raised the practical cost by a factor of ~2^16. With both source-port randomization AND the existing window-based RST check, the joint per-packet blind probability is ~window / 2^48. The remaining gap is the RST acceptance rule itself.RFC 5961 section 3.2
RFC 5961 section 3.2 tightens RFC 793 page 37:
Linux
net/ipv4/tcp_input.ctcp_validate_incominghas implemented this since version 3.6 (2012). gVisor partially implements RFC 5961: section 4.1 (SYN-in-window challenge ACK) is present atconnect.go:1290-1312, with an inline RFC 5961 link in the comment. Section 3.2 (RST strict-match) was the remaining gap that #1132 tracks.Change
handleResetis rewritten to RFC 5961 section 3.2:RCV.NXT: send a challenge ACK via the existing rate-limited helpere.snd.maybeSendOutOfWindowAck(s), then drop. (NEW.)RCV.NXT: accept and reset the connection. (Unchanged for legitimate peers.)The challenge ACK path reuses the same helper used by the existing RFC 5961 section 4.1 implementation in this same file. The rate-limit inside
maybeSendOutOfWindowAckalso defends against the CVE-2016-5696 class of challenge-ACK side channels.Tests
New file
pkg/tcpip/transport/tcp/test/e2e/handle_reset_rfc5961_test.goadds three focused regression tests:TestRFC5961_RSTOutOfWindowIsDropped(silent drop, unchanged path)TestRFC5961_RSTInWindowNotExactSendsChallengeAck(NEW behavior: no abort, challenge ACK observed via the test sniffer)TestRFC5961_RSTExactMatchAbortsConnection(legitimate RST still aborts)Local run:
Challenge-ACK behavior verified via the test sniffer:
RST at SEQ=1814 (in window, not equal to RCV.NXT=790) is answered with a challenge ACK at SND.NXT=854776498 / ACK=790, instead of a connection reset.
//pkg/tcpip/transport/tcp/test/e2e:rcv_testalso passes on this branch (independent verification that the receiver path is unchanged for non-RST segments).bazel build //pkg/tcpip/transport/tcp:tcpbuilds clean againstmaster.Framing
Hardening contribution. Class is denial of service (off-path blind RST termination of an established connection). Google VRP does not bounty DoS, and gVisor's published threat model does not claim RFC 5961 compliance. This PR is a Linux-parity uplift contributing to the existing open issue, not a security advisory.
References
net/ipv4/tcp_input.ctcp_validate_incoming(RFC 5961 section 3 since Linux 3.6, 2012)cbdb2c61b1, 2023-11)