内容简介:但是 Cobra 目前基本没有专门针对 Node.js 的源代码扫描规则。以我上一篇文章分析 CVE-2017-16082 时使用的示例漏洞代码为例:这个代码中存在着明显的 SQL 语句拼接,有 SQL 注入风险,但是使用 Cobra 扫描会得到:
Cobra 是一款 源代码安全审计 工具,支持检测多种开发语言源代码中的 大部分显著 的安全问题和漏洞。
但是 Cobra 目前基本没有专门针对 Node.js 的源代码扫描规则。以我上一篇文章分析 CVE-2017-16082 时使用的示例漏洞代码为例:
const app = new Koa() const client = new Client({ user: "f1sh", password: "f1sh", database: "postgres", host: "127.0.0.1", port: 5432 }) client.connect() app.use(async ctx => { ctx.response.type = 'html' let id = ctx.request.query.id || 1 let sql = `SELECT * FROM "user" WHERE "id" = ${id}` const res = await client.query(sql) ctx.body = `<html> <body> <table> <tr><th>id</th><td>${res.rows[0].id}</td></tr> <tr><th>name</th><td>${res.rows[0].name}</td></tr> <tr><th>score</th><td>${res.rows[0].score}</td></tr> </table> </body> </html>` }) app.listen(3000)
这个代码中存在着明显的 SQL 语句拼接,有 SQL 注入风险,但是使用 Cobra 扫描会得到:
查看 Cobra 的 rules 文件夹下的扫描规则也可以发现,当前的 Cobra 只支持扫描 java 和 php 中的 SQL 注入漏洞,而没有 Node.js 的对应规则。
那么我们何不自己动手添加呢?编写 Cobra 的扫描规则并不难,在 官方文档 中给了非常详细的说明和示例。
根据文档的说明和参考当前存在的规则,编写一个扫描 Node.js 中拼接 SQL 语句的规则如下:
<?xml version="1.0" encoding="UTF-8"?> <cobra document="https://github.com/WhaleShark-Team/cobra"> <name value="拼接SQL注入"/> <language value="javascript"/> <match mode="regex-only-match"><![CDATA[(['"`]\s*(select|SELECT|insert|INSERT|update|UPDATE|delete|DETELE)[^;]*?(\$\{(.+?)\}|['"`]\s*\+\s*[$\w]+))]]></match> <level value="8"/> <test> <case assert="true"><![CDATA[let sql = `SELECT * FROM "user" WHERE "id" = ${id}`]]></case> <case assert="false"><![CDATA[let sql = 'SELECT * FROM "user" WHERE "id" = 1']]></case> <case assert="true"><![CDATA[let sql = 'SELECT * FROM "user" WHERE "id" = ' + id]]></case> <case assert="true"><![CDATA[const result = await req.db.run(`UPDATE notes SET pinned = ${req.body.value}::boolean WHERE id = ${req.params.noteId}`);]]></case> </test> <solution> ## 安全风险 拼接SQL语句存在SQL注入风险 ## 修复方案 - 已不再使用的功能,直接做下线处理 - 引入安全组件 - 代码层修复:尽量不要拼接SQL语句。如必要,需对用户可控的参数进行严格过滤 </solution> <status value="on"/> <author name="f1sh" email="f1shunicorns@gmail.com"/> </cobra>
规则的核心就是 <match>
标签中的正则表达式。
这个正则表达式分成三个部分,第一个部分
['"`]\s*(select|SELECT|insert|INSERT|update|UPDATE|delete|DETELE)
匹配的是 SQL 语句开头的关键字;第二个部分
[^;]*?
匹配的是 SQL 语句结束前的部分;第三个部分
(\$\{(.+?)\}|['"`]\s*\+\s*[$\w]+)
我匹配了 js 中两种字符串拼接的情况:
let sql = `SELECT * FROM "user" WHERE "id" = ${id}` let sql = 'SELECT * FROM "user" WHERE "id" = ' + id
另外这里需要注意的地方是 Cobra 并没有使用 python 的 re 库来解析 <match>
中的正则表达式,而是使用的 grep 命令,并且没有使用 -i 参数,所以关键字的大小写敏感,得把关键字大小写的情况都写进去(或者手动给 grep 加上 -i 参数,在 cobra/engine.py
第317行)。
保存规则为 CVI-160005.xml ,再一次扫描之前的示例代码得:
这样就成功地给 Cobra 加上了 Node.js 源代码 SQL 注入风险扫描的规则。
我们还知道 CVE-2017-16082 这个漏洞的成因其实是传入 Function 这个类的最后一个参数可控,造成了代码注入,那么我们还可以写个规则来扫描 Function 代码注入风险:
<?xml version="1.0" encoding="UTF-8"?> <cobra document="https://github.com/WhaleShark-Team/cobra"> <name value="远程代码执行"/> <language value="javascript"/> <match mode="regex-only-match"><![CDATA[([^\w]Function\(.*?([$\w]+|(['"`].*?(\$\{(.+?)\}|['"`]\s*\+\s*[$\w]+).*?))\s*\))]]></match> <level value="10"/> <test> <case assert="true"><![CDATA[this.RowCtor = Function('parsers', 'rowData', ctorBody)]]></case> <case assert="true"><![CDATA[this.RowCtor = Function('parsers', 'rowData', 'var ' + ctorBody + ';')]]></case> <case assert="true"><![CDATA[this.RowCtor = Function('parsers', 'rowData', `var ${ctorBody};`)]]></case> <case assert="false"><![CDATA[var sum = new Function('a', 'b', 'return a + b');]]></case> </test> <solution> ## 安全风险 代码注入(Code Injection) - Funtion() 没有对用户输入的参数进行足够的过滤,可能导致攻击者传入的恶意代码执行。 因此危险函数应该尽量避免在开发中使用。 ## 修复方案 不要把用户可控的参数带入 Function 的最后一个参数中,或者进行安全的过滤后再带入。 </solution> <status value="on"/> <author name="f1sh" email="f1shunicorns@gmail.com"/> </cobra>
这个规则匹配了 Function 类最后一个参数可控的三种情况:
this.RowCtor = Function('parsers', 'rowData', ctorBody) this.RowCtor = Function('parsers', 'rowData', 'var ' + ctorBody + ';') this.RowCtor = Function('parsers', 'rowData', `var ${ctorBody};`)
规则写好后,保存为 CVI-180002.xml ,再次扫描。但是这时会发现并没有扫描出 Function 代码注入风险,为什么呢?
我们运行 Cobra 时加上 -d 参数可以查看扫描时的 debug 信息:
可以看到其实是成功扫描出了 result.js 中存在漏洞的那一行代码了的,但是输出了:
[13:37:39] [DEBUG] Not vulnerability: Special File(特殊文件)
也就是说被当成了特殊文件,所以没有算作漏洞。
怎么样才会被当成特殊文件呢,在 Cobra 的源代码目录里全局搜索一下关键字 Special File
:
跟进 cobra/engine.py
第588行:
if self.is_special_file(): logger.debug("[RET] Special File") return False, 'Special File(特殊文件)'
跟进 is_special_file()
函数,在同文件 493 行:
def is_special_file(self): """ Is special file :method: According to the file name to determine whether the special file :return: boolean """ special_paths = [ '/node_modules/', '/bower_components/', '.min.js', '.log', '.log.', 'nohup.out', ] for path in special_paths: if path in self.file_path: return True return False
可以看到在这个函数中维护了一个 special_paths
,当文件存在于 special_paths
中时就不会被当作漏洞。而我们扫描出存在漏洞的 result.js
正存在于 /node_modules/
目录下,所以就没有被当作漏洞了。我们尝试把 /node_modules/
从 special_paths
注释掉,然后再次扫描:
就可以正常扫描出漏洞风险了。
以这两条规则为例,我们就可以很轻易的写出一份针对 Node.js 各种漏洞风险的扫描规则库。
当然这两条规则还非常简陋,仅仅考虑了变量的简单的拼接和传入,并没有去检测拼接或传入进来的变量是否可控或经过了过滤。但 Cobra 最强大的一点就是:
对于OWASP Top 10的漏洞,Cobra通过预先梳理能造成危害的函数,并定位代码中所有出现该危害函数的地方,继而基于Lex(Lexical Analyzer Generator, 词法分析生成器)和Yacc(Yet Another Compiler-Compiler, 编译器代码生成器)将对应源代码解析为AST(Abstract Syntax Tree, 抽象语法树),分析危害函数的入参是否可控来判断是否存在漏洞(目前仅接入了PHP-AST,其它语言AST接入中)
我们可以参考 Cobra 的 PHP-AST ,给 Node.js 也加上 AST ,这样就可以更准确更灵活地扫描源代码中的漏洞。(挖坑待填)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
UML基础与Rose建模教程
人民邮电出版社 / 人民邮电出版社 / 2006-1 / 36.00元
《UML基础与Rose建模教程》全面,详细地介绍了 UML 的基础知识和Rational Rose的使用方法,并通过4个综合性的案例,展示了使用UML和Rose进行软件建模的具体方法和步骤。全书共分20章,前4章是基础部分,介绍了UML和Rose的基础知识;第5章到第13章是《UML基础与Rose建模教程》的重点,介绍了UML的9种图和组成元素,以及相关的建模技术,并在每章的最后介绍了各种图在Ro......一起来看看 《UML基础与Rose建模教程》 这本书的介绍吧!