Automatic fuzzer for hapi.js
Warning this is a proof of concept and is currently a work in progress. It is mostly used by me to automatically add fuzzing to my hapi test suites so stability and accuracy though important is not a major factor.
slides from SecTalks meetup about funzz
Funzz
should work with any testing framework that exposes a describe
and it
methods.
Like mocha -
const Hapi = require('@hapi/hapi');
const Funzz = require('funzz');
const server = Hapi.server();
server.route({ method: 'GET', path: '/test', handler: () => 'ok' });
Funzz(server);
Or Lab -
const Hapi = require('@hapi/hapi');
const Funzz = require('funzz');
const Lab = require('lab');
const { describe, it } = exports.lab = Lab.script();
const server = Hapi.server();
server.route({ method: 'GET', path: '/test', handler: () => 'ok' });
Funzz(server, { it, describe });
Or you can even try and see that no secrets are leaked in the result. Here is a naive example making making sure secret is never leaked -
const Hapi = require('@hapi/hapi');
const Funzz = require('funzz');
const Joi = require('@hapi/joi');
const Lab = require('@hapi/lab');
const { describe, it } = exports.lab = Lab.script();
const secret = Math.random().toString(32); //value that should not be leaked
const server = Hapi.server();
const code = '007';
server.route({
method: 'GET',
path: '/guess/{code}',
handler(req, res) {
if (req.params.code === code) {
return secret;
}
return Math.random().toString(32);
},
config: {
validate: {
params: {
code: Joi.string().regex(/\d{3}/)
}
}
}
});
Funzz(server, {
it,
describe,
permutations: 2500,
validResponse: Joi.object({
statusCode: Joi.number().integer().less(500),
payload: Joi.string().regex(new RegExp(secret), { name: 'secret', invert: true }) // make sure secret value is never leaked in response payload
}).unknown()
});
Funzz
is still a work in progress so you might want to be sure it actually manages to pass your route validations otherwise fuzzing will not have much effect
On the first couple of runs you should set the option validateData
to true so Funzz
will try to verify if the data generated for the schema is indeed a valid data that should pass your route validation.
Generate automatic tests for your hapi server routes returns array of all fuzzed data records
but you don't have to call server.start
automate: automate the test if set to false will only return records array but will not actually run the test default(true),
routeMatcher: RegExp to match against route path. only matching routes will be included default(undefined)
validateData: if true will use the validation schema to assert the data and will throw an error if data is not valid default(false),
permutations: how many records to create for each route default(10),
validResponse: Joi schema to validate the response default(Joi.object({ statusCode: Joi.number().integer().less(500) }).unknown())
juzzOptions: Options to be passed directly to Juzz default({})
state: Object('cookie_name': Joi.schema) | null state cookies to be fuzzed when no cookie validation was set on route. By default when no specific cookie validation was set to route a fuzzing will be created as a string value to all cookies that were defined by server.state
. Set to null to not inject any cookies or to object where key: schema
to inject specific cookies.
usePayloads: array of payloads to be loaded from assets Fuzz db files ['all', 'string.all', 'file.all', 'string.generic', 'string.sql', 'string.javascript', string.noSql', 'string.JSON', 'string.XSS', 'string.URI', 'string.userAgent', 'file.image', 'file.zip']
default([])
payloadsProbability: Probability in percents to replace a payload 100 will replace all payloads, 0 will replace none default(100)
regexPayloadsAttempts: if rule is a regular expression pattern try to find a payload that matches it default(10)
injectReplace: function to allow you manipulate data before it is injected to the server default((record, data) => data)
it: test suite it
function required when automate is true
default(global.it),
describe: test suite describe
function required when automate is true
default(global.describe)
Inject a specific record into the server
Create a list of injectable records for specific route
Funzz
is mostly a small wrapper around Juzz. Juzz is still very unstable.
if you have any issues where Funzz
fail to generate a valid schema that will pass the route validation, or if it is not reaching all available data nodes it is most likely an issue with Juzz
This library is using payloads taken from SecLists (all sits in ./assets path) For Specific attribution see SecLists CONTRIBUTORS.md