pig4cloud (Pig) 微服务后台 安全审计报告

93次阅读
没有评论

pig4cloud (Pig) 微服务后台 安全审计报告

审计对象:pig(pig4cloud 4.1.0,Spring Cloud 2025.x + Spring Boot 4.x + Spring Authorization Server 微服务版中后台,552 个 Java 文件约 4.8 万行)
审计方式:静态代码审计(仅读代码,未运行项目、未发起任何利用请求)
审计范围:pig-auth(授权中心)、pig-gateway(网关)、pig-upms(用户权限)、pig-common(12 个公共子模块)、pig-visual(codegen/quartz/monitor)、pig-register(Nacos)、db/*.sql 种子脚本、docker-compose、pom.xml、git 历史
披露级别:完整披露(默认口令、硬编码凭据原文公开,供审计与防御参考;若你正在使用本项目,请先阅读第 7 节并立即轮换相关凭据)

⚠️ 本报告包含真实凭据原文,博客公开可见。文中涉及的阿里云 ACR 口令、Nacos 密钥、MySQL/Nacos/admin/monitor 默认口令、登录报文 AES 密钥、jasypt 根口令均为源码仓库中真实存在的内容,任何按默认配置部署的实例都应视为已失陷,须立即轮换。


1. 总体结论

本项目是经典的 Spring Cloud 微服务快速开发平台,代码分层清晰、近期已做过一轮安全加固(codegen JDBC 参数校验、文件路径穿越校验、quartz REST 白名单、JobSecurityValidator 等),MyBatis 全部参数化查询、密码统一 BCrypt、刷新令牌走官方 Provider 等基础不错。但存在 7 个可导致账户接管 / 配置中心沦陷 / 供应链污染的严重漏洞,且默认部署即暴露大量未授权监控面、默认凭据全公开、多个高价值接口缺少权限注解,整体不满足生产上线条件。

等级:数量 | 说明

🔴 严重:7 | 短信登录认证绕过、验证码键注入任意改密、Nacos 密钥伪造、镜像仓库口令泄露、监控台无认证、Actuator/Druid 全暴露

🟠 高危:21 | 密码哈希/客户端密钥/三方 appSecret 泄露、任意文件上传与路径穿越、quartz RCE 面、codegen SSRF/文件写、@Inner 头伪造、短信轰炸、验证码绕过爆破、XSS 防线失效等

🟡 中危:20 | IDOR、用户枚举、管理接口缺权限、弱口令策略、日志脱敏绕过、CORS、Swagger 暴露等

🟢 低危:12 | token 查询参数传递、演示过滤器绕过、多语句支持、Excel 导入 DoS 等

合计:60 |

最致命的组合链:默认客户端 social:social(captcha_flag=0)→ grant_type=mobile&mobile=SMS@<手机号> 无需短信验证码直接登录任意用户;再加上 /code/image?randomStr=sms@<手机号> 键注入可任意重置密码;Nacos 密钥公开可伪造管理员令牌接管配置中心。三者叠加,默认部署的实例几乎等于裸奔。


2. 🔴 严重漏洞

2.1 短信/手机号登录认证绕过 → 任意账号接管(CWE-287)

位置:

  • pig-auth/src/main/java/com/pig4cloud/pig/auth/support/filter/ValidateCodeFilter.java:74-81(captcha_flag=0 时跳过 checkCode)
  • pig-auth/.../support/core/AuthCaptchaSupport.java:62-74(验证码开关绑定客户端配置)
  • pig-auth/.../support/core/PigDaoAuthenticationProvider.java:122-126(grant_type=mobile 免密)
  • pig-upms/.../handler/SmsLoginHandler.java:46-74(AbstractLoginHandler.check() 恒为 true,无短信码校验)
  • db/pig.sql:637-639(social/mini 客户端 captcha_flag="0" 且 secret=clientId)
// ValidateCodeFilter.java —— captcha_flag=0 → 短信验证码整体跳过
if (!isCheckCaptchaClient(request)) {
    filterChain.doFilter(request, response);   // 不校验!
    return;
}
// PigDaoAuthenticationProvider.java:122-126 —— mobile 模式免密码
if (StrUtil.equals(SecurityConstants.APP, grantType)) {
    return;   // app(mobile) 模式不校验密码
}
-- db/pig.sql:637-639 —— 默认客户端,captcha_flag=0、secret=clientId
INSERT INTO sys_oauth_client_details VALUES (7,'social',NULL,'social','server','password,refresh_token,mobile',...,'{ "enc_flag":"0","captcha_flag":"0"}','true','0',...);
INSERT INTO sys_oauth_client_details VALUES (8,'mini',NULL,'mini','server','password,mobile',...,160000000,160000000,'{"captcha_flag":"0","enc_flag":"0",...}','true','0',...);

漏洞描述:短信登录(grant_type=mobile,参数 mobile=SMS@<手机号>)的短信验证码校验被捆绑在客户端的”图形验证码开关”上。默认库中 social/mini/test 客户端 captcha_flag="0"(关闭),ValidateCodeFilter 直接跳过 checkCode(),短信验证码完全不校验;随后 PigDaoAuthenticationProvider 对 mobile 授权模式跳过密码校验,SmsLoginHandler 仅按手机号查用户即返回。

攻击链(无需任何账号):

POST /auth/oauth2/token
Authorization: Basic c29jaWFsOnNvY2lhbA==        # social:social(默认)
grant_type=mobile&mobile=SMS@<受害者手机号>&scope=server

→ 直接获得受害者(含管理员)access_token,全程无需短信验证码。

影响:任意已知手机号用户账户接管,可直达管理员,系统完全沦陷。

修复:① 短信验证码校验与图形验证码开关解耦,mobile 授权无条件强制校验短信码;② 收紧默认客户端,移除 social/mini/test 的 mobile 授权或强制 captcha_flag=1;③ 更换默认 client_secret;④ /oauth2/token 增加失败频率限制。

2.2 Redis 缓存键注入 → 短信验证码绕过 → 任意用户密码重置(CWE-287/639)

位置:

  • pig-auth/.../endpoint/ImageCodeEndpoint.java:41-54(第 51 行:用户可控 randomStr 拼 Redis 键)
  • pig-upms/.../service/impl/SysUserServiceImpl.java:693-704(forgetUserPassword,第 698 行读同前缀键)
  • pig-upms/.../controller/SysRegisterController.java:60-64(/register/forget/{code} 匿名可调,@Inner(value=false))
// ImageCodeEndpoint.java:41-54 —— randomStr 直接拼进 Redis 键
@GetMapping("/image")
public void image(String randomStr, HttpServletResponse response) {
    ArithmeticCaptcha captcha = new ArithmeticCaptcha(100, 40);
    String result = captcha.text();
    if (Validator.isMobile(randomStr)) { return; }   // "sms@138..." 不是手机号 → 继续
    RedisUtils.set(CacheConstants.DEFAULT_CODE_KEY + randomStr, result, SecurityConstants.CODE_TIME);
    captcha.out(response.getOutputStream());
}
// SysUserServiceImpl.java:693-704 —— 短信验证码键
String codeObj = RedisUtils.get(CacheConstants.DEFAULT_CODE_KEY
        + LoginTypeEnum.SMS.getType() + StringPool.AT + userDto.getPhone());
if (!StrUtil.equals(codeObj, code)) { return R.failed(...); }   // 与攻击者可控的值比对
this.update(... set(SysUser::getPassword, ENCODER.encode(userDto.getNewpassword1())) ...);

漏洞描述:/auth/code/image(公开接口,网关 ignore-urls 含 /code/)把用户可控的 randomStr 直接拼进 Redis 键,值为可从图片直接读出的算术验证码;而短信验证码(SMS OTP)的键是 DEFAULT_CODE_KEY + "sms@" + 手机号,两者共享同一 Redis 命名空间**。攻击者可把自己生成的、可读的算术验证码写入受害者的短信验证码键,从而绕过短信验证。

攻击链:

  1. GET /auth/code/image?randomStr=sms@<受害者手机号> → Redis 键 DEFAULT_CODE_KEY:sms@<手机号> 被写入算术答案(60s TTL),从图片读出答案;
  2. POST /admin/register/forget/{code},body:phone=<受害者手机号>&code=<算术答案>&newpassword1=<攻击者密码>(该接口 @Inner(value=false) 匿名可调);
  3. 比对通过 → 重置受害者密码 → 用新密码登录,任意已绑定手机号用户被接管。同一键还被注册、绑定手机、短信登录流程复用。

影响:任意账户接管(可接管管理员),全程无需给受害者发短信。

修复:① randomStr 严格白名单(仅字母数字),短信键与图形验证码键前缀隔离(如 captcha:math: / captcha:sms:);② 找回密码校验”已发送短信”标志 + 一次性键;③ 校验通过后立即删键并增加失败次数限制。

2.3 Nacos 认证密钥硬编码 → 伪造管理员令牌接管配置中心(CWE-798/321)

位置:pig-register/src/main/resources/application.properties:62-68(Nacos 3.2.2,pig-register/pom.xml:30)

nacos.core.auth.server.identity.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=
nacos.core.auth.server.identity.value=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=
nacos.core.auth.plugin.nacos.token.secret.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=
# base64 解码 = ThisIsMyCustomSecretKey012345678(32 字节,HS256 签名密钥)

漏洞描述:Nacos JWT 令牌签名密钥(token.secret.key)与 server identity key/value 三者相同且硬编码为公开默认值。Nacos 8848/9848/18080 端口直接映射宿主机(docker-compose.yml),攻击者用公开密钥即可离线伪造任意 Nacos 用户(含 admin)的 JWT。

攻击链:已知密钥 → 伪造 nacos 管理员令牌 → 登录配置中心 → 读取/篡改所有服务配置(数据库口令、jasypt 密文、登录 AES 密钥、各服务密钥)→ 向已连接服务注入恶意配置 → 潜在 RCE。

影响:配置中心完全沦陷,全集群密钥泄露,可升级为代码执行。

修复:密钥改为环境变量注入并在部署时随机生成;立即轮换;对 8848/9848/18080 做网络隔离。

2.4 pom.xml 硬编码阿里云 ACR 真实凭据 → 供应链污染(CWE-798)

位置:pom.xml:52-56

<docker.registry>registry.cn-hangzhou.aliyuncs.com</docker.registry>
<docker.namespace>pigcloudx</docker.namespace>
<docker.username>佩小格科技</docker.username>
<docker.password>qq123456</docker.password>

漏洞描述:Maven docker 插件配置里硬编码了阿里云容器镜像仓库(ACR)的真实账号与口令。git 历史证实 2024-07-09 由 Harbor admin/Harbor12345 切换而来,历史中还残留 Harbor12345、MinIO lengleng/lengleng、历史 Nacos SecretKey 等凭据。

攻击链:仓库公开 → 任何人可用该口令推送镜像覆盖 pigcloudx 命名空间下的官方镜像 → 部署方拉取被投毒的镜像 → 供应链 RCE。

影响:供应链投毒、私有镜像泄露。

修复:删除 pom 中的明文凭据,改用 CI secrets / docker login 注入;立即轮换 ACR 口令并开启二次验证;git 历史做凭据清洗(filter-repo)。

2.5 pig-monitor 完全无认证(SBA + Druid + Redis 信息全公开)(CWE-306)

位置:pig-visual/pig-monitor/pom.xml(无 pig-common-security/spring-security 依赖);PigMonitorApplication.java:31-32(@EnableAdminServer);config/DruidMonitorConfigurer.java:22-28(/druid/* 注册 MonitorViewServlet);controller/RedisController.java:27-30(/redis/info);pig-gateway/src/main/resources/application.yml:43-46(Path=/monitor/** 公开路由)

漏洞描述:monitor 是纯裸 Web 应用(无任何安全依赖),网关却为其配置了公开路由 /monitor/**。SBA 管理台(可代理读取被监控实例的 actuator/env/heapdump)、Druid SQL 聚合控制台(显示全部业务 SQL 文本)、/redis/info(Redis INFO 与 commandstats)全部匿名可达。

攻击链:GET http://<网关:9999>/monitor/druid/index.html → 全部业务 SQL;GET /monitor/applications → SBA 代理读 env/heapdump;GET /monitor/redis/info。

影响:内网服务运行数据、全部业务 SQL、配置信息泄露。

修复:monitor 引入安全依赖强制认证;网关对 /monitor/** 加认证或移除路由;SBA 配置强口令并限制代理端点。

2.6 Actuator 默认全量暴露且 /actuator/** 免认证(CWE-200/306)

位置:pig-common-security/.../PermitAllUrlProperties.java:47(DEFAULT_IGNORE_URLS 含 /actuator/**);PigResourceServerConfiguration.java:61-70(ignoreUrls → permitAll);db/pig_config.sql application-dev.yml(exposure.include: ' *'、restart.access: unrestricted、health.show-details: ALWAYS);pig-gateway-dev.yml(management.endpoint.gateway.access: unrestricted)

# db/pig_config.sql application-dev.yml(默认部署种子配置)
management:
  endpoints:
    web:
      exposure:
        include: ' *'          # 全量暴露
  endpoint:
    restart:
      access: unrestricted
    health:
      show-details: ALWAYS

攻击链:未认证 GET /actuator/heapdump(内存中的 token/口令/密码哈希)、GET /actuator/env(配置与 ENC 密文)、POST /actuator/restart(DoS)、对网关 POST /actuator/gateway/routes 注入路由把 /admin/ 转发到攻击者服务器截获全部 Authorization 头**。

修复:exposure 仅保留 health,info;移除 /actuator/** 默认放行;restart/gateway 端点设鉴权;管理端口网络隔离。

2.7 Druid 监控控制台默认免认证开放(全量 SQL + 参数泄露)(CWE-306/532)

位置:db/pig_config.sql pig-upms-biz-dev.yml

security:
  oauth2:
    client:
      ignore-urls:
        - /druid/**          # 安全放行
...
      stat-view-servlet:
        enabled: true
        allow: ""            # 放行所有 IP
        url-pattern: /druid/*
        #login-username: admin    # 被注释:无登录校验
        #login-password: admin

漏洞描述:Druid StatViewServlet 被加入安全放行列表且自身无访问账号 → 未认证访问 /admin/druid/*。可查看全部执行过的 SQL 及绑定参数(含用户数据)、JDBC URL/用户名、会话信息,并可 reset-all 使监控失效。

修复:删除 /druid/** 放行项;StatViewServlet 配置强口令;生产关闭或仅内网访问。


3. 🟠 高危漏洞

3.1 用户密码哈希泄露:/user/ancestor/{username} 返回 SysUser 实体(CWE-200/522)

  • 位置:SysUserController.java:192-195;SysUserServiceImpl.java:351-368;SysUser.java:66
  • GET /admin/user/ancestor/{username} 无权限注解,返回 List<SysUser>,SysUser.password 无 @JsonIgnore(仅 salt 被忽略)→ 任意登录用户可获取任意用户名上级部门的全部用户 BCrypt 哈希,离线破解后接管(默认口令多为 123456 或手机号,见 3.17/4.5)。
  • 修复:改返回 UserVO(password 已 @JsonIgnore)或显式 setPassword(null);补权限注解。
@GetMapping("/ancestor/{username}")          // 无权限注解
public R listAncestorUsers(@PathVariable String username) {
    return R.ok(userService.listAncestorUsers(username));   // List<SysUser> 含 password 哈希
}

3.2 OAuth 客户端密钥明文泄露:/client/{clientId}、/client/export(CWE-200/522)

  • 位置:SysClientController.java:69-83、176-181
  • 两个接口无权限注解,BeanUtils.copyProperties 把 clientSecret 原样返回/导出(默认客户端 secret 即 clientId,生产为随机密钥)。泄露后可伪造 OAuth 客户端发起 token 请求。
  • 修复:clientSecret 加 @JsonIgnore;接口补 @HasPermission。

3.3 三方登录 appSecret 明文泄露:/social/{type}、/social/getById/{id}、/social/export(CWE-200/522)

  • 位置:SysSocialDetailsController.java:84-93、157-161
  • 无权限注解,返回含 appSecret 的实体(微信/钉钉/企业微信应用密钥、Clarity API Token)→ 以该应用身份调用开放平台 API。
  • 修复:一律使用不含 secret 的 VO;导出接口脱敏 + 权限。

3.4 任意文件上传(无权限、无类型校验、文件名可控)+ 匿名下载(CWE-434/862)

  • 位置:SysFileController.java:106-112(/upload 无 @HasPermission)、138-142(/oss/file @Inner(false) 匿名);SysFileServiceImpl.java:87-119(无扩展名/Content-Type/魔数校验,客户端可指定 fileName 保留任意扩展名)
  • 任意登录用户可上传任意文件(LOCAL 落盘 / OSS 上传),OSS 公共读场景下 HTML 文件直接访问即存储型 XSS;/oss/file 匿名下载任意已上传文件。
  • 修复:上传补权限;扩展名+魔数双白名单;服务端强制 UUID 文件名;下载接口去匿名化。

3.5 /sys-file/local/file/{fileName} classpath 路径穿越(CWE-22)

  • 位置:SysFileController.java:149-155
  • new ClassPathResource("file/" + fileName) 直接拼接路径变量,无 .. 过滤 → GET /admin/sys-file/local/file/../application.yml 读取 classpath 下任意资源。
  • 修复:fileName 规范化校验,拒绝 ..、/、\。

3.6 本地文件模板路径穿越 + 调用方 checkSlip 前缀匹配缺陷(CWE-22)

  • 位置:pig-common-oss/.../local/LocalFileTemplate.java:74,106,134(bucketName/objectName 零校验直接拼路径);SysFileServiceImpl.java:201-217(FileUtil.checkSlip 为 startsWith 前缀判断,无路径分隔符边界:../local2/x 规范化后 /base/local2/x 以 /base/local 开头即通过)
  • 存储根目录内跨桶读写删、覆盖他人文件;公共库 API 对第三方复用者构成任意文件读写风险。
  • 修复:LocalFileTemplate 内部 Path.normalize() + startsWith(basePath) 精确边界校验。

3.7 日程模块完全缺失权限与归属校验(CWE-639/862)

  • 位置:SysScheduleController.java:60-130(page/{id}/save/updateById/removeById/export 全部无 @HasPermission);SysScheduleServiceImpl.java:53-79;SysScheduleEntity 无 owner 字段
  • 任意登录用户可查看/修改/删除/导出所有用户的日程(page 无当前用户过滤,getById/update/delete 直接按 id)。
  • 修复:实体增加 userId;所有查询/更新/删除按当前用户过滤。

3.8 /social/bind 可无验证码绑定任意手机号(CWE-290/639)

  • 位置:SysSocialDetailsController.java:149-152;SysSocialDetailsServiceImpl.java:64-75;SmsLoginHandler.java:82-87
  • POST /social/bind?state=SMS&code=<手机号> 仅需登录:SMS 类型 identify(code) 直接把 code 当手机号返回,无任何校验,随后覆盖写入当前用户 → 任意手机号被绑定到攻击者账户(受害者短信登录进入攻击者账户 / 无法找回密码)。
  • 修复:bind 接口 type 白名单(禁止 SMS);手机号变更强制短信验证码;校验手机号未被占用。

3.9 codegen 数据源管理越权 → 任意 JDBC 连接(SSRF/内网探测)+ 口令可解密(CWE-918/862/312)

  • 位置:GenDsConfController.java 全部端点无 @HasPermission(:60-148);GenDatasourceConfServiceImpl.java:156-182(对任意 jdbc URL 真实建连);JdbcUrlSecurityValidator 仅封危险参数(autoDeserialize/allowLoadLocalInfile 等,近期已加固)不封主机
  • 任意登录用户可:POST /gen/dsconf 提交 jdbc:mysql://<内网IP>:<端口>/x 做端口探测;GET /gen/dsconf/doc?dsName=master 导出主库表结构;GET /gen/dsconf/list 回显 jasypt 密文 → 用公开根口令 pig(PBEWithMD5AndDES)离线解密得到全部数据库口令。
  • 修复:补 @HasPermission;禁止内网/回环地址目标;list/getById 去掉 password;更换 jasypt 密钥。

3.10 codegen 任意文件写入(CWE-862/73)

  • 位置:GenTableController.java:155-158(PUT /gen/table 无权限);GeneratorController.java:83-91;GeneratorServiceImpl.java:174-196(FileUtil.writeUtf8String(content, path))
  • 任意登录用户可 PUT /gen/table 把 backendPath 改为任意绝对路径 → GET /gen/generator/code?tableIds=x 向服务器任意位置写文件(内容部分可控)→ 持久化/RCE 前置;checkPath 可做目录存在性探测。
  • 修复:补权限;渲染路径必须限制在预配置根目录内。

3.11 codegen 生成代码/表结构泄露(CWE-862/200)

  • 位置:GeneratorController.java:56-77;GenTableController.java:86-103
  • GET /gen/generator/download?tableIds=1,2 无权限 → 下载全部业务源码;listTable/getTable 无权限枚举数据源表结构/DDL。
  • 修复:补 codegen_* 权限。

3.12 quartz JAR 类型任务零校验 → 任意路径 java -jar 执行(CWE-78/94)

  • 位置:util/JarTaskInvok.java:41-60(ProcessBuilder 直接 start);SysJobController.java:117-130(save 仅校验 REST 白名单);SysJobServiceImpl.java:59-91(checkJob 只校验 SPRING_BEAN/JAVA 类型,JAR 类型完全无校验)
  • 拥有 job_sys_job_add 权限(配合 3.10 文件写 / 共享卷放置 jar)→ POST /job/sys-job {"jobType":"JAR","executePath":"/tmp/evil.jar",...} → POST /job/sys-job/run-job/{id} 立即执行 → quartz 进程权限 RCE。
  • 修复:JAR 类型默认禁用或 executePath 必须位于受控目录并管理员审批;或直接移除该类型。

3.13 quartz 反射调用黑名单不完整 → JdbcTemplate 任意 SQL(CWE-94/184)

  • 位置:util/JobSecurityValidator.java:48-93(精确匹配 denylist)、:181-199(白名单严格模式 isInAllowedPackage 是死代码);SpringBeanTaskInvok.java:47-57;JavaClassTaskInvok.java:46-55
  • 方法名封禁 execute 不封 update/query/queryForList;类封禁未覆盖 org.springframework.jdbc.core.JdbcTemplate → className=jdbcTemplate, methodName=update, params=<任意SQL> 对 quartz 库执行任意增删改(含 INTO OUTFILE 写文件链上 RCE)。
  • 修复:改白名单(仅允许 com.pig4cloud.pig.daemon.quartz.task.*);启用严格模式;禁止反射框架基础设施类。

3.14 HttpBasicGatewayFilter 恒返回 true(认证形同虚设 + 凭据日志泄露)(CWE-287/532)

  • 位置:pig-gateway/.../filter/HttpBasicGatewayFilter.java:60-65(hasAuth() 无条件 return true)、:63(INFO 日志明文打印 Authorization 头)
  • 一旦管理员在路由中启用该过滤器保护 swagger/内网页面,认证完全失效;日志还泄露 Basic 凭据。
  • 修复:实现真正的 Base64 Basic 校验;删除凭据日志。

3.15 @Inner 接口免鉴权仅凭可伪造的 from:Y 头(CWE-287/441)

  • 位置:PigSecurityInnerAspect.java:58-67(header FROM==’Y’ 即放行);PigRequestGlobalFilter.java:62(仅网关删除 FROM);单体版 PigInnerHeaderRemoveFilter.java:43-61 用 JakartaServletUtil.getClientIP(信任 X-Forwarded-For)+ WebUtils.getIP()(取 XFF 首值)→ X-Forwarded-For: 127.0.0.1 + from:Y 即可调用 @Inner 接口
  • 任何服务端口可被直接访问时(k8s Service、docker 未隔离),攻击者直接打服务端口带 from:Y 绕过认证进入 @Inner 接口;单体版可用 XFF 伪造 127.0.0.1 绕过 PigInnerHeaderRemoveFilter → GET /admin/social/info/{inStr} 获取含 BCrypt 哈希的 UserInfo。
  • 修复:@Inner 改签名/mTLS 校验;服务端口不对公网开放;FROM 头改随机内部密钥。

3.16 /sysMessage/send/smsCode 公开 + XFF 绕过限速 → 短信轰炸与手机号枚举(CWE-799)

  • 位置:SysMessageController.java:183-190(@Inner(value=false) 全公开);SysMessageServiceImpl.java:282-293(IP 限速取 WebUtils.getIP(),信任 X-Requested-For/X-Forwarded-For,可伪造绕过 5 次/IP 限制)
  • 匿名接口按手机号发短信(费用消耗/轰炸),且 registered=true 时区分”手机号未注册” → 手机号枚举。
  • 修复:接口加认证或图形验证码前置;IP 取真实对端地址;按手机号维度限速。

3.17 默认凭据集群(CWE-798/521)

位置:db/pig.sql:1021、db/pig_config.sql:321、docker-compose.yml:10-11、pig_config.sql:42、pom.xml:282-283、db/pig.sql:632-639

凭据:位置 | 已本地校验(htpasswd -B)

admin / 123456:db/pig.sql:1021(bcrypt $2a$10$c/Ae0p...) | ✅ 100% 确认

nacos / nacos:db/pig_config.sql:321 | ✅ 100% 确认

MySQL root / root(MYSQL_ROOT_HOST=”%”):docker-compose.yml:10-11 | —

Spring Boot Admin pig / pig:pig_config.sql:42 | —

OAuth2 client secret 全部 = client_id(app/pig/social/mini/test/gen/mp/daemon),{noop} 明文比对:db/pig.sql:632-639、PigRemoteRegisteredClientRepository.java:116 | —

mini 客户端 access_token 有效期 160000000s ≈ 5 年:db/pig.sql:639 | —

修复:全部改为环境变量注入 + 随机强口令;admin/nacos/root 首登强制改密;client secret 加密存储并轮换。

3.18 登录报文 AES 密钥 / jasypt 根密码硬编码(CWE-321/327)

  • 位置:pig-boot/src/main/resources/application-dev.yml:28(security.encodeKey: thanks,pig4cloud,16 字节);:33(jasypt.encryptor.password: pig);db/pig_config.sql:38(Nacos 种子同样内嵌);PasswordDecoderFilter.java:137-147(AES-128-CFB/NoPadding,IV=密钥)
  • 密钥公开 → 登录密文可解/可伪造(”加密传输”形同虚设)、所有 ENC(...) 配置密文可用 pig + PBEWithMD5AndDES 离线解密(配合 3.9/2.6 拿到密文即还原明文口令)。
  • 修复:密钥改环境变量/KMS 注入;jasypt 升级 PBEWITHHMACSHA512ANDAES_256;登录改 TLS。

3.19 密码登录验证码可绕过 → 在线爆破(CWE-307)

  • 位置:ValidateCodeFilter.java:101-105(仅从 Authorization Basic 头取 clientId,缺头返回 null);AuthCaptchaSupport.java:62-65(clientId 为 null → isCaptchaEnabled 返回 false → 跳过验证码);PigRemoteRegisteredClientRepository.java:117-120(客户端注册了 CLIENT_SECRET_POST);RateLimiterConfiguration.java(限流器未挂载任何路由)
  • 把 client_id/client_secret 放请求体(form 参数)即整体跳过验证码 → POST /auth/oauth2/token 无限尝试密码(配合刷新令牌 30 天有效期)。
  • 修复:从请求体解析 client_id;”查不到就跳过”改为”白名单才可跳过”;网关挂载 RequestRateLimiter;登录失败 Redis 计数锁定。

3.20 XSS 防护默认关闭 + 白名单可绕过(CWE-79)

  • 位置:PigXssProperties.java:41(enabled = false,仓库所有 yml 均未开启,已 grep 核实);XssUtil.java:66-116
  • ① 全站无 XSS 清洗;② 即使开启,白名单放行 <embed>/<object>/<style>,src/href 协议白名单全部被注释,isSafeAttribute 仅做 startsWith("javascript") 前缀匹配——java&#9;script:alert(1)(scheme 内 ASCII tab)可绕过,浏览器 URL 解析器剥离空白后仍按 javascript: 执行;③ :all 标签放行 style 属性(CSS 注入/数据外带)。
  • 修复:生产开启 security.xss.enabled: true(escape 模式);注册严格协议白名单并对值先规范化再校验;移除 embed/object/style;富文本用独立严格白名单。

3.21 API Key IP 白名单可被伪造客户端头绕过(CWE-807)

  • 位置:WebUtils.java:176-198(依次信任 X-Requested-For/X-Forwarded-For/Proxy-Client-IP/… 并取 split(",")[0]);PigCustomOpaqueTokenIntrospector.java:148-153(sk- API Key IP 白名单);网关不清洗这些头
  • 持有任意 sk- key 的攻击者带 X-Requested-For: <白名单IP> 即绕过 IP 绑定;登录/审计日志 IP 亦可伪造。
  • 修复:网关统一改写可信 XFF;服务端只信任可信代理头/remoteAddr。

4. 🟡 中危漏洞

  1. /user/details/{id} IDOR(SysUserController.java:99-102,无权限注解):任意登录用户遍历 userId 获取任意用户手机号/邮箱/openid 等 PII(password 有 @JsonIgnore 不泄露)。
  2. /user/details 匿名用户枚举(SysUserController.java:109-114,@Inner(value=false)):GET /admin/user/details?username=admin 或 ?phone=xxx 匿名确认用户名/手机号存在性,配合 2.1 撞库。
  3. 短信验证码明文写日志 + 仅 4 位 + 用后不失效(SysMessageServiceImpl.java:313、318 打印 mobile, code 明文;SecurityConstants.CODE_SIZE=”4″;CODE_TIME=60s;registerUser/forgetUserPassword 校验成功未删 Redis 键,60s 内可复用)。
  4. 管理接口大量缺失 @HasPermission(功能级越权):/menu/tree、/role/list、/dept/org、/dict/list、/sys-file/group/** 等仅需登录即可调用,低权限用户可读取全量菜单/角色/部门、搜索全站用户、增删改文件组。
  5. Excel 批量导入用户初始密码 = 手机号(SysUserServiceImpl.java:498-500):弱口令且无强制首登改密,配合 3.1 哈希泄露极易破解。
  6. 注册/重置 DTO 无校验 + 匿名改密无频率限制(RegisterUserDTO 无 @NotBlank/强度校验;/register/password 匿名可对已知用户名无限尝试旧密码)。
  7. Swagger/OpenAPI 默认开启且 /v3/api-docs permitAll(OpenAPIDefinition.java:54 matchIfMissing=true;网关 openapi 自代理路由聚合全部服务文档,/doc.html 匿名可看全量接口清单)。
  8. 登录用户枚举(OAuth2ResourceOwnerBaseAuthenticationProvider.java:272-281:username_not_found vs bad_credentials 响应差异)。
  9. 登录失败锁定可做任意账号 DoS(PigAuthenticationFailureEventHandler.java:131-149:默认 5 次失败锁死账号,攻击者可故意输错锁死目标用户)。
  10. 登出开放重定向 + GET 登出无 CSRF(SsoLogoutSuccessHandler.java:27-36;FormIdentityLoginConfigurer.java:26-31);登出日志写入完整 Authorization 头(PigLogoutSuccessEventHandler.java:84)。
  11. 数学验证码可自动化绕过(ImageCodeEndpoint.java:39-54:算术验证码可 OCR/穷举,校验失败删键可重取,无限速)。
  12. SQL 日志默认开启且参数明文落盘(PigMybatisProperties.java:24 showSql=true;DruidSqlLogFilter.java:137-164 把绑定参数内联进日志,含 PII/哈希)。
  13. Order-by 黑名单过滤可绕过(SqlFilterArgumentResolver.java:93-102:ascs/descs 仅过 SqlInjectionUtils 关键词黑名单,MySQL ORDER BY 支持函数表达式如 if(1=1,1,2)、extractvalue(...) 可盲注/报错注入)。
  14. 日志脱敏按精确字段名匹配可绕过(SysLogAspect.java:72 + PigLogProperties.java:50-51:大小写变体 Password、嵌套 Map、oldPassword 等未列字段明文入库)。
  15. codegen 表名/列名校验仅关键词黑名单(GenCreateTableController.java:90-93 列名完全不校验;Anyline DDL 构造若对标识符不加引号存在 DDL 注入纵深不足)。
  16. **CORS 默认 allowCredentials=true + 通配来源 “\*”**(PigBootCorsProperties.java:43,58:一旦开启 security.cors.enabled=true 即任意来源可带凭证跨域)。
  17. Redis 默认 JDK 序列化 + @Cacheable 启用 Jackson defaultTyping(RedisTemplateConfiguration.java:47-48;RedisCacheAutoConfiguration.java:102-106):一旦出现任意 Redis 写入原语(未授权 Redis、键注入、Lua 注入)即升级为反序列化 RCE;OAuth2Authorization 也存 Redis(PigRedisOAuth2AuthorizationService)。
  18. 动态数据源默认从 DB 表加载 + @DS(“#last”) 末参决定数据源(JdbcDynamicDataSourceProvider.java:146-148;LastParamDsProcessor.java:56-59):数据源配置可被低权限用户污染、参数可控接口可切到任意已注册数据源跨库越权。
  19. /token/check_token 未鉴权(PigTokenEndpoint.java:152-171);资源服务器异常 message 回显(ResourceAuthExceptionEntryPoint.java:60-63)。
  20. 网关无认证层 + openapi 自代理路由可做服务探测(/v3/api-docs/{x} 404/200 差异枚举已注册服务)。

5. 🟢 低危漏洞

  1. access_token 支持 URL 查询参数传递(PigBearerTokenExtractor.java:103-113,CWE-598):token 进入访问日志/浏览器历史/Referer。
  2. PreviewGatewayFilter 非 GET 请求只要路径含 “token” 子串即放行(PreviewGatewayFilter.java:46-49):演示环境可绕过只读限制。
  3. JDBC allowMultiQueries=true + druid wall multi-statement-allow: true(pig_config.sql id=3/7/8):放大任何潜在 SQL 注入为堆叠注入。
  4. 硬编码本地路径 /Users/lengleng/Downloads/files(pig_config.sql id=7);quartz 日志删除接口无权限(SysJobLogController.java:59-63);monitor 聚合 URL 参数未 URL 编码(MonitorStatService.java:407-423)。
  5. 匿名读公共参数值 /param/publicValue/{key}(SysPublicParamController.java:63-80):若管理员在公共参数中存放敏感配置可被匿名读取。
  6. API Key 管理接口权限标识错配(sys_social_details_* 而非 sys_api_key_*):普通用户无法删除自己的 Key 而 PUT 却无权限注解。
  7. /user/check 与匿名 /register/password 无失败锁定(独立于登录锁定逻辑)。
  8. Excel 导入无大小/行数限制(RequestExcelArgumentResolver.java:60-79,默认 multipart 100MB):超大/zip 炸弹文件耗尽资源。
  9. Excel 导出无公式注入清洗(CWE-1236):以 = + - @ 开头数据原样写入单元格(xlsx 显式字符串风险较低,CSV 场景风险高)。
  10. Sentinel 限流 origin 基于可伪造 IP(PigHeaderRequestOriginParser.java:38-40):轮换 XFF 绕过按 IP 流控。
  11. OAuth2 授权存储 remove()/removeByUsername() 用 KEYS 通配匹配(PigRedisOAuth2AuthorizationService.java:143,180-182):键量大时阻塞 Redis。
  12. 登录请求体整体缓存进内存(RepeatBodyRequestWrapper.java:46-48,85-94):并发大体积登录请求耗尽堆内存。

6. 明确”未发现”项(值得肯定)

  • SQL 注入:pig-upms 全部 Mapper 注解 SQL 与 XML 均使用 #{} 参数化;分页排序经 SqlFilterArgumentResolver 白名单化(虽有 4.13 表达式绕过纵深问题)。
  • SSRF(业务模块):SysAreaController/ClarityFetchTaskHandler 无用户可控 URL(请求目标为固定常量)。
  • 密码存储:统一 BCrypt(DelegatingPasswordEncoder),且有防时序枚举的 userNotFoundEncodedPassword。
  • 刷新令牌轮换/重用:走 Spring Authorization Server 默认 Provider;access token 为不透明 UUID + Redis,无 JWT 伪造面。
  • 组件已知漏洞:mybatis-plus 3.5.16、hutool 5.8.47、jsoup 1.15.4、druid 1.2.28、mysql-connector-j 9.5.0、nacos-client 3.2.3、log4j2 2.25.5(远离 Log4Shell)均无明显已知可利用 CVE;BOM 声明的 fastjson 1.2.84 全仓库无实际 import 使用。
  • 代码生成器已加固:JdbcUrlSecurityValidator(拦截 autoDeserialize/allowLoadLocalInfile 等 MySQL 驱动 RCE 参数)、表名拦截、文件路径 checkSlip 均为近期新增。

7. 修复优先级建议

优先级:动作

P0(立即):① 2.1 短信登录强制校验验证码并收紧默认客户端;② 2.2 验证码键前缀隔离 + randomStr 白名单;③ 2.3 轮换 Nacos 三密钥并环境变量注入;④ 2.4 轮换 ACR 口令并删除 pom 明文

P1(本周):⑤ 2.5/2.6/2.7 收敛 monitor/actuator/Druid 暴露;⑥ 3.1-3.8 补齐 /user、/client、/social、/sys-file、/schedule 权限注解与脱敏;⑦ 3.12/3.13 quartz 任务白名单化并禁用 JAR 类型;⑧ 3.9-3.11 codegen 补权限

P2(本月):⑨ 3.17-3.21 轮换全部默认凭据、密钥、修复验证码绕过与 XFF 信任;⑩ 4.x 中危项逐项收敛

常态化:⑪ 开启 security.xss.enabled;⑫ 关闭 SQL 明文日志;⑬ 生产 swagger.enabled=false、exposure 仅 health,info;⑭ CI 接入 gitleaks 类 secret 扫描并对 git 历史清洗


8. 审计范围与方法说明

  • 全部结论基于源码与种子配置核实(含 pig-common-security 的 PermitAllUrlProperties、PigSecurityInnerAspect、PigCustomOpaqueTokenIntrospector、WebUtils 等支撑代码),每条发现均给出 文件:行号 可复核。
  • 默认口令(admin/123456、nacos/nacos)经 bcrypt 本地校验 100% 确认;Nacos 密钥经 base64 解码确认;git 历史凭据经 git log -p/git grep 检索确认。
  • 未运行任何项目、未发起任何利用请求;涉及 pig-auth/pig-gateway/pig-common-security 的部分为跨模块交叉核验结论。
  • 该仓库近期已有明显安全加固投入(JDBC URL 校验、checkSlip、quartz 白名单、JobSecurityValidator、API Key SHA-256 存储等),本次发现主要集中在新功能接口权限遗漏、默认配置与凭据、验证码与认证链路设计三方面。
正文完
 0
评论(没有评论)