Describe the bug
A security-distinct OSX push request can resolve to the same Eggroll session as another request when both requests share the same computed session key:
rollSiteSessionId + "_" + dstRole + "_" + dstPartyId
The broker uses this computed string as the only key for PutBatchSinkUtil.sessionCache and as ErSessionMeta.id for the Eggroll cluster manager lookup. The lookup does not bind the session to the request owner, tenant, user, external job id, or source party. As a result, an attacker who can submit a crafted RollSiteHeader with a colliding rollSiteSessionId, dstRole, and dstPartyId can reuse the same backend session identity as a victim.
Confirmed against commit 5a06d9e4c4cd7ab97a5c8357828adbffaca87785.
To Reproduce
Steps to reproduce the behavior:
- Review the session key construction in
java/osx/osx-broker/src/main/java/org/fedai/osx/broker/grpc/QueuePushReqStreamObserver.java.
- Submit or simulate two
RollSiteHeader objects with different security context, such as different tenant/user/job/source party, but the same rollSiteSessionId, dstRole, and dstPartyId.
- Observe that both requests compute the same session id, for example
sess-42_host_10000.
- Observe that this single string is used as the key for
PutBatchSinkUtil.sessionCache and then passed as ErSessionMeta.id to ClusterManagerClient.getSession.
Minimal simulation:
def broker_session_key(header):
return "_".join([header["rollSiteSessionId"], header["dstRole"], header["dstPartyId"]])
victim = {
"tenant_id": "tenant_alpha",
"user_id": "alice",
"job_id": "job-train-1",
"rollSiteSessionId": "sess-42",
"srcRole": "guest",
"srcPartyId": "9999",
"dstRole": "host",
"dstPartyId": "10000",
}
attacker = {
"tenant_id": "tenant_beta",
"user_id": "bob",
"job_id": "job-train-9",
"rollSiteSessionId": "sess-42",
"srcRole": "guest",
"srcPartyId": "1234",
"dstRole": "host",
"dstPartyId": "10000",
}
assert victim != attacker
assert broker_session_key(victim) == broker_session_key(attacker)
print(broker_session_key(victim))
Expected output:
Expected behavior
Session lookup should include or verify all fields required to determine session ownership and security equivalence. At minimum, a request should not be allowed to reuse an existing Eggroll session unless the broker verifies that the caller is authorized for that session and that the session belongs to the expected security context.
Screenshots
Not applicable.
Desktop (please complete the following information):
- OS: Linux verification environment
- Browser: Not applicable
- Version: Repository commit
5a06d9e4c4cd7ab97a5c8357828adbffaca87785
Smartphone (please complete the following information):
- Device: Not applicable
- OS: Not applicable
- Browser: Not applicable
- Version: Not applicable
Additional context
Relevant code locations:
QueuePushReqStreamObserver.initEggroll computes sessionId from rollSiteSessionId, dstRole, and dstPartyId, then calls PutBatchSinkUtil.sessionCache.get(sessionId).
PutBatchSinkUtil.sessionCache is a LoadingCache<String, ErSession>.
ErSession sets ErSessionMeta.id to the supplied sessionId.
ClusterManagerClient.getSession sends that SessionMeta to the Eggroll cluster manager.
SessionMeta only contains id, name, status, tag, processors, and options; it has no tenant/user/job ownership fields.
This report concerns a security-sensitive bug. The project README lists the Security Response Committee contact as FATE-security @ groups.io.
Describe the bug
A security-distinct OSX push request can resolve to the same Eggroll session as another request when both requests share the same computed session key:
The broker uses this computed string as the only key for
PutBatchSinkUtil.sessionCacheand asErSessionMeta.idfor the Eggroll cluster manager lookup. The lookup does not bind the session to the request owner, tenant, user, external job id, or source party. As a result, an attacker who can submit a craftedRollSiteHeaderwith a collidingrollSiteSessionId,dstRole, anddstPartyIdcan reuse the same backend session identity as a victim.Confirmed against commit
5a06d9e4c4cd7ab97a5c8357828adbffaca87785.To Reproduce
Steps to reproduce the behavior:
java/osx/osx-broker/src/main/java/org/fedai/osx/broker/grpc/QueuePushReqStreamObserver.java.RollSiteHeaderobjects with different security context, such as different tenant/user/job/source party, but the samerollSiteSessionId,dstRole, anddstPartyId.sess-42_host_10000.PutBatchSinkUtil.sessionCacheand then passed asErSessionMeta.idtoClusterManagerClient.getSession.Minimal simulation:
Expected output:
Expected behavior
Session lookup should include or verify all fields required to determine session ownership and security equivalence. At minimum, a request should not be allowed to reuse an existing Eggroll session unless the broker verifies that the caller is authorized for that session and that the session belongs to the expected security context.
Screenshots
Not applicable.
Desktop (please complete the following information):
5a06d9e4c4cd7ab97a5c8357828adbffaca87785Smartphone (please complete the following information):
Additional context
Relevant code locations:
QueuePushReqStreamObserver.initEggrollcomputessessionIdfromrollSiteSessionId,dstRole, anddstPartyId, then callsPutBatchSinkUtil.sessionCache.get(sessionId).PutBatchSinkUtil.sessionCacheis aLoadingCache<String, ErSession>.ErSessionsetsErSessionMeta.idto the suppliedsessionId.ClusterManagerClient.getSessionsends thatSessionMetato the Eggroll cluster manager.SessionMetaonly containsid,name,status,tag,processors, andoptions; it has no tenant/user/job ownership fields.This report concerns a security-sensitive bug. The project README lists the Security Response Committee contact as
FATE-security @ groups.io.