Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security roles checked after constraints validation with quarkus-resteasy-reactive #16897

Closed
gwenneg opened this issue Apr 29, 2021 · 18 comments · Fixed by #19598
Closed

Security roles checked after constraints validation with quarkus-resteasy-reactive #16897

gwenneg opened this issue Apr 29, 2021 · 18 comments · Fixed by #19598
Labels
Milestone

Comments

@gwenneg
Copy link
Member

gwenneg commented Apr 29, 2021

Describe the bug

I noticed something weird while migrating a project from quarkus-resteasy to quarkus-resteasy-reactive:

  • with quarkus-resteasy, security roles are checked before constraints validation when the request content type is JSON
  • with quarkus-resteasy-reactive, security roles are checked after constraints validation when the request content type is JSON

There's no difference between the two extensions when the content type is text.

Expected behavior

I would expect the same behavior with both versions of quarkus-resteasy*.

Actual behavior

Different behavior.

To Reproduce

https://github.com/gwenneg/quarkus-resteasy-reactive-security

It contains two folders with the exact same code with one exception: the quarkus-resteasy* dependency.

Steps to reproduce the behavior:

  1. cd quarkus-resteasy
  2. ./mvnw clean test > BUILD SUCCESS
  3. cd quarkus-resteasy-reactive
  4. ./mvnw clean test > BUILD FAILURE

Environment (please complete the following information):

Output of java -version

openjdk version "11.0.9.1" 2020-11-04
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.9.1+1)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.9.1+1, mixed mode)

Quarkus version or git rev

1.13.3.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)

@gwenneg gwenneg added the kind/bug Something isn't working label Apr 29, 2021
@quarkus-bot
Copy link

quarkus-bot bot commented Apr 29, 2021

@sberyozkin
Copy link
Member

@gwenneg Hi, what side-effects do you observe ? In both cases the end resultt should be the method is only being invoked if both security roles and constrains validation checks pass ?

thanks

@gwenneg
Copy link
Member Author

gwenneg commented Apr 29, 2021

I'm still in the middle of the migration and didn't have the occasion to use the app with quarkus-resteasy-reactive. So the only side-effect I observed so far is one of our unit tests which checks security that started failing.

I created this issue because I'm a bit concerned that security comes second. The problem could also be larger than the simple @NotNull constraint I used in the reproducer.

@sberyozkin
Copy link
Member

@gwenneg I see - as far as the test is concerned - it is a test problem since it is failing now because of the constraints check failing. The constraints check in itself has no side-effects (I hope, CC @gsmet ) so as long the method is protected all is safe - but I agree it would be better to run the sec check first - @geoand - hi, looks like an authorization filter priority is not taken into consideration ?

@gsmet
Copy link
Member

gsmet commented Apr 29, 2021

Security checks should ALWAYS be executed first. Otherwise you expose your endpoint somehow. Obviously, it's not a big problem if your constraint is @NotNull but if you have some business related constraints, you could expose some logic that you don't want to expose.

@sberyozkin
Copy link
Member

So the constraints check can have side-effects, they are not just checking the input values...

@sberyozkin
Copy link
Member

@gsmet By the way - if the constraint validation exception can return information about the endpoint - it would be a CVE material.

@gsmet
Copy link
Member

gsmet commented Apr 29, 2021

They are checking the input values but they can be business related anyway i.e. "@ValidOrderNumber" or whatever.

People can implement their own constraints and you have absolutely no idea of what they will do with them. So you cannot assume they are entirely safe to execute before the security checks.

@gwenneg
Copy link
Member Author

gwenneg commented Apr 29, 2021

Poorly written validation can also lead to DoS attacks. I wouldn't want that to be exposed before the security check is done.

@geoand
Copy link
Contributor

geoand commented Apr 29, 2021

@geoand - hi, looks like an authorization filter priority is not taken into consideration ?

I haven't looked into it (and probably won't for the next few days as we have some public holidays here), but I would be surprised if that is the case as the TCK tests this extensively.
What does the filter look like?

@sberyozkin
Copy link
Member

@gsmet @gwenneg thanks for the explanation - you see I've been naively thinking it is just NotNull or This Integer must be > 1, etc :-)

@sberyozkin
Copy link
Member

Hey @geoand Enjoy the long weekend, I thought it was a JAX-RS filter but it is a CDI interceptor

@geoand
Copy link
Contributor

geoand commented Apr 29, 2021

Hey @geoand Enjoy the long weekend, I thought it was a JAX-RS filter but it is a CDI interceptor

Aha, OK :)

@geoand
Copy link
Contributor

geoand commented Apr 29, 2021

I had a quick look and what you are seeing is actually not caused by the interceptors at all - neither the validation interceptor nor the security interceptor get invoked at all.

The code that results in HTTP 400 is:
https://github.com/quarkusio/quarkus/blob/1.13.3.Final/extensions/resteasy-reactive/quarkus-resteasy-reactive-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/serialisers/ServerJacksonMessageBodyReader.java#L55

I think we have had this conversation somewhere before... The question is whether we should not return HTTP 400, but let the processing continue with a null value.
In this case it may make sense, but in general it seems pretty risky...

@stuartwdouglas
Copy link
Member

At the moment this is implemented as a CDI interceptor (this is not just a Resteasy Reactive thing, @RolesAllowed works on any CDI bean).

We probably need to turn this into a handler, and push this up the chain and run it first thing after the pre-match interceptors.

@geoand
Copy link
Contributor

geoand commented Apr 30, 2021

We could certainly do that, as it would run security before input is ever read

@sberyozkin
Copy link
Member

@RolesAllowed works on any CDI bean

Cool, this must be documented - will take care of it, thanks Stuart @stuartwdouglas for reminding about it

@geoand
Copy link
Contributor

geoand commented Jun 4, 2021

I wonder if it makes sense to this sort of thing with other kinds of interceptors as well - like Caching for example

stuartwdouglas added a commit to stuartwdouglas/quarkus that referenced this issue Aug 24, 2021
This makes sure they are run before serialization. It also means that
fully async checks will work as expected.

Fixes quarkusio#16897
Fixes quarkusio#15935
@quarkus-bot quarkus-bot bot added this to the 2.3 - main milestone Aug 24, 2021
@gsmet gsmet modified the milestones: 2.3 - main, 2.2.0.Final Aug 24, 2021
gsmet pushed a commit to gsmet/quarkus that referenced this issue Aug 24, 2021
This makes sure they are run before serialization. It also means that
fully async checks will work as expected.

Fixes quarkusio#16897
Fixes quarkusio#15935

(cherry picked from commit 51c4052)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants