0

In ZAP (Zed Attack Proxy) its possible to fuzz requests. I have two values cookieUserId and cookieUser. They both have the same value and i want to change the ID for both fuzzing location. If i add a new payload for the second fuzz location ZAP will do 1,1 1,2 1,3 and not 1,1 2,2 3,3. Has anyone an idea how i can do the same payload for multiple fuzzing locations?

Axel
  • 21
  • 5

1 Answers1

1

Here's how you'd accomplish what you need.

Assume the following request for my answer/example:

GET http://localhost:8090/bodgeit/product.jsp?typeid=3&foo=3 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Host: localhost:8090

Let's say that typeid and foo are the param values that you want to pitchfork. Your going to create a Payload Generator script in ZAP, such as the following (this is a simple minor tweak to the default template, the important differences are outlined below after the code sample):

// Auxiliary variables/constants for payload generation.
var NUMBER_OF_PAYLOADS = 10;
var INITIAL_VALUE = 1;
var count = INITIAL_VALUE;
var MID= '&foo='

/**

  • Returns the number of generated payloads, zero to indicate unknown number.
  • The number is used as a hint for progress calculations.
  • @return {number} The number of generated payloads.

*/ function getNumberOfPayloads() { return NUMBER_OF_PAYLOADS; }

/**

  • Returns true if there are still payloads to generate, false otherwise.
  • Called before each call to next().
  • @return {boolean} If there are still payloads to generate.

*/ function hasNext() { return (count <= NUMBER_OF_PAYLOADS); }

/**

  • Returns the next generated payload.
  • This method is called while hasNext() returns true.
  • @return {string} The next generated payload.

*/ function next() { payload = count; count++; return payload+MID+payload; }

/**

  • Resets the internal state of the payload generator, as if no calls to
  • hasNext() or next() have been previously made.
  • Normally called once the method hasNext() returns false and while payloads
  • are still needed.

*/ function reset() { count = INITIAL_VALUE; }

/**

  • Releases any resources used for generation of payloads (for example, a file).
  • Called once the payload generator is no longer needed.

*/ function close() { }

Note: Declaration of the MID constant, which is the middle part of the string between the two param values. Modification of the next() method which returns the same value for both param values with the "MID" string inserted between.

In the request highlight 3&foo=3 right click and select "Fuzz...". Click the "Payloads" button, click the "Add" button, set the "Type" dropdown as "Script", select your "Script" by name in the dropdown (I called mine "Pitchfork"). ("Generate Preview" if you like.) Click the "Add" button. Click the "Ok" button. Click "Start Fuzzer". You've now run a "Pitchfork" fuzz in ZAP.

Results in the following payloads:

1&foo=1
2&foo=2
3&foo=3
4&foo=4
5&foo=5
6&foo=6
7&foo=7
8&foo=8
9&foo=9
10&foo=10

Things to keep in mind:

  1. Assuming you're fuzzing a normal GET or POST you should be able to order the params however you like. (Targets "shouldn't" care which order params are in, you can copy/paste them into whatever order you need and send the request manually.) If it's some sort of well formed content (JSON/XML, or whatever) then you can just turn MID into a huge string...
  2. You can install/use a scripting add-on such as Python (Jython) if you want to access payloads from a file.

If you wanted to process a header based on the same payload as the initial injection then you'd do a slight variation.

Create a "Fuzzer HTTP Processor" script, which is just a slight variation on the template. The following example simply checks the value of the payload in foo and uses it in a header:

/**
 * Processes the fuzzed message (payloads already injected).
 * 
 * Called before forwarding the message to the server.
 * 
 * @param {HttpFuzzerTaskProcessorUtils} utils - A utility object that contains functions that ease common tasks.
 * @param {HttpMessage} message - The fuzzed message, that will be forward to the server.
 */
function processMessage(utils, message) {
    // To obtain the list of payloads:
    //    utils.getPayloads()
    // To obtain original message:
    //    utils.getOriginalMessage()
    // To stop fuzzer:
    //    utils.stopFuzzer()
    // To increases the error count with a reason:
    //    utils.increaseErrorCount("Reason Error Message...")
    // To send a message, following redirects:
    //    utils.sendMessage(myMessage)
    // To send a message, not following redirects:
    //    utils.sendMessage(myMessage, false)
    // To add a message previously sent to results:
    //    utils.addMessageToResults("Type Of Message", myMessage)
    // To add a message previously sent to results, with custom state:
    //    utils.addMessageToResults("Type Of Message", myMessage, "Key Custom State", "Value Custom State")
    // The states' value is shown in the column 'State' of fuzzer results tab
    // To get the values of the parameters configured in the Add Message Processor Dialog.
    //    utils.getParameters() 
    // A map is returned, having as keys the parameters names (as returned by the getRequiredParamsNames()
    // and getOptionalParamsNames() functions below)
    // To get the value of a specific configured script parameter
    //    utils.getParameters().get("exampleParam1")
// Process fuzzed message...
 var payload = null;

for (var iterator = message.getUrlParams().iterator(); iterator.hasNext();) {
    var urlParam = iterator.next();

    if (urlParam.getName() == 'foo') {
        payload = urlParam.getValue();
        break;
    }
}
message.getRequestHeader().setHeader(&quot;X-Some-Id&quot;, payload);

}

/**

  • Processes the fuzz result.
  • Called after receiving the fuzzed message from the server.
  • @param {HttpFuzzerTaskProcessorUtils} utils - A utility object that contains functions that ease common tasks.
  • @param {HttpFuzzResult} fuzzResult - The result of sending the fuzzed message.
  • @return {boolean} Whether the result should be accepted, or discarded and not shown.

*/ function processResult(utils, fuzzResult){ // All the above 'utils' functions are available plus: // To raise an alert: // utils.raiseAlert(risk, confidence, name, description) // To obtain the fuzzed message, received from the server: // fuzzResult.getHttpMessage() // To get the values of the parameters configured in the Add Message Processor Dialog. // utils.getParameters() // A map is returned, having as keys the parameters names (as returned by the getRequiredParamsNames() // and getOptionalParamsNames() functions below) // To get the value of a specific configured script parameter // utils.getParameters().get("exampleParam1") return true; }

/**

  • This function is called during the script loading to obtain a list of the names of the required configuration parameters,
  • that will be shown in the Add Message Processor Dialog for configuration. They can be used
  • to input dynamic data into the script, from the user interface

*/ function getRequiredParamsNames(){ return []; }

/**

  • This function is called during the script loading to obtain a list of the names of the optional configuration parameters,
  • that will be shown in the Add Message Processor Dialog for configuration. They can be used
  • to input dynamic data into the script, from the user interface

*/ function getOptionalParamsNames(){ return []; }

You'd select just the param value you want to fuzz. In the above example if you wanted to fuzz foo you'd just select the 3. Setup the fuzzer much as above (you could use a built-in generator instead of a script), but add your "Message Processor" in the "Message Processors" tab, run the fuzzer.

Based on this example foo should get the values 1 thru 10 and each request will have a header such as X-Some-Id: 1 added (where the Id is ` to 10 kept in pace with the payload).

Of course you could also do a substring, encoding, etc. it doesn't have to be exactly the same.

kingthorin
  • 584
  • 4
  • 6