PR - Abusing Hidden Properties to Attack the Node.js Ecosystem

原文作者:F Xiao, J Huang, Y Xiong, G Yang, H Hu, G Gu

原文标题:Abusing Hidden Properties to Attack the Node.js Ecosystem

原文链接:https://www.usenix.org/system/files/sec21fall-xiao.pdf

原文来源:USENIX Security 2021

笔记作者:outx

0x01 Introduction

由于目前还没有特别完善的针对JavaScript和Node.js程序中的安全风险的研究和理解。于是在本文中,作者定义了一种新型攻击手法用于说明在JavaScript和Node.js程序中也存在着一定的安全风险。这种攻击手法被命名为HPA(hidden property abusing),攻击者可以利用其特性窃取机密数据、绕过安全检查并发起拒绝服务攻击,其实例如下图。

具体过程可以简单描述为:攻击者首先向服务端发送精心制作好的json数据,这个json数据会携带一个额外的而非服务端所期望的属性I2(被称之为隐藏属性)。接着服务端按照正常流程对该json数据进行处理,那么这个I2将会传播至一个内部对象中,如图中标红处,I2将覆盖内部对象的属性。一旦这些属性可以被攻击者所控制,那么攻击者就能够绕过一些安全检查,触发一些本不会触发的代码流程,例如下图中利用HPA绕过Node.js框架routing-controller的输入验证检测。

0x02 Contribution

  • 定义了针对Node.js程序的隐藏属性滥用(hidden property abusing, HPA)攻击,并说明了其带来的严重的安全后果
  • 设计并实现了LYNX,这是一个自动检测HPA漏洞并进行综合利用的工具
  • 其结果评估揭示了实际情况下Npm软件包中的HPA问题,这会导致严重的安全问题

0x03 Hidden Property Abusing

在JavaScript中,每个对象都有一个指向原型对象的链接。当程序要访问一个对象的某个属性时,该属性不仅会在该对象上搜索,而且会在该对象的原型上搜索(甚至在原型的原型上搜索),直到找到一个名称匹配的属性。因此,每个对象除了自己的属性外,还有许多继承的属性。然而,如果有一个冲突的名称属性位于搜索树的更高层次,这样的继承链就会被劫持。

需要注意的是这与原型链污染不同,具体来说原型污染需要对原型进行修改,而HPA并不需要这么做,其本质上只是劫持而非修改。

0x04 Lynx设计与实现

隐藏属性的定义

给定一个模块,其包含一个输入对象和一个内部对象。满足以下条件便定义一个属性P为输入对象中的隐藏属性:

  1. 这个属性P属于内部对象,且在这个模块中被引用
  2. 当发生属性重名问题时,内部对象的属性P能够被外部对象的属性P所覆盖
  3. 属性P并不是输入对象的默认参数

挑战与解决方案

如何发现Node.js程序的隐藏属性?

作者设计了一种结合了动态和静态分析各自优势的方法用以发现隐藏属性。首先,利用了一个轻量级的标记系统来动态跟踪输入对象和相关属性载体,并将属性载体的所有属性作为隐藏属性候选。为了尽可能多地发现执行路径,尤其是一些关键路径,作者对输入对象进行了广泛地递归标记,并对目标程序进行了测试。但上述的动态测试还是会造成一些假阴性,这是因为很多时候即使相应的属性载体被标记了,最为重要的隐藏属性却被忽略了。为了缓解这个问题,作者通过贪婪算法搜索那些被忽略的属性,然后引入静态分析。最终,得到一个隐藏属性候选列表。

在大量的隐藏属性中,如何确定哪些属性对攻击者而言是有价值和可利用的?

作者利用符号执行来探索所有相关的路径,收集路径约束,检测敏感行为,并最终生成漏洞利用方案。

设计总览


第一部分,LYNX会动态地运行一个标记系统,用于递归地跟踪输入对象,并尽可能多地识别属性载体。然后通过收集上述标记结果,引入静态分析来搜索那些被忽略的隐藏属性,构建隐藏属性候选列表。

第二部分,LYNX首先利用第一部分得到的隐藏属性候选列表生成漏洞模板,运行符号执行来推理得出隐藏属性的值,以此验证其有害性及攻击结果。

0x05 局限性

  • 依赖外部输入来触发分析过程
  • 与其他动态分析工具一样,存在许多的假阴性
  • 并没有覆盖完整的Node.js生态