Securing JSON-PATCH paths in Spring Boot Data Rest application
Asked Answered
Y

2

13

I'm using a pretty vanilla spring-boot-starter-data-rest setup and enabled the PATCH method. All is working, but I have a security concern and wonder what's the recommended way of mitigating it.

The problem is that PATCH paths allow reachable entities to be updated from a different endpoint. So, suppose I have a comments endpoint and an article endpoint. Each comment has a to-one association with its article. A user that has permission to edit a comment could then do something like this:

PATCH http://some.domain.foo/api/comments/1234
Content-Type: application/json-patch+json

[
    { "op": "replace", "path": "/article/title", "value": "foobar2" }
]

and thereby change the title of the article !!

Clearly this ain't good.

In this case, for other parts of the API the association to the "article" needs to be traversable. But it must be read-only.

So... how do I accomplish this in Spring?

Intercept the request? Implement a handler method? Write my own Controller from scratch ?

Thanks!

Yovonnda answered 3/3, 2017 at 23:17 Comment(0)
U
6

Seems that current implementation on spring-data-rest converts paths to SpEL to apply values directly on beans. See PatchOperation (v2.5.x).

Consider these options:

  • Instead of json-patch use json-merge PATCH request to send partial updates (with "application/json" or "application/merge-patch+json" content type). This will respect @JsonIgnore and other Jackson annotations and also treat associations differently.
  • You can disable "json-patch+json" completely, for example by adding a security filter
  • You can always create your custom json-patch implementation, if you still need it
  • Use application-level joining not relying on JPA, i.e. only exposing IDs of the linked entities and providing custom links in your ResourceProcessor.

Additionally, if you're using JPA and Comment.article is annotated with @ManyToOne make sure that there's no cascading on association. Even if the article object is modified with patch it won't be saved together with the comment.

Unknot answered 16/3, 2017 at 10:3 Comment(4)
So far I've gone ahead and implemented a custom method to handle PATCH with the application/json-patch+json content-type. And that works.Yovonnda
I'm unfamiliar with Spring's support for json-merge PATCH. Will look at that.Yovonnda
There's no cascading on the association, but the changes are most definitely being persisted. I don't think it's via a cascade mechanism -- in fact the cascading concept doesn't even apply here. This is pure path navigation in the object graph via SpEL with the changes to the graph persisted from the Session to the DB.Yovonnda
Good to know, thank you. I would suggest adding an issue to spring-data-rest project. That would be also great if you can share your own patch impl, if applicable. Btw, we ended with disabling json-patch and using only json-merge in our project.Unknot
S
1

There's been a recent fix in Spring Data Rest:

https://github.com/spring-projects/spring-data-rest/issues/2177

The commit that resolves this issue is:

https://github.com/spring-projects/spring-data-rest/commit/5d0687d1a1bb9a84264ecb4cd088907837c382d3

From a quick read this seems to be checking that when applying a JSON patch to an entity a check is done with Jackson that the path should be accessible (read/write).

This should prevent users from being able to specify paths in the JSON patch that aren't normally exposed through POST/GET requests that are mapped directly onto entities through Jackson. I think that if you had marked the article as readable from the comment and the title attribute as writeable then the new code should allow it. Or that's I think what org.springframework.data.rest.webmvc.json.patch.JsonPointerMapping#verify is trying to do.

So if you marked the article on the comment as not being readable through Jackson (@JsonIgnore on the getter) then JSON patch shouldn't allow the title of the article to be set through a comment. The association would still exist, just not be exposed through JSON serialization, I'm not sure if this would cause problems for your application.

The change is released in Spring Data Rest 4.0.0 which is part of Spring Data 2022.0.1 which is in Spring Boot 3.0.2.

https://github.com/spring-projects/spring-data-rest/releases/tag/4.0.0 https://github.com/spring-projects/spring-data-bom/releases/tag/2022.0.1 https://github.com/spring-projects/spring-boot/releases/tag/v3.0.2

Scribble answered 21/2, 2023 at 14:3 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.