TCP重置攻击如何工作

使用大小不超过几个字节的单个数据包执行TCP重置攻击。由攻击者创建和传输的由欺骗代替的TCP段欺骗了两个受害者终止TCP连接,中断了它们之间的连接,这可能很关键。


这种攻击在现实世界中产生了后果。对TCP协议本身的更改引起了对它的使用的担心。据信,该攻击是“中国大防火墙”(金盾)的重要组成部分,中国政府使用该防火墙对中国境外的互联网进行审查。尽管她有令人印象深刻的背景,但了解这种攻击背后的机制并不一定需要深入了解TCP。当然,了解它的精妙之处可以教会您很多有关实施TCP协议的功能,并且,正如我们很快将看到的,您甚至可以只用一台笔记本电脑对自己进行这种攻击。

在这篇文章中,我们:

  • 学习TCP基础知识
  • 了解攻击的工作原理。
  • 让我们用一个简单的Python脚本对自己进行攻击。

在开始分析攻击机制之前,让我们首先了解一下它在现实世界中的用法。

防火墙中如何使用TCP重置攻击?


长防火墙(GFW)是中国政府用来审查内部中国用户互联网的一套系统和技术。GFW主动阻止和断开与该国家/地区内外服务器的连接,并被动监视受禁止内容的Internet通信。

为了防止用户甚至连接到受禁服务器,GFW使用了DNS污染IP阻止等技术(它们都需要单独撰写文章)。但是,有时需要允许GFW防火墙建立连接,然后在中间断开连接。例如,如果要对连接执行缓慢的,挂起的分析(例如,它与其他操作的关联),则这是必需的。或者,如果防火墙需要分析在连接过程中交换的数据,然后使用此信息来决定是继续还是阻止它,则使用它。例如,新闻网站的流量可能被允许,但是包含禁止关键字的视频将被审查。

为此,GFW需要能够中断已经建立的连接的工具。TCP重置攻击就是这样一种工具。

TCP重置攻击如何起作用?


在TCP重置攻击中,攻击者断开两个受害者之间的连接,发送一条或两条伪造消息,告诉他们立即断开连接。这些消息称为TCP重置段。在没有攻击者参与的正常操作中,计算机在接收到意外的TCP流量并希望发送方停止发送时会发送TCP丢弃段。

TCP重置攻击恶意利用了这种机制,诱使受害者过早地终止TCP连接,向其发送伪造的重置段。如果正确设置了错误的重置段,则接收者会将其用作真实段,并关闭其连接部分,从而中断有关此连接的信息的进一步传输。为了继续进行数据交换,受害者可以尝试创建新的TCP连接,但是攻击者可能有机会重置此新连接。幸运的是,由于攻击者需要时间来构建和发送伪造的数据包,因此丢弃攻击实际上仅对长期连接有效。短期连接。例如,用于传输小型网页,通常有时间按时完成任务攻击者何时才能重置它们。

从某种意义上说,发送伪造的TCP段是一个简单的过程,因为TCP和IP都没有自己的验证发送方身份的方式。有一个称为IPSec的IP扩展可提供身份验证,但使用范围不广。 Internet服务提供商必须拒绝传输来自明显错误的IP地址的IP数据包,但是据称此检查非常平庸。接收者所能做的就是以数据包或段中的源IP地址和端口为准,并尽可能使用更高级别的协议(例如TLS)来识别发送者。但是,由于TCP转储数据包本身是TCP协议的一部分,因此无法使用这些高级协议进行验证。

尽管发送假段很简单,但制作假段并执行成功的TCP重置攻击仍然是一项艰巨的任务。要了解为什么会发生这种情况,我们需要了解TCP协议的操作。

TCP如何工作


TCP协议的目的是向接收方发送数据块的精确副本。例如,如果我的服务器通过TCP将HTML发送到您的计算机,则计算机的TCP堆栈(其操作系统中处理TCP的部分)应以与服务器发送它的形式和顺序完全相同的形式输出HTML。


但是,我的HTML并不是以这种完美的顺序在Internet上传输的。它分为许多小片段(称为TCP片段),每个片段都通过Internet单独传输,并由计算机的TCP堆栈按传输顺序重新创建。恢复的输出称为TCP流。每个TCP段都是在其自己的IP数据包中传输的,但是,要了解这种攻击,我们无需了解有关IP的任何详细信息。


将段转换为流需要特别小心,因为Internet不可靠。TCP段可能会丢失。它们可能会故障,发送两次,损坏并经历许多其他灾难。因此,TCP协议的目的是确保在不可靠的网络上进行可靠的数据传输。TCP执行此任务,要求连接双方保持彼此之间的紧密联系,并不断发送有关接收到哪些数据块的信息。这使发件人可以了解收件人尚未收到的数据,并重新传输丢失的数据。

要了解该过程如何工作,我们需要了解发送者和接收者如何使用TCP序列号 用于标记和跟踪通过TCP传输的数据。

TCP序列号


通过TCP连接传输的每个字节都有一个由发送方分配的序列号。接收机使用序列号将接收到的数据移至原始顺序。


当两台计算机协商TCP连接时,每台计算机都会发送另一个随机起始序列号。这是机器将分配给它发送的第一个字节的序列号。每个后续字节都分配有前一个字节的序号加1。TCP段包含TCP标头,这些标头是附加到段开头的元数据。段主体中第一个字节的序列号包含在此段的TCP报头中。

应该注意的是,TCP连接是双向的,也就是说,数据可以在两个方向上传输,并且TCP连接中的每台机器都充当发送者和接收者。因此,每台机器都必须分配和处理自己独立的序列号集。

确认收到数据


当机器接收到TCP段时,它会告诉该段的发送方它已被接收。接收者通过发送一个段ACK(“ acknowledge”的缩写)来完成此操作,该段包含他期望从发送者接收到的下一个字节的序列号发送方使用此信息来了解接收方已成功接收到所有其他字节(直到此数字)。

通过段的TCP报头中ACK标志的存在ACK和相应的确认编号指示段。TCP协议中只有6个标记,其中包括(如我们将很快看到的)一个标记RST(“ reset”-“ reset”的缩写),指示重置段。


注意:TCP还允许使用选择性ACK,当接收器收到数字范围内的部分但不是全部段时发送。例如,“我收到了1000-3000和4000-5000字节,但没有收到3001-3999。”为简单起见,在讨论TCP重置攻击时,我将不考虑选择性ACK。

如果发件人发送数据但未收到ACK对于他们在一定时间间隔内的数据,他认为数据已丢失并重新发送,并为其提供了相同的序列号。这意味着,如果接收者两次接受相同的字节,那么它会轻而易举地使用序列号来消除重复项,而不会中断流。接收者可以接受重复的数据,这是因为原始段是在以后被接收,再次发送之后接收的,或者是因为原始段已被成功接收,但是相应的段ACK在发送者的途中丢失了。


尽管这样的重复数据非常少见,但由它引起的过多资源浪费不会导致问题。如果所有数据迟早都到达接收者,并且相应的数据ACK到达发送者,则TCP连接将执行其工作。

为假段选择序列号


创建虚假段时,RST攻击者需要给他一个序列号。接收者很高兴您需要接受序列号不一致的段,并以正确的顺序独立地连接它们。但是,它们的功能是有限的。如果接收方收到的序列号“太”乱序的段,则将其丢弃。

因此,对于成功的TCP重置攻击,需要一个合理的序列号。但是,什么是这样的数字呢?对于大多数段(尽管,我们将在后面看到,但不是RST),答案取决于TCP窗口大小

TCP窗口大小


想象一下一台1990年代初期的古老计算机,它连接到现代的千兆位光纤网络。超高速网络可以惊人的速度将数据传输到这台老式计算机,其速度比计算机处理数据的速度快。这将困扰我们,因为只有在接收者可以处理之前,TCP段才被视为已接收。


计算机具有TCP缓冲区,当计算机处理之前到达的数据时,新到达的数据将在其中等待处理。但是,此缓冲区的大小有限。如果收件人无法应付网络发送给他的数据量,则缓冲区将溢出。当缓冲区已满时,接收者别无选择,只能摆脱冗余数据。接收者不会发送ACK丢弃的数据,因此,当接收者的缓冲区中有可用空间时,发送者必须重新发送它们。如果接收者没有时间处理数据,则网络可以以多快的速度传输数据都没有关系。

想象一下一个过于热心的朋友,他以比您能阅读的速度快的速度向您发送一封完整的信件到您的邮件。邮箱内有一定的缓冲空间,但在其满后,所有未放置的字母都会掉落到地面,狐狸和其他生物会在这里吞噬它们。一个朋友将不得不重新发送他吃过的信件,但是现在您将有时间接收他以前的消息。发送太多收件人无法处理的信件或数据量会浪费能源和传输通道。

“太多”-它有多少数据?发送方如何理解何时发送更多数据,何时值得等待?这是TCP窗口大小派上用场的地方。。收件人窗口的大小是发件人可以随时传送给他的未确认字节的最大数量。假设接收者报告其窗口大小为100,000(我们将很快发现它如何传递此值),因此发送者发送100,000个字节。假设到发送方发送十万个字节时,接收方已发送了ACK这些字节的前10,000个段。这意味着尚未确认90,000字节。由于窗口大小为100,000,因此发送者可以在等待新的字节之前再传输10,000个字节ACK。如果在发送完这10,000个额外字节后ACK如果未收到,则发送方将达到其100,000个未确认字节的限制。因此,发件人将不得不等待并停止发送数据(除非重新传输他认为丢失的数据),直到他收到新的数据为止ACK


在打开连接时执行的握手过程中,TCP连接的每一侧都会将其窗口的大小通知对方。此外,在连接过程中可以动态更改窗口大小。具有较大TCP缓冲区的计算机可以声明较大的窗口大小,以最大化吞吐量。这样一来,与之通信的机器就可以通过TCP连接连续传输数据,而无需暂停或等待确认。 TCP缓冲区较小的计算机可能会被迫报告较小的窗口大小。有时,发件人完全填满了窗口,并被迫等待直到确认了某些段。因此,带宽会受到影响,但是有必要确保TCP缓冲区不溢出。


TCP窗口的大小是对传输的未确认数据量的严格限制。我们可以使用它来计算最大可能的序列号(在下面的等式中,我指定为max_seq_no),发送者可以在当前时间发送该序列号

max_seq_no = max_acked_seq_no + window_size

max_acked_seq_no-这是收件人已发送的最大序列号ACK这是发件人知道收件人已正确接收的最大序列号。由于发送方只能发送window_size未确认的字节,因此它可以发送的最大序列号为max_acked_seq_no + window_size

因此,TCP规范指出接收者应忽略其接收到的,具有有效窗口之外的序列号的任何数据。例如,如果接收者确认了所有不超过15,000的字节,并且其窗口大小为30,000,则它将接收序列号介于15,000至(15,000 + 30,000 = 45,000)之间的任何数据。而且,接收者完全忽略了此间隔之外的序列号数据。如果该段包含数据,其中一些位于该窗口内,而某些位于该窗口外,则该窗口内的数据将被接受并确认,但其外部的数据将被丢弃。请注意,我们仍然忽略在文章开头简短提及选择性内容的ACK可能性

对于大多数TCP段,此规则为我们提供了可接受序列号的间隔。但是,如前所述,对段RST的限制甚至比对普通数据传输段的限制更为严格。就像我们将很快看到的那样,这样做是为了使称为“盲TCP重置攻击”的TCP重置攻击的变体复杂化

RST段可接受的序列号


如果常规段的序列号在下一个预期序列号与该序列号之间加上窗口大小之间,则可以接受。但是,RST仅在数据包的序列号下一个预期序列号完全相等时才接收数据包。让我们回到前面的示例,在该示例中接收方发送了确认号15,000。对于RST要接收的数据包,其序列号必须恰好是15,000。如果接收方收到RST的序列号不等于15,000的段,则他将不接受它。


如果序列号在间隔之外,则接收器将完全忽略它。但是,如果它在预期序列号的窗口内,则接收器发送“质询ACK”(“ ACK呼叫”)。这是一个段,告诉发送方该段RST的序列号无效。他还告诉发送者接收者期望的序列号。发送者可以使用ACK呼叫中的此信息来重新创建并重新发送其信息RST

直到2010年,TCP才没有施加这些附加的段限制RSTRST根据与其他任何规则相同的规则,接受或拒绝细分但是,这也简化了盲目TCP重置攻击

盲目TCP攻击


如果攻击者能够拦截受害者之间交换的流量,则他可以读取受害者的TCP数据包的序列号和确认号。他可以使用此信息来选择要提供给他的假段的序列号RST。但是,如果攻击者无法拦截受害者的流量,他将不知道要插入哪个序列号。但是他仍然可以传输RST具有任意数量的不同序列号的任意数量的段,希望其中之一被证明是正确的。这种攻击称为盲TCP重置攻击。

就像我们已经说过的那样,在TCP协议的初始版本中,攻击者只需获取序列号RST在接收者的TCP窗口中。一篇标题为“在窗口中滑动”的文章表明,这使得盲目攻击变得太容易了,因为几乎可以肯定的成功是,攻击者只需发送成千上万个网段。为了解决这个问题,强制接收者接受该段的规则RST被上述更严格的标准所取代。由于执行TCP重置攻击的新规则,数百万个段需要盲目发送,这使得它们实际上是无法实现的。有关详细信息,请参见RFC-5963

对自己进行TCP重置攻击


注意:我在OSX上测试了此过程,但是收到一些评论,说它在Linux上无法正常工作。

现在,我们了解了有关执行TCP重置攻击的所有信息。攻击者必须:

  • 观察两个受害者之间的网络流量(“嗅探”它)
  • 嗅探启用了标志的TCP段ACK并读取其确认编号
  • 制作一个错误的TCP段,使其标志打开,RST并且序列号等于所截获的段的确认编号(请注意,这意味着传输速度慢,否则所选的序列号将很快过时。(要增加成功的机会,您可以RST以较大的序列号间隔传输多个段
  • 将伪造的片段发送给一个或两个受害者,希望这能断开他们的TCP连接

为了练习,让我们在同一台计算机上对自己进行TCP攻击,并通过进行通信localhost为此,我们需要:

  1. 配置两个终端窗口之间的TCP连接
  2. 编写处理流量嗅探的攻击程序
  3. 修改程序,使其产生并发送假段RST

让我们开始吧。

1.在两个终端窗口之间建立TCP连接


我们将使用工具配置TCP连接,该工具netcat默认情况下可在许多操作系统上使用。任何其他TCP客户端都可以在第一个终端窗口中,我们将执行以下命令:

nc -nvl 8000

此命令启动一个TCP服务器,侦听我们本地计算机上的端口8000在第二个终端窗口中,执行以下命令:

nc 127.0.0.1 8000

该命令尝试通过127.0.0.1端口的IP地址创建与计算机的TCP连接8000现在,在终端的两个窗口之间,应该建立一个TCP连接。尝试在一个窗口中输入内容-数据将必须通过TCP连接传输并出现在另一窗口中。


2.流量监听


我们将编写一个攻击程序,该程序使用scapy流行的Python网络库执行流量监听该程序使用scapy读取终端的两个窗口之间传输的数据,尽管它不是连接的一部分。

程序代码发布在我在GitHub上的存储库中该程序将嗅探连接流量并将其显示在终端上。该代码的主要核心是位于文件末尾sniff的库中的方法调用scapy

t = sniff(
        iface='lo0',
        lfilter=is_packet_tcp_client_to_server(localhost_ip, localhost_server_port, localhost_ip),
        prn=log_packet,
        count=50)

这段代码告诉我们scapy在接口上嗅探数据包lo0并捕获所有数据包的详细信息,这是我们TCP连接的一部分。该调用具有以下参数:

  • iface-命令scapy监听网络接口lo0或本地主机
  • lfilter — , scapy , IP- localhost . , , lo0. , .
  • prn — , scapy , lfilter. . , RST.
  • count — , scapy .

要测试该程序,请从步骤1开始配置TCP连接。克隆我的GitHub存储库,按照配置说明进行操作,并在终端的第三个窗口中运行该程序。在TCP连接的终端之一中输入一些文本。您应该看到该程序将开始记录有关连接段的信息。

3.发送假包裹 RST


我们已经建立了连接,程序可以嗅探通过它的所有TCP段。我们剩下的唯一事情就是修改程序,使其通过传输假段来执行TCP重置攻击RST。为此,我们将更改功能prn(请参阅上面的参数列表),调用scapy满足功能要求的软件包lfilter。在函数的修改版本中,我们研究它,提取必要的参数,然后使用这些参数来构建和发送该段,而不是简单地修复相应的包RST

假设我们截取了一个从(src_ip, src_port)k开始的段(dst_ip, dst_port)。他设置ACK一个标志,确认号为100,000。要制造和发送细分,我们:

  • IP- , . , . , .
  • RST , , RST
  • , ,
  • send scapy — .

要根据需要修改我们以前的程序,请取消注释该行并注释掉其上方的行。

现在,我们准备进行全面攻击。根据步骤1配置TCP连接。在终端的第三个窗口中,从步骤2运行攻击程序。然后在TCP连接的终端之一中输入一些文本。在您输入文本的终端中,TCP连接将突然神秘地断开。攻击完成了!


进一步的工作


  1. 继续尝试使用攻击工具。跟踪如果从程序包的序列号中添加或减去1会发生什么RST确保它必须截获的数据包的值完全相等ack
  2. Wireshark lo0 . TCP-, RST. ip.src == 127.0.0.1 && ip.dst == 127.0.0.1 && tcp.port == 8000 .
  3. , . RST, RST , . , RST, .


TCP重置攻击既深刻又简单。祝您实验顺利,如有疑问或意见,请告诉我

All Articles