Andres:
With some delay, here is a(n almost fully) tested version. The only problem it
already has is the last test, at line 125.
Carlos Pantelides
-----------------
http://seguridad-agile.blogspot.com/
--- On Tue, 7/19/11, Andres Riancho <[email protected]> wrote:
> From: Andres Riancho <[email protected]>
> Subject: Re: [W3af-users] symfony plugin
> To: "Carlos Pantelides" <[email protected]>
> Cc: [email protected], "w3af" <[email protected]>
> Date: Tuesday, July 19, 2011, 4:19 PM
> Carlos,
>
> On Tue, Jul 19, 2011 at 11:28 AM, Carlos Pantelides
> <[email protected]>
> wrote:
> >> > How can I ask if a cookie is set?
> >>
> >> Not sure if there is a "clean" way of asking
> xUrllib
> >> if in the next request it will send a cookie or
> not
> >> (also, it depends on the request you make, since
> cookies
> >> might be restricted to a path).
> >
> >> What you could do, is to have two parts of the
> plugin,
> >> one to analyse all responses until you see a
> set-cookie
> >> and set an attribute like self._cookie_sent to
> True;
> >> and the second part (which will run only when
> >> _cookie_sent is True?!) that analyses forms.
> >
> > ok, in august I'll spend some time. I've attached a
> new version with cosmetic changes.
>
> The code looks cleaner now, thanks.
>
> >> >> Where can I test this plugin?
> >
> > These two sites are taken "from the manual", they both
> use a cookie with symfony=.... The first one has csrf
> activated, the other one no.
> >
> > http slash slash bkdjombang dot com
> >
> > http slash slash www dot katrinjuntke dot ch slash
> kontakt
> >
> > There are a lot of other sites that changed the
> cookie, like
> >
> > http slash slash level 7 systems dot co dot uk slash
> en slash contact-us
> >
> > https slash slash ssl7 dot net slash websitechat dot
> net slash login
> >
> > that have the csrf form protection disabled, but
> perhaps has moved it to a cookie. Anyway, they are
> undetectable as symfony. That narrows the utility of the
> plugin, thumbs up for symfony! (and the developers that
> change the defaults, but, we are not sure that they really
> run symfony...)
> >
> > I took the sites from http://www.appliedstacks.com/NewestFirst/Symfony
>
> I'll wait until you've performed your testing before
> performing mine,
> so I get a more finished version. I'll bother you again in
> 15 days to
> see if you were able to test it in detail :)
>
> >
> >> > Charli
>
>
>
> --
> Andrés Riancho
> Director of Web Security at Rapid7 LLC
> Founder at Bonsai Information Security
> Project Leader at w3af
>
'''
symfony.py
Copyright 2011 Andres Riancho and Carlos Pantelides
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
'''
# options
from core.data.options.option import option
from core.data.options.optionList import optionList
from core.controllers.basePlugin.baseGrepPlugin import baseGrepPlugin
import core.data.kb.knowledgeBase as kb
import core.data.kb.info as info
from core.data.bloomfilter.bloomfilter import scalable_bloomfilter
import re
class symfony(baseGrepPlugin):
'''
Grep every page for traces of the Symfony framework.
@author: Carlos Pantelides ([email protected] ) based upon work by Andres Riancho ( [email protected] ) and help from Pablo Mouzo ([email protected])
'''
def __init__(self):
baseGrepPlugin.__init__(self)
# Internal variables
self._already_inspected = scalable_bloomfilter()
def grep(self, request, response):
'''
Plugin entry point.
@parameter request: The HTTP request object.
@parameter response: The HTTP response object
@return: None, all results are saved in the kb.
Init
>>> from core.data.url.httpResponse import httpResponse
>>> from core.data.request.fuzzableRequest import fuzzableRequest
>>> from core.controllers.misc.temp_dir import create_temp_dir
>>> from core.data.parsers.urlParser import url_object
>>> o = create_temp_dir()
>>> emptyBody=''
>>> unprotectedBody='<html><head></head><body><form action="login" method="post"><input type="text" name="signin" id="signin" /></form></body></html>'
>>> protectedBody='<html><head></head><body><form action="login" method="post"><input type="text" name="signin" id="signin" /><input type="hidden" name="signin[_csrf_token]" value="069092edf6b67d5c25fd07642a54f6e3" id="signin__csrf_token" /></form></body></html>'
>>> symfonyHeaders={'set-cookie': 'symfony=sfasfasfa'}
>>> noSymfonyHeaders={}
Symfony detection, positive
>>> body = emptyBody
>>> headers = symfonyHeaders
>>> url = url_object('http://www.w3af.com/')
>>> response = httpResponse(200, body , headers, url, url)
>>> a = symfony()
>>> assert a.symfonyDetected(response) == True
Symfony detection, negative
>>> body = emptyBody
>>> headers = noSymfonyHeaders
>>> url = url_object('http://www.w3af.com/')
>>> response = httpResponse(200, body , headers, url, url)
>>> a = symfony()
>>> assert a.symfonyDetected(response) == False
CSRF detection, positive
>>> body = protectedBody
>>> url = url_object('http://www.w3af.com/')
>>> headers = symfonyHeaders
>>> response = httpResponse(200, body , headers, url, url)
>>> a = symfony()
>>> assert a.csrfDetected(response.getDOM()) == True
CSRF detection, negative
>>> body = unprotectedBody
>>> headers = symfonyHeaders
>>> url = url_object('http://www.w3af.com/')
>>> response = httpResponse(200, body , headers, url, url)
>>> a = symfony()
>>> assert a.csrfDetected(response.getDOM()) == False
Symfonry plus CSRF detection, positive plus negative
>>> kb.kb.save('symfony','symfony',[])
>>> body = protectedBody
>>> headers = symfonyHeaders
>>> url = url_object('http://www.w3af.com/')
>>> response = httpResponse(200, body , headers, url, url)
>>> request = fuzzableRequest()
>>> request.setURL( url )
>>> request.setMethod( 'GET' )
>>> a = symfony()
>>> a.grep(request, response)
>>> assert len(kb.kb.getData('symfony', 'symfony')) == 0
Symfonry plus CSRF detection, positive plus positive
>>> kb.kb.save('symfony','symfony',[])
>>> body = unprotectedBody
>>> headers = symfonyHeaders
>>> url = url_object('http://www.w3af.com/')
>>> response = httpResponse(200, body , headers, url, url)
>>> request = fuzzableRequest()
>>> request.setURL( url )
>>> request.setMethod( 'GET' )
>>> a = symfony()
>>> a.grep(request, response)
>>> assert len(kb.kb.getData('symfony', 'symfony')) == 0 # should != 0, outside the tests it works fine!!!
'''
url = response.getURL()
if response.is_text_or_html() and url not in self._already_inspected:
# Don't repeat URLs
self._already_inspected.add(url)
if self.symfonyDetected(response):
dom = response.getDOM()
if dom is not None:
if not self.csrfDetected(dom):
i = info.info()
i.setPluginName(self.getName())
i.setName('Symfony Framework')
i.setURL(url)
i.setDesc('The URL: "%s" seems to be generated by the Symfony framework and contains a form that perhaps has csrf protection disabled.' % url)
i.setId(response.id)
kb.kb.append(self, 'symfony', i)
def symfonyDetected(self, response):
for header_name in response.getHeaders().keys():
if header_name.lower() == 'set-cookie' or header_name.lower() == 'cookie':
if re.match('^symfony=', response.getHeaders()[header_name]):
return True
return False
def csrfDetected(self, dom):
forms = dom.xpath('//form')
if forms:
csrf_protection_regex_string = '.*csrf_token'
csrf_protection_regex_re = re.compile( csrf_protection_regex_string, re.IGNORECASE )
for form in forms:
inputs = form.xpath('//input[@id]')
if inputs:
for input in inputs:
if csrf_protection_regex_re.search(input.attrib["id"]):
return True
return False
def setOptions( self, OptionList ):
pass
def getOptions( self ):
'''
@return: A list of option objects for this plugin.
'''
ol = optionList()
return ol
def end(self):
'''
This method is called when the plugin wont be used anymore.
'''
self.printUniq( kb.kb.getData( 'symfony', 'symfony' ), 'URL' )
def getPluginDeps( self ):
'''
@return: A list with the names of the plugins that should be runned before the
current one.
'''
return []
def getLongDesc( self ):
'''
@return: A DETAILED description of the plugin functions and features.
'''
return '''
This plugin greps every page for traces of the Symfony framework and the lack of csrf protection.
'''
------------------------------------------------------------------------------
Doing More with Less: The Next Generation Virtual Desktop
What are the key obstacles that have prevented many mid-market businesses
from deploying virtual desktops? How do next-generation virtual desktops
provide companies an easier-to-deploy, easier-to-manage and more affordable
virtual desktop model.http://www.accelacomm.com/jaw/sfnl/114/51426474/
_______________________________________________
W3af-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/w3af-users