Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
368 lines
8.1 KiB
Markdown
368 lines
8.1 KiB
Markdown
# 🔒 YARP 网关安全审计报告
|
||
|
||
> 审计日期:2026-02-28
|
||
> 审计范围:认证授权、注入漏洞、敏感信息、访问控制、配置安全
|
||
|
||
---
|
||
|
||
## 执行摘要
|
||
|
||
| 严重程度 | 数量 |
|
||
|---------|------|
|
||
| 🔴 严重 (CRITICAL) | 3 |
|
||
| 🟠 高危 (HIGH) | 3 |
|
||
| 🟡 中危 (MEDIUM) | 4 |
|
||
| 🟢 低危 (LOW) | 3 |
|
||
| **总计** | **13** |
|
||
|
||
---
|
||
|
||
## 🔴 严重漏洞
|
||
|
||
### 1. 硬编码数据库凭据泄露
|
||
|
||
**文件:** `src/appsettings.json` 第 19 行
|
||
|
||
**问题代码:**
|
||
```json
|
||
"DefaultConnection": "Host=81.68.223.70;Port=15432;Database=fengling_gateway;Username=movingsam;Password=sl52788542"
|
||
```
|
||
|
||
**攻击场景:**
|
||
- 代码泄露或被推送到公开仓库时,攻击者直接获得数据库完整访问权限
|
||
- 可读取、修改、删除所有业务数据
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
// 使用环境变量或 Secret Manager
|
||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
||
// 或使用 Azure Key Vault / AWS Secrets Manager
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 硬编码 Redis 凭据泄露
|
||
|
||
**文件:** `src/Config/RedisConfig.cs` 第 5 行
|
||
|
||
**问题代码:**
|
||
```csharp
|
||
public string ConnectionString { get; set; } = "81.68.223.70:16379,password=sl52788542";
|
||
```
|
||
|
||
**攻击场景:**
|
||
- 攻击者可连接 Redis 服务器,读取缓存数据、修改路由配置、注入恶意数据
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
public string ConnectionString { get; set; } = string.Empty;
|
||
// 从环境变量或配置中心读取
|
||
```
|
||
|
||
---
|
||
|
||
### 3. 管理 API 完全无认证保护
|
||
|
||
**文件:** `src/Controllers/GatewayConfigController.cs` 及 `src/Controllers/PendingServicesController.cs`
|
||
|
||
**问题描述:**
|
||
- 所有 API 端点均无 `[Authorize]` 特性
|
||
- `Program.cs` 中未配置 `AddAuthentication()` 和 `UseAuthentication()`
|
||
- 项目搜索未发现任何认证中间件
|
||
|
||
**攻击场景:**
|
||
```
|
||
# 攻击者可直接调用以下 API:
|
||
POST /api/gateway/tenants # 创建任意租户
|
||
DELETE /api/gateway/tenants/{id} # 删除租户
|
||
POST /api/gateway/routes # 创建恶意路由
|
||
POST /api/gateway/config/reload # 重载配置
|
||
DELETE /api/gateway/clusters/{id} # 删除服务集群
|
||
```
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
// Program.cs
|
||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||
.AddJwtBearer(options => { /* 配置 JWT 验证 */ });
|
||
|
||
builder.Services.AddAuthorization();
|
||
|
||
app.UseAuthentication();
|
||
app.UseAuthorization();
|
||
|
||
// Controllers
|
||
[ApiController]
|
||
[Route("api/gateway")]
|
||
[Authorize] // 添加认证要求
|
||
public class GatewayConfigController : ControllerBase
|
||
```
|
||
|
||
---
|
||
|
||
## 🟠 高危漏洞
|
||
|
||
### 4. JWT 签名验证缺失
|
||
|
||
**文件:** `src/Middleware/JwtTransformMiddleware.cs` 第 39-40 行
|
||
|
||
**问题代码:**
|
||
```csharp
|
||
var jwtHandler = new JwtSecurityTokenHandler();
|
||
var jwtToken = jwtHandler.ReadJwtToken(token); // 仅读取,不验证!
|
||
```
|
||
|
||
**攻击场景:**
|
||
```python
|
||
# 攻击者可伪造任意 JWT
|
||
import jwt
|
||
fake_token = jwt.encode({"tenant": "admin-tenant", "sub": "admin"}, "any_secret", algorithm="HS256")
|
||
# 网关会接受这个伪造的 token
|
||
```
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
var validationParameters = new TokenValidationParameters
|
||
{
|
||
ValidateIssuer = true,
|
||
ValidateAudience = true,
|
||
ValidateLifetime = true,
|
||
ValidateIssuerSigningKey = true,
|
||
ValidIssuer = _jwtConfig.Authority,
|
||
ValidAudience = _jwtConfig.Audience,
|
||
IssuerSigningKey = /* 从 Authority 获取公钥 */
|
||
};
|
||
|
||
var principal = jwtHandler.ValidateToken(token, validationParameters, out _);
|
||
```
|
||
|
||
---
|
||
|
||
### 5. 租户隔离可被 Header 注入绕过
|
||
|
||
**文件:** `src/Middleware/JwtTransformMiddleware.cs` 第 54 行
|
||
|
||
**问题代码:**
|
||
```csharp
|
||
context.Request.Headers["X-Tenant-Id"] = tenantId;
|
||
```
|
||
|
||
**攻击场景:**
|
||
```bash
|
||
# 攻击者直接注入 Header 绕过 JWT
|
||
curl -H "X-Tenant-Id: target-tenant" \
|
||
-H "X-User-Id: admin" \
|
||
-H "X-Roles: admin" \
|
||
https://gateway/api/sensitive-data
|
||
```
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
// 在中间件开始时移除所有 X-* Header
|
||
foreach (var header in context.Request.Headers.Where(h => h.Key.StartsWith("X-")).ToList())
|
||
{
|
||
context.Request.Headers.Remove(header.Key);
|
||
}
|
||
|
||
// 然后再从 JWT 设置可信的 header
|
||
```
|
||
|
||
---
|
||
|
||
### 6. 租户路由信息泄露
|
||
|
||
**文件:** `src/Middleware/TenantRoutingMiddleware.cs` 第 44 行
|
||
|
||
**问题代码:**
|
||
```csharp
|
||
_logger.LogWarning("Route not found - Tenant: {Tenant}, Service: {Service}", tenantId, serviceName);
|
||
```
|
||
|
||
**攻击场景:**
|
||
- 日志中记录租户 ID 和服务名,攻击者可通过日志收集系统架构信息
|
||
- 配合其他攻击进行侦察
|
||
|
||
**修复建议:**
|
||
- 敏感信息不应记录到普通日志
|
||
- 使用脱敏处理或仅记录哈希值
|
||
|
||
---
|
||
|
||
## 🟡 中危漏洞
|
||
|
||
### 7. 日志记录敏感连接信息
|
||
|
||
**文件:** `src/Services/RedisConnectionManager.cs` 第 44 行
|
||
|
||
**问题代码:**
|
||
```csharp
|
||
_logger.LogInformation("Connected to Redis at {ConnectionString}", _config.ConnectionString);
|
||
```
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
_logger.LogInformation("Connected to Redis at {Host}",
|
||
configuration.EndPoints.FirstOrDefault()?.ToString());
|
||
```
|
||
|
||
---
|
||
|
||
### 8. CORS 凭据配置存在风险
|
||
|
||
**文件:** `src/Program.cs` 第 89-100 行
|
||
|
||
**问题代码:**
|
||
```csharp
|
||
if (allowAnyOrigin)
|
||
{
|
||
policy.AllowAnyOrigin();
|
||
}
|
||
// ...
|
||
policy.AllowAnyHeader()
|
||
.AllowAnyMethod()
|
||
.AllowCredentials(); // 与 AllowAnyOrigin 不兼容
|
||
```
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
if (allowAnyOrigin)
|
||
{
|
||
policy.AllowAnyOrigin()
|
||
.AllowAnyHeader()
|
||
.AllowAnyMethod();
|
||
// 不允许 AllowCredentials
|
||
}
|
||
else
|
||
{
|
||
policy.WithOrigins(allowedOrigins)
|
||
.AllowAnyHeader()
|
||
.AllowAnyMethod()
|
||
.AllowCredentials();
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 9. 健康检查端点信息泄露
|
||
|
||
**文件:** `src/Program.cs` 第 115 行
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
// 添加访问限制或使用标准健康检查
|
||
builder.Services.AddHealthChecks();
|
||
app.MapHealthChecks("/health", new HealthCheckOptions
|
||
{
|
||
ResponseWriter = async (c, r) =>
|
||
await c.Response.WriteAsync("healthy")
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
### 10. JWT Authority 使用占位符 URL
|
||
|
||
**文件:** `src/appsettings.json` 第 22 行
|
||
|
||
**问题代码:**
|
||
```json
|
||
"Authority": "https://your-auth-server.com"
|
||
```
|
||
|
||
**修复建议:**
|
||
- 强制要求配置有效的 Authority URL
|
||
- 启动时验证配置有效性
|
||
|
||
---
|
||
|
||
## 🟢 低危漏洞
|
||
|
||
### 11. 可预测的 ID 生成
|
||
|
||
**文件:** `src/Controllers/GatewayConfigController.cs` 第 484-487 行
|
||
|
||
**问题代码:**
|
||
```csharp
|
||
private long GenerateId()
|
||
{
|
||
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||
}
|
||
```
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
// 使用 GUID 或雪花算法
|
||
private long GenerateId() => SnowflakeIdGenerator.NextId();
|
||
// 或
|
||
private string GenerateId() => Guid.NewGuid().ToString("N");
|
||
```
|
||
|
||
---
|
||
|
||
### 12. 缺少输入验证
|
||
|
||
**文件:** `src/Controllers/GatewayConfigController.cs` 多处
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
public class CreateTenantDto
|
||
{
|
||
[Required]
|
||
[RegularExpression(@"^[a-zA-Z0-9-]{1,50}$")]
|
||
public string TenantCode { get; set; } = string.Empty;
|
||
|
||
[Required]
|
||
[StringLength(100, MinimumLength = 1)]
|
||
public string TenantName { get; set; } = string.Empty;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 13. 错误消息暴露内部信息
|
||
|
||
**文件:** `src/Controllers/PendingServicesController.cs` 第 116 行
|
||
|
||
**修复建议:**
|
||
```csharp
|
||
return BadRequest(new { message = "Invalid cluster configuration" });
|
||
```
|
||
|
||
---
|
||
|
||
## 📋 修复优先级建议
|
||
|
||
| 优先级 | 漏洞编号 | 修复时间建议 |
|
||
|-------|---------|------------|
|
||
| P0 (立即) | #1, #2, #3 | 24小时内 |
|
||
| P1 (紧急) | #4, #5, #6 | 1周内 |
|
||
| P2 (重要) | #7, #8, #9, #10 | 2周内 |
|
||
| P3 (一般) | #11, #12, #13 | 1个月内 |
|
||
|
||
---
|
||
|
||
## 🛡️ 安全加固建议
|
||
|
||
### 1. 认证授权
|
||
- 实施完整的 JWT 验证流程
|
||
- 为所有管理 API 添加 `[Authorize]`
|
||
- 实施基于角色的访问控制 (RBAC)
|
||
|
||
### 2. 配置安全
|
||
- 使用 Azure Key Vault / AWS Secrets Manager 管理密钥
|
||
- 移除所有硬编码凭据
|
||
- 生产环境禁用调试模式
|
||
|
||
### 3. 租户隔离
|
||
- 在网关层强制验证租户归属
|
||
- 使用加密签名验证内部 Header
|
||
- 实施租户数据隔离审计
|
||
|
||
### 4. 日志安全
|
||
- 敏感信息脱敏
|
||
- 限制日志访问权限
|
||
- 使用结构化日志便于审计
|
||
|
||
---
|
||
|
||
*报告由安全审计生成,建议人工复核后纳入迭代计划。* |