51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

在安全开发中,如何通过代码审查防止SQL注入漏洞?请给出一个存在SQL注入风险的代码示例,并修改为安全的版本,说明修改后的原理。

360安全开发实习生-引擎难度:中等

答案

1) 【一句话结论】在安全开发中,防止SQL注入的核心是避免动态拼接SQL语句,通过参数化查询(预编译语句)或严格转义特殊字符,确保用户输入仅作为数据而非SQL代码执行。

2) 【原理/概念讲解】SQL注入的本质是恶意用户利用应用对用户输入的信任,构造包含特殊字符(如单引号、分号)的输入,改变原SQL语句的语义(例如将“SELECT * FROM users”改为“SELECT * FROM users; DROP TABLE users;”)。参数化查询(如PreparedStatement)通过将SQL模板与参数分离,数据库引擎预先编译SQL结构,参数作为独立数据传递,不会影响SQL语法解析。类比:就像填空题,你把问题(SQL模板)和答案(用户输入)分开,答案不会改变问题的结构,即使答案里有“; DROP TABLE”这样的内容,也不会影响问题本身的语法。

3) 【对比与适用场景】

方法定义特性使用场景注意点
手动转义对用户输入中的特殊字符(如单引号)进行转义(如替换为\')需要手动处理所有特殊字符,易遗漏,依赖开发者经验简单场景(如静态SQL,少量参数)风险高,适用于复杂SQL时易出错
参数化查询将SQL模板与参数分离,参数作为独立数据传递数据库引擎预先编译SQL结构,参数不影响语法大多数场景(尤其是动态SQL,多参数)需要支持参数化查询的数据库驱动

4) 【示例】
存在风险的代码(伪代码):

# 风险代码
user_id = request.get('id')  # 假设从请求获取用户输入
sql = f"SELECT * FROM users WHERE id = '{user_id}'"
result = db.execute(sql)  # 执行SQL

修改后的安全代码(使用参数化查询,以Python的psycopg2为例):

# 安全代码
user_id = request.get('id')
sql = "SELECT * FROM users WHERE id = %s"
result = db.execute(sql, (user_id,))  # 参数作为元组传递

原理:原代码将用户输入user_id直接拼接进SQL字符串,恶意输入如' OR '1'='1会导致SQL变为SELECT * FROM users WHERE id = '' OR '1'='1',绕过条件筛选。修改后,%s是占位符,数据库引擎会先编译SELECT * FROM users WHERE id = ?,再将user_id作为独立数据传递,无论输入是什么,都不会改变SQL的语法结构,从而防止注入。

5) 【面试口播版答案】好的,面试官,关于如何通过代码审查防止SQL注入,核心结论是避免动态拼接SQL语句,通过参数化查询(预编译语句)或严格转义特殊字符,确保用户输入仅作为数据而非SQL代码执行。
原理上,SQL注入的本质是恶意用户构造特殊字符(如单引号、分号)改变SQL语义。参数化查询通过将SQL模板与参数分离,数据库引擎预先编译SQL结构,参数作为独立数据传递,不会影响SQL语法解析,比如填空题,把问题(SQL模板)和答案(用户输入)分开,答案不会改变问题的结构。
对比来看,手动转义需要手动处理所有特殊字符,易遗漏,而参数化查询更安全,适用于大多数动态SQL场景。
举个例子,存在风险的代码是直接拼接用户输入:sql = f"SELECT * FROM users WHERE id = '{user_id}'",当用户输入' OR '1'='1时,SQL会变成SELECT * FROM users WHERE id = '' OR '1'='1',绕过条件筛选。修改后用参数化查询,比如sql = "SELECT * FROM users WHERE id = %s",将用户输入作为参数传递,数据库先编译SQL结构,再处理参数,这样无论输入什么,都不会改变SQL的语法,从而防止注入。

6) 【追问清单】

  • 问:手动转义和参数化查询有什么区别?
    回答要点:手动转义需手动处理特殊字符,易遗漏,适用于简单场景;参数化查询更安全,适用于复杂动态SQL。
  • 问:如果遇到存储过程或动态SQL的情况,如何处理?
    回答要点:存储过程需检查输入参数是否被正确参数化;动态SQL需尽量减少,若必须,需对输入进行严格验证和转义(但优先用参数化)。
  • 问:除了SQL注入,还有其他注入类型吗?
    回答要点:有,如命令注入(执行系统命令)、文件包含注入等,但SQL注入最常见,需重点防范。
  • 问:参数化查询中,是否所有数据库驱动都支持?
    回答要点:主流数据库(MySQL、PostgreSQL、SQL Server等)的驱动都支持,需使用对应的参数化语法(如Python的psycopg2、MySQLdb,Java的PreparedStatement)。
  • 问:如何检测SQL注入漏洞?
    回答要点:可通过工具(如OWASP ZAP、Burp Suite)测试,或代码审查时检查动态拼接SQL的情况。

7) 【常见坑/雷区】

  • 坑1:使用字符串拼接但加了转义,但未覆盖所有特殊字符(如分号、注释符号),导致仍可注入。
  • 坑2:参数化查询中仍用字符串拼接参数(如sql = "SELECT * FROM users WHERE id = %s"但执行时db.execute(sql, user_id)未正确传递参数,或使用%s但数据库驱动不支持,导致实际仍为拼接)。
  • 坑3:忽略输入类型验证,比如数字输入被当作字符串拼接,导致SQL语法错误或注入风险(如数字输入123拼接后id = 123是安全的,但'123会注入)。
  • 坑4:使用ORM框架时,未开启参数化查询(如某些ORM默认使用字符串拼接),需确认框架配置。
  • 坑5:处理存储过程时,输入参数未被正确参数化,导致存储过程内部存在注入风险。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1