本帖最后由 小七 于 2025-4-18 14:52 编辑
我们在开发 Web 应用的时候有考虑过安全问题吗?比如用户密码、数据的泄露,服务被恶意代码攻击导致瘫痪等,攻击者可以通过应用程序中许多不同的路径方法去危害我们的业务或者企业组织。 据统计,全球平均每39秒就发生一次网络攻击,而其中75%的突破口正是 Web 应用的安全漏洞。在这种背景下,全球性安全组织 OWASP(Open Web Application Security Project 开放网络应用安全项目) 发布了 Top 10 项目(每 3-4 年更新一次,目前最新版本是 2021 版)。 该项目列出了全球公认的十大最严重 Web 应用程序安全风险清单。旨在帮助开发人员、安全团队和企业优先关注对应用程序危害最大的安全威胁,并提供防御建议。 这篇文章从该清单前三项入手介绍一下 Web 应用常见攻击方式及防御措施(想了解完整 Top 10 清单的小伙伴 注:本文后端代码以 Java 为例
A01:失效的访问控制(Broken Access Control) 指系统未能正确验证用户权限,导致攻击者可以越权访问敏感数据或执行危险操作 通常由以下原因导致: - 未验证权限:直接信任用户请求中的参数(如 URL、Cookie)来决定权限
- 配置错误:默认开放高权限接口,或未限制敏感功能(如删除、管理员操作)
- 逻辑漏洞:通过修改参数(如用户 ID、角色标识)绕过权限检查
案例 1:水平越权(同角色用户互相访问) 用户 A 和用户 B 是普通用户,A 将 URL https://example.com/xxx?userId=123 改为 userId=456,直接查看用户 B 的数据
[AppleScript] 纯文本查看 复制代码 // 错误:直接使用用户传入的 ID 查询数据,未检查权限
String userId = request.getParameter("userId");
String sql = "SELECT * FROM orders WHERE user_id = " + userId;
案例 2:垂直越权(低权限用户访问高权限功能) 普通用户通过 Burp Suite 等工具直接调用 /admin/deleteUser 接口删除其他用户 [AppleScript] 纯文本查看 复制代码 // 错误:仅通过前端隐藏管理员按钮,但未在后端校验用户角色
@PostMapping("/admin/deleteUser")
public void deleteUser(String userId) {
userService.delete(userId);
}
防御措施(后端): - 所有权限校验必须由服务端完成,前端辅助校验
- 每个用户只能访问与其角色或属性匹配的资源
[AppleScript] 纯文本查看 复制代码 // 查询数据时绑定当前用户ID
String currentUserId = SecurityContext.getUser().getId();
String sql = "SELECT * FROM orders WHERE user_id = ?";
preparedStatement.setString(1, currentUserId); // 防止水平越权
- 使用 UUID 替代自增数字 ID / 对资源标识加密
- 记录用户操作日志,监控异常行为
防御措施(前端): [AppleScript] 纯文本查看 复制代码 // 错误:在 URL 中传递用户 ID
window.location.href = `/user?userId=123`;
// 正确:通过加密 token 或后端 Session 管理
window.location.href = `/user`; // 后端通过 Cookie 或 JWT 识别用户
- 避免在 localStorage 中存储密码或 token
- 屏蔽浏览器自动填充
[AppleScript] 纯文本查看 复制代码 <!-- 对敏感字段禁用自动填充 -->
<input type="password" autocomplete="new-password">
A02:加密机制失效(Cryptographic Failures)
指在保护敏感数据(如密码、信用卡号、API密钥)时,因错误使用加密算法或不当管理密钥,导致数据易被窃取或破解 通常由以下原因导致: - 使用弱加密算法:如 MD5、SHA-1、DES 等已被证明不安全的算法
- 明文存储或传输:敏感数据未加密(如密码明文存数据库)或通过 HTTP 明文传输
- 硬编码密钥/密码:将密钥直接写在代码或配置文件中
案例 1:弱哈希存储用户密码 用户密码用 MD5 哈希存储,无盐值(Salt)。攻击者通过彩虹表快速破解弱密码 [AppleScript] 纯文本查看 复制代码 // 错误:直接使用 MD5 哈希
import java.security.MessageDigest;
public class PasswordUtils {
public static String hashPassword(String password) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(password.getBytes());
return bytesToHex(hash); // e10adc3949ba59abbe56e057f20f883e
}
}
案例 2:HTTP 明文传输敏感数据
用户登录页未启用 HTTPS,密码通过 HTTP 传输。攻击者通过中间人攻击(如公共 Wi-Fi)窃听数据 [AppleScript] 纯文本查看 复制代码 // Spring Boot 未启用 HTTPS 的配置(application.properties)
server.port=80
server.ssl.enabled=false
防御措施(后端): - 使用 BCrypt 强哈希存储密码
- 强制 HTTPS 与 HSTS
- 使用 AES-GCM 模式加密算法
防御措施(前端):
- 避免前端处理敏感数据。直接传输明文密码(通过 HTTPS),由后端哈希和验证
- 禁用 localStorage 存储敏感数据
A03:注入(Injection)指攻击者通过将恶意代码/命令插入应用程序的输入参数中,欺骗后端执行非预期的操作 注入类型与攻击原理: - SQL 注入:通过篡改 SQL 查询逻辑,绕过验证或窃取数据
- OS 命令注入:通过用户输入执行非法系统命令(如 rm -rf /)
- NoSQL 注入:针对 MongoDB 等数据库的查询参数篡改
- LDAP 注入:篡改 LDAP 查询语句,绕过目录服务认证
- 模板注入:在服务端模板(如 Thymeleaf)中插入恶意代码
案例 1:SQL 注入绕过登录验证 直接拼接用户输入到 SQL 语句,攻击者输入 username admin' -- [AppleScript] 纯文本查看 复制代码 // 错误:直接拼接 SQL
String username = request.getParameter("username");
String password = request.getParameter("password");
String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
[AppleScript] 纯文本查看 复制代码 // 最终 SQL
SELECT * FROM users WHERE username = 'admin' -- ' AND password = '...'
|