Appearance
本模块涵盖 Web 安全最核心的攻击手段与防御方案,包括 XSS、CSRF、SQL 注入、文件上传、SSRF、命令注入等常见漏洞类型,以及 OWASP Top 10 安全风险清单。是安全工程师、后端开发、前端开发面试的必考内容。
Q1: 什么是XSS攻击?有哪些类型?如何防御? 「🟡 中级」
考察点:考察 Web 安全最基础也是最重要的 XSS 漏洞。筛掉对 Web 安全毫无概念、不知道前端渲染风险的开发人员。
参考答案:
XSS(Cross-Site Scripting,跨站脚本攻击)是指攻击者在网页中注入恶意脚本,当用户浏览页面时脚本在浏览器中执行,从而窃取用户信息、操纵页面内容或进行其他恶意操作。
三种主要类型:
反射型 XSS(Reflected XSS)
- 恶意脚本通过 URL 参数传递,服务端将参数反射到页面中
- 攻击流程:攻击者构造恶意链接 → 用户点击 → 服务端返回包含脚本的页面 → 脚本执行
- 特点:非持久化,需要诱导用户点击链接
- 示例:
http://example.com/search?q=<script>alert(1)</script>
存储型 XSS(Stored XSS)
- 恶意脚本被存储到服务端(数据库、文件等),其他用户访问时自动执行
- 攻击流程:攻击者提交包含脚本的内容 → 服务端存储 → 其他用户浏览页面 → 脚本执行
- 特点:持久化,危害更大,常见于评论区、留言板、个人资料等
DOM 型 XSS(DOM-based XSS)
- 恶意脚本在客户端 DOM 解析时执行,不经过服务端处理
- 攻击流程:攻击者构造恶意 URL → 前端 JS 读取 URL 参数并插入 DOM → 脚本执行
- 特点:完全发生在客户端,服务端日志可能无记录
防御方案:
- 输入转义/输出编码:对所有用户输入进行转义,根据输出上下文(HTML/JS/CSS/URL)使用不同的编码方式
- CSP(内容安全策略):设置
Content-Security-Policy响应头,限制脚本加载来源,禁止内联脚本执行 - HttpOnly Cookie:将敏感 Cookie 设置为 HttpOnly,防止被 XSS 窃取
- 输入验证:对白名单字符进行校验,过滤危险标签和属性
- 使用安全的模板引擎:现代前端框架(Vue/React)默认会对插值内容进行转义
追问延伸:
- CSP 有哪些指令?
default-src、script-src、style-src、img-src分别控制什么? - 如果 CSP 设置了
script-src 'self',还能被 XSS 利用吗?(可以,通过上传 JS 文件、JSONP 绕过等) - 什么是 XSS 蠕虫?如何传播?
- 如何绕过前端转义?双写绕过、编码绕过、利用标签事件等
Q2: 什么是CSRF攻击?原理是什么?怎么防御? 「🟡 中级」
考察点:考察跨站请求伪造的理解。筛掉不清楚浏览器同源策略、Cookie 发送机制的开发人员。
参考答案:
CSRF(Cross-Site Request Forgery,跨站请求伪造)是指攻击者诱导用户在已登录的情况下,访问恶意网站,利用用户的登录状态,以用户的名义向目标网站发送请求,执行非用户本意的操作。
攻击原理:
用户已登录 A 网站(浏览器保存了 A 的 Cookie)
↓
用户访问攻击者的 B 网站
↓
B 网站的页面中包含向 A 网站发起请求的代码(img/form/script 等)
↓
浏览器自动携带 A 网站的 Cookie 发送请求
↓
A 网站验证通过,执行了用户不知情的操作与 XSS 的区别:
- XSS:利用用户对网站的信任,注入脚本在网站内执行
- CSRF:利用网站对用户浏览器的信任,伪造用户发起请求
- XSS 可以用来实现 CSRF(通过 XSS 窃取 Token 后发起请求)
防御方案:
CSRF Token
- 服务端生成随机 Token,嵌入到表单或请求头中
- 每次请求携带 Token,服务端验证有效性
- 攻击者无法获取到 Token,因此无法伪造请求
SameSite Cookie 属性
Strict:完全禁止第三方 Cookie,跨站时不发送Lax:仅允许安全的顶级导航(如点击链接)携带 CookieNone:允许跨站发送,但必须配合 Secure 属性
验证 Referer / Origin
- 检查请求的来源是否为合法域名
- 缺点:Referer 可能被伪造或禁用
二次验证
- 敏感操作要求输入密码、短信验证码等
追问延伸:
- SameSite 的 Lax 和 Strict 有什么区别?什么场景下 Cookie 会被发送?
- 如果网站使用 JSON 接口(Content-Type: application/json),还需要担心 CSRF 吗?
- 常规情况下 form 表单无法发送 JSON Content-Type,但可以通过 Flash 或某些 CORS 配置绕过
- CSRF Token 为什么放在请求头里比放在表单里更安全?
- 什么是 CSRF 的登录攻击?
Q3: 什么是SQL注入?有哪些类型?如何防止? 「🟡 中级」
考察点:考察数据库安全最经典的漏洞。筛掉写代码时直接拼接 SQL、不了解预编译的开发人员。
参考答案:
SQL 注入(SQL Injection)是指攻击者通过在输入中插入恶意 SQL 代码,操纵后端数据库执行非预期的查询,从而获取、篡改数据,甚至控制服务器。
攻击原理:
php
// 不安全的代码:直接拼接 SQL
$sql = "SELECT * FROM users WHERE username = '" . $_GET['username'] . "'";
// 输入:' OR '1'='1
// 变成:SELECT * FROM users WHERE username = '' OR '1'='1'主要类型:
联合注入(Union-based)
- 使用
UNION SELECT合并查询结果,直接获取数据 - 要求前后查询列数一致、数据类型兼容
- 使用
盲注(Blind SQL Injection)
- 布尔盲注:根据页面返回是否正确判断条件真假
- 时间盲注:通过
SLEEP()等函数根据响应时间判断 - 特点:页面不直接显示查询结果,需要逐字符猜解
堆叠注入(Stacked Queries)
- 利用分号
;同时执行多条 SQL 语句 - 取决于数据库驱动是否支持多语句执行
- 利用分号
报错注入(Error-based)
- 利用数据库报错信息带出数据
- 如 MySQL 的
updatexml()、extractvalue()函数
防御方案:
预编译(Prepared Statements)+ 参数化查询
- 使用
?占位符,SQL 结构和数据分离 - 是最根本、最有效的防御手段
- 使用
ORM 框架
- 使用 MyBatis、Hibernate、Django ORM 等
- 注意避免在 ORM 中写原生 SQL 拼接
输入验证和过滤
- 白名单校验:限制输入格式(数字、邮箱、手机号等)
- 黑名单过滤:转义特殊字符(辅助手段,不建议作为主要防御)
WAF(Web 应用防火墙)
- 检测和拦截常见 SQL 注入特征
- 作为纵深防御的一环
最小权限原则
- 数据库账号只授予必要权限,禁止 DROP、FILE 等高危操作
追问延伸:
- 预编译为什么能防 SQL 注入?原理是什么?
- MyBatis 中
#{}和${}的区别?哪个会导致注入? - 什么是宽字节注入?什么场景下会出现?
- SQL 注入 bypass WAF 的方法有哪些?(注释绕过、编码绕过、大小写绕过等)
- order by 字段如何防注入?(因为字段名不能用预编译,需要白名单)
Q4: 什么是文件上传漏洞?怎么利用和防御? 「🟡 中级」
考察点:考察文件处理安全意识。筛掉对上传文件不做校验、直接存储执行的开发人员。
参考答案:
文件上传漏洞是指网站允许用户上传文件,但没有正确校验文件类型、内容或存储方式,导致攻击者可以上传恶意脚本文件(如 webshell),并通过访问该文件执行代码,最终控制服务器。
常见绕过方式:
后缀名绕过
- 黑名单绕过:
php5、phtml、php3、asp、asa、cer等 - 大小写绕过:
Php、pHp、ASP等(Windows 不区分大小写) - 点号绕过:
shell.php.(Windows 自动去掉末尾点号) - 空格绕过:
shell.php(Windows 自动去掉末尾空格) - ::DATA 绕过:
shell.php::DATA(NTFS 文件系统特性)
- 黑名单绕过:
MIME 类型绕过
- 只校验 Content-Type 字段
- 攻击者修改请求头为
image/jpeg即可绕过
00 截断绕过
- 利用
%00空字节截断文件名 - 常见于老版本 PHP(< 5.3.4),
move_uploaded_file等函数
- 利用
文件头绕过
- 只校验文件头(魔数),如 GIF89a
- 在脚本开头加上
GIF89a即可绕过
解析漏洞
- Apache:
shell.php.jpg可能被当作 PHP 解析 - Nginx:
/shell.jpg/shell.php路径解析漏洞 - IIS:文件名分号截断
shell.asp;.jpg
- Apache:
竞争条件上传
- 先上传后删除,在删除前访问执行
防御方案:
- 白名单校验:只允许指定的文件后缀上传(比黑名单安全)
- 文件重命名:上传后使用随机文件名 + 白名单后缀,避免直接访问原文件名
- 存储隔离:将上传文件存储在非 Web 可访问目录,通过脚本读取输出
- 内容检测:
- 检查文件头(魔数)
- 使用 getimagesize 检测图片尺寸
- 图片二次渲染(重新生成图片)
- 设置正确的 Content-Type:下载时强制设置为
application/octet-stream或对应类型 - 独立域名:上传文件使用独立域名,避免 Cookie 泄露和 XSS 影响主站
追问延伸:
- 如果只能上传图片,还能有什么危害?(图片马配合解析漏洞、XSS 中的 SVG 图片)
- 什么是 webshell?一句话木马原理是什么?
- 如何检测服务器上是否被植入了 webshell?
- 文件上传和 XSS 能结合吗?(上传 SVG/HTML 文件实现 XSS)
Q5: 什么是SSRF攻击?有什么危害? 「🔴 高级」
考察点:考察服务端请求伪造的深度理解。筛掉对内部网络安全无概念、随意调用外部 URL 的后端开发。
参考答案:
SSRF(Server-Side Request Forgery,服务端请求伪造)是指攻击者利用服务端的请求功能,构造请求访问内网资源或本地服务,从而探测内网结构、读取本地文件、攻击内网系统。
攻击原理:
用户提交一个 URL 给服务端
↓
服务端后端代码请求该 URL(如图片加载、网页抓取、资源获取)
↓
攻击者将 URL 改为内网地址或本地文件协议
↓
服务端以自身身份发起请求,访问了内网资源常见利用场景:
内网探测与端口扫描
- 访问
http://127.0.0.1:3306/判断 MySQL 是否存在 - 访问
http://192.168.1.0/24探测内网网段 - 根据响应时间、错误信息判断端口是否开放
- 访问
读取本地文件
- 使用
file:///etc/passwd协议读取本地文件 - 使用
gopher://协议构造 TCP 数据包
- 使用
攻击内网服务
- 攻击 Redis(未授权访问):
gopher://127.0.0.1:6379/_*1%0d%0a... - 攻击内网 MySQL、MongoDB 等
- 攻击内网 Web 应用(如 Jenkins、Elasticsearch)
- 攻击 Redis(未授权访问):
云环境元数据泄露
- 访问云服务商的元数据服务(169.254.169.254)
- 获取临时 Access Key、实例信息等
DoS 攻击
- 请求大文件、慢响应资源,消耗服务端资源
防御方案:
- 协议限制:只允许 http/https 协议,禁止 file://、gopher://、dict:// 等危险协议
- 内网地址黑名单:
- 禁用内网 IP 段(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、127.0.0.0/8)
- 禁用云元数据地址(169.254.169.254)
- DNS Rebinding 防护:
- 先解析 DNS,再校验 IP → 存在时间差问题
- 使用 DNS 缓存或直接使用 IP 白名单
- 设置 DNS TTL 为 0 并在请求后再次验证
- URL 白名单:只允许访问指定域名的资源
- 统一错误处理:不对外暴露目标服务的响应详情,防止信息泄露
- 使用独立出口:外网请求走独立的网络出口,与内网隔离
追问延伸:
- 什么是 DNS Rebinding?如何绕过 IP 黑名单?
- DNS 第一次返回外网 IP 通过校验,第二次返回内网 IP 实际请求
- SSRF 中常用的协议有哪些?各自能做什么?
- 如何利用 SSRF 攻击 Redis?能达到什么效果?
- 什么是半连接式 SSRF(blind SSRF)?如何利用?
- Java 和 PHP 中的 SSRF 有什么不同?(如 Java 的 URLConnection 会自动跳转)
Q6: 什么是命令注入/代码注入? 「🟡 中级」
考察点:考察系统安全意识。筛掉随意调用系统命令、不做参数校验的后端开发。
参考答案:
命令注入(Command Injection) 是指攻击者通过在输入中注入恶意命令,利用系统命令执行函数,在服务器上执行任意系统命令。
代码注入(Code Injection) 是指攻击者注入恶意代码,由应用程序的解释器执行,如 PHP 的 eval()、Python 的 exec() 等。
命令注入原理:
php
// 不安全的代码:直接将用户输入拼接到命令中
$ip = $_GET['ip'];
system("ping -c 4 " . $ip);
// 输入:127.0.0.1; cat /etc/passwd
// 执行:ping -c 4 127.0.0.1; cat /etc/passwd常见注入符号:
;:命令分隔符,顺序执行&&:前一个成功才执行后一个||:前一个失败才执行后一个|:管道符,将前一个输出作为后一个输入&:后台执行- 反引号
``和$():命令替换
代码注入示例:
php
// eval 代码注入
$str = $_GET['str'];
eval("\$str = $str;");
// 输入:phpinfo();python
# Python 代码注入
exec("result = " + user_input)防御方案:
- 避免使用危险函数:尽量不使用
system()、exec()、eval()等函数,改用编程语言内置 API - 白名单校验:如果必须执行命令,对输入参数进行严格的白名单校验
- 参数转义:使用
escapeshellarg()、escapeshellcmd()等函数转义特殊字符 - 使用安全的 API:
- 执行命令时使用参数数组形式(如 Python 的
subprocess.run([], shell=False)) - 避免使用
shell=True
- 执行命令时使用参数数组形式(如 Python 的
- 禁用危险函数:在 PHP.ini 中禁用
exec、system、shell_exec等 - 沙箱隔离:将执行命令的服务放在隔离环境中,限制权限和资源
追问延伸:
- 命令注入和代码注入有什么区别?
- 什么是无回显的命令注入?如何利用?(带外通信:DNS Log、HTTP 请求)
- 过滤了空格怎么绕过命令注入?(
${IFS}、%09、重定向等) - 什么是模板注入(SSTI)?和代码注入有什么关系?
- Windows 和 Linux 下命令注入的语法差异?
Q7: OWASP Top 10 有哪些? 「🟡 中级」
考察点:考察安全知识面的广度。筛掉不关注安全社区、对行业标准不了解的候选人。
参考答案:
OWASP(Open Web Application Security Project)是一个非营利的安全组织,其 Top 10 项目每几年更新一次,列出 Web 应用最关键的 10 项安全风险。
2021 版 OWASP Top 10:
A01:2021 - 失效的访问控制(Broken Access Control)
- 用户可以访问未经授权的资源或执行越权操作
- 包括水平越权、垂直越权、IDOR 等
- 从第 5 位上升到第 1 位
A02:2021 - 加密机制失效(Cryptographic Failures)
- 数据传输或存储时未使用适当的加密
- 明文密码、弱加密算法、证书问题等
- 由之前的"敏感数据泄露"更名而来,从第 3 位上升到第 2 位
A03:2021 - 注入(Injection)
- SQL 注入、命令注入、XSS 等
- 攻击者将恶意代码注入到应用中执行
- 从第 1 位下降到第 3 位
A04:2021 - 不安全设计(Insecure Design)
- 设计层面的缺陷,如缺少安全设计模式、威胁建模不足
- 2021 年新增类别,排名第 4
A05:2021 - 安全配置错误(Security Misconfiguration)
- 默认配置、不必要的功能、错误的权限设置
- 目录遍历、默认密码、错误信息泄露等
- 从第 6 位上升到第 5 位
A06:2021 - 自带缺陷和过时的组件(Vulnerable and Outdated Components)
- 使用存在已知漏洞的第三方库、框架
- 组件版本过久未更新
- 由之前的"使用含有已知漏洞的组件"更名
A07:2021 - 识别和认证失败(Identification and Authentication Failures)
- 身份认证机制存在缺陷
- 弱密码、暴力破解、Session 管理不当等
- 由之前的"身份认证失效"更名
A08:2021 - 软件和数据完整性故障(Software and Data Integrity Failures)
- 软件更新、关键数据未验证完整性
- 供应链攻击、CI/CD 管道漏洞
- 2021 年新增类别
A09:2021 - 安全日志和监控故障(Security Logging and Monitoring Failures)
- 缺乏安全日志记录和监控机制
- 攻击无法被及时发现和响应
- 由之前的"不足的日志记录和监控"更名,从第 10 位上升到第 9 位
A10:2021 - 服务端请求伪造(SSRF)
- 服务端请求伪造漏洞
- 2021 年新增,直接进入 Top 10
追问延伸:
- 2021 版相比 2017 版有哪些变化?新增了哪些类别?
- 你觉得哪个风险在实际项目中最常见?为什么?
- 针对 A01 失效的访问控制,你会怎么做?
- 什么是安全左移?和 Top 10 有什么关系?
- 你如何在项目中落地 OWASP Top 10 的防护?