enjoy-iot 物联网平台 代码安全审计报告
审计对象: enjoy-iot 乐飞智联开源物联网平台后端(Java)
分支: v1.0.0-jdk21
审计日期: 2026-08-10
审计方式: 静态代码审计(人工核查 + 多代理并行扫描),只读分析,未修改任何文件
代码规模: 1550 个 Java 文件,约 12.5 万行
一、技术栈与安全基线
| 项 | 值 |
|---|---|
| 框架 | Spring Boot 3.4.1 / Spring Framework 6.2.1 / Spring Security 6.4.2 |
| 语言 | Java 21 |
| ORM | MyBatis Plus 3.5.9(无 mapper XML,注解式 SQL + Wrapper) |
| 时序库 | TDengine / KaiwuDB / TimescaleDB 三实现并存 |
| JSON | Jackson + fastjson 1.2.83 |
| 认证 | Spring Security + Token(OAuth2)+ 可选 Mock 登录 |
| 协议接入 | MQTT / HTTP / TCP / UDP / CoAP / Modbus / EMQX |
| 脚本引擎 | GraalVM JS(polyglot) |
| 其它 | Redis(Redisson)、Druid、Actuator、swagger/knife4j |
默认配置基线(重点): application.yaml 激活 profile eiot;application-eiot.yaml 中 platform.security.mock-enable: true、platform.captcha.enable: false、platform.xss.enable: false、Actuator exposure.include: '*'。
二、风险总览
| 等级 | 数量 | 说明 |
|---|---|---|
| 🔴 严重 | 3 | Mock 登录认证绕过(全站鉴权失效)、未授权任意文件读、未授权任意文件写 |
| 🟠 高危 | 9 | SQL 注入×3 实现、脚本引擎 RCE、Actuator 匿名暴露、设备接口越权(IDOR)、时序数据无租户隔离、云 AK/SK 泄露、DB/MQTT 弱口令、存储型 XSS(告警邮件) |
| 🟡 中危 | 10 | SSRF(规则动作/告警 Webhook)、XSS 过滤器被关、设备名存储型 XSS、未授权任意类型上传、MQTT 设备仿冒、开放注册+验证码关闭、OTA 测试接口、短信回调伪造、用户枚举、AES 密钥硬编码 |
| 🟢 低危/信息 | 9 | OAuth2 默认 client 弱口令、默认管理员密码、Druid 监控开放、测试代码凭据、SQL 内嵌 token、依赖版本风险、docker.env 弱口令、Jackson 多态(不可利用)、UDP fastjson(疑似) |
⚠️ 一句话结论: 该平台默认部署配置即处于"全站无有效鉴权"状态(Mock 登录开启 + 默认密钥
test),叠加未授权文件读写与多外露面,可直接获取系统权限与全部业务数据。上线前必须关闭 Mock 并修复文件接口。
三、漏洞详情
🔴 严重
S-1 Mock 登录认证绕过(全站鉴权失效,默认配置开启)
确认可利用 ✅(本人已核实)
- 位置:
server/src/main/resources/application.yaml:6—spring.profiles.active: eiot(默认激活)server/src/main/resources/application-eiot.yaml:269—platform.security.mock-enable: trueframework/spring-boot-starter-security/src/main/java/com/enjoyiot/framework/security/config/SecurityProperties.java:62—private String mockSecret = "test";framework/spring-boot-starter-security/src/main/java/com/enjoyiot/framework/security/core/filter/TokenAuthenticationFilter.java:132-147
- 代码:
private LoginUser mockLoginUser(HttpServletRequest request, String token, Integer userType) { if (!securityProperties.getMockEnable()) { return null; } // 必须以 mockSecret 开头 if (!token.startsWith(securityProperties.getMockSecret())) { return null; } // 构建模拟用户 Long userId = Long.valueOf(token.substring(securityProperties.getMockSecret().length())); return LoginUser.builder().id(userId).userType(userType) .tenantId(WebFrameworkUtils.getTenantId(request)).build(); } - 攻击路径: 任意请求携带
Authorization: test1(test+ 任意 userId)即被认证为 用户 ID=1(admin,绑定 super_admin);tenant-id请求头直接作为用户租户,TenantSecurityWebFilter的租户一致性校验恒通过 → 跨租户任意操作。默认密钥test无需爆破。代码注释亦自述"在线上环境下,一定要关闭该功能!!!"。 - 影响: 全平台认证+授权双重绕过,等价于无鉴权;所有
@PreAuthorize形同虚设。 - 修复:
application-eiot.yaml设mock-enable: false(生产强制);或随机化mock-secret且仅限内网开发;增加 profile 隔离,生产禁用 eiot 默认 profile。
S-2 未授权任意文件读(路径穿越 LFI)
确认可利用 ✅(本人已核实)
- 位置:
module-infra/module-infra-biz/src/main/java/com/enjoyiot/module/infra/controller/admin/file/FileController.java:93-115—@GetMapping("/{configId}/get/**") @PermitAllmodule-infra/module-infra-biz/src/main/java/com/enjoyiot/module/infra/framework/file/core/client/local/LocalFileClient.java:71-73—getFilePath(path) = config.getBasePath() + path
- 代码:
@GetMapping("/{configId}/get/**") @PermitAll public void getFileContent(HttpServletRequest request, HttpServletResponse response, @PathVariable("configId") Long configId) throws Exception { String path = StrUtil.subAfter(request.getRequestURI(), "/get/", false); path = URLUtil.decode(path); // %2e%2e%2f → ../ ,在容器规范化之后解码 byte[] content = fileService.getFileContent(configId, path); // → client.getContent(path) } // LocalFileClient private String getFilePath(String path) { return config.getBasePath() + path; } // 无 .. 归一化 - 攻击路径:
GET /admin-api/infra/file/{configId}/get/..%2f..%2f..%2fetc%2fpasswd。Tomcat 不规范化%2f,URLUtil.decode在容器规范化后还原/,basePath + ../../..越界读取任意文件(配置文件、源码、云 AK 等)。@PermitAll免登录,本地存储为默认。 - 修复: 规范化路径并拒绝
../绝对路径;文件接口加鉴权;存储层用Path.normalize+startsWith(basePath)校验。
S-3 未授权任意文件写(匿名上传 + 可控路径)
确认可利用 ✅(本人已核实,写权取决于主存储为本地)
- 位置:
module-infra/module-infra-biz/src/main/java/com/enjoyiot/module/infra/controller/app/file/AppFileController.java:55-76—/upload、/presigned-url、/create均@PermitAllmodule-infra/module-infra-biz/src/main/java/com/enjoyiot/module/infra/service/file/FileServiceImpl.java:68-85module-infra/module-infra-biz/src/main/java/com/enjoyiot/module/infra/framework/file/core/client/local/LocalFileClient.java:55-57—FileUtil.writeBytes(content, basePath + path)
- 代码:
@PostMapping("/upload") @PermitAll public CommonResult<String> uploadFile(AppFileUploadReqVO uploadReqVO) throws Exception { MultipartFile file = uploadReqVO.getFile(); String path = uploadReqVO.getPath(); // 完全用户可控,无任何校验 return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream()))); } - 攻击路径: 未认证用户上传任意内容(HTML/SVG/二进制),
path可控;主存储为本地时basePath + ../../...可向服务器任意路径写文件(写 webshell、覆盖配置)。文件类型/扩展名零校验,对象存储域名直出 → 存储型 XSS/恶意文件托管。 - 修复: 去掉
@PermitAll;路径归一化;文件类型白名单;上传鉴权 + 限流。
🟠 高危
H-1 SQL 注入 — 时序库属性名 name 拼入 SELECT 列名(三实现同根因)
确认可利用 ✅(本人已核实 TDengine 实现与完整调用链)
- 位置:
module-eiot/module-eiot-temporal/iot-temporal-serviceimpl-td/src/main/java/com/enjoyiot/eiot/temporal/td/service/DevicePropertyDataImpl.java:63-66module-eiot/module-eiot-temporal/iot-temporal-serviceimpl-kw/src/main/java/com/enjoyiot/eiot/temporal/kw/service/DevicePropertyDataImpl.java:72-74(KaiwuDB,PG 兼容,UNION 完全可利用)module-eiot/module-eiot-temporal/iot-temporal-serviceimpl-timescaledb/src/main/java/com/enjoyiot/eiot/temporal/timescaledb/service/DevicePropertyDataImpl.java:72-74
- 入口链:
DeviceInfoController.java:235-242POST /deviceProperty/log/list(@PreAuthorize("iot:deviceLog:query")) → bodyDevicePropertyLogQueryBo.name(无任何校验注解) →DeviceManagerServiceImpl.java:116 getPropertyHistory→IDevicePropertyData.findDevicePropertyHistory(deviceId, name, ...) - 代码:
String fieldName = name.contains(".") ? "`" + name + "`" : name; List<TbDeviceProperty> deviceProperties = tdTemplate.query(String.format( "select time,%s as `value`,device_id from %s where device_id=? and time>=? and time<=? order by time asc limit 0,%d", fieldName.toLowerCase(), tableName, size), ...); - 攻击路径:
{"deviceId":1,"name":"version()",...}→select time,version() as \value` …,结果映射回TbDeviceProperty.value**并直接返回给客户端**;KaiwuDB/PG 端可UNION SELECT读时序库任意表、pg_read_file`、时间盲注。 - 修复: 对
name增加物模型 identifier 白名单校验(复用^[a-zA-Z][a-zA-Z0-9_:.\-]*$);或列名映射表参数化;废弃String.format拼列。
H-2 RCE — GraalVM JS 沙箱被 HostAccess.ALL 完全放开(规则/虚拟设备脚本)
确认可利用 ✅(本人已核实)
- 位置:
module-eiot/module-eiot-core/iot-script-engine/src/main/java/com/enjoyiot/eiot/engine/JavaScriptEngine.java:121 - 代码:
context = Context.newBuilder("js") .option("engine.WarnInterpreterOnly", "false") .allowHostAccess(HostAccess.ALL) // 完全放行宿主访问,未限制 allowHostClassLookup .build(); - 脚本注入链: 脚本存于 DB,经管理端 API 写入:
- 规则动作:
iot-rule-engine/.../rule/RuleManager.java:225-245+action/ScriptService.java:39,46-49(HttpService/MqttService/KafkaService/TcpService/AlertService 均继承) - 虚拟设备:
iot-virtual-device/.../VirtualManager.java:205-210
- 规则动作:
- 攻击路径: 持有
iot:rule-info:create/eiot:virtual-device:create权限(租户管理员/运营)的用户 → 配置恶意 JS → 引擎执行。Java.type("java.lang.Runtime").getRuntime().exec("id")直接 RCE。在 Mock 登录开启时,任意请求即可获得该权限,RCE 无门槛。 - 修复:
allowHostAccess(HostAccess.NONE)或仅放行白名单方法;禁用Java.type/宿主互操作;启用 GraalVM--sandbox;脚本走独立低权限进程/容器。
H-3 Actuator 全端点匿名暴露
确认可利用 ✅(本人已核实)
- 位置:
server/src/main/resources/application-eiot.yaml:191-192—management.endpoints.web.exposure.include: '*'module-infra/module-infra-biz/src/main/java/com/enjoyiot/module/infra/framework/security/config/SecurityConfiguration.java:49-53—registry.requestMatchers("/actuator/**").permitAll();
- 攻击路径: 未登录访问
/actuator/env(环境变量含 DB 口令/云密钥)、/actuator/heapdump(JVM 堆,抓内存中 token/密码)、/actuator/configprops、/actuator/mappings等,严重信息泄露。 - 修复: exposure 仅保留
health;/actuator/**加鉴权;关闭 heapdump。
H-4 设备接口缺失 @PreAuthorize — 设备属性跨租户读取(IDOR)
确认可利用 ✅(本人已核实 DeviceInfoController 权限注解分布)
- 位置:
module-eiot/module-eiot-biz/src/main/java/com/enjoyiot/module/eiot/controller/admin/device/DeviceInfoController.java:193POST /children/list、:201/children/unbindList、:209/bind、:218/unbind— 无@PreAuthorize:396POST /getDeviceWithProperty— 无@PreAuthorize,凭deviceId返回设备详情+实时属性:402GET /genSerialNO— 无@PreAuthorize
- 代码:
@PostMapping("/getDeviceWithProperty") // ← 无 @PreAuthorize(同文件 /get、/page 均有) public CommonResult<DeviceInfoWithPropertyVO> getDeviceInfoWithProperty(@RequestBody @Validated DeviceIdReqVo bo) { return success(deviceManagerService.getDeviceInfoWithProperty(bo.getDeviceId())); } - 攻击路径: 任意已登录用户(或 Mock 用户)凭
deviceId读取任意租户设备当前属性——属性走 Redis 缓存(getPropertiesFromCache(deviceId)无租户维度);还可改绑设备拓扑。同类接口/get、/page有校验,形成不一致。 - 修复: 补齐
@PreAuthorize;Redis/时序层增加租户维度校验。
H-5 设备时序数据无租户隔离
确认可利用 ✅(代码路径核实)
- 位置:
module-eiot/module-eiot-biz/src/main/java/com/enjoyiot/module/eiot/service/device/DeviceManagerServiceImpl.java:104-118;iot-temporal-serviceimpl-td/.../ThingModelMessageDataImpl.java、DevicePropertyDataImpl.java - 代码:
public PageResult<ThingModelMessage> logs(DeviceLogPageReqVo req) { return thingModelMessageData.findByTypeAndIdentifier(req.getDeviceId(), ...); // 仅按 deviceId } - 攻击路径: 时序层查询仅按
deviceId、不带租户条件,绕过 MyBatis-Plus 多租户拦截器(不生效于自定义 JDBC)。遍历deviceId读任意租户物模型日志/属性历史;simulateSend(:127-136)可向任意设备注入伪造遥测。 - 修复: 时序存储层追加租户条件/校验;
simulateSend加权限。
H-6 硬编码云厂商 AK/SK、短信密钥(已入库仓库)
确认可利用 ✅(本人已核实 system.sql 内容)
- 位置:
_sql/mysql/system.sql:1004-1009, 2858(system_mysql5.7.sql、postgresql/enjoy-iot.sql同源) - 内容(标注"示例"但为完整真实值):
- 七牛 AK/SK:
3TvrJ70gl2Gt6IBe7_IZT1F6i_k0iMuRtyEv4EyS/wd0tbVBEiotp0S-ihA8Qg2hPLncoP83wyrIq24OZuY - 阿里云 OSS:
LTAI5tEQLgnDyjh3WpNcdMKA - 腾讯 COS:
AKIDAF6WSh1uiIjwqtrOsGSN3WryqTM6cTMt - 火山:
AKLTZjc3Zjc4MzZmMjU3NDk0ZTgxYmIyMmFkNTIwMDI1ZGE;华为:PVDONDEIOTW88LF8DC4U - 阿里云短信:
LTAI5tCnKso2uG3kJ5gRav88/fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C
- 七牛 AK/SK:
- 影响: 克隆仓库即获取云资源凭据,可造成云资源滥用/数据泄露/费用损失。
- 修复: 视为已泄露,立即轮换所有密钥;删除 SQL 种子中的真实凭据,改用环境变量/占位符;
.gitignore排除含密钥的种子文件。
H-7 数据库/MQTT/缓存弱口令明文
确认可利用 ✅
- 位置:
server/src/main/resources/application-eiot.yaml、_script/docker/docker.env、_script/docker/docker-compose.yml - 内容: MySQL
root/123456、TDengineroot/taosdata、PostgreSQLpostgres/postgres、RabbitMQrabbit/rabbit、Redis 无密码;docker.env 含百度云 keyfadc1bd5db1a1d6f581df60a1807f8ab。 - 影响: 内网默认口令,DB/消息队列端口暴露即可直连拖库。
- 修复: 强口令 + 密钥管理(Vault/环境变量);DB 不监听公网。
H-8 存储型 XSS — 告警邮件 HTML 未转义
确认可利用 ✅(本人已核实 setText 调用)
- 位置:
module-eiot/module-eiot-core/iot-message-notify/src/main/java/com/enjoyiot/eiot/message/listener/EmailEventListener.java:74-82module-eiot/module-eiot-api/src/main/java/com/enjoyiot/module/eiot/api/alert/dto/Message.java:51-56
- 代码:
String content = message.getFormatContent(); // content.replace("${key}", paramValue) 无转义 messageHelper.setText(content, true); // true = 按 HTML 发送 - 攻击路径: 告警模板
${deviceName}/属性值由设备可控(设备名可自注册上报,见 M-4),含<img src=x onerror=...>→ 管理员邮箱客户端渲染执行 → 存储型 XSS。 - 修复: 邮件内容 HTML 转义/白名单标签;设备名等输入做字符过滤。
🟡 中危
M-1 SSRF — 规则引擎 HTTP/TCP/MQTT 动作无内网地址限制
- 位置:
module-eiot/module-eiot-core/iot-rule-engine/.../action/http/HttpService.java:51-96;link/impl/TcpClientLink.java:65-80;link/impl/MqttClientLink.java:72-85 - 说明:
url = this.url + httpData.getPath()来自规则配置(iot:rule-info:create);规则由设备消息自动触发。可配置http://169.254.169.254/、http://127.0.0.1/由服务器发起 → 云元数据/内网探测。 - 修复: 内网 IP/元数据地址黑名单 + DNS rebinding 防护;URL 白名单。
M-2 SSRF — 告警通道 Webhook 地址用户可控
- 位置:
module-eiot/module-eiot-core/iot-message-notify/.../listener/DingTalkEventListener.java:60、QyWechatEventListener.java:60 - 说明:
dingTalkWebhook/qyWechatWebhook来自通道配置,触发告警时向任意地址 POST。 - 修复: 校验 webhook 域名;SSRF 防护。
M-3 后端 XSS 过滤器被显式关闭
- 位置:
server/src/main/resources/application.yaml—platform.xss.enable: false;framework/spring-boot-starter-web/.../xss/config/EnjoyXssAutoConfiguration.java:36 - 说明: 项目已实现
XssFilter/JsoupXssCleaner/XssStringJsonDeserializer,但部署配置将其关闭,JSON 反序列化与请求过滤全部失效。 - 修复: 生产
xss.enable: true;对富文本/告警/展示字段做输出编码。
M-4 设备名存储型 XSS(设备可控输入入库展示)
- 位置:
module-eiot/module-eiot-biz/src/main/java/com/enjoyiot/module/eiot/api/device/DeviceApiImpl.java:94-130;service/device/DeviceInfoServiceImpl.java:360-379 - 说明: 支持自注册产品时,设备 clientId 中的
deviceName直接入库(未清洗),进入管理后台列表/告警/邮件/Excel 导出。与 H-8 叠加成完整 XSS 链。 - 修复: 设备名白名单/字符过滤;输出统一转义。
M-5 未授权上传任意类型文件(存储型 XSS/恶意托管)
- 位置: 同 S-3 的
AppFileController@PermitAll上传,无扩展名/Content-Type 白名单;S3FileClient.upload返回domain + path指向对象存储公网域名,上传.html/.svg可直出执行。 - 修复: 类型白名单 + Content-Disposition;鉴权。
M-6 MQTT 设备密码校验被硬编码关闭(设备仿冒)
- 位置:
module-eiot/iot-components/iot-component-mqtt/src/main/java/com/enjoyiot/eiot/component/mqtt/service/MqttComponent.java:289-297 - 代码:
if (false){ // 校验密码-默认不校验,为了让新手快速上手 String md5 = MD5.create().digestHex(productSecret + clientId); if (!md5.equals(auth.getPassword())) { ... reject ... } } - 攻击路径: 连接认证仅校验
clientId = pk_dn_model、username = dn;知道设备pk/dn即可无凭据伪装设备上线、registerDevice自动注册、上报数据(数据可触发规则动作)。设备名/pk 常可枚举/从产品信息获取。 - 修复: 恢复密码校验;设备接入侧增加唯一密钥与限流。
M-7 开放注册 + 生产 profile 关闭验证码
- 位置:
application-eiot.yaml:268(captcha.enable: false);module-system/.../controller/admin/auth/AuthController.java:108(@PermitAll /system/auth/register);service/auth/AdminAuthServiceImpl.java:221-225(captcha 跳过) - 说明: 未登录无限自助注册 + 无验证码登录爆破。
- 修复: 生产开启验证码;注册加验证码/限流/邀请制。
M-8 OTA 测试接口无鉴权
- 位置:
module-eiot/module-eiot-biz/src/main/java/com/enjoyiot/module/eiot/controller/admin/ota/OtaController.java:116-118—POST /testStartUpgrade无@PreAuthorize - 说明: 遗留测试接口,触发设备 1 OTA 升级动作。URL 固定,影响为测试性质,但属未受控下发入口。
- 修复: 删除或补鉴权。
M-9 短信回调接口匿名可触发(状态篡改)
- 位置:
module-system/module-system-biz/.../controller/admin/sms/SmsCallbackController.java:49,58,68,76— 4 个@PermitAll回调 - 说明: 无签名验签,未登录可伪造短信投递状态,影响短信登录/密码重置等依赖状态的功能。
- 修复: 回调签名校验;匿名回调仅记录不入状态。
M-10 用户精简列表无 @PreAuthorize(用户枚举)
- 位置:
module-system/module-system-biz/.../controller/admin/user/UserController.java:130-137—/list-all-simple、/simple-list无校验 - 说明: 租户内任意登录用户可枚举全部用户名/昵称/部门(同文件
/get、/page有system:user:query)。 - 修复: 补权限注解。
M-11 数据库字段加密密钥硬编码
- 位置:
server/src/main/resources/application.yaml—mybatis-plus.encryptor.password: XDV71a+xqStEA3WH;framework/spring-boot-starter-mybatis/.../EncryptTypeHandler.java:46-87 - 说明: AES 密钥入库,DB 一旦泄露加密字段(OAuth token、短信配置)可被解密。
- 修复: 密钥外置密钥管理系统。
🟢 低危 / 信息级
| # | 项 | 位置 | 说明 |
|---|---|---|---|
| L-1 | OAuth2 client 默认弱口令 | _sql/mysql/system.sql:2473 |
client default / secret admin123,授权码/密码/隐式/刷新全开 |
| L-2 | 默认管理员密码 | _sql/mysql/system.sql:3201 |
admin bcrypt 为若依系默认 admin123 已知哈希,无强制修改 |
| L-3 | Druid 监控台开放 | application-eiot.yaml |
stat-view-servlet.enabled: true 且 allow/口令为空,可看 SQL/Session |
| L-4 | 测试代码含真实设备密钥 | module-eiot/iot-components/iot-component-coap/.../test/CoapClientTest.java:13-15 |
PRODUCT_KEY="wSnpXDZJ3BQGrQmS"、SECRET="gEdatxKkHMEZyO",位于 src/main |
| L-5 | MinIO 凭据硬编码 | module-infra/.../file/core/client/FileClientFactoryImpl.java:79-83 |
main() 内 minio/minio@123!/http://8.134.104.234:9000 |
| L-6 | SQL 内嵌 OAuth2 access_token | _sql/mysql/system.sql:2398-2409 |
真实 token 入库(可能已过期) |
| L-7 | Excel 公式注入(疑似) | DeviceInfoController 等导出 |
设备名等以 = 开头字段在 Excel 打开时可能执行公式 |
| L-8 | UDP fastjson 1.2.83 解析设备数据(疑似) | module-eiot/iot-components/iot-component-udp/.../UdpComponent.java:128 |
设备 UDP 载荷直接 JSON.parseObject;autoType 默认关闭,当前利用难度高,建议迁 fastjson2 |
| L-9 | Jackson 多态反序列化(核实不可利用) | module-infra/.../file/core/client/FileClientConfig.java:34 |
@JsonTypeInfo(Id.CLASS);已核实 FileConfigServiceImpl.java:137-139 用固定 configClass 反序列化,不以 @class 实例化 → 不可经此路径利用 |
依赖与配置层
- Spring Framework 6.2.1(CVE-2025-22228 静态资源路径穿越,6.2.8 修复;当前应用静态资源自 classpath,利用面有限,建议升级)
- fastjson 1.2.83: 存在公开 autoType 绕过链研究;用于设备上行 UDP 数据解析,建议升级 fastjson2
- swagger/knife4j、Spring Boot Admin 默认放行;
/druid/**permitAll(见 L-3)
已排查排除(未发现)
- 全仓无
Runtime.exec/ProcessBuilder命令执行 sink - 无
ObjectInputStream.readObject/XMLDecoder/ XStream / Hessian / Kryo 经典反序列化 sink - MyBatis 注解 SQL 均用
#{},无${};无用户可控 order by/group by 拼接 - 规则引擎
Expression为纯数值/字符串比较器,无表达式求值 - Modbus/TCP 二进制解析为纯字节运算,
processor公式仅定义未执行
四、修复优先级清单
| 优先级 | 项 | 理由 |
|---|---|---|
| P0 立即 | ① 关闭 Mock 登录(mock-enable: false + 随机 secret) |
全站鉴权失效根因 |
| P0 立即 | ② 文件接口:补鉴权、路径归一化禁 ..、类型白名单 |
未授权任意文件读/写 |
| P0 立即 | ③ 轮换已入库的云 AK/SK、微信/钉钉/企微/短信密钥与默认口令 | 凭据泄露 |
| P1 高 | ④ 时序库 name 列名注入加 identifier 白名单 |
SQL 注入可回显 |
| P1 高 | ⑤ 脚本引擎 HostAccess.NONE/沙箱 + 禁 Java.type |
规则权限→RCE |
| P1 高 | ⑥ Actuator 只留 health + 加鉴权 | 信息泄露 |
| P1 高 | ⑦ eiot 设备接口补 @PreAuthorize;Redis/时序层加租户校验 |
越权/跨租户 |
| P2 中 | ⑧ SSRF 防护(规则动作/Webhook)、邮件 HTML 转义、XSS 过滤开启、MQTT 恢复密码校验 | 扩大防御面 |
| P2 中 | ⑨ 升级 Spring Framework / fastjson2;收紧 Druid/swagger/注册/验证码 | 基线加固 |
五、审计覆盖范围与说明
已覆盖模块: framework(web/security/mybatis/redis/mq/websocket)、module-system(认证/用户/短信/OAuth2)、module-infra(文件/代码生成)、module-eiot(协议组件/物模型/规则引擎/脚本引擎/告警/虚拟设备/时序存储)、module-ai。
方法: 4 组并行专项扫描(反序列化/RCE、SQL 注入、未授权/越权、硬编码/XSS/SSRF)+ 人工逐条复核关键攻击链;每条发现标注 ✅已核实 / 代理报待复核。
说明:
- 本报告基于静态分析,部分"疑似/待复核"项(如 L-8 UDP fastjson、M-1/M-2 SSRF 实际利用)建议结合动态测试确认。
- 本报告为只读审计产物,未对代码做任何修改。