Example #1
0
    def modifyRequest(self, request ):
        '''
        Mangles the request
        
        @parameter request: HTTPRequest instance that is going to be modified by the evasion plugin
        @return: The modified request

        >>> from core.data.parsers.urlParser import url_object
        >>> fwe = fullWidthEncode()
        
        >>> u = url_object('http://www.w3af.com/')
        >>> r = HTTPRequest( u )
        >>> fwe.modifyRequest( r ).url_object.url_string
        'http://www.w3af.com/'

        >>> u = url_object('http://www.w3af.com/hola-mundo')
        >>> r = HTTPRequest( u )
        >>> fwe.modifyRequest( r ).url_object.url_string
        'http://www.w3af.com/%uFF48%uFF4f%uFF4c%uFF41%uFF0d%uFF4d%uFF55%uFF4e%uFF44%uFF4f'

        >>> u = url_object('http://www.w3af.com/hola-mundo')
        >>> r = HTTPRequest( u )
        >>> fwe.modifyRequest( r ).url_object.url_string
        'http://www.w3af.com/%uFF48%uFF4f%uFF4c%uFF41%uFF0d%uFF4d%uFF55%uFF4e%uFF44%uFF4f'
        >>> #
        >>> #    The plugins should not modify the original request
        >>> #
        >>> u.url_string
        'http://www.w3af.com/hola-mundo'
        '''
        # This is a test URL
        # http://172.16.1.132/index.asp?q=%uFF1Cscript%3Ealert(%22Hello%22)%3C/script%3E
        # This is the content of index.asp :
        # <%=Request.QueryString("q")%>
        
        # First we mangle the URL        
        path = request.url_object.getPath()
        path = self._mutate( path )
        
        # Now we mangle the postdata
        data = request.get_data()
        if data:
            
            try:
                # Only mangle the postdata if it is a url encoded string
                parse_qs( data )
            except:
                pass
            else:
                # We get here only if the parsing was successful
                data = self._mutate( data )            
        
        # Finally, we set all the mutants to the request in order to return it
        new_url = request.url_object.copy()
        new_url.setPath( path )
        
        new_req = HTTPRequest( new_url , data, request.headers, 
                               request.get_origin_req_host() )
        
        return new_req
Example #2
0
    def modifyRequest(self, request ):
        '''
        Mangles the request
        
        @parameter request: HTTPRequest instance that is going to be modified by the evasion plugin
        @return: The modified request
        
        >>> from core.data.parsers.urlParser import url_object
        >>> rp = rndParam()
        
        >>> u = url_object('http://www.w3af.com/')
        >>> r = HTTPRequest( u )
        >>> qs = rp.modifyRequest( r ).url_object.getQueryString()
        >>> len(qs)
        1

        >>> u = url_object('http://www.w3af.com/?id=1')
        >>> r = HTTPRequest( u )
        >>> qs = rp.modifyRequest( r ).url_object.getQueryString()
        >>> len(qs)
        2

        >>> u = url_object('http://www.w3af.com/?id=1')
        >>> r = HTTPRequest( u, data='a=b' )
        >>> data = parse_qs( rp.modifyRequest( r ).get_data() )
        >>> len(data)
        2
        
        >>> data = rp.modifyRequest( r ).url_object.getQueryString()
        >>> len(data)
        2

        '''
        # First we mangle the URL        
        qs = request.url_object.getQueryString()
        qs = self._mutate(qs)
        
        # Finally, we set all the mutants to the request in order to return it
        new_url = request.url_object.copy()
        new_url.setQueryString( qs )
        
        # Mangle the postdata
        post_data = request.get_data()
        if post_data:
            
            try:
                # Only mangle the postdata if it is a url encoded string
                post_data = parse_qs( post_data )
            except:
                pass
            else:
                post_data = str( self._mutate(post_data) ) 
        
        new_req = HTTPRequest( new_url , post_data, request.headers, 
                               request.get_origin_req_host() )
        
        return new_req
Example #3
0
    def modifyRequest(self, request ):
        '''
        Mangles the request
        
        @parameter request: HTTPRequest instance that is going to be modified by the evasion plugin
        @return: The modified request
        
        >>> from core.data.parsers.urlParser import url_object
        >>> modsec = modsecurity()
        
        >>> u = url_object('http://www.google.com/')
        >>> r = HTTPRequest( u )
        >>> modsec.modifyRequest( r ).url_object.url_string
        'http://www.google.com/'

        >>> u = url_object('http://www.google.com/')
        >>> r = HTTPRequest( u, data='' )
        >>> modsec.modifyRequest( r ).get_data()
        ''

        >>> u = url_object('http://www.google.com/')
        >>> r = HTTPRequest( u, data='a=b' )
        >>> modsec.modifyRequest( r ).get_data()
        '\\x00a=b'

        '''
        # Mangle the postdata
        data = str(request.get_data())
        if data:
            
            try:
                # Only mangle the postdata if it is a url encoded string
                parse_qs( data )
            except:
                pass
            else:
                data = '\x00' + data 
                headers_copy = copy.deepcopy(request.headers)
                headers_copy['content-length'] = str(len(data))
                
                request = HTTPRequest( request.url_object, data, headers_copy, 
                                       request.get_origin_req_host() )
                
        return request
Example #4
0
 def setOptions( self, optionsMap ):
     '''
     This method sets all the options that are configured using the user interface 
     generated by the framework using the result of getOptions().
     
     @parameter OptionList: A dictionary with the options for the plugin.
     @return: No value is returned.
     ''' 
     self._url = optionsMap['url'].getValue()
     self._method = optionsMap['method'].getValue()
     self._data = parse_qs( optionsMap['data'].getValue() )
     self._fileVars = optionsMap['fileVars'].getValue()
     self._fileDest = optionsMap['fileDest'].getValue()
Example #5
0
    def execute( self, command ):
        '''
        This method is called when a user writes a command in the shell and hits enter.
        
        Before calling this method, the framework calls the generic_user_input method
        from the shell class.

        @parameter command: The command to handle ( ie. "read", "exec", etc ).
        @return: The result of the command.
        '''
        to_send = self.getExploitURL()
        to_send.setQueryString( parse_qs('cmd=' + command ) )
        response = self._urlOpener.GET( to_send )
        return response.getBody()
Example #6
0
 def setOptions( self, optionsMap ):
     '''
     This method sets all the options that are configured using the user interface 
     generated by the framework using the result of getOptions().
     
     @parameter optionsMap: A dict with the options for the plugin.
     @return: No value is returned.
     ''' 
     self._changeToPost = optionsMap['changeToPost'].getValue()
     self._url = optionsMap['url'].getValue()
     self._method = optionsMap['method'].getValue()
     self._data = parse_qs( optionsMap['data'].getValue() )
     self._inj_var = optionsMap['injvar'].getValue()
     self._generateOnlyOne = optionsMap['generateOnlyOne'].getValue()
Example #7
0
 def fastExploit( self ):
     '''
     Exploits a web app with [blind] sql injections vulns.
     The options are configured using the plugin options and setOptions() method.
     '''
     om.out.debug( 'Starting sqlmap fastExploit.' )
     om.out.console( SQLMAPCREATORS )
     
     if self._url is None or self._method is None or self._data is None or self._injvar is None:
         raise w3afException('You have to configure the plugin parameters')
     else:
         
         freq = None
         if self._method == 'POST':
             freq = httpPostDataRequest.httpPostDataRequest()
         elif self._method == 'GET':
             freq = httpQsRequest.httpQsRequest()
         else:
             raise w3afException('Method not supported.')
         
         freq.setURL( self._url )
         freq.setDc( parse_qs( self._data ) )
         freq.setHeaders( {} )
         
         bsql = blind_sqli_response_diff()
         bsql.setUrlOpener( self._urlOpener )
         bsql.setEqualLimit( self._equalLimit )
         bsql.setEquAlgorithm( self._equAlgorithm )
         
         vuln_obj = bsql.is_injectable( freq, self._injvar )
         if not vuln_obj:
             raise w3afException('Could not verify SQL injection ' + str(vuln) )
         else:
             om.out.console('SQL injection could be verified, trying to create the DB driver.')
             
             # Try to get a shell using all vuln
             msg = 'Trying to exploit using vulnerability with id: ' + str( vuln_obj.getId() )
             msg += '. Please wait...'
             om.out.console( msg )
             shell_obj = self._generateShell( vuln_obj )
             if shell_obj is not None:
                 kb.kb.append( self, 'shell', shell_obj )
                 return [shell_obj, ]
                 
             raise w3afException('No exploitable vulnerabilities found.')
Example #8
0
    def fastExploit( self ):
        '''
        Exploits a web app with [blind] sql injections vulns.
        The options are configured using the plugin options and setOptions() method.
        '''
        om.out.debug( 'Starting sql_webshell fastExploit.' )
        
        if any(
             lambda attr: attr is None,
             (self._url, self._method, self._data, self._injvar)
             ):
            raise w3afException('You have to configure the plugin parameters')
        else:
            if self._method == 'POST':
                freq = httpPostDataRequest(self._url)
            elif self._method == 'GET':
                freq = HTTPQSRequest(self._url)
            else:
                raise w3afException('Method not supported.')
            
            freq.setDc(parse_qs(self._data))

            bsql = blind_sqli_response_diff(self._uri_opener)
            bsql.set_eq_limit(self._eq_limit)
            
            fake_mutants = createMutants(freq, [''], fuzzableParamList=[self._injvar,])
            for mutant in fake_mutants:            
                vuln_obj = bsql.is_injectable(mutant)
                if vuln_obj is not None:
                    om.out.console('SQL injection verified, trying to create the DB driver.')
                    
                    # Try to get a shell using all vuln
                    msg = 'Trying to exploit using vulnerability with id: ' + str(vuln_obj.getId())
                    msg += '. Please wait...'
                    om.out.console(msg)
                    shell_obj = self._generateShell(vuln_obj)
                    if shell_obj is not None:
                        kb.kb.append(self, 'shell', shell_obj)
                        return [shell_obj, ]
            else:    
                raise w3afException('No exploitable vulnerabilities found.')
Example #9
0
    def modifyRequest(self, request ):
        '''
        Mangles the request
        
        @parameter request: HTTPRequest instance that is going to be modified by the evasion plugin
        @return: The modified request
        
        >>> from core.data.parsers.urlParser import url_object
        >>> rhe = rndHexEncode()
        
        >>> u = url_object('http://www.w3af.com/')
        >>> r = HTTPRequest( u )
        >>> rhe.modifyRequest( r ).url_object.url_string
        u'http://www.w3af.com/'

        >>> u = url_object('http://www.w3af.com/a/')
        >>> r = HTTPRequest( u )
        >>> rhe.modifyRequest( r ).url_object.getPath() in ['/a/','/%61/']
        True

        >>> u = url_object('http://www.w3af.com/')
        >>> r = HTTPRequest( u, data='a=b' )
        >>> rhe.modifyRequest( r ).get_data() in ['a=b','%61=b','a=%62','%61=%62']
        True

        >>> u = url_object('http://www.w3af.com/aa/')
        >>> r = HTTPRequest( u )
        >>> rhe.modifyRequest( r ).url_object.getPath() in ['/aa/','/%61a/','/a%61/','/%61%61/']
        True

        >>> #
        >>> #    The plugins should not modify the original request
        >>> #
        >>> u.url_string
        u'http://www.w3af.com/aa/'

        '''
        # First we mangle the URL        
        path = request.url_object.getPath()
        path = self._mutate(path)
        
        # Finally, we set all the mutants to the request in order to return it
        new_url = request.url_object.copy()
        new_url.setPath( path )
        
        # Mangle the postdata
        data = request.get_data()
        if data:
            
            try:
                # Only mangle the postdata if it is a url encoded string
                parse_qs( data )
            except:
                pass
            else:
                data = self._mutate(data) 
        
        new_req = HTTPRequest( new_url , data, request.headers, 
                               request.get_origin_req_host() )
        
        return new_req
Example #10
0
def create_fuzzable_request(req_url, method='GET', post_data='',
                            add_headers=None):
    '''
    Creates a fuzzable request based on the input parameters.

    @param req_url: Either a url_object that represents the URL or a
        HTTPRequest instance. If the latter is the case the `method` and
        `post_data` values are taken from the HTTPRequest object as well
        as the values in `add_headers` will be merged with the request's
        headers.
    @param method: A string that represents the method ('GET', 'POST', etc)
    @param post_data: A string that represents the postdata.
    @param add_headers: A dict that holds the headers. If `req_url` is a
        request then this dict will be merged with the request's headers.
    '''
    if isinstance(req_url, HTTPRequest):
        url = req_url.url_object
        post_data = str(req_url.get_data() or '')
        method = req_url.get_method()
        headers = dict(req_url.headers)
        headers.update(add_headers or {})
    else:
        url = req_url
        headers = add_headers or {}

    # Just a query string request! No postdata
    if not post_data:
        req = HTTPQSRequest(url, method, headers)
 
    else: # Seems to be something that has post data
        data = {}
        conttype = ''
        for hname in headers.keys(): # '.keys()' is just fine. Don't
            hnamelow = hname.lower() # remove it.
            if hnamelow == 'content-length':
                del headers[hname]
            elif hnamelow == 'content-type':
                conttype = headers.get('content-type', '').lower()
        
        # Case #1 - JSON request
        try:
            data = json.loads(post_data)
        except:
            pass

        if data:
            req = JSONPostDataRequest(url, method, headers, dc=data)
        
        # Case #2 - XMLRPC request
        elif all(map(lambda stop: stop in post_data.lower(), XMLRPC_WORDS)):
            req = XMLRPCRequest(post_data, url, method, headers)

        else:
            # Case #3 - multipart form data - prepare data container
            if conttype.startswith('multipart/form-data'):
                pdict = cgi.parse_header(conttype)[1]
                try:
                    dc = cgi.parse_multipart(StringIO(post_data), pdict)
                except:
                    om.out.debug('Multipart form data is invalid, the browser '
                                 'sent something weird.')
                else:
                    data = QueryString()
                    data.update(dc)
                    # 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'
            
            # Case #4 - a typical post request
            else:
                try:
                    data = parse_qs(post_data)
                except:
                    om.out.debug('Failed to create a data container that '
                                 'can store this data: "' + post_data + '".')
            # Finally create request
            req = httpPostDataRequest(url, method, headers, dc=data)
    return req
Example #11
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