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
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
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
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()
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()
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()
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.')
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.')
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
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
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