Skip to content

Commit

Permalink
Updated fuzzer and fixed validation bug.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mickael van der Beek committed Jan 13, 2015
1 parent f79bebe commit ec3ba89
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 141 deletions.
173 changes: 112 additions & 61 deletions src/fuzzer/fuzzer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var crypto = require('crypto');
var http = require('http');

var Validator = require('./validator');
var Validator = require('../validator/validator');

var Functions = require('./payloads/functions');
var Booleans = require('./payloads/booleans');
Expand All @@ -13,7 +13,9 @@ var Errors = require('./payloads/errors');
var Arrays = require('./payloads/arrays');
var Dates = require('./payloads/dates');

var CryptoSchema = require('./schemas/core/crypto');
var HttpSamples = require('../samples/core/http');

var HttpSchema = require('../schemas/core/http');

module.exports = (function () {
'use strict';
Expand Down Expand Up @@ -47,96 +49,145 @@ module.exports = (function () {
);

this.modules = {
crypto: crypto
http: http
};

this.samples = {
http: HttpSamples
};

this.schemas = {
crypto: CryptoSchema
http: HttpSchema
};

this.mutationChance = 0.05;
this.turns = 10000;
}

Fuzzer.prototype.fuzzModules = function () {
var schema;
var schemas;
var samples;
var module;

for(var moduleName in this.schemas) {
schema = this.schemas[moduleName];
for (var moduleName in this.schemas) {
schemas = this.schemas[moduleName];
module = this.modules[moduleName];
samples = this.samples[moduleName];

this.fuzzModule(schema, module);
this.fuzzModule(schemas, samples, module);
}
};

Fuzzer.prototype.fuzzModule = function (schema, module) {
for(var methodName in schema) {
this.fuzzMethod(schema, module, methodName);
}
};
Fuzzer.prototype.fuzzModule = function (schemas, samples, module) {
var schema;
var sample;

Fuzzer.prototype.fuzzMethod = function (schema, module, methodName) {
var outputSchema = schema[methodName].output;
var inputSchema = schema[methodName].input;
for (var methodName in schemas) {
schema = schemas[methodName];
sample = samples[methodName];

var overload = [];
for(var i = 0; i < inputSchema.length; i++) {
overload.push(this.payloads);
this.fuzzMethod(schema, sample, module, methodName);
}
};

var payloads = this.generatePayloads(overload);
var len = payloads.length;
var output;
var input;

var errors = {};

while(len--) {
input = payloads[len];

console.log('1 INPUT:', input);
console.log('1 NAME:', methodName);
Fuzzer.prototype.fuzzMethod = function (schema, sample, module, methodName) {
var errorMap = {};
var callback;
var payloads;
var results;

for (var i = 0; i < this.turns; i++) {
payloads = this.generatePayloads(schema, sample);

callback = (function () {
return function (e) {
if (e instanceof Error && !(e in errorMap)) {
console.log('(', i, ') ERROR:', e);
// errorMap[e] = {
// payloads: payloads,
// error: e,
// stack: e.stack
// };

errorMap[e] = payloads[0];
}
};
})();

try {
output = module[methodName].apply(module, input);
// console.log('(', i, ') INPUT:', payloads);
payloads.push(callback);
results = module[methodName].apply(module, payloads);
results.on('error', callback);
results.on('close', callback);
results.on('end', callback);
results.on('finish', callback);
results.end();
}
catch(e) {
output = e;
catch (e) {
results = e;
}

if(output instanceof Error) {
if(!errors[output]) {
errors[output] = output;
console.log('\n---------------------');
console.log('1 OUTPUT:', output);
console.log('1 ERROR:', input);
if (results instanceof Error) {
if (!(results in errorMap)) {
// errorMap[results] = {
// payloads: payloads[0],
// error: results,
// stack: results.stack
// };
errorMap[results] = payloads[0];

// console.log('(', i, ') ERROR:', results);
// console.log('(', i, ') ERROR:', results.stack);
// console.log('(', i, ') INPUT:', payloads);
}
}
else if(!Validator.validate(outputSchema, output)) {
console.log('\n---------------------');
console.log('2 OUTPUT:', output);
console.log('2 CORRUPT:', input);
else {
// console.log('(', i, ') CORRUPT:', results);
// console.log('(', i, ') INPUT:', payloads);
}
}

console.log(new Array(81).join('-'));
console.log(errorMap);
};

Fuzzer.prototype.generatePayloads = function (payloads) {
var inputs = [];
var max = payloads.length - 1;
function getCombinations(array, i) {
for (var j = 0, l = payloads[i].length; j < l; j++) {
var combination = array.slice(0);
combination.push(payloads[i][j]);
if (i === max) {
inputs.push(combination);
}
else {
getCombinations(combination, i + 1);
}
Fuzzer.prototype.generatePayloads = function (schema, sample) {
var hasMutated = false;
var payloads = Array.isArray(schema) ? [] : {};
var keys = Object.keys(schema);
var len = keys.length;
var subschema;
var subsample;
var key;

while (len--) {
key = keys[len];
subschema = schema[key];
subsample = sample[key];

if ('keys' in subschema) {
payloads[key] = this.generatePayloads(subschema.keys, subsample);
}
else if (hasMutated === false && Math.random() <= this.mutationChance) {
hasMutated = true;
payloads[key] = this.generatePayload(subschema);
}
else if (key in sample) {
payloads[key] = subsample;
}
}
getCombinations([], 0);
return inputs;

return payloads;
};

return new Fuzzer();
Fuzzer.prototype.generatePayload = function (schema) {
var random = Math.floor(Math.random() * ((this.payloads.length - 1) + 1));
var payload = this.payloads[random];

return Validator.validate(payload) ? this.generatePayload(schema) : payload;
};

var fuzzer = new Fuzzer();
fuzzer.fuzzModules();
})();
1 change: 1 addition & 0 deletions src/fuzzer/payloads/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = [
';',
'&',
'@',
'/',
'--',
'\\',
'//',
Expand Down
24 changes: 24 additions & 0 deletions src/samples/core/http.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = {

request: [{
host: 'www.example.com',
// hostname: {
// type: 'String'
// },
// port: {
// type: 'Number'
// },
// localAddress: {},
// socketPath: {},
method: 'HEAD',
path: '/',
headers: {
Authorization: 'bearer example'
},
auth: 'user:password',
// agent: {},
}/*,
function () {}
*/]

};
80 changes: 0 additions & 80 deletions src/schemas/core/crypto.js

This file was deleted.

40 changes: 40 additions & 0 deletions src/schemas/core/http.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module.exports = {

request: [{
type: 'Object',
keys: {
host: {
type: 'String'
},
hostname: {
type: 'String'
},
port: {
type: 'Number'
},
localAddress: {
type: 'String'
},
socketPath: {
type: 'String'
},
method: {
type: 'String'
},
path: {
type: 'String'
},
headers: {
optional: true,
type: 'Object'
},
auth: {
type: 'String'
}
}
}/*, {
type: 'Function',
formats: []
}*/]

};
4 changes: 4 additions & 0 deletions src/validator/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ module.exports = (function () {
);
}

if (valid === false) {
return valid;
}

if ('formats' in schema) {
valid &= this.validateFormats(schema.formats, value);
}
Expand Down
Loading

0 comments on commit ec3ba89

Please sign in to comment.