codecamp

Node.js 执行命令

1.2.1 【必须】使用child_process执行系统命令,应限定或校验命令和参数的内容

  • 适用场景包括:child_process.exec, child_process.execSync, child_process.spawn, child_process.spawnSync, child_process.execFile, child_process.execFileSync

  • 调用上述函数,应首先考虑限定范围,供用户选择。

  • 使用child_process.execchild_process.execSync时,如果可枚举输入的参数内容或者格式,则应限定白名单。如果无法枚举命令或参数,则必须过滤或者转义指定符号,包括:|;&$()><`!

  • 使用child_process.spawnchild_process.execFile时,应校验传入的命令和参数在可控列表内。

const Router = require("express").Router();
const validator = require("validator");
const { exec } = require('child_process');


// bad:未限定或过滤,直接执行命令
Router.get("/vul_cmd_inject", (req, res) => {
    const txt = req.query.txt || "echo 1";
    exec(txt, (err, stdout, stderr) => {
        if (err) { res.send({ err: 1 }) }
        res.send({stdout, stderr});
    });
});


// good:通过白名单,限定外部可执行命令范围
Router.get("/not_vul_cmd_inject", (req, res) => {
    const txt = req.query.txt || "echo 1";
  const phone = req.query.phone || "";
    const cmdList = {
        sendmsg: "./sendmsg "
    };
    if (txt in cmdList && validator.isMobilePhone(phone)) {
        exec(cmdList[txt] + phone, (err, stdout, stderr) => {
          if (err) { res.send({ err: 1 }) };
          res.send({stdout, stderr});
        });
    } else {
        res.send({
            err: 1,
            tips: `you can use '${Object.keys(cmdList)}'`,
        });
    }
});


// good:执行命令前,过滤/转义指定符号
Router.get("/not_vul_cmd_inject", (req, res) => {
    const txt = req.query.txt || "echo 1";
  let phone = req.query.phone || "";
    const cmdList = {
        sendmsg: "./sendmsg "
    };
    phone = phone.replace(/(\||;|&|\$\(|\(|\)|>|<|\`|!)/gi,"");
    if (txt in cmdList) {
        exec(cmdList[txt] + phone, (err, stdout, stderr) => {
          if (err) { res.send({ err: 1 }) };
          res.send({stdout, stderr});
        });
    } else {
        res.send({
            err: 1,
            tips: `you can use '${Object.keys(cmdList)}'`,
        });
    }
});

关联漏洞:高风险 - 任意命令执行

Node.js 输入验证
Node.js 文件操作
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }