0

In Apache Sling: If you have a multi tenant setting or an environment where users can deploy their own code (e.g. JSPs or actual Java / Groovy code or whatnot): is there a way to determine the identity of the user that has sent the current request from within a called OSGI service? It'd have to be safe against malicious code.

Background: often it is sufficient to rely on the JCR permissions to protect stuff that the user should not see. But sometimes you want an OSGI service to use a service user to access internal stuff for JCR resources needed for the service implementation, but to which you do not want the user to have access to. Here, you might have a somewhat tamper proof way to identify the user in order to check his permissions to the service.

There are some things which obviously do not work.

  • You could pass the users ResourceResolver as argument to the call into the OSGI service and check what ResourceResolver.getUserId() returns. This can easily be subverted by passing in a wrapper that delegates to the original ResourceResolver but returns something arbitrary for getUserId() here.
  • One could pass the users ResourceResolver as argument to the service, and check the users access to a certain path in the resource tree, and set JCR permissions to protect this path. Unfortunately that's not as easy as it sounds: malicious code could again pass a wrapper here which returns mock resources for this path, simulating access. The only way I see this could work is that the user has to do a write access to that path, and the service user is used to check whether this was actually modified. But that's not a nice way due to performance and other reasons.

Do you have other ideas which might actually work? Thanks a lot!

Note: I am aware that there are other attacks here you'd have to block (for instance the use of reflection to intrude into the OSGI services, but I'd like to at least make it nontrivial.

Dr. Hans-Peter Störr
  • 25,298
  • 30
  • 102
  • 139

2 Answers2

0

It is a multitenant system so every user will fall into some tenant. Based on the tenant context you can use RequestContext Object which actually checks whether the user of that tenant has proper access or not using SecurityManager and allows the specific users.

CodeCool
  • 193
  • 2
  • 12
  • Thank you, but could you please elaborate? How would I find out a tenant context from inside the OSGI service? After all, it cannot be passed as argument, as arguments can be set arbitrarily by malicious code. I didn't find a RequestContext class in any of the Sling libraries, too. – Dr. Hans-Peter Störr Sep 10 '20 at 17:43
0

Well, I found at least something: ResourceResolverFactory.getThreadResourceResolver returns the last ResourceResolver for which the request authenticated itself. So if one injects the ResourceResolverFactory into the service, then getUserId of the ResourceResolver returned by this seems to give at least an user id the user can impersonate.

(Notice that this is not necessarily the original id of the user itself, since if the code used ResourceResolverFactory.getResourceResolver, this changes the result. But this at least means the user can impersonate the returned user id.)

Another thing would be to employ a ServletFilter like Composum's PlatformAccessFilter that keeps the ResourceResolver used by the original SlingHttpRequest around in a ThreadLocal. (That scheme breaks down if the malicious code is able to deploy a ServletFilter with higher priority, but we have to stop somewhere.)

Unfortunately, both ideas do not work with a service resolver, since ResourceResolverFactory.getServiceResolver does not set esourceResolverFactory.getThreadResourceResolver .

Dr. Hans-Peter Störr
  • 25,298
  • 30
  • 102
  • 139