enjoy-iot-安全审计报告

22次阅读
没有评论

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: true
    • framework/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/**") @PermitAll
    • module-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 均 @PermitAll
    • module-infra/module-infra-biz/src/main/java/com/enjoyiot/module/infra/service/file/FileServiceImpl.java:68-85
    • module-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-66
    • module-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-242 POST /deviceProperty/log/list(@PreAuthorize("iot:deviceLog:query")) → body DevicePropertyLogQueryBo.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
    • :193 POST /children/list、:201 /children/unbindList、:209 /bind、:218 /unbind — 无 @PreAuthorize
    • :396 POST /getDeviceWithProperty — 无 @PreAuthorize,凭 deviceId 返回设备详情+实时属性
    • :402 GET /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
  • 影响: 克隆仓库即获取云资源凭据,可造成云资源滥用/数据泄露/费用损失。
  • 修复: 视为已泄露,立即轮换所有密钥;删除 SQL 种子中的真实凭据,改用环境变量/占位符;.gitignore 排除含密钥的种子文件。

H-7 数据库/MQTT/缓存弱口令明文

确认可利用 ✅

  • 位置: server/src/main/resources/application-eiot.yaml、_script/docker/docker.env、_script/docker/docker-compose.yml
  • 内容: MySQL root/123456、TDengine root/taosdata、PostgreSQL postgres/postgres、RabbitMQ rabbit/rabbit、Redis 无密码;docker.env 含百度云 key fadc1bd5db1a1d6f581df60a1807f8ab。
  • 影响: 内网默认口令,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-82
    • module-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 实际利用)建议结合动态测试确认。
  • 本报告为只读审计产物,未对代码做任何修改。
正文完
 0
评论(没有评论)