CodeQL 文档

日志注入

ID: js/log-injection
Kind: path-problem
Security severity: 6.1
Severity: error
Precision: medium
Tags:
   - security
   - external/cwe/cwe-117
Query suites:
   - javascript-security-extended.qls
   - javascript-security-and-quality.qls

点击查看 CodeQL 仓库中的查询

如果未经清理的用户输入被写入日志条目,恶意用户可能会伪造新的日志条目。

如果用户提供了一些在显示日志输出时会被解释的字符作为输入,则可能会发生伪造。如果日志以纯文本文件形式显示,那么恶意用户可以使用换行符。如果日志以 HTML 形式显示,那么就可以包含任意 HTML 来伪造日志条目。

建议

用户输入在记录之前应进行适当清理。

如果日志条目为纯文本,则应使用 String.prototype.replace 或类似方法从用户输入中删除换行符。还应注意清楚地标记日志条目中的用户输入。

对于将在 HTML 中显示的日志条目,用户输入在记录之前应进行 HTML 编码,以防止伪造和其他形式的 HTML 注入。

示例

在第一个示例中,使用 `console.info` 记录用户提供的用户名。在第一种情况下,记录时没有任何清理。在第二种情况下,用户名用于构建一个使用 `console.error` 记录的错误。如果恶意用户提供 `username=Guest%0a[INFO]+User:+Admin%0a` 作为用户名参数,则日志条目将被分成两行,其中第二行为 `[INFO]+User:+Admin`。

const http = require('http');
const url = require('url');

const server = http.createServer((req, res) => {
    let q = url.parse(req.url, true);

    console.info(`[INFO] User: ${q.query.username}`); // BAD: User input logged as-is
})

server.listen(3000, '127.0.0.1', () => {});

在第二个示例中,String.prototype.replace 用于确保用户输入中不存在换行符。

const http = require('http');
const url = require('url');

const server = http.createServer((req, res) => {
    let q = url.parse(req.url, true);

    // GOOD: remove newlines from user controlled input before logging
    let username = q.query.username.replace(/\n|\r/g, "");

    console.info(`[INFO] User: ${username}`);
});

server.listen(3000, '127.0.0.1', () => {});

参考资料

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