You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用node-postgres的JavaScript代码是否存在SQL注入及优化疑问

关于node-postgres SQL拼接与注入的疑问

场景代码

查询语句拼接实现

const sql = `
  SELECT * 
  FROM "Employees"
  where employee_id = '${employee_id}' ; 
`;
console.log(`Query formatted: ${sql}`);
const result = await this.db.run(sql)

DB的run方法实现

async run(sql) {
    let retVal = "";
    let client;
    try {
      await this.init();
      console.log(`Connecting to ${this.connection.host}`);
      client = new pg.Client(this.connection);
      await client.connect();
      console.log(`inner sql:  ${sql}`);
      const res = await client.query(sql);
      
      retVal = res.rows;
 
      client.end();
    } catch (e) {
      console.log(`ERROR: ${e}`);
      retVal = e;
      client.end();
    }
    return retVal;
}

问题背景

employee_id来自POST请求的用户输入,SQLMAP检测出存在SQL注入漏洞,但手动输入"123'; SELECT * from employees;'"后查询无结果,现存在两个疑问:

  1. 计划改为参数化查询,当前代码的SQL注入风险等级如何?
  2. 代码中多处类似SQL拼接逻辑,每个查询结构不同,无法用通用方法处理,是否必须逐个重构这些代码来实现参数化查询?

问题解答

1. 当前代码的SQL注入风险等级

当前代码属于极高风险。你手动测试没得到预期结果只是场景问题,不代表漏洞不存在:

  • 你用的payload拼接后,最终SQL是:
    SELECT * 
    FROM "Employees"
    where employee_id = '123'; SELECT * from employees;' ; 
    
    第二个SELECT确实会执行,但你的run方法只返回第一个查询的结果(res.rows对应第一个语句的输出),所以看不到第二个查询的数据。但攻击者可以构造更具危害性的payload:
    • 比如' OR 1=1;--,会直接返回所有员工数据;
    • 权限足够时,攻击者还能执行删除、修改数据的操作,甚至读取其他敏感表、执行系统命令。
  • SQLMAP能检测出漏洞,说明存在可被利用的注入点,这种字符串拼接的写法完全没有对用户输入做安全处理,攻击者可以完全控制SQL执行逻辑,风险极高。

2. 是否必须逐个重构代码实现参数化查询

是的,必须逐个重构,这是彻底解决SQL注入的唯一可靠方式:

  • node-postgres的参数化查询依赖占位符($1、$2等),不同查询的占位符位置、参数数量都不一样,没有通用工具能自动把拼接好的SQL转换成参数化查询。
  • 改造可以按以下步骤来:
    • 把SQL中的变量替换成占位符,比如where employee_id = '${employee_id}'改成where employee_id = $1;
    • 修改run方法,支持接收参数数组:
      async run(sql, params = []) {
          let retVal = "";
          let client;
          try {
            await this.init();
            console.log(`Connecting to ${this.connection.host}`);
            client = new pg.Client(this.connection);
            await client.connect();
            console.log(`inner sql:  ${sql}`);
            const res = await client.query(sql, params);
            
            retVal = res.rows;
            client.end();
          } catch (e) {
            console.log(`ERROR: ${e}`);
            retVal = e;
            if (client) client.end();
          }
          return retVal;
      }
      
    • 调用时传入参数数组:const result = await this.db.run(sql, [employee_id])。
  • 你可以封装常用查询模板,但结构差异大的查询,还是得逐个调整占位符和参数列表。

内容的提问来源于stack exchange,提问作者Ace McCloud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 04:53:31