Example #1
0
def parse_qs( url_encoded_string, ignoreExceptions=True ):
    '''
    Parse a url encoded string (a=b&c=d) into a queryString object.
    
    @param url_encoded_string: The string to parse
    @return: A queryString object (a dict wrapper). 

    >>> parse_qs('id=3')
    {'id': ['3']}
    >>> parse_qs('id=3&id=4')
    {'id': ['3', '4']}
    >>> parse_qs('id=3&ff=4&id=5')
    {'id': ['3', '5'], 'ff': ['4']}

    '''
    parsed_qs = None
    result = queryString()

    if url_encoded_string:
        try:
            parsed_qs = cgi.parse_qs( url_encoded_string ,keep_blank_values=True,strict_parsing=False)
        except Exception, e:
            if not ignoreExceptions:
                raise w3afException('Strange things found when parsing query string: "' + url_encoded_string + '"')
        else:
            #
            #   Before we had something like this:
            #
            #for i in parsed_qs.keys():
            #    result[ i ] = parsed_qs[ i ][0]
            #
            #   But with that, we fail to handle web applications that use "duplicated parameter
            #   names". For example: http://host.tld/abc?sp=1&sp=2&sp=3
            #
            #   (please note the lack of [0]) , and that if the value isn't a list... 
            #    I create an artificial list
            for p, v in parsed_qs.iteritems():
                if type(v) is not list:
                    v = [v]
                result[p] = v
Example #2
0
def getQueryString( url, ignoreExceptions=True ):
    '''
    Parses the query string and returns a dict.

    @parameter url: The url with the query string to parse.
    @return: A QueryString Object, example :
        - input url : http://localhost/foo.asp?xx=yy&bb=dd
        - output dict : { xx:yy , bb:dd }
    '''
    parsedQs = None
    result = queryString()

    scheme, domain, path, params, qs, fragment = _uparse.urlparse( url )

    if qs:
        try:
            parsedQs = cgi.parse_qs( qs ,keep_blank_values=True,strict_parsing=False)
        except Exception, e:
            if not ignoreExceptions:
                raise w3afException('Strange things found when parsing query string: "' + qs + '"')
        else:
            #
            #   Before we had something like this:
            #
            #for i in parsedQs.keys():
            #    result[ i ] = parsedQs[ i ][0]
            #
            #   But with that, we fail to handle web applications that use "duplicated parameter
            #   names". For example: http://host.tld/abc?sp=1&sp=2&sp=3
            #
            #   (please note the lack of [0]) , and that if the value isn't a list... 
            #    I create an artificial list
            for i in parsedQs.keys():
                if isinstance( parsedQs[ i ], list ):
                    result[ i ] = parsedQs[ i ]
                else:
                    result[ i ] = [parsedQs[ i ], ]
Example #3
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
Example #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