前言:为什么这两个漏洞永远面不腻?
在2026年的今天,你可能会想:ORM一把梭、框架自带防护,SQL注入和XSS这类「古典漏洞」早该退出历史舞台了吧?
现实很打脸。根据最新安全审计数据,SQL注入和XSS依然霸榜Web漏洞Top 2。原因很简单:框架能帮你挡掉大部分明面上的问题,但拼接SQL的场景无处不在——报表导出、动态排序、复杂查询、存储过程调用……只要有一个地方手写了字符串拼接,整座城堡就可能出现裂缝。
这也是为什么面试官永远爱问这两道题——它考察的不是你背答案的能力,而是你对Web安全底层逻辑的理解深度。
第一章 SQL注入:从原理到六种类型全覆盖
1.1 什么是SQL注入?一句话说清楚
SQL注入(SQL Injection)是指攻击者通过在用户输入中嵌入恶意的SQL代码片段,欺骗后端数据库引擎执行非预期的SQL命令,从而达到窃取、篡改或删除数据的目的。
// 有漏洞的代码(Java示例) String sql = "SELECT * FROM users WHERE username = '" + request.getParameter("username") + "'" + " AND password = '" + request.getParameter("pwd") + "'";// 攻击者输入 username 为:' OR '1'='1' --// 实际执行的SQL变成: SELECT * FROM users WHERE username = '' OR '1'='1' --' AND password = ''→ 永真条件绕过认证,直接登录!
1.2 SQL注入的六大类型(面试必答)
① 联合查询注入(Union-based) 适用场景:页面会回显数据库查询结果 核心Payload:' UNION SELECT username,password FROM users -- 关键点:列数要匹配(用 ORDER BY 判断列数)② 报错注入(Error-based) 适用场景:开启详细错误信息输出 典型函数:ExtractValue(), UpdateXML(), exp()(MySQL) 原理:构造让数据库报错的SQL,从错误信息中提取数据③ 布尔盲注(Boolean-based Blind) 适用场景:页面只有「正常/异常」两种状态 判断逻辑:' AND 1=1 (正常)/ ' AND 1=2 (异常) 逐字符猜解:ASCII() + SUBSTRING() 逐位提取④ 时间盲注(Time-based Blind) 适用场景:页面没有任何差异响应 核心函数:SLEEP(), BENCHMARK()(MySQL) 判断依据:响应时间差异(如 IF(1=1,SLEEP(5),0))⑤ 堆叠查询注入(Stacked Queries) 前提条件:数据库支持多语句执行且权限允许 示例:'; DROP TABLE users; -- 危害最大:可直接执行任意DDL/DML语句⑥ 二次注入(Second Order) 特点:恶意数据先存入数据库,后被读取时触发注入 场景:注册→存储→其他功能读取时被执行 最难防范:即使入库时做了转义,读取拼接时仍可能触发
1.3 注入位置不仅限于输入框
面试加分项:能说出更多注入点说明实战经验丰富。
📍 常见注入点分布: • GET参数:?id=1, ?search=keyword, ?category=xxx • POST表单:登录框、搜索框、订单筛选 • HTTP Header:User-Agent、Referer、Cookie(XFF也常见) • RESTful API:/api/users/1, /api/orders?sort=price • JSON请求体:{"filter": {"name": "admin'}} • NoSQL:MongoDB的 $where、$ne 操作符注入
第二章 XSS跨站脚本:三种形态与攻击链路
2.1 XSS本质:代码在错误的上下文中执行
XSS(Cross Site Scripting)的核心原理是:攻击者注入的JavaScript代码在受害者的浏览器中被当作合法脚本执行。注意关键词——「受害者浏览器」,这意味着XSS攻击的目标是用户,而不是服务器。
2.2 三种XSS类型对比(面试核心考点)
🔴 反射型XSS(Reflected XSS)触发方式:恶意URL中的参数直接被页面输出典型场景:搜索框、错误页、跳转链接攻击流程:构造恶意链接 → 发给受害者点击 → 参数反射到页面 → JS执行持久性:非持久,需要诱骗点击示例:/search?q=<script>stealCookie()</script>🟠 存储型XSS(Stored / Persistent XSS)触发方式:恶意内容被服务器存入数据库,每次访问都触发典型场景:评论区、留言板、个人信息页、商品评价攻击流程:提交恶意内容 → 服务端存储 → 其他用户访问时加载执行持久性:持久,危害最大,可蠕虫式传播案例:2005年 Samy 蠕虫(MySpace),20014年微博XSS蠕虫🟡 DOM型XSS(DOM-based XSS)触发方式:前端JS动态修改DOM时未过滤输入典型场景:location.hash、document.URL、document.referrer特点:恶意代码不经过服务器,纯前端问题难点:传统WAF无法检测(请求中不含恶意代码)示例:eval(location.hash.slice(1))
2.3 XSS能干什么?(危害全景)
☠️ XSS攻击矩阵: 🍪 窃取Cookie → document.cookie发送到攻击者服务器 → 会话劫持 🔑 键盘记录 → 监听onkeydown事件 → 记录密码/银行卡号 📸 网页篡改 → 修改DOM内容 → 钓鱼页面/虚假公告 🚪 流量劫持 → window.location重定向 → 恶意站点 📷 摄像头/麦克风 → getUserMedia() API → 隐私窃取 🕷️ 蠕虫传播 → 自动发消息/发帖 → 指数级扩散 🔗 结合CSRF → 利用已登录状态 → 执行非预期操作
第三章 防御方案:从原理到落地
3.1 SQL注入防御三板斧
🥇 第一板斧:参数化查询(Prepared Statement)
这是最有效、最根本的防御手段。原理:SQL语句结构与数据分离,数据库驱动程序负责正确处理参数转义,用户输入永远不会被解释为SQL代码。
// Java PreparedStatement 示例 String sql = "SELECT * FROM users WHERE username = ? AND password = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, username); // 安全,自动转义 pstmt.setString(2, password); // 安全,自动转义 ResultSet rs = pstmt.executeQuery();
🥈 第二板斧:输入验证与白名单
• 类型检查:ID字段必须是整数,用 parseInt()/intval() • 长度限制:用户名不超过20字符,搜索词不超过100字符 • 白名单优于黑名单:只允许已知安全的字符通过 • ⚠️ 注意:输入验证是辅助手段,不能替代参数化查询
🥉 第三板斧:最小权限原则 + 错误处理
• 数据库账号不用root/sa,只给必要的SELECT/INSERT/UPDATE权限 • 关闭生产环境的详细错误信息输出 • 使用ORM时避免原生SQL拼接(如 raw() 方法) • 存储过程同样需要注意SQL拼接问题
3.2 XSS防御策略
🛡️ XSS防御层次模型:L1 输出编码(Output Encoding) ★★★★★ 根据输出上下文选择正确的编码方式: • HTML实体编码:& < > " ' • JS编码:\xHH, \uHHHH • URL编码:encodeURIComponent() • CSS编码:\HHHHHHL2 Content Security Policy (CSP) ★★★★☆ 通过HTTP头限制资源加载来源: Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.comL3 HttpOnly Cookie ★★★★★ Set-Cookie: sessionid=xxx; HttpOnly; Secure; SameSite=Strict → 即使发生XSS,JS也无法读取cookieL4 输入过滤(Input Filtering) ★★★☆☆ 使用成熟的HTML净化库(如DOMPurify) ⚠️ 过滤不能替代编码,只是额外防线
3.3 WAF绕过:面试高频追问
面试官经常追问:「如果对方部署了WAF怎么办?」以下是一些经典绕过思路(仅用于安全研究和授权测试):
🔄 SQL注入WAF绕过技巧: • 大小写混合:SeLeCt * FrOm • 内联注释:/*!50000UNION*/ SELECT • 编码绕过:URL编码、Unicode、Hex • 空格替代:/**/, %09(TAB), %0a(换行) • 等价函数:CONCAT()||SUBSTR(), CHAR()||ASCII() • HTTP参数污染(HPP):?id=1&id=2🔄 XSS WAF绕过技巧: • 事件属性变体:onload/onerror/onfocus/onmouseover • 标签变体:<img/svg/body/details/marquee> • 编码混淆:HTML实体、Base64、Unicode • JavaScript伪协议变体:javascript:, vbscript:, data: • CSP绕过:jsonp endpoint、domain relaxtion、
第四章 面试模拟:高频问题标准回答
Q1:参数化查询为什么能防止SQL注入?A:因为参数化查询将SQL命令结构和用户数据分开传输。数据库驱动在执行前先将SQL语句编译为执行计划(Prepare阶段),此时参数占位符的类型已确定。后续传入的参数无论内容是什么,都只会被当作字面量数据处理,不会被二次解析为SQL语法。就像预编译好的模板,填空的内容不会改变模板结构本身。Q2:存储型XSS和反射型XSS哪个危害更大?为什么?A:存储型XSS危害更大。原因有三:(1) 持久性——恶意代码存在服务器端,每个访问该页面的用户都会中招;(2) 隐蔽性——攻击者无需持续发送链接,一次提交长期生效;(3) 可蠕虫化——如Samy Worm、新浪微博XSS蠕虫,可实现指数级自我复制传播。反射型XSS需要社会工程学配合(诱骗点击),影响范围有限。Q3:如何对一个目标做完整的SQL注入测试?A:标准流程如下: ① 信息收集 → 确定技术栈(报错信息、响应特征) ② 注入点探测 → 单引号、双引号、and 1=1/1=2 ③ 判断注入类型 → 联合/报错/布尔/时间 ④ 字段/表名猜测 → information_schema / sysobjects ⑤ 数据提取 → 脱敏/加密字段重点关照 ⑥ 权限提升 → 读写文件、UDF提权 ⑦ 清理痕迹 → 删除日志(仅授权测试)Q4:CSP能不能完全防止XSS?A:CSP是重要的纵深防御手段,但不能完全依赖。已知绕过方式包括:JSONP端点、<base>标签劫持、域名配置过于宽松(如允许 *.cdn.com)、某些浏览器CSP实现差异等。正确的做法是CSP + 输出编码 + HttpOnly组合使用,形成多层防御。
第五章 总结:安全思维比背诵更重要
面试官问SQL注入和XSS,真正想考察的不是你能不能背出十种绕过技巧,而是:
✅ 你是否理解漏洞产生的根本原因(信任边界模糊) ✅ 你是否掌握系统化的防御方法论(而非单一手段) ✅ 你是否有实战经验(能说出真实场景中的坑) ✅ 你的安全意识是否融入日常开发习惯
记住:安全不是一个功能,而是一种贯穿全生命周期的思维方式。从需求评审时的威胁建模,到代码审查时的安全Checklist,再到上线前的渗透测试——每一步都不能缺席。