<?xml version="1.0" encoding="utf-8"?>
<?xml-model href="rfc7991bis.rnc"?> 

<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>

<rfc
  xmlns:xi="http://www.w3.org/2001/XInclude"
  category="std"
  docName="draft-pan-tcpm-tcp-ghost-acks-00"
  ipr="trust200902"
  obsoletes=""
  updates=""
  submissionType="IETF"
  xml:lang="en"
  version="3">

  <front>
    <!-- <title abbrev="Abbreviated Title">Improving TCP handling of Out-of-Window Packets</title>  -->
    <title abbrev="Ghost ACKs Mitigation">Improve TCP Handling of Out-of-Window Packets to Mitigate Ghost ACKs</title>
    <seriesInfo name="Internet-Draft" value="draft-pan-tcpm-tcp-ghost-acks-00"/> 
  
    <author fullname="Yepeng Pan" initials="Y." surname="Pan"> 
      <organization>CISPA Helmholtz Center for Information Security</organization> 
      <address>
        <email>yepeng.pan@cispa.de</email>
      </address>
    </author>
    <author fullname="Christian Rossow" initials="C." surname="Rossow">
        <organization>CISPA Helmholtz Center for Information Security</organization>
        <address>
        <email>rossow@cispa.de</email>
      </address>
    </author>

    <date year="2024" month="7" day="8"/> 

    <area>Transport</area>
    <workgroup>TCPM</workgroup>
    <keyword>TCP</keyword>
    <keyword>TCPM</keyword>
    <keyword>transport layer</keyword>
    <keyword>internet transport</keyword>
    <!-- 
    I will not discuss the TCP TCP spoofing/injection attacks in detail,
    People could refer to RFC 5961 for the motivation of streghten acceptable ACK value validation.
    The aim of the RFC draft is thus: to prevent TCP from accepting invalid ACK values.
   -->
    <abstract pn="section-abstract">
      <t indent="0" pn="section-abstract-1">
        Historically, TCP as specified in RFC 793 was threatened 
        by the blind data injection attack because of the loose acceptable ACK value validation, where the ACK value of a 
        data segment is considered valid as long as it does not acknowledge data ahead of the next segment to send.
        RFC 5961 improved the defect by 
        shrinking the range of acceptable ACK values in a data segment. Later, RFC 9293
        involved the updates proposed by RFC 5961 as a TCP stack implementation option.<br></br>

        However, an endpoint that follows the RFC 9293 specifications can still accept a data segment containing 
        an ACK value acknowledging data that the endpoint has never sent. This document specifies small modifications to the 
        way TCP verifies incoming data segments' ACK value to prevent TCP from accepting invalid ACK values.
      </t>
    </abstract>
  </front>

  <middle>
    <section>
      <name>Introduction</name>
      <t>
        TCP as specified in <xref target="RFC0793"/> is widely deployed in today's Internet. 
        Against the threat of the blind data injection attack, <xref target="RFC5961"/> 
        section 5 proposed to improve the validation of data segments with duplicate/old ACK values.
        <!-- However, the ACK validation proposed by RFC 5961 fails for newly established TCP connections 
        where there is no data acknowledged previously by the peer (unless data is already sent during the handshake), 
        and thus duplicate/old ACK values shall not be accepted. -->
        Currently, <xref target="RFC9293"/> is the latest main document for TCP, which obsoletes <xref target="RFC0793"/> and involves the ACK validation proposed by <xref target="RFC5961"/>
        as an optional implementation choice.

        ACK validation introduced in <xref target="RFC9293"/> (with or without the <xref target="RFC5961"/> implementation choice) 
        accepts a certain range of ACK values before SND.UNA as duplicate/old ACK values.
        This also applies to connections without data (or with little data) transferred previously.
        Consequently, current ACK validation accepts segments with invalid ACK values that acknowledge data that a server has never sent as "duplicate/old" ACK values (ghost ACKs).
        <br></br>


        This document aims to improve the ACK value validation 
        in <xref target="RFC9293"/>, 
        such that TCP would only accept duplicate/old ACK values acknowledging data already sent by the endpoint, eliminating the security risks imposed by ghost ACKs. 
      </t>
      
      <section anchor="Terminology">
      <!-- anchor is an optional attribute -->
        <name>Terminology</name>
        <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>",
        "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL NOT</bcp14>",
        "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>",
        "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
        "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to
        be interpreted as described in
        BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when,
        they appear in all capitals, as shown here.</t>
        <t>TCP terminology should be interpreted as described in <xref target="RFC9293"/>. 
        </t>
      </section>
      <!-- The 'Requirements Language' section is optional -->
    </section>
    
    <section>
      <name>Ghost ACKs</name>
      <t>
      As described in <xref target="RFC9293"/>, when receiving a segment, 
      the endpoint performs checks on the ACK field of the incoming segment.
      
      Suppose the TCP stack has implemented the mitigation for blind data injection attack proposed by Section 5 of <xref target="RFC5961"/>, 
      an incoming segment whose ACK value satisfies the condition SND.UNA - MAX.SND.WND =&lt; SEG.ACK =&lt; SND.NXT is considered acceptable, 
      and the segment is further processed.
      
      When the <xref target="RFC5961"/> mitigation is not implemented, an incoming segment with SND.UNA - (2<sup>31</sup> - 1) =&lt; SEG.ACK =&lt; SND.NXT is accepted and further processed.
      </t>

      <t>
      <!-- However, for a newly established TCP connection, assuming there is no data transferred during the handshake, 
      there is SND.UNA == SND.NXT == ISS + 1.
      However, in this case, the above acceptable ACK value condition also accepts ACK vlues before ISS+1, 
      which represents data that the endpoint has never sent. -->

      <!-- 
        I decide to avoid discussing early data tranmission in handshake phase. 
        In the end, the accpetable ACK conditions introduced in the following section should apply to the early data case.
        The early data should only affect the SND.UNA initial value discussion here.
      -->

      However, there are cases where the number of bytes sent by the endpoint is less than MAX.SND.WND or 2<sup>31</sup> - 1, and this can result in
      accepting a segment with an ACK value acknowledging bytes the endpoint has never sent.<br/>

      As a concrete example, consider a newly established TCP connection without data transferred during the handshake.
      There is SND.UNA == SND.NXT == ISS + 1. 
      In this case, any segments with SEG.ACK &lt; SND.UNA acknowledges bytes that the endpoint has never sent, but they are still considered acceptable
      since they satisfy the above ACK validation condition.



    </t>
    </section>


    <section>
      <name>Security Implications of Ghost ACKs</name>

      <t>
        Ghost ACKs allow an attacker to inject payloads into a newly established connection.
        This extends the threat model as described in <xref target="RFC5961"/>, where an off-path attacker can perform injection attacks against an existing foreign connection.
        Ghost ACKs further allow attackers that spoof the TCP handshake to use the spoofed TCP connection and transmit payloads <xref target="SP2024Spoof" format="default" sectionFormat="of" derivedContent="1"/>.
      </t>

    </section>

    <section>
      <name>Mitigation</name>
      <t>
      TCP stacks <bcp14>MAY</bcp14> implement one of the following two mitigations.
      </t>
      <!--  I'm planning to give two choices, one from *bsd one from linux

      1. One could save the ISS number and a wraparound flag. 
      Before wraparound, check whether the ISS+1 is larger than incoming segment's ACK value.

      2. Another option is to save the number of bytes acknowledged by peer. 
      only accept ACK value within SND.UNA - min(MAX.SND.WND,bytes_acked) =< SEG.ACK =< SND.NXT

      -->
      
      <dl newline="true" spacing="normal" indent="8">
          <dt>Mitigation Option 1 (generic):</dt>
          <dd>
            TCP stacks that implement this mitigation <bcp14>MUST</bcp14> add an additional state variable for each established connection, ISS_CHECK_NOT_REQUIRED.
            <!-- to track whether the current SND.UNA wraps around the ISS number. -->
            When validating the ACK value of any incoming segments, TCP stacks that implement this mitigation <bcp14>MUST</bcp14> add an additional input check ISS_CHECK_NOT_REQUIRED || SND.UNA =&lt; SEG.ACK  || ISS + 1 =&lt; SEG.ACK.
            The first part of the condition checks if the ISS comparison is required, more details regarding the ISS_CHECK_NOT_REQUIRED state follow later.
            <!-- (a) ISS has been (almost/half) wrapped by SND.NXT (==> no more ghost ACKs are possible for any MAX.SND.WND <= 2^31), or -->
            When ISS comparison is required, the second part of the condition verifies if the segment acknowledges unacknowledged data (no ghost ACKs by definition).
            If not, the last part of the condition verifies whether the segment's ACK value is after ISS, which guarantees no ghost ACKs are accepted.
            <!-- (b) no wrap yet, ACK for unacknowledged data (no ghost ACKs by definition)
            (c) no wrap yet, ACK for data past the ISS (no ghost ACKs by definition), or -->
            Segments with ACK values satisfying the above condition are further validated and processed as specified in <xref target="RFC9293"/>.
            <!-- the addiontal input chekc only verifies whether SEG.ACK >= ISS+1, original checks regarding SND.NXT and SND.UNA shall still be applied -->
            Otherwise, the incoming segment <bcp14>MUST</bcp14> be discarded and a challenge ACK sent back.
            <!-- In principle, our statement shall be similar to RFC 5961. The only difference is that now we need add an additional input check.
            But regarding the last sentence, "the incoming segment MUST be discarded and an ACK sent back",
            this is not true if the connection is in SYN_RECV state, rather we should send a reset back.
            But anyway, I think I should phrase the statement as per RFC 5961  -->
            <br></br>
            
            <!-- There are several cases we don't care
            1. ISS_CHECK_NOT_REQUIRED = TRUE, ISS already wrapped around, original validation proposed by RFC 5961 and 9293 shall be enough to capture invalid ack values
            2. SEG.ACK >= SND.UNA, this ACK is not an old/duplicate ACK, so not our concern (invalid ACK shall be captured by other conditions in RFC 9293)
            -->
            
            When a connection is initialized, ISS_CHECK_NOT_REQUIRED is set to false.
            Once the SND.UNA satisfies condition SND.UNA != ISS &amp;&amp; ISS + 1 =&lt; SND.UNA - (2<sup>31</sup>-1), ISS_CHECK_NOT_REQUIRED is set to true.
            When the current send window meets the above condition, any acceptable old ACK values are after ISS, and thus no ghost ACKs by definition.
            In this case, the original <xref target="RFC9293"/> specification is enough to validate the ACK value.

            <!-- During the handshake, there can be SND.UNA=ISS (endpoint send syn but hasn't received ACK to the SYN yet)
            we don't want to flip the flag at this time -->
            <!-- When ISS_CHECK_NOT_REQUIRED is true, the above ACK validation for whether ISS+1 =&lt; SEG.ACK can be skipped, and the ACK validation in RFC 9293 can be applied directly. -->
            <!-- As in this case, any acceptable ACK values by RFC 9293 also satisfy ISS+1 =&lt; SEG.ACK.  -->
            <!--  This should be enough,  when the snd.una is already 2G away from the ISS+1, any acceptable ACK number by RFC 793 and RFC 5961 should also have ISS+1<=SEG.ACK (or more precisely, they should all represents bytes already sent)
            SND.UNA - (2^31-1) is the last old ack number possibly acceptable to RFC 793 and RFC 5961, if this number is already larger than ISS+1, then there is no risk of acknowleding
            something beofre ISS+1 in the future
            -->


          </dd>
          

          <dt>Mitigation Option 2 (assumes <xref target="RFC4898"/> support)</dt>
          <dd>
            TCP stacks that implemented the <xref target="RFC4898"/> tcpEStatsAppHCThruOctetsAcked statistics, which tracks the number of bytes that are already acknowledged by the peer, can adopt this option.<br></br> 
            To implement this mitigation, TCP stacks <bcp14>MUST</bcp14> add the SND.UNA - min(MAX.SND.WND, tcpEStatsAppHCThruOctetsAcked) =&lt; SEG.ACK input checks for ACK values of any incoming segments.
            Segments with ACK values satisfying the above condition are further validated and processed as specified in <xref target="RFC9293"/>.
            Otherwise, the segment <bcp14>MUST</bcp14> be discarded and an ACK sent back.
            For TCP stacks that do not implement the <xref target="RFC5961"/> ACK validation, MAX.SND.WND should be replaced with 2<sup>31</sup> - 1.
            <!-- For TCP stacks that implement this mitigation, depending on whether the RFC 5961 section 5 ACK validation is implemented, 
            TCP stacks MUST add one of the two following input checks for ACK values of any incoming segments. <br></br>
            
            When the RFC 5961 validation is implemented, the TCP stack MUST add input check SND.UNA - min(MAX.SND.WND, tcpEStatsAppHCThruOctetsAcked) =&lt; SEG.ACK. <br></br>            
            When the RFC 5961 validation is not implemented, the TCP stack MUST add input check SND.UNA - min((2^31) - 1, tcpEStatsAppHCThruOctetsAcked) =&lt; SEG.ACK. <br></br>
            Segments with ACK values satisfying the above condition are further validated and processed as specified in RFC 9293.
            Otherwise, the segment MUST be discarded and an ACK sent back. <br></br> -->
          </dd>
      </dl>


    </section>


    
  </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.0793.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4898.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5961.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9293.xml"/>

      </references>
 
      <references>
        <name>Informative References</name>             
          <reference anchor="SP2024Spoof" target="https://doi.ieeecomputersociety.org/10.1109/SP54263.2024.00182">
            <front>
              <title>TCP Spoofing: Reliable Payload Transmission Past the Spoofed TCP Handshake</title>
              <author initials="Y." surname="Pan" fullname="Y. Pan"></author>
              <author initials="C." surname="Rossow" fullname="C. Rossow"></author>
              <date year="2024" month="may"></date>
            </front>
            <seriesInfo name="DOI" value="10.1109/SP54263.2024.00182"></seriesInfo>
          </reference>
      </references>
    </references>
    
    <!-- <section>
      <name>Appendix 1</name>
      <t>This becomes an Appendix</t>
    </section> -->

    <section anchor="Acknowledgements" numbered="false">
      <!-- an Acknowledgements section is optional -->
      <name>Acknowledgements</name>
      <t>This template uses extracts from templates written by Pekka Savola, Elwyn Davies and 
        Henrik Levkowetz.</t>
      <t>We thank Eric Dumazet for proposing the second mitigation option using tcpEStatsAppHCThruOctetsAcked.</t>
      <!-- Maybe I should also add an acknowledgment for *BSD developers, they provide one possible implementation for the 1nd mitigation option in *BSD systems' netfilter -->
    </section>
    
    <!-- <section anchor="Contributors" numbered="false">
      
      <name>Contributors</name>
      <t>Thanks to all of the contributors.</t>
      <contact fullname="Jane Doe" initials="J" surname="Doe">
        
        <organization>Acme</organization>
        <address>
          <email>jdoe@example.com</email>
        </address>
      </contact>
    </section> -->
    
 </back>
</rfc>
