惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
GRAHAM CLULEY
T
Tenable Blog
Know Your Adversary
Know Your Adversary
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Privacy International News Feed
S
Security Affairs
NISL@THU
NISL@THU
O
OpenAI News
Attack and Defense Labs
Attack and Defense Labs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Hacker News: Ask HN
Hacker News: Ask HN
Webroot Blog
Webroot Blog
Schneier on Security
Schneier on Security
S
SegmentFault 最新的问题
S
Schneier on Security
G
Google Developers Blog
V
V2EX
C
Check Point Blog
U
Unit 42
Google DeepMind News
Google DeepMind News
T
Threatpost
阮一峰的网络日志
阮一峰的网络日志
T
The Exploit Database - CXSecurity.com
Recent Announcements
Recent Announcements
M
MIT News - Artificial intelligence
S
Secure Thoughts
博客园 - 司徒正美
Recorded Future
Recorded Future
P
Proofpoint News Feed
Spread Privacy
Spread Privacy
K
Kaspersky official blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
AI
AI
博客园 - 聂微东
N
News and Events Feed by Topic
SecWiki News
SecWiki News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Vulnerabilities – Threatpost
P
Palo Alto Networks Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
Recent Commits to openclaw:main
Recent Commits to openclaw:main
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
The Hacker News
The Hacker News
The Last Watchdog
The Last Watchdog
Project Zero
Project Zero
W
WeLiveSecurity
博客园 - Franky

Yesterday17's Blog

2026 新年解密红包 / Melody Flag | Yesterday17's Blog 谈谈 Iori 的设计思路(二):如何实现一个 Showroom 录制工具? | Yesterday17's Blog 谈谈 Iori 的设计思路(一):从 Nico Timeshift 说起 | Yesterday17's Blog Iori Minyami 0.1.0 发布 | Yesterday17's Blog 2025 新年解密红包 / Melody Flag | Yesterday17's Blog 使用 Cloudflare Warp 解决罗森票务的海外登录问题 | Yesterday17's Blog How To Blog 04: The Astro v5 Era | Yesterday17's Blog 谈谈 tokio::select! 的公平性 | Yesterday17's Blog Learning Pingora 05 - Connect with TLS | Yesterday17's Blog Leaving Bytedance | Yesterday17's Blog 大橋彩香 AsiaTour「Reflection」上海公演 个人向记录 & Repo | Yesterday17's Blog Recoving from burnout - What happened? | Yesterday17 Yubikey 重建手册 | Yesterday17's Blog How To Blog 03: Heimus | Yesterday17's Blog 🪧 Blog Migration Accouncement | Yesterday17's Blog Learn Your IDE - VSCode 是如何仅重启插件的? | Yesterday17's Blog How To Blog 02: Astro❤️Password | Yesterday17's Blog How To Blog 01: Why, How, and the Future | Yesterday17's Blog Learning Pingora 04 - Establish L4 Connection | Yesterday17's Blog Learning Pingora 03 - Upstreams and Peers | Yesterday17's Blog Learning Pingora 02 - A Simple HTTP Server | Yesterday17's Blog Learning Pingora 01 - Getting Started | Yesterday17's Blog 2024 新年解密红包 / Melody Flag | Yesterday17's Blog 向新的一年飞驰——记录 2023 | Yesterday17's Blog 「サクラノ刻」对话选摘(2) | Yesterday17's Blog PGP Key Revocation 注销声明 | Yesterday17's Blog 「サクラノ刻」对话选摘(1) | Yesterday17's Blog 2023 新年解密红包 / Melody Flag | Yesterday17's Blog 『蒼の彼方のフォーリズム』通关感想 | Yesterday17's Blog 单显卡直通教程 | Yesterday17's Blog 对博客与笔记的思考 | Yesterday17's Blog Project Anni 之旅(3)自动化 Flutter 应用 CI/CD 上架流程 | Yesterday17's Blog AsobiStage 直接播放链接 | Yesterday17 如何在后分P时代进行投稿——sswa使用详解 | Yesterday17's Blog JSON RPC 与 LSP 协议基础 | Yesterday17's Blog Grajapa Shueisha / BookEnd 加密方式调查 | Yesterday17's Blog 【2022篇+WriteUp】如何再收一个新年红包? | Yesterday17's Blog 如何将良心云的良心功能清理干净 | Yesterday17's Blog 【油猴脚本】bilibili 投稿页面返回旧版+旧版页面强制允许分P上传 | Yesterday17's Blog Cloudr1v1 授权方式分析 | Yesterday17 Typora 1.0.2 逆向实录 | Yesterday17's Blog Project Anni 之旅(2)ValueAfterTable——toml-rs的实现与限制 | Yesterday17's Blog IPv4透明代理+IPv6 Passthrough——树莓派单臂软路由折腾记 | Yesterday17's Blog Chaos; Child 汉化补丁 神秘编码探索 | Yesterday17's Blog 镣铐与舞蹈——个性与共性之迷思 | Yesterday17's Blog Go 学习笔记 02 - 找准 io 之道 | Yesterday17's Blog 绕过「9-nine-」的 CDKEY 验证——KrkrPlugin 正(?)向实录 | Yesterday17's Blog 静流的青春纪念册——「サクラノ刻 -櫻の森の下を歩む-」体验版感言 | Yesterday17's Blog Project Anni 之旅 01 - 从 clap-builder 到 derive | Yesterday17's Blog [Google CTF 2021] CPP WriteUp | Yesterday17's Blog 获取 アソビステージ 的实际播放链接 | Yesterday17's Blog 90 行 Rust 代码实现 AsyncTeeReader | Yesterday17's Blog 或许还算有价值一读的文章列表 | Yesterday17's Blog 从零开始的 Seedbox 之旅 | Yesterday17's Blog [随笔]技术型博客行文迷思(1) | Yesterday17's Blog 浅谈 git fetch 的工作方式 | Yesterday17's Blog 『ソーサレス*アライヴ! ~the World's End Fallen Star~』通关感想" | Yesterday17's Blog Rust std::fmt 格式语法简述 | Yesterday17's Blog 日亚修改居住国的解决方案 | Yesterday17's Blog [Windows/Linux] GC553 的 Switch 完美采集之路 | Yesterday17's Blog 【翻译】Subtyping and Variance / 子类型与变型 | Yesterday17's Blog Berd's Red Envelope 2021 WriteUp | Yesterday17's Blog 【中英对照】ALSA 音频 API 使用教程/A Tutorial on Using the ALSA Audio API | Yesterday17's Blog 从 cue_scanner.l 看 CUE Sheet 的词法单元 | Yesterday17's Blog Postman 历史记录导出的解决方案 | Yesterday17's Blog 《恋爱绮谭 不存在的夏天》通关感想 | Yesterday17's Blog [微机实验/TD-PITE] 微机接口综合实验 | Yesterday17's Blog [微机实验/TD-PITE] 键盘扫描及数码管显示实验 | Yesterday17's Blog [微机实验/TD-PITE] 数码管显示实验 | Yesterday17's Blog Airsonic Advanced+Google Drive+Caddy 部署纪实 | Yesterday17's Blog X-NUCA 2020 - hellowasm 题解 | Yesterday17's Blog [微机实验/TD-PITE] 8251 串行接口实验 | Yesterday17's Blog Node.js child_process.fork 与 env 污染 RCE | Yesterday17's Blog EP.01 「夜の向日葵」 | Yesterday17's Blog [微机实验/TD-PITE] 8254 定时/计数器实验+选做实验 | Yesterday17's Blog [JLU CTF/2020] babywasm WriteUp | Yesterday17's Blog PHP 反序列化与经典利用 | Yesterday17's Blog WebAssembly 逆向简述 | Yesterday17's Blog 『彼女、お借りします』一期完结点评 | Yesterday17's Blog [微机实验/TD-PITE] D/A 转换实验+选做实验 | Yesterday17's Blog [微机实验/TD-PITE] A/D 转换实验+选做实验 | Yesterday17's Blog 开源项目申请 JetBrains Open Source License 简单流程 | Yesterday17's Blog 微软拼音与 JetBrains 搜索快捷键冲突的解决方案 | Yesterday17's Blog [微机实验/TD-PITE] 8259 中断优先级实验+选做实验 | Yesterday17's Blog IFTTT 测试(续) | Yesterday17 IFTTT 测试 | Yesterday17's Blog [微机实验/TD-PITE] 存储器扩展实验+选做实验 | Yesterday17's Blog 新版 GCC 针对 -fdump-translation-unit 的替代方案 | Yesterday17's Blog 一次 HSTS 策略配置的排错之旅 | Yesterday17's Blog YukiNative 踩坑记——Windows 的消息队列 | Yesterday17's Blog 我是我自己——论获取 HTTPS 证书时的验证步骤 | Yesterday17's Blog 【设计文档】对 PUG 的大规模设计修订(1.1) | Yesterday17's Blog GS65 折腾记(2)加装固态,分区,Grub2 引导 Manjaro LiveCD | Yesterday17's Blog 「さくら、もゆ。」的空白字体列表——一次逆向问题定位过程实录 | Yesterday17's Blog GSuite 探索篇(1)使用 Service Account 向 Google Drive 传输文件 | Yesterday17's Blog 『サクラノ詩 -櫻の森の上を舞う-』通关感想 | Yesterday17's Blog 《ATRI -My Dear Moments-》通关感想 | Yesterday17's Blog [工具][VSCode 扩展] AegiKit——方便 Aegisub 使用的工具箱 | Yesterday17's Blog 贝塞尔曲线、字体矢量化与曲线运算 | Yesterday17's Blog NAT 类型初探 | Yesterday17's Blog
NAT Slipstreaming v1 原理浅析 | Yesterday17's Blog
Yesterday17 · 2021-09-12 · via Yesterday17's Blog

大家好,好久不见,这里是某昨。这是一篇从 2021 年春节一直咕到现在的文章,因此文中的「今天」等指代时间的词语均代表当时的时间,请各位在阅读时自行转换(笑)

ToC

  • 开始
  • NAT
  • 应用层网关(ALG
  • 问题所在
  • SIP 协议
  • TURN 协议
  • 内网主机探测
  • 结语
  • 参考

开始

今天无意在 OSChina 的公众号看到一篇讲解 Chrome 将一些端口加入黑名单以防止 NAT Slipstreaming 攻击的新闻。原文是这样描述的:

这个新型 NAT Slipstreaming 漏洞使网站可以托管恶意脚本,这些恶意脚本发送经过特殊设计的响应,从而绕过网站访问者的 NAT 防火墙并能够访问用户内部网络上的任何 TCP/UDP 端口。

https://mp.weixin.qq.com/s/Z5tuhhlt4uZGDVKCuOGCOQ

这个漏洞的结果令我产生了强烈的好奇:这个洞到底是怎么打出来的?!这篇文章就是在明白了其原理之后诞生的。

值得注意的是,这篇文章中描述的是 NAT Slipstreamingv1 版本。上述新闻中描述的是 v2v1 能做到的是能连通内网的 5060 端口,而 v2 则可以支持任意的端口。v2v1 的主要区别在于选取的协议不同,但很多原理都是共通的。因此这里只介绍 v1 的原理。

NAT

在之前的一篇文章,我详细介绍了 NAT 的几种类型。但无论是哪种 NAT,都无法解决这样的问题:协议选择使用多条连接时,外部连接无法穿过 NAT

FTP 协议为例,当使用主动模式时,FTP 客户端主动选择了端口 nFTP 服务器建立连接,并打开端口 n+1 接收 FTP 服务器传来的数据。此时,端口 n 由于内网机器主动穿过 NAT,建立了 NAT 映射;但对于端口 n+1,由于传输层并没有任何迹象表明这个端口会被使用,因此 FTP 服务器对这个端口的访问就会被 block,由此导致 FTP 主动模式无法使用。

尽管 FTP 提供了被动模式,但被动模式会受到服务端端口数量的限制,从而限制了同时使用的用户数量。并且,如果配置了防火墙策略,服务端还需要放行一部分被动模式使用的端口。

FTP 只是许多这样协议中的一种。它工作在应用层,其预期行为由于 NAT 的存在而无法正常进行。由此,应用层网关应运而生。

应用层网关(ALG

应用层网关,顾名思义,就是工作在应用层的网关。我们来看一看 ALG 是如何解决上述问题的。

还是以 FTP 协议为例。我们知道,当 FTP 客户端建立主动连接时,其自身选择了一个端口 n。对于 ALG,其可以通过各种方式判断当前连接的协议为 FTP。当主动连接时,ALG 透明地增加一条与目标机器端口的映射。这样,FTP 协议就可以正常使用了。

简单总结一下,就是 ALG 通过识别某些特殊的协议报文,自动判断并建立需要建立的端口映射,从而使得应用层协议能够正常运行。

问题所在

乍一看这样的流程好像没什么问题,那究竟是什么导致了危险呢?

我们知道,数据在传输的过程中,IP 数据报由于 MTU 的限制,必须进行分片;TCP 数据包由于 MSS 的限制,必须进行分段。而网关作为需要处理大量数据报的设备,其效率永远是第一位的。这也就意味着 ALG 的对报文的识别通常是无状态的。当 ALG 接收到报文,通过协议特征判断出其对应的应用层协议,下一步就是建立 NAT 映射。

于是利用方式就出现了。当我们知道了网络的 MTUMSSIP 头长度、TCP 头长度,我们就可以通过巧妙构造 HTTP 请求,通过 POSTbody 产生 TCP 报文分段。如果分段后的报文恰好是合法的 FTP 主动模式连接建立报文,那么 ALG 就会被欺骗并创建端口 n+1 与被攻击者之间的 NAT 映射。

因此问题就恰巧出现在了上图的第二步:识别 FTP 协议。当 ALG 识别到了这样的协议,就会自动放行对应的流量;而当流量得到放行,攻击者就可以访问对应内网机器的其他端口了。

SIP 协议

上文中为了方便理解,我们一直举了 FTP 协议作为例子。而在实际的攻击行为中,SIP 协议才是被选取的受害者。

简单来说,SIP 协议的 INVITEREGISTER 需要构造类似 FTP 协议中 n+1 端口的开放才能正常工作,因此只要能够构造数据包,带有 SIP 的注册信息,就可以对内网的任意主机5060 端口进行打洞了。

TURN 协议

有的 ALG 实现 SIP 协议实现只允许 TCPTCP 的,UDPUDP 的,因此我们需要一个突破 UDP 的手段。TURN 就是被选中的受害者了。TURN 协议中有认证的环节,其中的 username 是以明文传输的,并且没有任何限制,这就是利用点了。

我们知道,UDP 协议是没有 MSS 的,其分片只会受 MTU 的影响。而当 IP 包被分片时,第二片报文中就不存在 UDP 报头了。也就是说,除了这个报文是 UDP 协议的报文之外,其他的一切 ALG 都一无所知。由此,我们就可以构造任意的 UDP 报文内容了,自然也包括 SIP 协议。

内网主机探测

现在我们有了能够打通 NAT 的能力,那被打的人在哪儿呢?原文给出了两种手段。

一种是通过 ICE 协议,还是 WebRTC 那一套探测内网;而另一种则是通过诸如 <img>onsuccessonerrortimeout 实现,当成功探测到 Web 服务器时是 success,其他 TCP 服务发送 RST 则为 onerrorIP 不存在则会产生一秒以上的耗时,可以通过计时器判断。

结语

有了打洞方式、探测手段和受害者,NAT Slipstreaming v1 的使命就完成了。利用 ALG 的合理行为,IP 协议的合理行为,TURN 协议的合理行为,以及 ICE 协议和 <img> 的合理行为,挡在我们面前的 NAT 被层层剥开,暴露出了其中一无所知的被害主机。

这也就是 NAT Slipstreaming 的暴露出来的核心问题:当所有协议都以其正确的方式运行时,却产生了足以致命的安全问题。而这,也对后续的协议设计有着巨大的启示意义。

参考

  1. https://samy.pl/slipstream/