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

Denial of service when parsing too long JSON numbers as double or float #1040

Closed
plokhotnyuk opened this issue Dec 20, 2018 · 4 comments
Closed

Comments

@plokhotnyuk
Copy link
Contributor

plokhotnyuk commented Dec 20, 2018

Sub-quadratic decreasing of throughput when length of the JSON number to parse is increasing.

On contemporary CPUs parsing of such JSON numbers that are bound on doubles or floats and has 1000000 decimal digits (~1Mb) can took more than 14 seconds. Below are results of the benchmark where the size parameter is a number of digits to parse:

[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] DoubleBenchmark.readCirce                   1  thrpt    5  13406952.737 ± 2032432.395  ops/s
[info] DoubleBenchmark.readCirce                  10  thrpt    5  10997675.235 ±  619560.310  ops/s
[info] DoubleBenchmark.readCirce                 100  thrpt    5    351697.951 ±    4377.854  ops/s
[info] DoubleBenchmark.readCirce                1000  thrpt    5     19590.316 ±    1601.505  ops/s
[info] DoubleBenchmark.readCirce               10000  thrpt    5       482.626 ±       2.149  ops/s
[info] DoubleBenchmark.readCirce              100000  thrpt    5         6.579 ±       0.629  ops/s
[info] DoubleBenchmark.readCirce             1000000  thrpt    5         0.071 ±       0.005  ops/s

Reproducible Test Case

To run that benchmarks on your JDK:

  1. Install latest version of sbt and/or ensure that it already installed properly:
sbt about
  1. Clone jsoniter-scala repo:
git clone https://github.com/plokhotnyuk/jsoniter-scala.git
  1. Enter to the cloned directory and checkout for the specific branch:
cd jsoniter-scala
git checkout circe-DoS-for-doubles-and-floats
  1. Run benchmarks using a path parameter to your JDK:
sbt -no-colors 'jsoniter-scala-benchmark/jmh:run -jvm /usr/lib/jvm/jdk-11/bin/java -wi 2 -i 5 DoubleBenchmark.*Circe.*'
@plokhotnyuk
Copy link
Contributor Author

plokhotnyuk commented Dec 20, 2018

BTW, BigDecimal and BigInt types are still vulnerable.

The simplest code to reproduce the problem:

io.circe.parser.decode[BigInt]("9" * 1000000)

Will anybody request a CVE number for this security issue?

@hamnis
Copy link
Collaborator

hamnis commented Jul 27, 2023

Closing in cleanup run, If anyone cares about this, please comment and I'll reopen.

@hamnis hamnis closed this as completed Jul 27, 2023
@plokhotnyuk
Copy link
Contributor Author

plokhotnyuk commented Jul 27, 2023

I would not close it blindly.

It is a security issue, circe is vulnerable under DoS attacks from untrusted inputs that exploit O(n^2) complexity of BigInt parsing.

@SethTisue
Copy link
Contributor

SethTisue commented Jul 27, 2023

as far as I can see, it's fine to close this one, since #1363 remains open (and also includes information about how users can avoid the problem)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants