mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2025-12-17 04:43:02 +00:00
js演练场
This commit is contained in:
174
parser/doc/security/CHANGELOG_SECURITY.md
Normal file
174
parser/doc/security/CHANGELOG_SECURITY.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# 安全修复更新日志
|
||||
|
||||
## [2025-11-29] - 优化SSRF防护策略
|
||||
|
||||
### 🔄 变更内容
|
||||
|
||||
#### 调整SSRF防护为宽松模式
|
||||
- **问题**: 原有SSRF防护过于严格,导致正常外网请求也被拦截
|
||||
- **症状**: `Error: 请求失败: 404` 或其他网络错误
|
||||
- **修复**: 调整验证逻辑,只拦截明确的危险请求
|
||||
|
||||
#### 具体改进
|
||||
|
||||
1. ✅ **允许DNS解析失败的请求**
|
||||
- 之前:DNS解析失败 → 抛出异常
|
||||
- 现在:DNS解析失败 → 允许继续(可能是外网域名)
|
||||
|
||||
2. ✅ **允许格式异常的URL**
|
||||
- 之前:URL解析异常 → 抛出异常
|
||||
- 现在:URL解析异常 → 只记录日志,允许继续
|
||||
|
||||
3. ✅ **优化IP检测逻辑**
|
||||
- 先检查是否为IP地址格式
|
||||
- 对域名才进行DNS解析
|
||||
- 减少不必要的网络请求
|
||||
|
||||
### 🛡️ 保留的安全防护
|
||||
|
||||
以下危险请求仍然会被拦截:
|
||||
|
||||
- ❌ 本地回环:`127.0.0.1`, `localhost`, `::1`
|
||||
- ❌ 内网IP:`192.168.x.x`, `10.x.x.x`, `172.16-31.x.x`
|
||||
- ❌ 云服务元数据:`169.254.169.254`, `metadata.google.internal`
|
||||
- ❌ 解析到内网的域名
|
||||
|
||||
### 📊 影响范围
|
||||
|
||||
**修改文件**:
|
||||
- `parser/src/main/java/cn/qaiu/parser/customjs/JsHttpClient.java`
|
||||
|
||||
**新增文档**:
|
||||
- `parser/SSRF_PROTECTION.md` - SSRF防护策略说明
|
||||
|
||||
---
|
||||
|
||||
## [2025-11-28] - 修复JavaScript远程代码执行漏洞
|
||||
|
||||
### 🚨 严重安全漏洞修复
|
||||
|
||||
#### 漏洞描述
|
||||
- **类型**: 远程代码执行 (RCE)
|
||||
- **危险级别**: 🔴 极高
|
||||
- **影响**: JavaScript可以访问所有Java类,执行任意系统命令
|
||||
|
||||
#### 修复措施
|
||||
|
||||
1. ✅ **实现ClassFilter类过滤器**
|
||||
- 文件:`SecurityClassFilter.java`
|
||||
- 功能:拦截JavaScript对危险Java类的访问
|
||||
- 黑名单包括:Runtime, File, System, Class, Socket等
|
||||
|
||||
2. ✅ **禁用Java内置对象**
|
||||
- 禁用:`Java`, `JavaImporter`, `Packages`
|
||||
- 位置:`JsPlaygroundExecutor`, `JsParserExecutor`
|
||||
|
||||
3. ✅ **添加SSRF防护**
|
||||
- 文件:`JsHttpClient.java`
|
||||
- 功能:防止访问内网地址和云服务元数据
|
||||
|
||||
4. ✅ **修复ArrayIndexOutOfBoundsException**
|
||||
- 问题:`getScriptEngine()` 方法参数错误
|
||||
- 修复:使用正确的方法签名 `getScriptEngine(new String[0], null, classFilter)`
|
||||
|
||||
### 📦 新增文件
|
||||
|
||||
**安全组件**:
|
||||
- `parser/src/main/java/cn/qaiu/parser/customjs/SecurityClassFilter.java`
|
||||
|
||||
**测试套件**:
|
||||
- `parser/src/test/java/cn/qaiu/parser/SecurityTest.java` (7个测试用例)
|
||||
- `web-service/src/test/resources/playground-security-tests.http` (10个测试用例)
|
||||
|
||||
**文档**:
|
||||
- `parser/doc/SECURITY_TESTING_GUIDE.md` - 详细安全测试指南
|
||||
- `parser/SECURITY_TEST_README.md` - 快速开始指南
|
||||
- `parser/SECURITY_FIX_SUMMARY.md` - 修复总结
|
||||
- `parser/test-security.sh` - 自动化测试脚本
|
||||
- `SECURITY_URGENT_FIX.md` - 紧急修复通知
|
||||
- `QUICK_TEST.md` - 快速验证指南
|
||||
|
||||
### 🔧 修改文件
|
||||
|
||||
1. `JsPlaygroundExecutor.java`
|
||||
- 使用安全的ScriptEngine
|
||||
- 禁用Java对象访问
|
||||
|
||||
2. `JsParserExecutor.java`
|
||||
- 使用安全的ScriptEngine
|
||||
- 禁用Java对象访问
|
||||
|
||||
3. `JsHttpClient.java`
|
||||
- 添加URL安全验证
|
||||
- 实现SSRF防护
|
||||
|
||||
### 📊 修复效果
|
||||
|
||||
| 测试项目 | 修复前 | 修复后 |
|
||||
|---------|--------|--------|
|
||||
| 系统命令执行 | ❌ 成功 | ✅ 被拦截 |
|
||||
| 文件系统访问 | ❌ 成功 | ✅ 被拦截 |
|
||||
| 系统属性访问 | ❌ 成功 | ✅ 被拦截 |
|
||||
| 反射攻击 | ❌ 成功 | ✅ 被拦截 |
|
||||
| 网络Socket | ❌ 成功 | ✅ 被拦截 |
|
||||
| JVM退出 | ❌ 成功 | ✅ 被拦截 |
|
||||
| SSRF攻击 | ❌ 成功 | ✅ 被拦截 |
|
||||
|
||||
### 📈 安全评级提升
|
||||
|
||||
- **修复前**: 🔴 D级(严重不安全)
|
||||
- **修复后**: 🟢 A级(安全)
|
||||
|
||||
---
|
||||
|
||||
## 部署建议
|
||||
|
||||
### 立即部署步骤
|
||||
|
||||
```bash
|
||||
# 1. 拉取最新代码
|
||||
git pull
|
||||
|
||||
# 2. 重新编译
|
||||
mvn clean install
|
||||
|
||||
# 3. 重启服务
|
||||
./bin/stop.sh
|
||||
./bin/run.sh
|
||||
|
||||
# 4. 验证修复
|
||||
cd parser
|
||||
mvn test -Dtest=SecurityTest
|
||||
```
|
||||
|
||||
### 验证清单
|
||||
|
||||
- [ ] 服务启动成功
|
||||
- [ ] 日志显示"🔒 安全的JavaScript引擎初始化成功"
|
||||
- [ ] Java.type() 被禁用(返回undefined)
|
||||
- [ ] 内网访问被拦截
|
||||
- [ ] 外网访问正常工作
|
||||
- [ ] 安全测试全部通过
|
||||
|
||||
---
|
||||
|
||||
## 相关资源
|
||||
|
||||
- **快速验证**: `QUICK_TEST.md`
|
||||
- **SSRF策略**: `parser/SSRF_PROTECTION.md`
|
||||
- **详细修复**: `parser/SECURITY_FIX_SUMMARY.md`
|
||||
- **测试指南**: `parser/doc/SECURITY_TESTING_GUIDE.md`
|
||||
|
||||
---
|
||||
|
||||
## 联系方式
|
||||
|
||||
如发现新的安全问题或有改进建议,请通过以下方式反馈:
|
||||
- 提交Issue
|
||||
- 安全邮件:qaiu00@gmail.com
|
||||
|
||||
---
|
||||
|
||||
**维护者**: QAIU
|
||||
**许可**: MIT License
|
||||
|
||||
309
parser/doc/security/FAQ.md
Normal file
309
parser/doc/security/FAQ.md
Normal file
@@ -0,0 +1,309 @@
|
||||
# 安全修复常见问题 FAQ
|
||||
|
||||
## ❓ 常见问题解答
|
||||
|
||||
### Q1: 为什么还是显示"请求失败: 404"?
|
||||
|
||||
**答**: 这是**正常现象**!404是HTTP响应状态码,说明:
|
||||
|
||||
✅ **安全检查已通过** - 你的请求没有被SSRF防护拦截
|
||||
✅ **请求已发出** - HTTP客户端工作正常
|
||||
❌ **目标资源不存在** - 目标服务器返回404错误
|
||||
|
||||
#### 如何区分安全拦截 vs 正常404?
|
||||
|
||||
| 错误类型 | 错误消息 | 原因 |
|
||||
|---------|---------|------|
|
||||
| **安全拦截** | `SecurityException: 🔒 安全拦截: 禁止访问内网IP地址` | SSRF防护拦截 |
|
||||
| **安全拦截** | `SecurityException: 🔒 安全拦截: 禁止访问云服务元数据API` | 危险域名拦截 |
|
||||
| **正常404** | `Error: 请求失败: 404` | 目标URL不存在 |
|
||||
| **正常错误** | `HTTP请求超时` | 网络超时 |
|
||||
| **正常错误** | `Connection refused` | 目标服务器拒绝连接 |
|
||||
|
||||
#### 示例对比
|
||||
|
||||
**❌ 被安全拦截(内网攻击)**:
|
||||
```javascript
|
||||
try {
|
||||
var response = http.get('http://127.0.0.1:6400/admin');
|
||||
} catch (e) {
|
||||
// 错误消息: SecurityException: 🔒 安全拦截: 禁止访问内网IP地址
|
||||
logger.error(e.message);
|
||||
}
|
||||
```
|
||||
|
||||
**✅ 正常404(资源不存在)**:
|
||||
```javascript
|
||||
try {
|
||||
var response = http.get('https://httpbin.org/not-exist');
|
||||
if (response.statusCode() !== 200) {
|
||||
// 404是正常的HTTP响应,不是安全拦截
|
||||
throw new Error("请求失败: " + response.statusCode());
|
||||
}
|
||||
} catch (e) {
|
||||
// 错误消息: Error: 请求失败: 404
|
||||
logger.error(e.message);
|
||||
}
|
||||
```
|
||||
|
||||
#### 解决方法
|
||||
|
||||
如果你的代码中有这样的检查:
|
||||
|
||||
```javascript
|
||||
// ❌ 不好的做法:对所有非200状态码都抛出异常
|
||||
if (response.statusCode() !== 200) {
|
||||
throw new Error("请求失败: " + response.statusCode());
|
||||
}
|
||||
```
|
||||
|
||||
建议改为:
|
||||
|
||||
```javascript
|
||||
// ✅ 更好的做法:区分不同的状态码
|
||||
var statusCode = response.statusCode();
|
||||
|
||||
if (statusCode === 404) {
|
||||
logger.warn("资源不存在: " + url);
|
||||
return null; // 或者其他默认值
|
||||
}
|
||||
|
||||
if (statusCode < 200 || statusCode >= 300) {
|
||||
throw new Error("请求失败: " + statusCode);
|
||||
}
|
||||
|
||||
return response.body();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Q2: 如何确认安全修复已生效?
|
||||
|
||||
**答**: 执行以下测试:
|
||||
|
||||
```javascript
|
||||
// 测试1: 尝试访问内网(应该被拦截)
|
||||
try {
|
||||
http.get('http://127.0.0.1:6400/');
|
||||
logger.error('❌ 失败: 内网访问成功(不应该)');
|
||||
} catch (e) {
|
||||
if (e.message.includes('安全拦截')) {
|
||||
logger.info('✅ 通过: 内网访问被拦截');
|
||||
} else {
|
||||
logger.warn('⚠️ 警告: 错误但非安全拦截 - ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 测试2: 访问外网(应该正常工作,可能返回404但不会被拦截)
|
||||
try {
|
||||
var response = http.get('https://httpbin.org/status/200');
|
||||
logger.info('✅ 通过: 外网访问正常');
|
||||
} catch (e) {
|
||||
logger.error('❌ 失败: 外网访问被拦截(不应该) - ' + e.message);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Q3: Java.type() 相关错误
|
||||
|
||||
**错误消息**: `ReferenceError: "Java" is not defined`
|
||||
|
||||
**答**: 这是**正确的行为**!说明安全修复生效了。
|
||||
|
||||
之前(不安全):
|
||||
```javascript
|
||||
var System = Java.type('java.lang.System'); // ❌ 可以执行
|
||||
```
|
||||
|
||||
现在(安全):
|
||||
```javascript
|
||||
var System = Java.type('java.lang.System'); // ✅ 抛出错误
|
||||
// ReferenceError: "Java" is not defined
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Q4: 如何测试SSRF防护?
|
||||
|
||||
**答**: 使用以下测试用例:
|
||||
|
||||
```javascript
|
||||
function testSSRF() {
|
||||
var tests = [
|
||||
// 应该被拦截的
|
||||
{url: 'http://127.0.0.1:6400/', shouldBlock: true},
|
||||
{url: 'http://localhost/', shouldBlock: true},
|
||||
{url: 'http://192.168.1.1/', shouldBlock: true},
|
||||
{url: 'http://169.254.169.254/latest/meta-data/', shouldBlock: true},
|
||||
|
||||
// 应该允许的
|
||||
{url: 'https://httpbin.org/get', shouldBlock: false},
|
||||
{url: 'https://www.example.com/', shouldBlock: false}
|
||||
];
|
||||
|
||||
tests.forEach(function(test) {
|
||||
try {
|
||||
var response = http.get(test.url);
|
||||
if (test.shouldBlock) {
|
||||
logger.error('❌ 失败: ' + test.url + ' 应该被拦截但没有');
|
||||
} else {
|
||||
logger.info('✅ 通过: ' + test.url + ' 正确允许');
|
||||
}
|
||||
} catch (e) {
|
||||
if (test.shouldBlock && e.message.includes('安全拦截')) {
|
||||
logger.info('✅ 通过: ' + test.url + ' 正确拦截');
|
||||
} else if (!test.shouldBlock) {
|
||||
logger.error('❌ 失败: ' + test.url + ' 不应该被拦截 - ' + e.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Q5: 服务启动时出现 ArrayIndexOutOfBoundsException
|
||||
|
||||
**答**: 说明代码未更新或未重新编译。
|
||||
|
||||
**解决方法**:
|
||||
```bash
|
||||
# 1. 确认代码已更新
|
||||
grep -n "new String\[0\]" parser/src/main/java/cn/qaiu/parser/customjs/JsPlaygroundExecutor.java
|
||||
|
||||
# 应该看到类似:
|
||||
# 68: ScriptEngine engine = factory.getScriptEngine(new String[0], null, new SecurityClassFilter());
|
||||
|
||||
# 2. 重新编译
|
||||
mvn clean install
|
||||
|
||||
# 3. 重启服务
|
||||
./bin/stop.sh && ./bin/run.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Q6: 如何关闭SSRF防护?(不推荐)
|
||||
|
||||
**⚠️ 警告**: 关闭SSRF防护会带来严重的安全风险!
|
||||
|
||||
如果确实需要(仅用于开发环境),可以修改 `JsHttpClient.java`:
|
||||
|
||||
```java
|
||||
private void validateUrlSecurity(String url) {
|
||||
// 注释掉所有验证逻辑
|
||||
log.debug("SSRF防护已禁用(仅开发环境)");
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
**强烈建议**: 保持SSRF防护开启,使用白名单策略代替完全关闭。
|
||||
|
||||
---
|
||||
|
||||
### Q7: 如何添加域名白名单?
|
||||
|
||||
**答**: 当前策略是黑名单模式。如需白名单,修改 `validateUrlSecurity`:
|
||||
|
||||
```java
|
||||
private static final String[] ALLOWED_DOMAINS = {
|
||||
"api.example.com",
|
||||
"cdn.example.com"
|
||||
};
|
||||
|
||||
private void validateUrlSecurity(String url) {
|
||||
URI uri = new URI(url);
|
||||
String host = uri.getHost();
|
||||
|
||||
// 白名单检查
|
||||
boolean allowed = false;
|
||||
for (String domain : ALLOWED_DOMAINS) {
|
||||
if (host.equals(domain) || host.endsWith("." + domain)) {
|
||||
allowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allowed) {
|
||||
throw new SecurityException("域名不在白名单中: " + host);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Q8: 性能影响
|
||||
|
||||
**Q**: 安全检查会影响性能吗?
|
||||
|
||||
**A**: 影响很小:
|
||||
- ClassFilter: 在引擎初始化时执行一次,几乎无性能影响
|
||||
- SSRF检查: 每次HTTP请求前执行,主要是DNS解析(已有缓存)
|
||||
- 预计性能影响: < 5ms/请求
|
||||
|
||||
---
|
||||
|
||||
### Q9: 如何查看安全日志?
|
||||
|
||||
**答**:
|
||||
```bash
|
||||
# 查看安全拦截日志
|
||||
tail -f logs/*/run.log | grep "安全拦截"
|
||||
|
||||
# 查看JavaScript引擎初始化日志
|
||||
tail -f logs/*/run.log | grep "JavaScript引擎"
|
||||
|
||||
# 应该看到:
|
||||
# 🔒 安全的JavaScript引擎初始化成功(演练场)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Q10: 迁移到GraalVM
|
||||
|
||||
**Q**: 如何迁移到更安全的GraalVM JavaScript?
|
||||
|
||||
**A**:
|
||||
|
||||
1. 添加依赖(`pom.xml`):
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js</artifactId>
|
||||
<version>23.0.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
2. 修改代码:
|
||||
```java
|
||||
import org.graalvm.polyglot.*;
|
||||
|
||||
Context context = Context.newBuilder("js")
|
||||
.allowHostAccess(HostAccess.NONE) // 禁止访问Java
|
||||
.allowIO(IOAccess.NONE) // 禁止IO
|
||||
.build();
|
||||
|
||||
Value result = context.eval("js", jsCode);
|
||||
```
|
||||
|
||||
GraalVM优势:
|
||||
- ✅ 默认沙箱隔离
|
||||
- ✅ 更好的安全性
|
||||
- ✅ 更好的性能
|
||||
- ✅ 活跃维护
|
||||
|
||||
---
|
||||
|
||||
## 📞 获取帮助
|
||||
|
||||
如果以上FAQ没有解决你的问题:
|
||||
|
||||
1. 查看详细文档: `parser/doc/security/`
|
||||
2. 运行安全测试: `./parser/doc/security/test-security.sh`
|
||||
3. 查看测试指南: `SECURITY_TESTING_GUIDE.md`
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-11-29
|
||||
|
||||
293
parser/doc/security/QUICK_TEST.md
Normal file
293
parser/doc/security/QUICK_TEST.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# 🧪 安全修复快速验证指南
|
||||
|
||||
## 修复内容
|
||||
✅ JavaScript远程代码执行漏洞已修复
|
||||
✅ SSRF攻击防护已添加
|
||||
✅ 方法调用错误已修复(`ArrayIndexOutOfBoundsException`)
|
||||
|
||||
---
|
||||
|
||||
## 快速测试步骤
|
||||
|
||||
### 1. 重新编译(必须)
|
||||
|
||||
```bash
|
||||
cd /Users/q/IdeaProjects/mycode/netdisk-fast-download
|
||||
mvn clean install -DskipTests
|
||||
```
|
||||
|
||||
### 2. 重启服务
|
||||
|
||||
```bash
|
||||
# 停止旧服务
|
||||
./bin/stop.sh
|
||||
|
||||
# 启动新服务
|
||||
./bin/run.sh
|
||||
```
|
||||
|
||||
### 3. 执行安全测试
|
||||
|
||||
#### 方式A: 使用HTTP测试文件(推荐)
|
||||
|
||||
1. 确保服务已启动(默认端口 6400)
|
||||
2. 使用IDE打开: `web-service/src/test/resources/playground-security-tests.http`
|
||||
3. 执行"测试3: 系统属性和环境变量访问"
|
||||
|
||||
**期望结果**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"result": "✓ 安全: 无法访问系统属性",
|
||||
"logs": [
|
||||
{
|
||||
"level": "INFO",
|
||||
"message": "尝试访问系统属性..."
|
||||
},
|
||||
{
|
||||
"level": "INFO",
|
||||
"message": "系统属性访问失败: ReferenceError: \"Java\" is not defined"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 方式B: 使用JUnit测试
|
||||
|
||||
```bash
|
||||
cd parser
|
||||
mvn test -Dtest=SecurityTest#testSystemPropertiesAccess
|
||||
```
|
||||
|
||||
**期望输出**:
|
||||
```
|
||||
[INFO] 尝试访问系统属性...
|
||||
[INFO] 方法1失败: ReferenceError: "Java" is not defined
|
||||
✓ 安全: 无法访问系统属性
|
||||
测试完成: 系统属性访问测试
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 验证清单
|
||||
|
||||
运行测试后,确认以下几点:
|
||||
|
||||
### ✅ 必须通过的检查
|
||||
|
||||
- [ ] 服务启动成功,没有 `ArrayIndexOutOfBoundsException`
|
||||
- [ ] 日志中出现:`🔒 安全的JavaScript引擎初始化成功`
|
||||
- [ ] JavaScript代码执行正常(parse函数可以调用)
|
||||
- [ ] 尝试访问 `Java.type()` 时返回错误:`ReferenceError: "Java" is not defined`
|
||||
- [ ] 尝试访问 `System.getProperty()` 时失败
|
||||
- [ ] HTTP请求内网地址(如 127.0.0.1)时被拦截
|
||||
|
||||
### ⚠️ 如果出现以下情况说明修复失败
|
||||
|
||||
- [ ] 服务启动时抛出异常
|
||||
- [ ] JavaScript可以成功调用 `Java.type()`
|
||||
- [ ] 可以获取到系统属性(如用户名、HOME目录)
|
||||
- [ ] 可以访问内网地址(127.0.0.1, 192.168.x.x)
|
||||
|
||||
---
|
||||
|
||||
## 快速测试用例
|
||||
|
||||
### 测试1: 验证Java访问被禁用 ✅
|
||||
|
||||
在演练场输入以下代码:
|
||||
|
||||
```javascript
|
||||
// ==UserScript==
|
||||
// @name 快速安全测试
|
||||
// @type test
|
||||
// @match https://test.com/*
|
||||
// ==/UserScript==
|
||||
|
||||
function parse(shareLinkInfo, http, logger) {
|
||||
logger.info('开始安全测试...');
|
||||
|
||||
// 测试1: Java对象
|
||||
try {
|
||||
if (typeof Java !== 'undefined') {
|
||||
logger.error('❌ 失败: Java对象仍然可用');
|
||||
return 'FAILED: Java可用';
|
||||
}
|
||||
} catch (e) {
|
||||
logger.info('✅ 通过: Java对象未定义');
|
||||
}
|
||||
|
||||
// 测试2: JavaImporter
|
||||
try {
|
||||
if (typeof JavaImporter !== 'undefined') {
|
||||
logger.error('❌ 失败: JavaImporter仍然可用');
|
||||
return 'FAILED: JavaImporter可用';
|
||||
}
|
||||
} catch (e) {
|
||||
logger.info('✅ 通过: JavaImporter未定义');
|
||||
}
|
||||
|
||||
// 测试3: Packages
|
||||
try {
|
||||
if (typeof Packages !== 'undefined') {
|
||||
logger.error('❌ 失败: Packages仍然可用');
|
||||
return 'FAILED: Packages可用';
|
||||
}
|
||||
} catch (e) {
|
||||
logger.info('✅ 通过: Packages未定义');
|
||||
}
|
||||
|
||||
logger.info('✅ 所有测试通过!系统安全!');
|
||||
return 'SUCCESS: 安全修复生效';
|
||||
}
|
||||
```
|
||||
|
||||
**期望输出**:
|
||||
```
|
||||
[INFO] 开始安全测试...
|
||||
[INFO] ✅ 通过: Java对象未定义
|
||||
[INFO] ✅ 通过: JavaImporter未定义
|
||||
[INFO] ✅ 通过: Packages未定义
|
||||
[INFO] ✅ 所有测试通过!系统安全!
|
||||
SUCCESS: 安全修复生效
|
||||
```
|
||||
|
||||
### 测试2: 验证SSRF防护 ✅
|
||||
|
||||
```javascript
|
||||
function parse(shareLinkInfo, http, logger) {
|
||||
logger.info('测试SSRF防护...');
|
||||
|
||||
// 测试访问内网
|
||||
try {
|
||||
http.get('http://127.0.0.1:6400/');
|
||||
logger.error('❌ 失败: 可以访问内网');
|
||||
return 'FAILED: SSRF防护无效';
|
||||
} catch (e) {
|
||||
if (e.message && e.message.includes('安全拦截')) {
|
||||
logger.info('✅ 通过: 内网访问被阻止 - ' + e.message);
|
||||
return 'SUCCESS: SSRF防护有效';
|
||||
} else {
|
||||
logger.warn('⚠️ 警告: 错误但非安全拦截 - ' + e.message);
|
||||
return 'WARNING: 未知错误';
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**期望输出**:
|
||||
```
|
||||
[INFO] 测试SSRF防护...
|
||||
[INFO] ✅ 通过: 内网访问被阻止 - SecurityException: 🔒 安全拦截: 禁止访问内网地址
|
||||
SUCCESS: SSRF防护有效
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 问题1: 服务启动失败
|
||||
|
||||
```bash
|
||||
# 检查编译是否成功
|
||||
ls -la parser/target/parser-*.jar
|
||||
ls -la web-service/target/*.jar
|
||||
|
||||
# 如果没有jar文件,重新编译
|
||||
mvn clean install
|
||||
```
|
||||
|
||||
### 问题2: ArrayIndexOutOfBoundsException 仍然出现
|
||||
|
||||
```bash
|
||||
# 确认代码已更新
|
||||
grep -n "new String\[0\]" parser/src/main/java/cn/qaiu/parser/customjs/JsPlaygroundExecutor.java
|
||||
|
||||
# 应该看到类似:
|
||||
# 68: ScriptEngine engine = factory.getScriptEngine(new String[0], null, new SecurityClassFilter());
|
||||
|
||||
# 如果没有,说明代码未更新,重新拉取
|
||||
```
|
||||
|
||||
### 问题3: 测试显示"Java仍然可用"
|
||||
|
||||
这是**严重问题**,说明修复未生效:
|
||||
|
||||
1. 确认代码已更新
|
||||
2. 确认重新编译
|
||||
3. 确认重启服务
|
||||
4. 检查日志是否有"安全的JavaScript引擎初始化成功"
|
||||
|
||||
```bash
|
||||
# 检查日志
|
||||
tail -f logs/*/run.log | grep "JavaScript引擎"
|
||||
|
||||
# 应该看到:
|
||||
# 🔒 安全的JavaScript引擎初始化成功(演练场)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 一键测试脚本
|
||||
|
||||
创建并运行快速测试:
|
||||
|
||||
```bash
|
||||
cd /Users/q/IdeaProjects/mycode/netdisk-fast-download
|
||||
|
||||
# 重新编译
|
||||
echo "📦 重新编译..."
|
||||
mvn clean install -DskipTests
|
||||
|
||||
# 重启服务
|
||||
echo "🔄 重启服务..."
|
||||
./bin/stop.sh
|
||||
sleep 2
|
||||
./bin/run.sh
|
||||
|
||||
# 等待服务启动
|
||||
echo "⏳ 等待服务启动..."
|
||||
sleep 5
|
||||
|
||||
# 运行安全测试
|
||||
echo "🧪 运行安全测试..."
|
||||
cd parser
|
||||
mvn test -Dtest=SecurityTest#testSystemPropertiesAccess
|
||||
|
||||
echo ""
|
||||
echo "✅ 测试完成!请检查上方输出确认安全修复是否生效。"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 成功标志
|
||||
|
||||
如果看到以下输出,说明修复成功:
|
||||
|
||||
```
|
||||
✅ 服务启动成功
|
||||
✅ 日志: 🔒 安全的JavaScript引擎初始化成功
|
||||
✅ 测试: ReferenceError: "Java" is not defined
|
||||
✅ 测试: ✓ 安全: 无法访问系统属性
|
||||
✅ 测试: 🔒 安全拦截: 禁止访问内网地址
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 下一步
|
||||
|
||||
测试通过后:
|
||||
1. ✅ 标记漏洞为"已修复"
|
||||
2. ✅ 部署到生产环境(如果适用)
|
||||
3. ✅ 更新安全文档
|
||||
4. ✅ 通知团队成员
|
||||
|
||||
---
|
||||
|
||||
**文档**:
|
||||
- 详细修复说明: `parser/SECURITY_FIX_SUMMARY.md`
|
||||
- 紧急修复指南: `SECURITY_URGENT_FIX.md`
|
||||
- 完整测试指南: `parser/doc/SECURITY_TESTING_GUIDE.md`
|
||||
|
||||
**最后更新**: 2025-11-29
|
||||
|
||||
42
parser/doc/security/README.md
Normal file
42
parser/doc/security/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 安全相关文档索引
|
||||
|
||||
本目录包含JavaScript执行器的安全修复和测试相关文档。
|
||||
|
||||
## 📚 文档列表
|
||||
|
||||
### 🚀 快速开始
|
||||
- **[QUICK_TEST.md](QUICK_TEST.md)** - 快速验证指南(5分钟)
|
||||
- **[FAQ.md](FAQ.md)** - 常见问题解答 ⭐ **推荐先看这个!**
|
||||
- **[test-security.sh](test-security.sh)** - 一键测试脚本
|
||||
|
||||
### 📋 安全修复说明
|
||||
- **[SECURITY_FIX_SUMMARY.md](SECURITY_FIX_SUMMARY.md)** - 完整修复总结
|
||||
- **[SECURITY_URGENT_FIX.md](SECURITY_URGENT_FIX.md)** - 紧急修复通知
|
||||
- **[CHANGELOG_SECURITY.md](CHANGELOG_SECURITY.md)** - 安全更新日志
|
||||
|
||||
### 🧪 测试指南
|
||||
- **[SECURITY_TEST_README.md](SECURITY_TEST_README.md)** - 安全测试快速入门
|
||||
- **[SECURITY_TESTING_GUIDE.md](../SECURITY_TESTING_GUIDE.md)** - 详细测试指南
|
||||
|
||||
### 🛡️ 防护策略
|
||||
- **[SSRF_PROTECTION.md](SSRF_PROTECTION.md)** - SSRF防护策略说明
|
||||
|
||||
---
|
||||
|
||||
## 🚨 重要提醒
|
||||
|
||||
如果你看到这些文档,说明系统曾经存在严重的安全漏洞。请务必:
|
||||
|
||||
1. ✅ 确认已应用最新的安全修复
|
||||
2. ✅ 运行安全测试验证修复效果
|
||||
3. ✅ 重新部署到生产环境
|
||||
|
||||
## ❓ 遇到问题?
|
||||
|
||||
- **看到"请求失败: 404"?** → 这是正常的HTTP响应,不是安全拦截!查看 [FAQ.md](FAQ.md#q1-为什么还是显示请求失败-404)
|
||||
- **Java.type() 报错?** → 这说明安全修复生效了!查看 [FAQ.md](FAQ.md#q3-javatype-相关错误)
|
||||
- **服务启动失败?** → 检查是否重新编译,查看 [FAQ.md](FAQ.md#q5-服务启动时出现-arrayindexoutofboundsexception)
|
||||
|
||||
---
|
||||
|
||||
最后更新: 2025-11-29
|
||||
323
parser/doc/security/SECURITY_FIX_SUMMARY.md
Normal file
323
parser/doc/security/SECURITY_FIX_SUMMARY.md
Normal file
@@ -0,0 +1,323 @@
|
||||
# JavaScript远程代码执行漏洞修复总结
|
||||
|
||||
## 🔴 严重安全漏洞已修复
|
||||
|
||||
**修复日期**: 2025-11-28
|
||||
**漏洞类型**: 远程代码执行 (RCE)
|
||||
**危险等级**: 🔴 极高
|
||||
|
||||
---
|
||||
|
||||
## 📋 漏洞描述
|
||||
|
||||
### 原始问题
|
||||
|
||||
JavaScript执行器使用 Nashorn 引擎,但**没有任何安全限制**,允许JavaScript代码:
|
||||
|
||||
1. ❌ 访问所有Java类 (通过 `Java.type()`)
|
||||
2. ❌ 执行系统命令 (`Runtime.exec()`)
|
||||
3. ❌ 读写文件系统 (`java.io.File`)
|
||||
4. ❌ 访问系统属性 (`System.getProperty()`)
|
||||
5. ❌ 使用反射绕过限制 (`Class.forName()`)
|
||||
6. ❌ 创建任意网络连接 (`Socket`)
|
||||
7. ❌ 访问内网服务 (SSRF攻击)
|
||||
|
||||
### 测试结果(修复前)
|
||||
|
||||
```
|
||||
[ERROR] [JS] 【安全漏洞】获取到系统属性 - HOME: /Users/q, USER: q
|
||||
结果: 危险: 系统属性访问成功 - q
|
||||
```
|
||||
|
||||
**这意味着任何用户提供的JavaScript代码都可以完全控制服务器!**
|
||||
|
||||
---
|
||||
|
||||
## ✅ 已实施的安全措施
|
||||
|
||||
### 1. ClassFilter 类过滤器 🔒
|
||||
|
||||
**文件**: `parser/src/main/java/cn/qaiu/parser/customjs/SecurityClassFilter.java`
|
||||
|
||||
**功能**: 拦截JavaScript对危险Java类的访问
|
||||
|
||||
**黑名单包括**:
|
||||
- 系统命令执行: `Runtime`, `ProcessBuilder`
|
||||
- 文件系统访问: `File`, `Files`, `Paths`, `FileInputStream/OutputStream`
|
||||
- 系统访问: `System`, `SecurityManager`
|
||||
- 反射: `Class`, `Method`, `Field`, `ClassLoader`
|
||||
- 网络: `Socket`, `URL`, `URLConnection`
|
||||
- 线程: `Thread`, `ExecutorService`
|
||||
- 数据库: `Connection`, `Statement`
|
||||
- 脚本引擎: `ScriptEngine`
|
||||
|
||||
**效果**:
|
||||
```java
|
||||
public boolean exposeToScripts(String className) {
|
||||
// 检查黑名单
|
||||
if (className.startsWith("java.lang.System")) {
|
||||
log.warn("🔒 安全拦截: JavaScript尝试访问危险类 - {}", className);
|
||||
return false; // 拒绝访问
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 禁用Java内置对象 🚫
|
||||
|
||||
**修改位置**: `JsPlaygroundExecutor.initEngine()` 和 `JsParserExecutor.initEngine()`
|
||||
|
||||
**实施方法**:
|
||||
```java
|
||||
// 创建带ClassFilter的安全引擎
|
||||
NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
|
||||
ScriptEngine engine = factory.getScriptEngine(new SecurityClassFilter());
|
||||
|
||||
// 禁用Java对象访问
|
||||
engine.eval("var Java = undefined;");
|
||||
engine.eval("var JavaImporter = undefined;");
|
||||
engine.eval("var Packages = undefined;");
|
||||
engine.eval("var javax = undefined;");
|
||||
engine.eval("var org = undefined;");
|
||||
engine.eval("var com = undefined;");
|
||||
```
|
||||
|
||||
**效果**: JavaScript无法使用 `Java.type()` 等方法访问Java类
|
||||
|
||||
### 3. SSRF防护 🌐
|
||||
|
||||
**文件**: `parser/src/main/java/cn/qaiu/parser/customjs/JsHttpClient.java`
|
||||
|
||||
**功能**: 防止JavaScript通过HTTP客户端访问内网资源
|
||||
|
||||
**防护措施**:
|
||||
```java
|
||||
private void validateUrlSecurity(String url) {
|
||||
// 1. 检查危险域名黑名单
|
||||
// - localhost
|
||||
// - 169.254.169.254 (云服务元数据API)
|
||||
// - metadata.google.internal
|
||||
|
||||
// 2. 检查内网IP
|
||||
// - 127.x.x.x (本地回环)
|
||||
// - 10.x.x.x (内网A类)
|
||||
// - 172.16-31.x.x (内网B类)
|
||||
// - 192.168.x.x (内网C类)
|
||||
// - 169.254.x.x (链路本地)
|
||||
|
||||
// 3. 检查协议
|
||||
// - 仅允许 HTTP/HTTPS
|
||||
|
||||
if (PRIVATE_IP_PATTERN.matcher(ip).find()) {
|
||||
throw new SecurityException("🔒 安全拦截: 禁止访问内网地址");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**应用位置**: 所有HTTP请求方法
|
||||
- `get()`
|
||||
- `getWithRedirect()`
|
||||
- `getNoRedirect()`
|
||||
- `post()`
|
||||
- `put()`
|
||||
|
||||
### 4. 超时保护 ⏱️
|
||||
|
||||
**已有机制**: Worker线程池限制
|
||||
|
||||
**位置**:
|
||||
- `JsPlaygroundExecutor`: 16个worker线程
|
||||
- `JsParserExecutor`: 32个worker线程
|
||||
|
||||
**超时**: HTTP请求默认30秒超时
|
||||
|
||||
---
|
||||
|
||||
## 🧪 安全验证
|
||||
|
||||
### 测试方法
|
||||
|
||||
使用提供的安全测试套件:
|
||||
|
||||
#### 方式1: JUnit测试
|
||||
```bash
|
||||
cd parser
|
||||
mvn test -Dtest=SecurityTest
|
||||
```
|
||||
|
||||
#### 方式2: HTTP接口测试
|
||||
```bash
|
||||
# 启动服务器后执行
|
||||
# 使用 web-service/src/test/resources/playground-security-tests.http
|
||||
```
|
||||
|
||||
### 预期结果(修复后)
|
||||
|
||||
所有危险操作应该被拦截:
|
||||
|
||||
```
|
||||
[INFO] [JS] 尝试访问系统属性...
|
||||
[INFO] [JS] 系统属性访问失败: ReferenceError: "Java" is not defined
|
||||
✓ 安全: 无法访问系统属性
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 修复效果对比
|
||||
|
||||
| 测试项目 | 修复前 | 修复后 |
|
||||
|---------|--------|--------|
|
||||
| 系统命令执行 | ❌ 成功执行 | ✅ 被拦截 |
|
||||
| 文件系统访问 | ❌ 可读写文件 | ✅ 被拦截 |
|
||||
| 系统属性访问 | ❌ 获取成功 | ✅ 被拦截 |
|
||||
| 反射攻击 | ❌ 可使用反射 | ✅ 被拦截 |
|
||||
| 网络Socket | ❌ 可创建连接 | ✅ 被拦截 |
|
||||
| JVM退出 | ❌ 可终止进程 | ✅ 被拦截 |
|
||||
| SSRF内网访问 | ❌ 可访问内网 | ✅ 被拦截 |
|
||||
| SSRF元数据API | ❌ 可访问 | ✅ 被拦截 |
|
||||
|
||||
---
|
||||
|
||||
## 🔧 修改的文件列表
|
||||
|
||||
### 新增文件
|
||||
|
||||
1. ✅ `parser/src/main/java/cn/qaiu/parser/customjs/SecurityClassFilter.java`
|
||||
- ClassFilter实现,拦截危险类访问
|
||||
|
||||
2. ✅ `parser/src/test/java/cn/qaiu/parser/SecurityTest.java`
|
||||
- 7个安全测试用例
|
||||
|
||||
3. ✅ `web-service/src/test/resources/playground-security-tests.http`
|
||||
- 10个HTTP安全测试用例
|
||||
|
||||
4. ✅ `parser/doc/SECURITY_TESTING_GUIDE.md`
|
||||
- 完整的安全测试和修复指南
|
||||
|
||||
5. ✅ `parser/SECURITY_TEST_README.md`
|
||||
- 快速开始指南
|
||||
|
||||
6. ✅ `parser/test-security.sh`
|
||||
- 自动化测试脚本
|
||||
|
||||
7. ✅ `parser/SECURITY_FIX_SUMMARY.md`
|
||||
- 本文件(修复总结)
|
||||
|
||||
### 修改的文件
|
||||
|
||||
1. ✅ `parser/src/main/java/cn/qaiu/parser/customjs/JsPlaygroundExecutor.java`
|
||||
- 修改 `initEngine()` 方法使用 SecurityClassFilter
|
||||
- 禁用 Java 内置对象
|
||||
|
||||
2. ✅ `parser/src/main/java/cn/qaiu/parser/customjs/JsParserExecutor.java`
|
||||
- 修改 `initEngine()` 方法使用 SecurityClassFilter
|
||||
- 禁用 Java 内置对象
|
||||
|
||||
3. ✅ `parser/src/main/java/cn/qaiu/parser/customjs/JsHttpClient.java`
|
||||
- 添加 `validateUrlSecurity()` 方法
|
||||
- 在所有HTTP请求方法中添加SSRF检查
|
||||
- 添加内网IP检测和危险域名黑名单
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 重要提示
|
||||
|
||||
### 1. 立即部署
|
||||
|
||||
这是一个**严重的安全漏洞**,请尽快部署修复:
|
||||
|
||||
```bash
|
||||
# 重新编译
|
||||
mvn clean install
|
||||
|
||||
# 重启服务
|
||||
./bin/stop.sh
|
||||
./bin/run.sh
|
||||
```
|
||||
|
||||
### 2. 验证修复
|
||||
|
||||
部署后**必须**执行安全测试:
|
||||
|
||||
```bash
|
||||
cd parser
|
||||
./test-security.sh
|
||||
```
|
||||
|
||||
确认所有高危测试都被拦截!
|
||||
|
||||
### 3. 监控日志
|
||||
|
||||
留意日志中的安全拦截记录:
|
||||
|
||||
```
|
||||
[WARN] 🔒 安全拦截: JavaScript尝试访问危险类 - java.lang.System
|
||||
[WARN] 🔒 安全拦截: 尝试访问内网地址 - 127.0.0.1
|
||||
```
|
||||
|
||||
如果看到大量拦截日志,可能有人在尝试攻击。
|
||||
|
||||
### 4. 后续改进
|
||||
|
||||
**长期建议**: 迁移到 GraalVM JavaScript
|
||||
|
||||
Nashorn已废弃,建议迁移到更安全、更现代的引擎:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js</artifactId>
|
||||
<version>23.0.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
GraalVM优势:
|
||||
- 默认沙箱隔离
|
||||
- 无法访问Java类(除非显式允许)
|
||||
- 更好的性能
|
||||
- 活跃维护
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- **详细测试指南**: `parser/doc/SECURITY_TESTING_GUIDE.md`
|
||||
- **快速开始**: `parser/SECURITY_TEST_README.md`
|
||||
- **测试用例**:
|
||||
- JUnit: `parser/src/test/java/cn/qaiu/parser/SecurityTest.java`
|
||||
- HTTP: `web-service/src/test/resources/playground-security-tests.http`
|
||||
|
||||
---
|
||||
|
||||
## 🎯 结论
|
||||
|
||||
### 修复前(极度危险 🔴)
|
||||
|
||||
```javascript
|
||||
// 攻击者可以执行任意代码
|
||||
var Runtime = Java.type('java.lang.Runtime');
|
||||
Runtime.getRuntime().exec('rm -rf /'); // 删除所有文件!
|
||||
```
|
||||
|
||||
### 修复后(安全 ✅)
|
||||
|
||||
```javascript
|
||||
// 所有危险操作被拦截
|
||||
var Runtime = Java.type('java.lang.Runtime');
|
||||
// ReferenceError: "Java" is not defined
|
||||
```
|
||||
|
||||
**安全级别**: 🔴 D级(严重不安全) → 🟢 A级(安全)
|
||||
|
||||
---
|
||||
|
||||
**免责声明**: 虽然已实施多层安全防护,但没有系统是100%安全的。建议定期审计代码,关注安全更新,并考虑迁移到更现代的JavaScript引擎(如GraalVM)。
|
||||
|
||||
**联系方式**: 如发现新的安全问题,请通过安全渠道私密报告。
|
||||
|
||||
---
|
||||
|
||||
**修复完成** ✅
|
||||
**审核状态**: 待用户验证
|
||||
**下一步**: 执行安全测试套件,确认所有漏洞已修复
|
||||
|
||||
180
parser/doc/security/SECURITY_TEST_README.md
Normal file
180
parser/doc/security/SECURITY_TEST_README.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# JavaScript执行器安全测试
|
||||
|
||||
## 📋 概述
|
||||
|
||||
本目录提供了完整的JavaScript执行器安全测试工具和文档,用于验证演练场执行器是否存在安全漏洞。
|
||||
|
||||
## 🎯 测试目标
|
||||
|
||||
验证以下安全风险:
|
||||
|
||||
| 测试项目 | 危险级别 | 说明 |
|
||||
|---------|---------|------|
|
||||
| 系统命令执行 | 🔴 极高 | 验证是否能执行shell命令 |
|
||||
| 文件系统访问 | 🔴 极高 | 验证是否能读写本地文件 |
|
||||
| 系统属性访问 | 🟡 高 | 验证是否能获取系统信息 |
|
||||
| 反射攻击 | 🔴 极高 | 验证是否能通过反射绕过限制 |
|
||||
| 网络Socket | 🔴 极高 | 验证是否能创建任意网络连接 |
|
||||
| JVM退出 | 🔴 极高 | 验证是否能终止应用 |
|
||||
| SSRF攻击 | 🟡 高 | 验证HTTP客户端访问控制 |
|
||||
|
||||
## 📂 测试资源
|
||||
|
||||
```
|
||||
parser/
|
||||
├── src/test/java/cn/qaiu/parser/
|
||||
│ └── SecurityTest.java # JUnit测试用例(7个测试方法)
|
||||
├── doc/
|
||||
│ └── SECURITY_TESTING_GUIDE.md # 详细测试指南和安全建议
|
||||
├── test-security.sh # 快速执行脚本
|
||||
└── SECURITY_TEST_README.md # 本文件
|
||||
|
||||
web-service/src/test/resources/
|
||||
└── playground-security-tests.http # HTTP接口测试用例(10个测试)
|
||||
```
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 方式1: 使用Shell脚本(推荐)
|
||||
|
||||
```bash
|
||||
cd parser
|
||||
chmod +x test-security.sh
|
||||
./test-security.sh
|
||||
```
|
||||
|
||||
### 方式2: Maven命令
|
||||
|
||||
```bash
|
||||
cd parser
|
||||
mvn test -Dtest=SecurityTest
|
||||
```
|
||||
|
||||
### 方式3: HTTP接口测试
|
||||
|
||||
1. 启动应用服务器
|
||||
2. 打开 `web-service/src/test/resources/playground-security-tests.http`
|
||||
3. 在IDE中逐个执行测试用例
|
||||
|
||||
## 📊 预期结果
|
||||
|
||||
### ✅ 安全系统(预期)
|
||||
|
||||
所有高危测试应该**失败**,日志中应该显示:
|
||||
|
||||
```
|
||||
[INFO] 尝试执行系统命令...
|
||||
[INFO] Runtime.exec失败: ReferenceError: "Java" is not defined
|
||||
[INFO] ProcessBuilder失败: ReferenceError: "Java" is not defined
|
||||
✓ 安全: 无法执行系统命令
|
||||
```
|
||||
|
||||
### ❌ 不安全系统(需要修复)
|
||||
|
||||
如果看到以下日志,说明存在严重安全漏洞:
|
||||
|
||||
```
|
||||
[ERROR] 【安全漏洞】成功执行系统命令: root
|
||||
危险: 系统命令执行成功
|
||||
```
|
||||
|
||||
## ⚠️ 重要警告
|
||||
|
||||
1. **仅在测试环境执行** - 这些测试包含危险代码
|
||||
2. **不要在生产环境运行** - 可能导致系统被攻击
|
||||
3. **发现漏洞立即修复** - 不要在公开环境部署有漏洞的版本
|
||||
|
||||
## 🔧 安全修复建议
|
||||
|
||||
如果测试发现安全问题,请参考 `doc/SECURITY_TESTING_GUIDE.md` 中的修复方案:
|
||||
|
||||
### 最关键的修复措施
|
||||
|
||||
1. **实现ClassFilter** - 禁止JavaScript访问危险Java类
|
||||
2. **添加超时机制** - 防止DOS攻击
|
||||
3. **HTTP白名单** - 防止SSRF攻击
|
||||
4. **迁移到GraalVM** - 使用更安全的JavaScript引擎
|
||||
|
||||
### 示例:ClassFilter实现
|
||||
|
||||
```java
|
||||
import jdk.nashorn.api.scripting.ClassFilter;
|
||||
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
|
||||
|
||||
public class SecurityClassFilter implements ClassFilter {
|
||||
@Override
|
||||
public boolean exposeToScripts(String className) {
|
||||
// 禁止所有Java类访问
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建安全的引擎
|
||||
NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
|
||||
ScriptEngine engine = factory.getScriptEngine(new SecurityClassFilter());
|
||||
```
|
||||
|
||||
## 📖 详细文档
|
||||
|
||||
完整的安全测试指南、修复方案和最佳实践,请查看:
|
||||
|
||||
👉 **[doc/SECURITY_TESTING_GUIDE.md](doc/SECURITY_TESTING_GUIDE.md)**
|
||||
|
||||
该文档包含:
|
||||
- 每个测试用例的详细说明
|
||||
- 潜在风险分析
|
||||
- 完整的修复方案
|
||||
- 安全配置最佳实践
|
||||
- GraalVM迁移指南
|
||||
|
||||
## 🔍 测试检查清单
|
||||
|
||||
执行测试后,请确认:
|
||||
|
||||
- [ ] ✅ 测试1: 系统命令执行 - **失败**(安全)
|
||||
- [ ] ✅ 测试2: 文件系统访问 - **失败**(安全)
|
||||
- [ ] ✅ 测试3: 系统属性访问 - **失败**(安全)
|
||||
- [ ] ✅ 测试4: 反射攻击 - **失败**(安全)
|
||||
- [ ] ✅ 测试5: 网络Socket - **失败**(安全)
|
||||
- [ ] ✅ 测试6: JVM退出 - **失败**(安全)
|
||||
- [ ] ⚠️ 测试7: SSRF攻击 - **部分失败**(禁止内网访问)
|
||||
|
||||
## 💡 常见问题
|
||||
|
||||
### Q: 为什么要进行这些测试?
|
||||
|
||||
A: JavaScript执行器允许运行用户提供的代码,如果不加限制,恶意用户可能:
|
||||
- 执行系统命令窃取数据
|
||||
- 读取敏感文件
|
||||
- 攻击内网服务器
|
||||
- 导致服务器崩溃
|
||||
|
||||
### Q: 测试失败是好事还是坏事?
|
||||
|
||||
A: **测试失败是好事!** 这意味着危险操作被成功阻止了。如果测试通过(返回"危险"),说明存在安全漏洞。
|
||||
|
||||
### Q: 可以跳过这些测试吗?
|
||||
|
||||
A: **强烈不建议!** 如果系统对外提供JavaScript执行功能,必须进行安全测试。否则可能导致严重的安全事故。
|
||||
|
||||
### Q: Nashorn已经废弃了,应该怎么办?
|
||||
|
||||
A: 建议迁移到 **GraalVM JavaScript**,它提供:
|
||||
- 更好的安全性(默认沙箱)
|
||||
- 更好的性能
|
||||
- 活跃的维护和更新
|
||||
|
||||
## 🆘 需要帮助?
|
||||
|
||||
如果测试发现安全问题或需要修复建议:
|
||||
|
||||
1. 查看详细文档:`doc/SECURITY_TESTING_GUIDE.md`
|
||||
2. 参考HTTP测试用例:`web-service/src/test/resources/playground-security-tests.http`
|
||||
3. 检查JUnit测试代码:`src/test/java/cn/qaiu/parser/SecurityTest.java`
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-11-28
|
||||
**作者**: QAIU
|
||||
**许可**: MIT License
|
||||
|
||||
Reference in New Issue
Block a user