Spring for GraphQL CVE-2026-41699反序列化RCE漏洞:分页查询接口成为远程代码执行入口

Spring for GraphQL框架在处理分页(Connection)类型GraphQL查询时存在不安全反序列化漏洞(CVE-2026-41699,CVSS 8.1)。攻击者可构造恶意GraphQL请求,在满足特定classpath条件的情况下实现远程代码执行。该漏洞影响Spring for GraphQL 1.3.0至2.0.3的全部活跃版本,波及大量基于Spring生态的GraphQL微服务。
漏洞技术背景:GraphQL分页机制的隐患

GraphQL的Relay规范定义了一种名为Connection的分页模式,用于处理大量数据的游标分页。Spring for GraphQL框架内置了对Connection类型的支持,允许开发者通过简单的注解即可暴露分页查询能力。但正是这个便利性埋下了安全隐患。
当Spring for GraphQL处理包含Connection字段的查询时,框架会对请求中的分页参数进行反序列化处理。CVE-2026-41699的核心问题在于:反序列化过程中没有对输入类型进行严格的白名单校验。如果应用的classpath中存在特定的可利用类(gadget classes),攻击者可以通过精心构造的GraphQL查询触发Java原生反序列化链,最终实现远程代码执行。
// 典型的易受攻击的GraphQL Controller
@Controller
public class UserController {
@QueryMapping
public Connection<User> users(
@Argument int first,
@Argument String after,
@Argument UserFilter filter) { // filter参数的反序列化存在问题
// Spring for GraphQL在此处对filter进行反序列化
// 如果filter中嵌套了恶意类型...
return userService.getUsers(first, after, filter);
}
}
攻击者发送的恶意GraphQL查询可能如下:
# 恶意GraphQL查询(概念演示)
query {
users(first: 10, after: "cursor", filter: {
// 嵌套恶意序列化数据
// 利用classpath中的gadget类
__typename: "com.example.MaliciousClass"
}) {
edges {
node {
id
name
}
}
}
}
影响范围与版本矩阵

Spring for GraphQL作为Spring生态的重要组成部分,被广泛应用于微服务架构中的API网关和BFF(Backend for Frontend)层。
| Spring for GraphQL版本 | 受影响 | 修复版本 | CVSS |
|---|---|---|---|
| 2.0.0 ~ 2.0.3 | 是 | 2.0.4 | 8.1 |
| 1.4.0 ~ 1.4.5 | 是 | 1.4.6 | 8.1 |
| 1.3.0 ~ 1.3.8 | 是 | 1.3.9 | 8.1 |
| < 1.3.0 | 未确认 | - | - |
漏洞利用的前置条件:
漏洞的利用需要满足两个条件:
- 应用暴露了包含Connection(分页)类型字段的GraphQL查询
- 应用的classpath中存在可被利用的反序列化gadget类
常见的可利用gadget来源包括:
- Apache Commons Collections(历史上最经典的Java反序列化gadget来源)
- Spring Framework自身的某些类
- 其他第三方库中的InvokerTransformer、ConstantTransformer等
# 检查classpath中是否存在已知gadget类
find /path/to/app/libs -name "*.jar" | while read jar; do
if jar tf "$jar" 2>/dev/null | grep -q "InvokerTransformer\|ConstantTransformer\|ChainedTransformer"; then
echo "[!] Potential gadget found in: $jar"
fi
done
漏洞检测方法

1. 版本检测
# Maven项目 - 检查pom.xml
grep -r "spring-graphql" pom.xml
# Gradle项目
grep -r "spring-graphql" build.gradle build.gradle.kts
# 运行时检测 - 通过Spring Boot Actuator
curl -s http://localhost:8080/actuator/info | jq '.build'
2. GraphQL端点发现
# 常见的GraphQL端点路径
for path in /graphql /api/graphql /graphiql /playground; do
status=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:8080${path}")
if [ "$status" != "404" ]; then
echo "[+] Found: ${path} (HTTP ${status})"
fi
done
# 通过introspection获取schema
curl -s -X POST http://localhost:8080/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ __schema { types { name fields { name type { name kind ofType { name } } } } } }"}' | \
python3 -c "
import json, sys
data = json.load(sys.stdin)
for t in data['data']['__schema']['types']:
if t.get('fields'):
for f in t['fields']:
if f['type'].get('kind') == 'OBJECT' and 'Connection' in (f['type'].get('name') or ''):
print(f'[!] Connection field found: {t[\"name\"]}.{f[\"name\"]}')
"
3. 恶意请求检测(WAF规则)
# Nginx/WAF规则 - 检测可疑的GraphQL introspection和嵌套类型
location /graphql {
# 检测__typename滥用
if ($request_body ~* "__typename.*com\.") {
return 403;
}
# 限制查询深度
# 建议使用graphql-depth-limit等中间件
}
修复方案

方案一:升级到修复版本(推荐)
<!-- Maven -->
<dependency>
<groupId>org.springframework.graphql</groupId>
<artifactId>spring-graphql</artifactId>
<version>2.0.4</version> <!-- 或 1.4.6 / 1.3.9 -->
</dependency>
// Gradle
implementation 'org.springframework.graphql:spring-graphql:2.0.4'
方案二:输入类型白名单(防御深度)
@Configuration
public class GraphQLSecurityConfig {
@Bean
public GraphQlSourceBuilderCustomizer typeValidationCustomizer() {
return builder -> builder.configureRuntimeWiring(wiring ->
wiring.wiringFactory(new SafeWiringFactory())
);
}
}
// 自定义WiringFactory,限制允许的输入类型
public class SafeWiringFactory extends NoopWiringFactory {
private static final Set<String> ALLOWED_TYPES = Set.of(
"UserFilter", "ProductFilter", "OrderFilter" // 仅允许已知安全类型
);
@Override
public boolean providesInputTypeDefinition(TypeDefinitionEnvironment environment) {
String typeName = environment.getTypeDefinition().getName();
if (!ALLOWED_TYPES.contains(typeName)) {
throw new SecurityException("Blocked unauthorized input type: " + typeName);
}
return super.providesInputTypeDefinition(environment);
}
}
方案三:查询深度与复杂度限制
@Bean
public GraphQlSourceBuilderCustomizer depthLimitCustomizer() {
return builder -> builder.configureGraphQl(config -> config
.instrumentation(new MaxQueryDepthInstrumentation(7)) // 限制查询深度
);
}
供应链视角:Spring生态的安全态势

Spring for GraphQL的这个漏洞再次提醒我们,框架层面的安全问题具有放大效应。根据Snyk 2025年度报告,Spring生态的安全漏洞平均影响范围是其他Java框架的3.2倍,主要原因是Spring在企业级Java应用中的市场占有率超过67%。
对于GraphQL技术栈而言,2026年已经出现了多个框架级安全事件:
- 2026年3月:Apollo GraphQL Server SSRF漏洞
- 2026年5月:Hasura GraphQL Engine认证绕过
- 2026年6月:Spring for GraphQL反序列化RCE
企业应建立GraphQL专属的安全基线:强制introspection在生产环境关闭、实施查询深度限制、启用查询白名单或持久化查询(Persisted Queries)机制。
数据来源与参考文献
- Spring.io. "CVE-2026-41699: Spring for GraphQL Unsafe Deserialization." Spring Security Advisory, 2026-06-11. https://spring.io/security/cve-2026-41699
- NVD. "CVE-2026-41699 Detail." National Vulnerability Database, 2026. https://nvd.nist.gov/vuln/detail/CVE-2026-41699
- OWASP. "GraphQL Cheat Sheet." OWASP Foundation, 2025. https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html
- Snyk. "State of Open Source Security 2025." Snyk, 2025.
- GitHub Advisory Database. "spring-graphql Security Advisories." https://github.com/advisories?query=spring-graphql
更新时间: 2026-06-24 作者: 安全情报分析团队
评论