
1) 【一句话结论】有效防止SQL注入和XSS攻击的核心是“输入端通过白名单/黑名单策略及复杂输入验证过滤非法数据,输出端针对不同上下文(HTML、JavaScript等)对动态内容进行字符编码转义”,结合参数化查询处理SQL注入,HTML实体编码或JavaScript转义处理XSS,两者协同可全面降低风险。
2) 【原理/概念讲解】SQL注入是用户输入恶意SQL语句,直接拼接进数据库查询,绕过验证。比如查询保单时,用户输入123' OR 1=1 --,拼接后SQL变成SELECT * FROM policy WHERE id = '123' OR 1=1 --',导致数据库返回所有记录。XSS是用户输入恶意脚本,直接输出到页面,浏览器执行脚本窃取信息。比如保单名称输入<script>alert('hacked')</script>,页面显示时脚本被执行。输入验证通过检查输入是否符合业务规则(如保单号是10位数字),过滤非法字符;输出编码将动态内容中的特殊字符(如<、>、&)转换为HTML实体(如<、>、&`),防止脚本执行。比如保单名称是用户输入的,输出前转义后显示为文本而非执行脚本。
3) 【对比与适用场景】
| 方法 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 参数化查询 | SQL语句与参数分离,参数用占位符,由数据库引擎处理 | 数据库自动处理参数,不会解析SQL | 任何动态SQL场景(查询、插入) | 需数据库支持(如MySQL的预编译语句,PostgreSQL的$1等) |
| 手动转义 | 拼接前对特殊字符(如'、;)转义(如'→'') | 依赖开发者正确转义所有字符 | 小型项目或旧系统 | 容易遗漏字符(如注释符--、分号;),导致漏洞 |
| 方法 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 输入验证 | 检查输入是否符合业务规则(如保单号长度、格式,状态为枚举值) | 过滤非法输入,防止注入 | 所有用户输入(表单、API参数) | 需覆盖所有输入点,复杂输入用正则或JSON Schema验证 |
| 输出编码 | 将动态内容中的特殊字符转换为HTML实体(HTML)或JavaScript转义(JS) | 防止浏览器解析为脚本 | 页面输出、API返回 | 需针对不同上下文编码(HTML转义<、>、&;JS转义引号"、反斜杠\;CSS转义引号") |
4) 【示例】(处理保单信息的代码示例,伪代码)
def validate_policy_input(policy_id, status):
# 白名单验证:保单号是10位数字,状态为枚举值(如active, inactive)
if not policy_id.isdigit() or len(policy_id) != 10:
raise ValueError("保单号格式错误")
if status not in ["active", "inactive"]:
raise ValueError("保单状态无效")
return policy_id, status
policy_id, status = validate_policy_input(request.form['policy_id'], request.form['status'])
query = "SELECT * FROM policy WHERE id = %s AND status = %s"
cursor.execute(query, (policy_id, status))
result = cursor.fetchall()
policy_name = result[0]['name']
policy_desc = result[0]['description']
# HTML实体编码
encoded_name = html.escape(policy_name)
encoded_desc = html.escape(policy_desc)
html_response = f"""
<div>
<h2>{encoded_name}</h2>
<p>{encoded_desc}</p>
</div>
"""
const statusText = result[0]['status'] === 'active' ? '活跃' : '不活跃';
// JavaScript转义
const safeStatus = statusText.replace(/"/g, '"').replace(/\\/g, '\\\\');
const js_code = `alert('保单状态:${safeStatus}')`;
const style = result[0]['style'] || 'default';
// CSS转义引号
const safeStyle = style.replace(/"/g, '"');
const css_code = `.policy-item { color: ${safeStyle}; }`;
5) 【面试口播版答案】(约90秒):
“面试官您好,防止SQL注入和XSS攻击的核心是输入端严格验证输入数据,输出端针对不同上下文对动态内容编码。比如处理保单信息时,首先对保单号做输入验证,确保是10位数字(白名单策略),然后用参数化查询,把用户输入当作参数,而不是拼接进SQL语句,这样数据库不会解析恶意SQL。比如查询代码是SELECT * FROM policy WHERE id = %s,传入保单号,数据库自动处理,不会执行非法操作。对于XSS,输出时对动态内容进行编码,比如保单名称是用户输入的,输出前转义HTML特殊字符,防止脚本执行。比如用户输入<script>alert(1)</script>,编码后变成<script>alert(1)</script>,显示为文本。另外,输入验证还要覆盖所有输入点,比如API参数,状态字段用枚举值验证。输出编码要区分上下文,HTML用实体编码,JavaScript用转义引号和反斜杠,CSS转义引号,这样能全面防御SQL注入和XSS。结合这些措施,能有效降低风险。”
6) 【追问清单】
?占位符,PostgreSQL用$1,SQL Server用@param,但核心都是将SQL和参数分离,由数据库引擎处理,避免SQL解析。7) 【常见坑/雷区】
--、分号;),导致SQL注入漏洞。a123也能通过。