Extensions
Functions
Cohesion can be extended with user-supplied functions written in JavaScript. These functions can be used to change requests, use custom business logic, provide extra logging and much more.
Function Usage
To define a function, simply create a file with a module export. You can use the following template:
module.exports = function (request) {
// TODO: add code here
return request
}
To execute, we need to use a function command option, such as the "--target-func". For example:
$ cohesion fuzzer --target-func=/path/to/auth.js 01.request
If the function is within the current directory, it can be referenced by name too. For example:
$ cohesion fuzzer --target-func=auth 01.request
This command will load the function from file "auth.js".
This mechanism also allows us to explicitly specify the name of the function if it is not the module export. For example:
exports.func = function (request) {
// TODO: add code here
return request
}
Then the command is:
$ cohesion fuzzer --target-func=auth.func 01.request
Functions cannot be configured via command-line options but the configuration is possible with environment variables. For example:
$ VAR1=a VAR2=b cohesion fuzzer --target-func=auth.func 01.request
The authentication function now can reference both VAR1 and VAR2 variables in the following way:
exports.func = function (request) {
const var1 = process.env.VAR1
const var2 = process.env.VAR2
// TODO: add code here
return request
}
Target Functions
The target function is executed once for each loaded target (file or URL). This type of function is useful when some dynamic parameters need to be supplied to the request at runtime, during initialization. You can use this function to supply data such as dates, exchange rates, and authentication tokens, etc. Requests can be generated dynamically too.
For example, the following function supplies an authorisation token:
const url = require('url')
const https = require('https')
module.exports = (request) => {
return new Promise((resolve, reject) => {
const options = url.parse('http://auth/token')
const req = https.request(options, (res) => {
const chunks = []
res.on('error', reject)
res.on('data', (data) => {
chunks.push(data)
})
res.on('end', () => {
const { token } = JSON.parse(Buffer.concat(chunks).toString())
if (!request.headers) {
request.headers = {}
}
request.headers['Authorization'] = `Bearer ${token}`
resolve(request)
})
})
req.on('error', reject)
})
}
Let's use the function:
$ cohesion fuzzer --target-func=auth.func 01.request
The file "01.request" contains the following request:
POST http://target/path HTTP/1.1
Host: target
Content-Type: application/json
{
"param": "value"
}
Once the function is executed, the request will be changed to the following:
POST http://target/path HTTP/1.1
Host: target
Content-Type: application/json
Authorization: Bearer token
{
"param": "value"
}
With this function, we can be certain that the fuzzer will always have the correct credentials for fuzzing.