reugn / scalikejackson

Lightweight Scala JSON library
Apache License 2.0
7 stars 1 forks source link

Denial of service when parsing a JSON object with an unexpected field that has a big number #13

Open plokhotnyuk opened 5 years ago

plokhotnyuk commented 5 years ago

Sub-quadratic decreasing of throughput when length of the JSON object is increasing

On contemporary CPUs parsing of such JSON object with an additional field that has of 1000000 decimal digits (~1Mb) can took ~15 seconds for the ScalikeJackson parser:

[info] REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
[info] why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
[info] experiments, perform baseline and negative tests that provide experimental control, make sure
[info] the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
[info] Do not assume the numbers tell you what you want them to tell.
[info] Benchmark                             (size)   Mode  Cnt        Score   Error  Units
[info] ExtractFieldsReading.scalikeJackson        1  thrpt    2  1432398.714          ops/s
[info] ExtractFieldsReading.scalikeJackson       10  thrpt    2  1377622.290          ops/s
[info] ExtractFieldsReading.scalikeJackson      100  thrpt    2   684892.763          ops/s
[info] ExtractFieldsReading.scalikeJackson     1000  thrpt    2    50046.000          ops/s
[info] ExtractFieldsReading.scalikeJackson    10000  thrpt    2      660.185          ops/s
[info] ExtractFieldsReading.scalikeJackson   100000  thrpt    2        6.947          ops/s
[info] ExtractFieldsReading.scalikeJackson  1000000  thrpt    2        0.067          ops/s

Steps to reproduce

To run that benchmarks on your JDK:

  1. Install latest version of sbt and/or ensure that it already installed properly:

    sbt about
  2. Clone jsoniter-scala repo:

    git clone https://github.com/plokhotnyuk/jsoniter-scala.git
  3. Enter to the cloned directory and checkout for the specific branch:

    cd jsoniter-scala
    git checkout scalikeJackson-DoS-by-a-big-number
  4. Run benchmarks using a path parameter to your JDK:

    sbt -no-colors 'jsoniter-scala-benchmark/jmh:run -wi 2 -i 2 ExtractFieldsReading.scalikeJackson'

BTW, Play-JSON hasn't such kind of vulnerability. It throws the following error for too big numbers:

[info] java.lang.IllegalArgumentException: Number is larger than supported for field "x"
[info]  at play.api.libs.json.jackson.JsValueDeserializer.parseBigDecimal(JacksonJson.scala:142)
[info]  at play.api.libs.json.jackson.JsValueDeserializer.deserialize(JacksonJson.scala:164)
[info]  at play.api.libs.json.jackson.JsValueDeserializer.deserialize(JacksonJson.scala:126)
[info]  at play.api.libs.json.jackson.JsValueDeserializer.deserialize(JacksonJson.scala:121)
[info]  at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:3984)
[info]  at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2276)
[info]  at play.api.libs.json.jackson.JacksonJson$.parseJsValue(JacksonJson.scala:252)
[info]  at play.api.libs.json.StaticBinding$.parseJsValue(StaticBinding.scala:12)
[info]  at play.api.libs.json.Json$.parse(Json.scala:173)
reugn commented 5 years ago

FasterXML/jackson-databind#2157 Should have been fixed in 2.9.8 but still reproduces with 2.9.9.