Safe deserialization

30 views
Skip to first unread message

Michael Rogers

unread,
Oct 5, 2018, 12:28:11 PM10/5/18
to jackso...@googlegroups.com
Hi,

I'd like to use Jackson to deserialize JSON from an untrusted source
into simple POJOs that can be used for further validation (checking that
values are within allowed ranges, etc). I've read a couple of blog posts
about deserialization attacks [1,2] and I'd like to ask if there are
some simple instructions I can follow to ensure my code isn't vulnerable
to these attacks, without having to keep up to date with the latest
gadget blacklists.

As far as I can tell from @cowtowncoder's blog post, I should avoid
polymorphic type handling for any object or field whose declared type is
broad enough to cover a gadget. But the list of such types grows as new
gadgets are discovered. So if I understand right, the only way to be
safe against as-yet-undiscovered gadgets is to avoid polymorphic type
handling altogether.

That's absolutely fine - I haven't written the code yet, so I'm not
stuck with a legacy decision to use polymorphic type handling. So in
that case my question is how to use Jackson without polymorphic type
handling:

a) to parse a JSON string into a JsonNode that I can walk to create a
POJO manually, or
b) to parse a JSON string into a POJO directly?

On the other hand, if I've misunderstood and it's *not* necessary to
avoid polymorphic type handling altogether, then how can I use it safely
without keeping up to date with gadget blacklists?

Thanks,
Michael

[1]
https://medium.com/@cowtowncoder/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062

[2] https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/

quetzlc...@gmail.com

unread,
Oct 5, 2018, 12:28:11 PM10/5/18
to jackson-user
Hi,

I'd like to use Jackson to deserialize JSON from an untrusted source into simple POJOs that can be used for further validation (checking that values are within allowed ranges, etc). I've read a couple of blog posts about deserialization attacks [1,2] and I'd like to ask if there are some simple instructions I can follow to ensure my code isn't vulnerable to these attacks, without having to keep up to date with the latest gadget blacklists.

As far as I can tell from @cowtowncoder's blog post, I should avoid polymorphic type handling for any object or field whose declared type is broad enough to cover a gadget (Object, Serializable, etc). But the list of such types grows as new gadgets are discovered. So if I understand right, the only way to be safe against as-yet-undiscovered gadgets is to avoid polymorphic type handling altogether.

That's absolutely fine - I haven't written the code yet, so I'm not stuck with a legacy decision to use polymorphic type handling. So in that case my question is how to use Jackson without polymorphic type handling:

a) to parse a JSON string into a JsonNode that I can walk to create a POJO manually, or
b) to parse a JSON string into a POJO directly?

On the other hand, if I've misunderstood, and it's *not* necessary to avoid polymorphic type handling altogether, then how can I use it safely without keeping up to date with gadget blacklists?

Thanks,
Michael

[1] https://medium.com/@cowtowncoder/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062

[2] https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/

Michael Rogers

unread,
Oct 5, 2018, 12:28:11 PM10/5/18
to jackso...@googlegroups.com
Hi,

I'd like to use Jackson to deserialize JSON from an untrusted source
into simple POJOs that can be used for further validation (checking that
values are within allowed ranges, etc). I've read a couple of blog posts
about deserialization attacks [1,2] and I'd like to ask if there are
some simple instructions I can follow to ensure my code isn't vulnerable
to these attacks, without having to keep up to date with the latest
gadget blacklists.

As far as I can tell from @cowtowncoder's blog post, I should avoid
polymorphic type handling for any object or field whose declared type is
broad enough to cover a gadget. But the list of such types grows as new
gadgets are discovered. So if I understand right, the only way to be
safe against as-yet-undiscovered gadgets is to avoid polymorphic type
handling altogether.

That's absolutely fine - I haven't written the code yet, so I'm not
stuck with a legacy decision to use polymorphic type handling. So in
that case my question is how to use Jackson without polymorphic type
handling:

a) to parse a JSON string into a JsonNode that I can walk to create a
POJO manually, or
b) to parse a JSON string into a POJO directly?

On the other hand, if I've misunderstood and it's *not* necessary to
0x11044FD19FC527CC.asc
signature.asc

Tatu Saloranta

unread,
Oct 5, 2018, 12:42:11 PM10/5/18
to jackson-user
On Fri, Oct 5, 2018 at 9:28 AM Michael Rogers <mic...@briarproject.org> wrote:
Hi,

I'd like to use Jackson to deserialize JSON from an untrusted source
into simple POJOs that can be used for further validation (checking that
values are within allowed ranges, etc). I've read a couple of blog posts
about deserialization attacks [1,2] and I'd like to ask if there are
some simple instructions I can follow to ensure my code isn't vulnerable
to these attacks, without having to keep up to date with the latest
gadget blacklists.

Ok.
 
As far as I can tell from @cowtowncoder's blog post, I should avoid
polymorphic type handling for any object or field whose declared type is
broad enough to cover a gadget. But the list of such types grows as new
gadgets are discovered. So if I understand right, the only way to be
safe against as-yet-undiscovered gadgets is to avoid polymorphic type
handling altogether.

Yes.
 

That's absolutely fine - I haven't written the code yet, so I'm not
stuck with a legacy decision to use polymorphic type handling. So in
that case my question is how to use Jackson without polymorphic type
handling:

a) to parse a JSON string into a JsonNode that I can walk to create a
POJO manually, or
b) to parse a JSON string into a POJO directly?

On the other hand, if I've misunderstood and it's *not* necessary to
avoid polymorphic type handling altogether, then how can I use it safely
without keeping up to date with gadget blacklists?

I think you summarized well pertinent points.

I would just mention one additional aspect: if you control the base type (and by definition subtypes I guess),
you are likely to be safe. So if you "own" the type hierarchy, there is no attack vector.

Another thing to consider is that attacks only work when using class name as the type id.
Type name - based approach is unlikely to allow attacks, since one essentially has to register
all subtypes: either via `@JsonSubTypes` or using Module to register them.
And since you do not absolutely have to own subtype definitions (you may register any types,
and via use of mix-in annotations [or reliance of type name defaulting to class name]), it does
allow safe handling.

But what can not be safely supported, without additional handler overrides, is support for open-ended
type hierarchies (that is, for types you do not know about a priori).

And for truly advanced use, you can technically write `TypeResolver`s (or `TypeIdResolver`s) that use
some other heuristics to specify some kind of inclusion criteria (sort of custom allow-listing).

I hope some of above helps: combination of open-ended flexibility and security are not easy to combine.

-+ Tatu +-
 
--
You received this message because you are subscribed to the Google Groups "jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-user...@googlegroups.com.
To post to this group, send email to jackso...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Michael Rogers

unread,
Oct 10, 2018, 12:32:43 PM10/10/18
to jackso...@googlegroups.com, Tatu Saloranta
Hi Tatu,

Thanks for your reply (and sorry for the duplicate posts).

We don't need to do anything complex, so I'd just like to confirm
whether the following things are safe:

1. Create a new ObjectMapper without calling enableDefaultTyping(). Use
readTree(String) to parse a JsonNode from an untrusted String.

2. Create a POJO class that doesn't use any Jackson annotations, and
doesn't have any fields with types that are broad enough to cover
gadgets. Create a new ObjectMapper without calling
enableDefaultTyping(). Use readValue(String, Class) to parse a POJO from
an untrusted String.

3. As above, except the POJO class has a field with a type that could
cover a gadget, such as Object. But we're still not using any
annotations or enabling default typing.

Thanks again,
Michael
> <mailto:jackson-user%2Bunsu...@googlegroups.com>.
> To post to this group, send email to jackso...@googlegroups.com
> <mailto:jackso...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google
> Groups "jackson-user" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to jackson-user...@googlegroups.com
> <mailto:jackson-user...@googlegroups.com>.
> To post to this group, send email to jackso...@googlegroups.com
> <mailto:jackso...@googlegroups.com>.

Tatu Saloranta

unread,
Oct 10, 2018, 9:12:22 PM10/10/18
to jackson-user, Tatu Saloranta
On Wed, Oct 10, 2018 at 9:32 AM Michael Rogers <mic...@briarproject.org> wrote:
>
> Hi Tatu,
>
> Thanks for your reply (and sorry for the duplicate posts).
>
> We don't need to do anything complex, so I'd just like to confirm
> whether the following things are safe:
>
> 1. Create a new ObjectMapper without calling enableDefaultTyping(). Use
> readTree(String) to parse a JsonNode from an untrusted String.
>
> 2. Create a POJO class that doesn't use any Jackson annotations, and
> doesn't have any fields with types that are broad enough to cover
> gadgets. Create a new ObjectMapper without calling
> enableDefaultTyping(). Use readValue(String, Class) to parse a POJO from
> an untrusted String.
>
> 3. As above, except the POJO class has a field with a type that could
> cover a gadget, such as Object. But we're still not using any
> annotations or enabling default typing.

Correct: all 3 usages listed are safe.

Deserialization without polymorphism (via type id) can only map to
other types if:

1. User has specified mapping from abstract to concrete type (to allow
for mapping, say, `User` to `UserImpl`) OR
2. There is a deserializer (standard Jackson one or custom) that
creates an instance of concrete subtype
3. Special case of `java.lang.Object` uses "natural" mapping to Lists,
Maps, wrappers and nulls.

So, declaring a field as, say, `Object` does not invoke gadget
construction without explicit indication of polymorphism (and
matching id), nor does `java.io.Serializable`.

Use of annotations other than `@JsonTypeInfo` does not enable unsafe
handling either.

-+ Tatu +-
> To unsubscribe from this group and stop receiving emails from it, send an email to jackson-user...@googlegroups.com.
> To post to this group, send email to jackso...@googlegroups.com.

Michael Rogers

unread,
Oct 11, 2018, 4:55:24 AM10/11/18
to jackso...@googlegroups.com, Tatu Saloranta, Tatu Saloranta
Fantastic - thanks very much for your help.

Cheers,
Michael

0x11044FD19FC527CC.asc
signature.asc
Reply all
Reply to author
Forward
0 new messages