CodeQL 文档

代码注入

ID: js/code-injection
Kind: path-problem
Security severity: 9.3
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-094
   - external/cwe/cwe-095
   - external/cwe/cwe-079
   - external/cwe/cwe-116
Query suites:
   - javascript-code-scanning.qls
   - javascript-security-extended.qls
   - javascript-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

在没有事先对输入进行适当清理的情况下,直接将用户输入(例如 HTTP 请求参数)评估为代码,允许攻击者进行任意代码执行。当用户输入被视为 JavaScript 或传递给将其解释为要评估的表达式的框架时,就会发生这种情况。例如,AngularJS 表达式或 JQuery 选择器。

建议

避免在可能动态评估的任何表达式中包含用户输入。如果必须包含用户输入,请在包含之前使用特定于上下文的转义。重要的是,要为将发生的评估类型使用正确的转义。

示例

以下示例显示页面 URL 的一部分被评估为 JavaScript 代码。这允许攻击者在 URL 中提供 JavaScript。如果攻击者可以诱使用户点击指向此类 URL 的链接,攻击者可以在用户的浏览器中评估任意 JavaScript,例如窃取包含会话信息的 cookie。

eval(document.location.href.substring(document.location.href.indexOf("default=")+8))

以下示例显示一个从用户输入构建的 Pug 模板,允许攻击者通过诸如 #{global.process.exit(1)} 之类的有效负载运行任意代码。

const express = require('express')
var pug = require('pug');
const app = express()

app.post('/', (req, res) => {
    var input = req.query.username;
    var template = `
doctype
html
head
    title= 'Hello world'
body
    form(action='/' method='post')
        input#name.form-control(type='text)
        button.btn.btn-primary(type='submit') Submit
    p Hello `+ input
    var fn = pug.compile(template);
    var html = fn();
    res.send(html);
})

以下是如何在不冒模板注入风险的情况下使用模板引擎的示例。用户输入通过一个插值表达式 #{username} 包含在内,该表达式的值作为选项提供给模板,而不是作为模板字符串本身的一部分

const express = require('express')
var pug = require('pug');
const app = express()

app.post('/', (req, res) => {
    var input = req.query.username;
    var template = `
doctype
html
head
    title= 'Hello world'
body
    form(action='/' method='post')
        input#name.form-control(type='text)
        button.btn.btn-primary(type='submit') Submit
    p Hello #{username}`
    var fn = pug.compile(template);
    var html = fn({username: input});
    res.send(html);
})

参考资料

  • ©GitHub, Inc.
  • 条款
  • 隐私