R0CKing666 opened a new issue, #11178:
URL: https://github.com/apache/rocketmq/issues/11178

   ### Runtime platform environment
   
   - OS: Linux (reproduced in a Docker container)
   - RocketMQ: branch `develop`, version `5.5.1`, commit `80e1ae557` (also 
still present in the latest upstream `develop`)
   
   ### JDK Version
   
   - Compiler: JDK 1.8
   
   ### Describe the Bug
   
   In the Remoting (TCP) authorization path, the authorization subject is taken 
directly from the client-supplied `AccessKey` in the request extFields, without 
any signature verification:
   
   ```java
   // DefaultAuthorizationContextBuilder#build(ChannelHandlerContext, 
RemotingCommand)
   Subject subject = null;
   if (fields.containsKey(SessionCredentials.ACCESS_KEY)) {
       subject = User.of(fields.get(SessionCredentials.ACCESS_KEY)); // 
client-controlled, unverified
   }
   ```
   
   `authorizationEnabled` and `authenticationEnabled` are independent switches 
with no cross-validation. With `authorizationEnabled=true` and 
`authenticationEnabled=false`, the `AuthenticationPipeline` returns early and 
does nothing, while the `AuthorizationPipeline` still derives the caller 
identity from the raw `AccessKey`. An attacker who knows any user's AccessKey 
(e.g. the SUPER user) can impersonate them — publish, consume, delete topics, 
etc. — without providing a SecretKey/signature.
   
   The gRPC path is not affected: it clears the client-supplied 
`AUTHORIZATION_AK` and only re-injects the verified identity after successful 
authentication.
   
   ### Steps to Reproduce
   
   1. Start a broker with `authorizationEnabled=true` and 
`authenticationEnabled=false`, and a SUPER user with a known AccessKey (e.g. 
`rocketmq2`) present in the auth metadata.
   2. Send a `SEND_MESSAGE` Remoting request whose extFields contain 
`AccessKey=rocketmq2` but no `Signature`.
   3. Observe that the request is authorized and processed.
   
   A minimal JUnit reproduction that exercises the exact broker authorization 
path (`DefaultAuthorizationContextBuilder` + `AuthorizationEvaluator` + 
`UserAuthorizationHandler`) is included in the accompanying PR. Its three tests 
confirm: the forged identity is authorized, an unknown AccessKey is denied, and 
enabling authentication rejects the unsigned request.
   
   ### What Did You Expect to See?
   
   With authorization enabled but authentication disabled, the broker should 
either refuse to start (fail-closed), or treat the caller as unauthenticated 
and deny the request.
   
   ### What Did You See Instead?
   
   The forged `AccessKey` is accepted as an authenticated SUPER identity and 
the request passes authorization.
   
   ### Additional Context
   
   Suggested fix (fail-closed): refuse to start when 
`authorizationEnabled=true` and `authenticationEnabled=false`, mirroring the 
existing fail-closed guards in `ProxyAdminAuthInterceptor` for the gRPC admin 
surface. The accompanying PR adds this startup validation plus a unit test.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to