SQL注入能否直接提权取决于数据库账户权限是否失控;绝大多数提权源于应用使用root/sa等超级账户连接,而非漏洞本身强度,因此须实施权限最小化策略,禁用高危权限如FILE、CREATE、SUPERUSER等。

SQL注入能直接提权?先看数据库账户权限是否失控
绝大多数SQL注入导致的提权,根本不是漏洞本身有多强,而是应用连数据库都用 root 或 sa 这类超级账户连接。一旦注入成功,攻击者就等于拿到数据库的“管理员钥匙”。防不住注入时,权限最小化就是最后一道闸门。
- 生产环境绝不能用
root(MySQL)、sa(SQL Server)、postgres(PostgreSQL)等默认高权限账号连接应用 - 为每个业务模块创建独立账号,比如
app_user_order、app_user_report,只赋予对应库表的SELECT、INSERT、UPDATE权限,禁用DROP、CREATE、ALTER、EXECUTE、FILE - 确认权限是否生效:用该账号登录后执行
SHOW GRANTS(MySQL)或\du++\dp(PostgreSQL),别只信配置文件里写了啥
为什么 prepared statement 不能代替权限控制
很多人以为用了 PreparedStatement(Java)、pg_query_params(PHP)、cursor.execute(sql, params)(Python)就万事大吉——其实它只防参数拼接型注入,对动态表名、列名、ORDER BY 子句、UNION SELECT 后的结构控制完全无效。这时候如果账号权限过大,照样能拖库甚至写 shell。
-
SELECT * FROM ? WHERE id = ?—— 第一个?在绝大多数驱动里根本不支持参数化,会直接报错或被忽略 -
ORDER BY ?虽然语法上允许,但实际可能绕过类型检查,拼进恶意字段如id; DROP TABLE users-- - 即便所有查询都参数化,若账号有
SELECT INTO OUTFILE(MySQL)或COPY ... FROM PROGRAM(PostgreSQL),仍可能通过注入触发系统命令执行
MySQL 中 FILE 权限是提权高危项,必须显式回收
只要数据库账号有 FILE 权限,配合注入就能读取服务器任意可读文件(如 /etc/passwd、Web 配置),甚至写入 Web 目录生成一句话木马。这个权限和增删改查无关,却常被忽略。
- 检查当前用户是否有
FILE:执行SELECT * FROM mysql.user WHERE User='app_user' AND File_priv='Y'; - 回收命令是
REVOKE FILE ON *.* FROM 'app_user'@'%';,不是DROP或注释掉配置 - 某些云数据库(如阿里云 RDS)默认关闭
secure_file_priv,但仍需人工确认账号无FILE权限,不能依赖平台限制
PostgreSQL 的 public schema 和默认角色要特别当心
PostgreSQL 默认把新用户加进 public schema,且 public 对所有用户可读写。一旦注入点出现在建表、临时表或函数调用场景,攻击者可能创建恶意函数或覆盖已有视图。
- 执行
REVOKE CREATE ON SCHEMA public FROM PUBLIC;,再为必要用户单独授权 - 避免使用
CREATEROLE或SUPERUSER属性,哪怕只给一个运维账号也极危险 - 检查是否存在未审计的自定义函数,如
CREATE OR REPLACE FUNCTION exec_cmd(text) RETURNS text AS $$...$$ LANGUAGE plsh;—— 这类函数本身就是提权后门
权限控制不是设完就完的事。每次上线新功能、接入新服务、迁移数据库,都要重新核对账号权限清单。最麻烦的是——你永远不知道哪行日志里藏着一句没走参数化的 query,所以数据库账号必须从第一天起就按“已被注入”来设计。

















