Taras, List,
I was reading through the whole rewritten-urls branch patch before
I merged into the trunk and realized that there are still a couple of
pending things and questions and we need to think about. Please read
the lines that start with "#APR" in the attached patch file. Thanks
and sorry to review this for the third time and still find new things
:(
Regards,
--
Andrés Riancho
Director of Web Security at Rapid7 LLC
Founder at Bonsai Information Security
Project Leader at w3af
Index: scripts/script-fuzzURLParts.w3af
===================================================================
--- scripts/script-fuzzURLParts.w3af (revision 0)
+++ scripts/script-fuzzURLParts.w3af (revision 4587)
@@ -0,0 +1,23 @@
+# This is a test for fuzzing URL parts!
+
+misc-settings
+set fuzzURLParts True
+back
+plugins
+output console,textFile
+output
+output config textFile
+set fileName output-w3af.txt
+set verbose True
+back
+output config console
+set verbose False
+back
+audit xss
+back
+target
+set target http://moth/w3af/core/fuzzURLParts/article/1
+back
+start
+assert len( kb.kb.getData('xss', 'xss') ) > 0
+exit
Index: core/controllers/miscSettings.py
===================================================================
--- core/controllers/miscSettings.py (revision 4506)
+++ core/controllers/miscSettings.py (working copy)
@@ -55,6 +55,7 @@
cf.cf.save('fuzzableCookie', False )
cf.cf.save('fuzzFileContent', True )
cf.cf.save('fuzzFileName', False )
+ cf.cf.save('fuzzURLParts', False )
cf.cf.save('fuzzFCExt', 'txt' )
cf.cf.save('fuzzFormComboValues', 'tmb')
cf.cf.save('autoDependencies', True )
@@ -104,6 +105,13 @@
o3 = option('fuzzFileName', cf.cf.getData('fuzzFileName'), d3,
'boolean', help=h3,
tabid='Fuzzer parameters')
+ d16 = 'Indicates if w3af plugins will send fuzzed URL parts in order
to find vulnerabilities'
+ h16 = 'For example, if the discovered URL is http://test/foo/bar/123,
and fuzzURLParts'
+ h16 += ' is enabled, w3af will request among other things: '
+ h16 += 'http://test/foo/bar/<script>alert(document.cookie)</script> in
order to find XSS.'
+ o16 = option('fuzzURLParts', cf.cf.getData('fuzzURLParts'), d16,
'boolean', help=h16,
+ tabid='Fuzzer parameters')
+
d4 = 'Indicates the extension to use when fuzzing file content'
o4 = option('fuzzFCExt', cf.cf.getData('fuzzFCExt'), d4, 'string',
tabid='Fuzzer parameters')
@@ -178,6 +186,7 @@
ol.add(o13)
ol.add(o14)
ol.add(o15)
+ ol.add(o16)
return ol
def getDesc( self ):
@@ -194,6 +203,7 @@
cf.cf.save('fuzzableCookie', optionsMap['fuzzCookie'].getValue() )
cf.cf.save('fuzzFileContent', optionsMap['fuzzFileContent'].getValue()
)
cf.cf.save('fuzzFileName', optionsMap['fuzzFileName'].getValue() )
+ cf.cf.save('fuzzURLParts', optionsMap['fuzzURLParts'].getValue() )
cf.cf.save('fuzzFCExt', optionsMap['fuzzFCExt'].getValue() )
cf.cf.save('fuzzFormComboValues',
optionsMap['fuzzFormComboValues'].getValue() )
cf.cf.save('autoDependencies',
optionsMap['autoDependencies'].getValue() )
Index: core/data/fuzzer/mutantUrlParts.py
===================================================================
--- core/data/fuzzer/mutantUrlParts.py (revision 0)
+++ core/data/fuzzer/mutantUrlParts.py (revision 4587)
@@ -0,0 +1,114 @@
+'''
+mutantUrlParts.py
+
+Copyright 2006 Andres Riancho
+
+This file is part of w3af, w3af.sourceforge.net .
+
+w3af is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation version 2 of the License.
+
+w3af is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with w3af; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+'''
+
+from core.data.fuzzer.mutant import mutant
+from core.controllers.w3afException import w3afException
+import urllib
+
+class mutantUrlParts(mutant):
+ '''
#APR: change to urlparts
+ This class is a urlpars mutant.
+ '''
+ def __init__( self, freq ):
+ mutant.__init__(self, freq)
+
+ self._doubleEncoding = False
+ self._safeEncodeChars = ''
+ self._mutant_dc = {}
+
+ def getMutantType( self ):
+ return 'urlpars'
+
+ def setDoubleEncoding( self, trueFalse ):
+ self._doubleEncoding = trueFalse
+
+ def setSafeEncodeChars( self, safeChars ):
+ '''
+ @parameter safeChars: A string with characters we don't want to URL
encode in the urlpars. Example:
+ - '/&!'
+ - '/'
+ '''
+ self._safeEncodeChars = safeChars
+
+ def getURL( self ):
+ '''
+ @return: The URL, as modified by "setModValue()"
#APR: I would like to see more doctests that represent the real use of this
class. By that I mean that we should use
setModValue() in the doctest instead of "m._mutant_dc = divided_path". The
ideal would be to use it just like in fuzzer.py
+ >>> from core.data.parsers.urlParser import url_object
+ >>> from core.data.request.fuzzableRequest import fuzzableRequest
+ >>> from core.data.dc.dataContainer import dataContainer as dc
+ >>> divided_path = dc()
+ >>> divided_path['start'] = ''
+ >>> divided_path['fuzzedUrlParts'] = 'ping!'
+ >>> divided_path['end'] = 'def'
+
+ >>> fr = fuzzableRequest(url_object('http://www.w3af.com/abc/def'))
+ >>> m = mutantUrlParts( fr )
+ >>> m._mutant_dc = divided_path
+ >>> m.setVar( 'fuzzedUrlParts' )
+ >>> m.getURL().url_string
+ u'http://www.w3af.com/ping%21/def'
+ '''
+ domain_path = self._freq.getURL().getDomainPath()
+
+ # Please note that this double encoding is needed if we want to work
with mod_rewrite
+ encoded = urllib.quote_plus( self._mutant_dc['fuzzedUrlParts'],
self._safeEncodeChars )
+ if self._doubleEncoding:
+ encoded = urllib.quote_plus( encoded, safe=self._safeEncodeChars )
+ domain_path.setPath( self._mutant_dc['start'] + encoded +
self._mutant_dc['end'] )
+ return domain_path
#APR: Are we sure about this? Shouldn't we have a real getURI that returns the
URI and a real getURL that only returns the URL?
+ getURI = getURL
+
+ def getData( self ):
+ return None
+
+ def printModValue( self ):
+ res = 'The sent '+ self.getMutantType() +' is: "' +
self._mutant_dc['start']
+ res += self._mutant_dc['fuzzedUrlParts'] + self._mutant_dc['end'] + '"
.'
+ return res
+
+ def setModValue( self, val ):
+ self._mutant_dc['fuzzedUrlParts'] = val
+
+ def getModValue(self):
+ return self._mutant_dc['fuzzedUrlParts']
+
+ def setURL( self, u ):
+ raise w3afException('You can\'t change the value of the URL in a
mutantUrlParts instance.')
#APR: Do we use this? How?
+ def dynamicURL( self ):
+ '''
+ The URL will change, don't try to use it to avoid reporting something
more than once.
+ '''
+ return True
+
+ def foundAt(self):
+ '''
+ @return: A string representing WHAT was fuzzed. This string is used
like this:
+ - v.setDesc( 'SQL injection in a '+ v['db'] +' was found at: '
+ mutant.foundAt() )
+ '''
+ res = ''
+ res += '"' + self.getURL() + '", using HTTP method '
+ res += self.getMethod() + '. The fuzzed parameter was the target URL,
with value: "'
+ res += self.getModValue() + '".'
+ return res
Index: core/data/fuzzer/fuzzer.py
===================================================================
--- core/data/fuzzer/fuzzer.py (revision 4506)
+++ core/data/fuzzer/fuzzer.py (working copy)
@@ -46,6 +46,7 @@
from core.data.fuzzer.mutantQs import mutantQs
from core.data.fuzzer.mutantPostData import mutantPostData
from core.data.fuzzer.mutantFileName import mutantFileName
+from core.data.fuzzer.mutantUrlParts import mutantUrlParts
from core.data.fuzzer.mutantHeaders import mutantHeaders
from core.data.fuzzer.mutantJSON import mutantJSON
from core.data.fuzzer.mutantCookie import mutantCookie
@@ -95,6 +96,12 @@
om.out.debug('Fuzzing file name')
result.extend(_createFileNameMutants(freq, mutantFileName,
mutant_str_list, fuzzableParamList, append))
+
+ if 'fuzzURLParts' in _fuzzable:
+ om.out.debug('Fuzzing URL parts')
#APR: Do we want to call _createUrlPartsMutants for all freq? Does it make
sense to fuzz the URL when
there are query string parameters? Hmmm... we should think about this.
+ result.extend(_createUrlPartsMutants(freq, mutantUrlParts,
+ mutant_str_list, fuzzableParamList, append))
+
# POST-data parameters
if isinstance(freq, httpPostDataRequest):
# If this is a POST request, it could be a JSON request, and I want
@@ -488,6 +495,40 @@
return result
+def _createUrlPartsMutants(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
#APR: doctest missing (sorry to ask for this now, but I did not identify the
lack of it before)
+ @return: Mutants that have the filename URL changed with the strings at
mutant_str_list
+ '''
+ res = []
+ path_sep = '/'
+ path = freq.getURL().getPath()
+ path_chunks = path.split(path_sep)
+ for idx, p_chunk in enumerate(path_chunks):
+ if not p_chunk:
+ continue
+ for mutant_str in mutant_str_list:
+ divided_path = dc()
+ divided_path['start'] = path_sep.join(path_chunks[:idx] + [''])
+ divided_path['end'] = path_sep.join([''] + path_chunks[idx+1:])
+ divided_path['fuzzedUrlParts'] = \
+ (p_chunk if append else '') + urllib.quote_plus(mutant_str)
+ freq_copy = freq.copy()
+ freq_copy.setURL(freq.getURL())
+ m = mutantClass(freq_copy)
+ m.setOriginalValue(p_chunk)
+ m.setVar('fuzzedUrlParts')
+ m._mutant_dc = divided_path
+ m.setModValue(mutant_str)
+ m.setDoubleEncoding(True)
+ res.append(m)
+ return res
+
def createRandAlpha(length=0):
'''
Create a random string ONLY with letters
@@ -588,6 +629,9 @@
if cf.cf.getData('fuzzFileContent' ):
_fuzzable['fuzzFileContent'] = None
+
+ if cf.cf.getData('fuzzURLParts'):
+ _fuzzable['fuzzURLParts'] = None
return _fuzzable
------------------------------------------------------------------------------
Write once. Port to many.
Get the SDK and tools to simplify cross-platform app development. Create
new or port existing apps to sell to consumers worldwide. Explore the
Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join
http://p.sf.net/sfu/intel-appdev
_______________________________________________
W3af-develop mailing list
W3af-develop@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/w3af-develop