Esempio n. 1
0
def isJSON(freq):
    # Only do the JSON stuff if this is really a JSON request...
    postdata = freq.getData()
    try:
        cgi.parse_qs(postdata, keep_blank_values=True, strict_parsing=True)
    except Exception, e:
        # We have something that's not URL encoded in the postdata, it could be something
        # like JSON, XML, or multipart encoding. Let's try with JSON
        try:
            jsonPostData = json.loads(postdata)
        except:
            # It's not json, maybe XML or multipart, I don't really care ( at least not in this section of the code )
            return False
        else:
            # Now, fuzz the parsed JSON data...
            return True
Esempio n. 2
0
def createFuzzableRequestRaw(method, url, postData, headers):
    '''
    Creates a fuzzable request based on a query sent FROM the browser. This is used in
    plugins like spiderMan.
    
    @parameter method: A string that represents the method ('GET', 'POST', etc)
    @parameter url: An url_object that represents the URL
    @parameter postData: A string that represents the postdata, if its a GET request, set to None.
    @parameter headers: A dict that holds the headers
    '''
    if not isinstance(url, url_object):
        msg = 'The "url" parameter of createFuzzableRequestRaw @ frFactory'
        msg += ' must be of urlParser.url_object type.'
        raise ValueError( msg )

    
    #
    # Just a query string request ! no postdata
    #
    if not postData:
        qsr = httpQsRequest.httpQsRequest()
        qsr.setURL(url)
        qsr.setMethod(method)
        qsr.setHeaders(headers)
        dc = url.getQueryString()
        qsr.setDc(dc)
        return qsr
    #
    # Seems to be something that has post data
    #
    pdr = httpPostDataRequest.httpPostDataRequest()
    pdr.setURL(url)
    pdr.setMethod(method)
    for header_name in headers.keys():
        if header_name.lower() == 'content-length':
            del headers[header_name]
    pdr.setHeaders(headers)
    #
    #   Parse the content
    #   Case #1, multipart form data
    #
    conttype = headers.get('content-type', '')
    if conttype and conttype.startswith('multipart/form-data'):
        tmp, pdict = cgi.parse_header(conttype)
        try:
            dc = cgi.parse_multipart(StringIO(postData), pdict)
        except:
            om.out.debug('Multipart form data is invalid, the browser sent something weird.')
        else:
            resultDc = queryString()
            for i in dc.keys():
                resultDc[i] = dc[i]
            # We process multipart requests as x-www-form-urlencoded
            # TODO We need native support of multipart requests!
            headers['content-type'] = 'application/x-www-form-urlencoded'
            pdr.setDc(resultDc)
            pdr.setHeaders(headers)
            return pdr
    #
    #   Case #2, JSON request
    #
    try:
        dc = json.loads(postData)
    except:
        pass
    else:
        # It's json! welcome to the party dude!
        pdr = jsonPostDataRequest.jsonPostDataRequest()
        pdr.setURL(url)
        pdr.setMethod(method)
        pdr.setHeaders(headers)
        pdr.setDc(dc)
        return pdr
    #
    #   Case #3, XMLRPC request
    #
    postDataLower = postData.lower()
    stopWords = [
            '<methodcall>',
            '<methodname>',
            '<params>',
            '</methodcall>',
            '</methodname>',
            '</params>'
            ]
    allStopWords = True
    for word in stopWords:
        if word not in postDataLower:
            allStopWords = False
    if allStopWords:
        xmlrpc_request = xmlrpcRequest.xmlrpcRequest(postData)
        xmlrpc_request.setURL( url )
        xmlrpc_request.setMethod( method )
        xmlrpc_request.setHeaders( headers )
        return xmlrpc_request
    #
    #   Case #4, the "default".
    #
    # NOT a JSON or XMLRPC request!, let's try the simple url encoded post data...
    #
    try:
        dc = parse_qs(postData)
        pdr.setDc( dc )
    except:
        om.out.debug('Failed to create a data container that can store this data: "' + postData + '".')
    else:
        return pdr
Esempio n. 3
0
def _createJSONMutants(freq, mutantClass, mutant_str_list, fuzzableParamList, append):
    """
    @parameter freq: A fuzzable request with a dataContainer inside.
    @parameter mutantClass: The class to use to create the mutants
    @parameter fuzzableParamList: What parameters should be fuzzed
    @parameter append: True/False, if we should append the value or replace it.
    @parameter mutant_str_list: a list with mutant strings to use
    @return: Mutants that have the JSON postdata changed with the strings at mutant_str_list
    """
    # We define a function that creates the mutants...
    def _makeMutants(freq, mutantClass, mutant_str_list, fuzzableParamList, append, jsonPostData):
        res = []

        for fuzzed_json, original_value in _fuzzJSON(mutant_str_list, jsonPostData, append):

            # Create the mutants
            freq_copy = freq.copy()
            m = mutantClass(freq_copy)
            m.setOriginalValue(original_value)
            m.setVar("JSON data")
            m.setDc(fuzzed_json)
            res.append(m)

        return res

    # Now we define a function that does the work...
    def _fuzzJSON(mutant_str_list, jsonPostData, append):
        """
        @return: A list with tuples containing
        (fuzzed list/dict/string/int that represents a JSON object, original value)
        """
        res = []

        if isinstance(jsonPostData, int):
            for mutant_str in mutant_str_list:
                if mutant_str.isdigit():
                    # This (a mutant str that really is an integer) will happend once every 100000 years,
                    # but I wanted to be sure to cover all cases. This will look something like:
                    #
                    # 1
                    #
                    # In the postdata.
                    if append:
                        fuzzed = int(str(jsonPostData) + str(mutant_str))
                        res.append((fuzzed, str(jsonPostData)))
                    else:
                        fuzzed = int(mutant_str)
                        res.append((fuzzed, jsonPostData))

        elif isinstance(jsonPostData, basestring):
            # This will look something like:
            #
            # "abc"
            #
            # In the postdata.
            for mutant_str in mutant_str_list:
                if append:
                    fuzzed = jsonPostData + mutant_str
                    res.append((fuzzed, jsonPostData))
                else:
                    res.append((mutant_str, jsonPostData))

        elif isinstance(jsonPostData, list):
            # This will look something like:
            #
            # ["abc", "def"]
            #
            # In the postdata.
            for item, i in zip(jsonPostData, xrange(len(jsonPostData))):
                fuzzed_item_list = _fuzzJSON(mutant_str_list, jsonPostData[i], append)
                for fuzzed_item, original_value in fuzzed_item_list:
                    jsonPostDataCopy = copy.deepcopy(jsonPostData)
                    jsonPostDataCopy[i] = fuzzed_item
                    res.append((jsonPostDataCopy, original_value))

        elif isinstance(jsonPostData, dict):
            for key in jsonPostData:
                fuzzed_item_list = _fuzzJSON(mutant_str_list, jsonPostData[key], append)
                for fuzzed_item, original_value in fuzzed_item_list:
                    jsonPostDataCopy = copy.deepcopy(jsonPostData)
                    jsonPostDataCopy[key] = fuzzed_item
                    res.append((jsonPostDataCopy, original_value))

        return res

    # Now, fuzz the parsed JSON data...
    postdata = freq.getData()
    jsonPostData = json.loads(postdata)
    return _makeMutants(freq, mutantClass, mutant_str_list, fuzzableParamList, append, jsonPostData)
Esempio n. 4
0
def createFuzzableRequestRaw(method, url, postData, headers):
    """
    Creates a fuzzable request based on a query sent FROM the browser. This is used in
    plugins like spiderMan.
    
    @parameter method: A string that represents the method ('GET', 'POST', etc)
    @parameter url: A string that represents the URL
    @parameter postData: A string that represents the postdata, if its a GET request, set to None.
    @parameter headers: A dict that holds the headers
    """
    #
    # Just a query string request ! no postdata
    #
    if not postData:
        qsr = httpQsRequest.httpQsRequest()
        qsr.setURL(url)
        qsr.setMethod(method)
        qsr.setHeaders(headers)
        dc = urlParser.getQueryString(url)
        qsr.setDc(dc)
        return qsr
    #
    # Seems to be something that has post data
    #
    pdr = httpPostDataRequest.httpPostDataRequest()
    pdr.setURL(url)
    pdr.setMethod(method)
    for header_name in headers.keys():
        if header_name.lower() == "content-length":
            del headers[header_name]
    pdr.setHeaders(headers)
    #
    #   Parse the content
    #   Case #1, multipart form data
    #
    if "content-type" in headers.keys() and headers["content-type"].startswith("multipart/form-data"):
        tmp, pdict = cgi.parse_header(headers["content-type"])
        try:
            dc = cgi.parse_multipart(StringIO(postData), pdict)
        except:
            om.out.debug("Multipart form data is invalid, the browser sent something wierd.")
        else:
            resultDc = queryString()
            for i in dc.keys():
                resultDc[i] = dc[i]
            # We process multipart requests as x-www-form-urlencoded
            # TODO We need native support of multipart requests!
            headers["content-type"] = "application/x-www-form-urlencoded"
            pdr.setDc(resultDc)
            pdr.setHeaders(headers)
            return pdr
    #
    #   Case #2, JSON request
    #
    try:
        dc = json.loads(postData)
    except:
        pass
    else:
        # It's json! welcome to the party dude!
        pdr = jsonPostDataRequest.jsonPostDataRequest()
        pdr.setURL(url)
        pdr.setMethod(method)
        pdr.setHeaders(headers)
        pdr.setDc(dc)
        return pdr
    #
    #   Case #3, XMLRPC request
    #
    postDataLower = postData.lower()
    stopWords = ["<methodcall>", "<methodname>", "<params>", "</methodcall>", "</methodname>", "</params>"]
    allStopWords = True
    for word in stopWords:
        if word not in postDataLower:
            allStopWords = False
    if allStopWords:
        xmlrpc_request = xmlrpcRequest.xmlrpcRequest(postData)
        xmlrpc_request.setURL(url)
        xmlrpc_request.setMethod(method)
        xmlrpc_request.setHeaders(headers)
        return xmlrpc_request
    #
    #   Case #4, the "default".
    #
    # NOT a JSON or XMLRPC request!, let's try the simple url encoded post data...
    #
    try:
        dc = urlParser.getQueryString("http://w3af/?" + postData)
        pdr.setDc(dc)
    except:
        om.out.debug('Failed to create a data container that can store this data: "' + postData + '".')
    else:
        return pdr