lambda函数本身不受sql注入影响,风险在于其调用数据库时未过滤用户输入而拼接sql字符串;必须使用参数化查询、白名单校验动态字段名,并防范nosql/redis注入。

Serverless架构下Lambda函数本身不会直接受SQL注入影响,真正风险在它调用的后端数据库层——尤其是当函数拼接SQL字符串、使用原生查询或ORM动态构造语句时。
为什么Lambda函数不“直接”被SQL注入
Lambda是执行环境,不是数据库。它没有SQL解析器,也不运行SQL引擎。所谓“Lambda被注入”,实际是函数代码里用 boto3、pg8000、mysql2 等驱动向RDS/MySQL/PostgreSQL发请求时,把用户输入未过滤地拼进了SQL字符串里。
- 常见错误模式:
"SELECT * FROM users WHERE id = " + event.queryStringParameters.id - 正确做法:所有变量必须走参数化查询(prepared statement)或ORM安全接口
- 注意:API网关传入的
event是不可信源,包括pathParameters、body、headers全部需视为攻击输入
Node.js Lambda中防SQL注入的实操要点
以连接PostgreSQL的 pg 模块为例,关键不是“用不用ORM”,而是“是否让用户输入进入SQL字符串拼接流程”:
- ❌ 危险写法:
client.query("SELECT * FROM orders WHERE user_id = " + userId) - ✅ 安全写法:
client.query("SELECT * FROM orders WHERE user_id = $1", [userId]) - ✅ 更推荐:
client.query({ text: "SELECT * FROM orders WHERE user_id = $1", values: [userId] })(显式分离文本与值) - ⚠️ 注意:即使用了
pg,若调用client.query("DROP TABLE " + tableName)(动态表名),仍会中招——表名/列名无法参数化,必须白名单校验
Java Lambda中容易被忽略的ORM注入点
Spring Boot + JPA 在Lambda里跑得很快,但几个典型坑位常被跳过:
- ❌
@Query(value = "SELECT * FROM user WHERE name LIKE '%"+name+"%'", nativeQuery = true)—— 字符串拼接+nativeQuery=高危 - ✅ 改为:
@Query("SELECT u FROM User u WHERE u.name LIKE %:name%")(JPQL + 命名参数) - ✅ 或:
@Query(value = "SELECT * FROM user WHERE name LIKE ?", nativeQuery = true)+template.query(sql, new Object[]{"%" + name + "%"}, ...) - ⚠️ 特别注意:
Specification、CriteriaBuilder动态构建时,若字段名来自event(如sortField = event.get("sort")),必须限制为预定义枚举,不能直接拼进root.get(sortField)
冷启动场景下连接池与预编译语句的双重保障
Java Lambda冷启动时反复初始化连接和语句会拖慢响应,但更危险的是:若每次请求都新建 PreparedStatement 而没复用,可能绕过预编译保护(尤其在低版本JDBC驱动中):
- ✅ 正确姿势:将
PreparedStatement实例声明为静态变量或在类初始化块中创建(配合连接池如HikariCP) - ✅ Node.js中:用
pg.Pool并开启prepare: true选项,确保语句自动预编译 - ⚠️ 避免:在
handleRequest()内部反复调用connection.prepareStatement(...),既低效又可能漏掉参数绑定
最常被绕过的其实是“非SQL数据库”——比如函数调用MongoDB时用 where: { $regex: userInput },这本质是NoSQL注入;或者调用Redis时拼接 EVAL "return redis.call('GET', '" + key + "')" 0。这些都不走SQL,但危害等同。防御逻辑一致:绝不拼接,只传参,字段名/命令名走白名单。











