-- 注释符危险在于使数据库忽略后续内容,攻击者可截断sql逻辑绕过校验;简单替换会破坏正常数据,必须用词法解析区分上下文;根本解法是参数化查询,确保输入作为纯数据不参与sql解析。

SQL注入中 -- 注释符为什么危险
因为 -- 会让数据库忽略其后所有内容,攻击者可借此“截断”原SQL逻辑,绕过校验或拼接恶意语句。例如用户输入 admin' -- ,配合查询 SELECT * FROM users WHERE name = 'input',最终执行的是 SELECT * FROM users WHERE name = 'admin' -- ',后面单引号被注释掉,语法合法且绕过了密码判断。
剥离 -- 不能只靠简单字符串替换
直接用 str.replace('--', '') 或正则全局删 -- 会误伤正常数据——比如字段值含 http://example.com/path--v2 或注释本身在字符串内('-- not a comment'),删掉就破坏业务语义。
- 必须区分 SQL 注释和普通文本:只有出现在非字符串、非标识符上下文中的
--才算注释起始 - 真正安全的做法是**参数化查询**,而非手动清洗输入
- 若必须预处理(如日志脱敏、中间件拦截),应基于 SQL 词法解析,而非字符串操作
参数化查询才是根本解法(以 Python + psycopg2 为例)
数据库驱动能确保用户输入始终作为数据值传递,不参与 SQL 结构解析,-- 在参数里就是普通字符,不会触发注释行为。
cursor.execute("SELECT * FROM users WHERE name = %s AND status = %s", (user_input, "active"))
注意:%s 是占位符,不是字符串格式化;user_input 中的 --、'、; 全部原样进数据库,无解析风险。
- 不要用
.format()或f""拼接 SQL - 不同驱动占位符不同:
?(SQLite)、%s(PostgreSQL/MySQL)、:name(Oracle) - 存储过程或动态列名等无法参数化的场景,需白名单校验,而非过滤符号
如果真要剥离(仅限调试/审计场景)
用现成 SQL 解析器比手写正则可靠得多。Python 可用 sqlparse 库识别注释节点并移除:
import sqlparse<br>parsed = sqlparse.parse("SELECT * FROM t WHERE x = '--abc'; -- real comment")[0]<br>for token in parsed.flatten():<br> if token.is_comment and token.ttype == sqlparse.tokens.Comment.Single:<br> token.value = ''
但请注意:这仅适用于完整、语法正确的 SQL 字符串;对用户单字段输入做这种处理仍是反模式——你永远不知道它会被拼进哪条语句、在哪种方言里执行。
最常被忽略的一点:前端 JS 的 escape()、encodeURI() 或服务端 URL decode 都不解决 SQL 注入,它们和数据库解析层完全不在一个维度。防御必须落在查询构造那一刻,而不是输入管道中途削符号。











