前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Xcheck之Node.js安全检查引擎

Xcheck之Node.js安全检查引擎

原创
作者头像
腾讯代码安全检查Xcheck
发布2021-03-15 18:27:35
1.4K0
发布2021-03-15 18:27:35
举报

0x00 Node.js安全检查引擎

Node.js作为常见的Web开发语言之一,Xcheck也针对该语言打造了对应的扫描引擎:JsCheck

同样基于污点传播模型,支持以下常见漏洞类型:

  • 命令注入
  • SQL注入
  • URL跳转
  • SSRF
  • 路径穿越
  • XXE
  • 反序列化
  • 模板注入
  • XPath注入

目前JsCheck支持以下2个框架:Koa、Express,其他框架有需要可以方便添加。

0x01 Node.js一些有意思的特性

JsCheck为了能够精准的做污点传播,对Node.js的特性进行了精确的适配,比如:this关键字,变量声明提升等。

this关键字

Node.js里的this根据所处的位置不同(普通函数,箭头函数),调用方式不同(直接调用,赋值给一个对象的属性再调用,当做构造函数调用),有着不同的指向含义。 1)当在文件的最上层的时候,this指向的当前文件的exports对象:

代码语言:javascript
复制
this.a = 1111
console.log(exports) 

输出:

代码语言:javascript
复制
{a: 1111}

2)当this在一个普通函数里,this指向的是global对象:

代码语言:javascript
复制
function foo(){
    this.a = 222
}
foo()
console.log(global.a)

输出:

代码语言:javascript
复制
222

3)当this在一个构造函数里,this指向的是该构造函数生成的对象:

代码语言:javascript
复制
function Foo(){
    this.a = 333;
}
var fn = new Foo();
console.log(fn.a); 
console.log(global.a); 

输出:

代码语言:javascript
复制
333
undefined

4)当this在箭头函数里,this指向的对象就会根据this定义时所处的为上下文而定:

代码语言:javascript
复制
class A {
    b(){
        let c = ()=>{
            this.a = 9
        }
        c()
    }
}

a = new A()
a.b()
console.log(a.a)

exports.s = 200
a.b = ()=>{
    tmp = this;
    console.log(tmp)
}
a.b()

输出:

代码语言:javascript
复制
9
{s: 200}

变量声明提升

在Node.js里,如果一个变量不使用var,const,let修饰,那么默认它是一个全局变量:

代码语言:javascript
复制
function test() {
    a = 100  // 这里声明a为全局变量
    console.log('1: ', a)
}
test()
console.log('2: ', global.a)

输出:

代码语言:javascript
复制
1:  100 
2:  100 

如果使用了var声明变量,则会出现变量声明提升:

代码语言:javascript
复制
function test() {
    // 由于变量声明提升,这里仅仅是对局部变量赋值
    a = 0      
    console.log('1: ', a)
    if (true) {
        var a  // 声明一个局部变量a
        a = 1
    }
    console.log('3: ', a)
}
test()
console.log(global.a)

输出:

代码语言:javascript
复制
1:  0 
3:  1 
undefined 

不但变量的声明会提升,函数的声明也会提升:

代码语言:javascript
复制
var getName = function(){
    console.log(2);
}
function getName (){
    console.log(1);
}
getName();

等价于:

代码语言:javascript
复制
var getName;    //变量声明提升
function getName(){    //函数声明提升到顶部
    console.log(1);
}
getName = function(){    //变量赋值依然保留在原来的位置
    console.log(2);
}
getName();    // 最终输出:2

0x02 误报消除的尝试

在处理误报的时候,最不好处理的就是用户自定义的过滤逻辑。因为,这里的写法形式很多,难以提取出固定的模式,其中有两个关键点: 1.识别出一段代码是过滤逻辑 2.判定此段过滤逻辑是完备的 针对这两个点,目前从业界来看,都没有完美的解决办法,Xcheck在这里做了一些尝试,对一些情况能够做出准确的判定。 比如,通过字符串直接比对的情况:

代码语言:javascript
复制
function isGoodCmd() {
    var cmd = taint()
    if(!("safecmd1" == cmd || "safecmd2" == cmd)) {
        return
    }
    eval(cmd)
}
isGoodCmd()

检测不满足条件后抛出异常的情况:

代码语言:javascript
复制
function isGoodCmd() {
    var cmd = taint()

    if(!("safecmd1" == cmd)) {
        throw new SQLException()
    }
    eval(cmd)
}
isGoodCmd()

对污点数据进行常量化替换(清洗):

代码语言:javascript
复制
function isGoodCmd() {
    var cmd = taint()
    if(!("safecmd1" == cmd)) {
        cmd = "help"
    }
    eval(cmd)
}
isGoodCmd()

过滤逻辑叠加污点对象传播时:

代码语言:javascript
复制
function isGoodCmd() {
    var cmd = taint()
    var safe_cmd
    if("safecmd1" == cmd) {
        safe_cmd = cmd
    }
    // 有风险
    eval(cmd)
    // 无风险
    eval(safe_cmd)
}
isGoodCmd()

判定对象和风险函数执行的对象不是同一个的情况:

代码语言:javascript
复制
function isGoodCmd() {
    var cmd1 = taint()
    var cmd2 = taint()
    if("safecmd1" == cmd1) {
        eval(cmd2)
    }
}
isGoodCmd()

常见目录穿越漏洞的过滤逻辑:

代码语言:javascript
复制
function safePath(filePath) {
    if (!filePath.startsWith("/media/file") || filePath.indexOf("./") != -1) {
        return ""
    } else {
        return filePath
    }
}
function isGoodCmd() {
    var cmd1 = taint()
    eval(safePath(cmd1))
}
isGoodCmd()

从实测效果来看,JsCheck的误报已经明显降低,但是后续还有优化提升空间。

0x03 扫描样例

目前,使用github上CodeQL的Node.js测试集来扫描,未做专门适配的情况下发现漏洞243个。

代码语言:javascript
复制
{'REDOS': 2, 'READ': 173, 'RCE': 7, 'XSS': 45, 'SQLI': 7, 'URL': 9}
图片
图片

查看详细的扫描报告,针对每个漏洞,各个污点传播节点有详细的展示:

污点传播
污点传播

想了解Xcheck更多信息或者代码安全审计相关技术欢迎关注xcheck公众号~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x00 Node.js安全检查引擎
  • 0x01 Node.js一些有意思的特性
    • this关键字
      • 变量声明提升
      • 0x02 误报消除的尝试
      • 0x03 扫描样例
      相关产品与服务
      应用安全开发
      应用安全开发(Application Security Development,下文中也叫 Xcheck)为您提供优质的代码分析服务。Xcheck 凭借优秀的算法和工程实现,能在极低的误报率和漏报率前提下,以极快的速度发现代码中存在的安全漏洞。Xcheck 采用私有化部署的模式,所以产品使用的整个生命周期,源码都不会流出公司网络,杜绝源码泄露风险。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档