Exemple #1
0
    def test_from_dict_encodings(self):
        for body, charset in TEST_RESPONSES.values():
            html = body.encode(charset)
            resp = self.create_resp(Headers([('Content-Type', 'text/xml')]),
                                    html)

            msg = msgpack.dumps(resp.to_dict())
            loaded_dict = msgpack.loads(msg)

            loaded_resp = HTTPResponse.from_dict(loaded_dict)

            self.assertEquals(
                smart_unicode(html,
                              DEFAULT_CHARSET,
                              ESCAPED_CHAR,
                              on_error_guess=False), loaded_resp.body)
Exemple #2
0
    def _grep(self, request, response):

        url_instance = request.url_object
        domain = url_instance.get_domain()

        if self._grep_queue_put is not None and\
        domain in cf.cf.get('target_domains'):

            # Create a fuzzable request based on the urllib2 request object
            headers_inst = Headers(request.headers.items())
            fr = create_fuzzable_request_from_parts(url_instance,
                                                    request.get_method(),
                                                    request.get_data(),
                                                    headers_inst)

            self._grep_queue_put((fr, response))
Exemple #3
0
    def test_multipart_post(self):
        boundary, post_data = multipart_encode([('a', 'bcd'), ], [])

        headers = Headers([('content-length', str(len(post_data))),
                           ('content-type', 'multipart/form-data; boundary=%s' % boundary)])

        fr = create_fuzzable_request_from_parts(self.url, add_headers=headers,
                                                post_data=post_data, method='POST')

        self.assertEqual(fr.get_url(), self.url)
        self.assertEqual(fr.get_headers(), headers)
        self.assertTrue(
            'multipart/form-data' in fr.get_headers()['content-type'])
        self.assertEqual(fr.get_method(), 'POST')
        self.assertEqual(fr.get_dc(), {'a': ['bcd', ]})
        self.assertIsInstance(fr, HTTPPostDataRequest)
Exemple #4
0
 def test_ssn_with_complex_html(self):
     '''
     Test for false positive "...discloses a US Social Security Number: "12-56-1011"..."
     '''
     body = '''<select name="servers">
                 <option value="0" selected="selected">0</option>
                 <option value="1">1</option>
                 <option value="2-5">2-5</option>
                 <option value="6-10">6-10</option>
                 <option value="11-19">11-19</option>
                 <option value="20+">20+</option>
             </select>'''
     headers = Headers([('content-type', 'text/html')])
     response = HTTPResponse(200, body, headers, self.url, self.url, _id=1)
     self.plugin.grep(self.request, response)
     self.assertEqual(len(kb.kb.get('ssn', 'ssn')), 0)
Exemple #5
0
    def test_find_vulns_case04(self):
        '''
        Test case in which we configure correctly policies for all directives.
        '''
        header_value = "default-src 'self';script-src 'self';object-src 'self';" \
                       "style-src 'self';img-src 'self';media-src 'self';" \
                       "frame-src 'self';font-src 'self';sandbox;" \
                       "form-action '/myCtx/act';connect-src 'self';"\
                       "plugin-types application/pdf;reflected-xss filter;"\
                       "script-nonce AABBCCDDEE;"
        hrds = {CSP_HEADER_W3C: header_value}.items()
        csp_headers = Headers(hrds)

        http_response = HTTPResponse(200, '', csp_headers, self.url, self.url)
        vulns = find_vulns(http_response)
        self.assertEqual(len(vulns), 0)
Exemple #6
0
    def test_xmlrpc_post(self):
        post_data = '''<methodCall>
            <methodName>system.listMethods</methodName>
            <params></params>
        </methodCall>'''

        headers = Headers([('content-length', str(len(post_data)))])

        fr = create_fuzzable_request_from_parts(self.url, add_headers=headers,
                                                post_data=post_data,
                                                method='POST')

        self.assertEqual(fr.get_url(), self.url)
        self.assertEqual(fr.get_headers(), headers)
        self.assertEqual(fr.get_method(), 'POST')
        self.assertIsInstance(fr, XMLRPCRequest)
Exemple #7
0
    def test_unsafe_inline_enabled_no_case01(self):
        '''
        Test case in which site do not provides "unsafe-inline" related CSP
        (no directive value "unsafe-inline").
        '''
        hrds = {}
        hrds[CSP_HEADER_FIREFOX] = CSP_DIRECTIVE_SCRIPT + " 'self'"
        hrds[CSP_HEADER_W3C_REPORT_ONLY] = CSP_DIRECTIVE_DEFAULT + \
            " 'self';" + CSP_DIRECTIVE_REPORT_URI + " http://example.com"
        hrds[CSP_HEADER_W3C] = CSP_DIRECTIVE_SCRIPT + " 'self';" + \
            CSP_DIRECTIVE_REPORT_URI + " /myrelativeuri"

        csp_headers = Headers(hrds.items())
        http_response = HTTPResponse(200, '', csp_headers, self.url, self.url)

        self.assertFalse(unsafe_inline_enabled(http_response))
Exemple #8
0
 def test_cache_control_http(self):
     '''
     No cache control, but the content is not sensitive (sent over http) so
     no bug is stored in KB.
     '''
     body = 'abc'
     url = URL('http://www.w3af.com/')
     headers = Headers([('content-type', 'text/html')])
     request = FuzzableRequest(url, method='GET')
     resp = HTTPResponse(200, body, headers, url, url, _id=1)
     
     self.plugin.grep(request, resp)
     self.plugin.end()
     
     infos = kb.kb.get('cache_control', 'cache_control')
     self.assertEquals(len(infos), 0)
Exemple #9
0
 def test_no_code_disclosure_xml(self, *args):
     body = '''
             <?xml version="1.0"?>
             <note>
                 <to>Tove</to>
                 <from>Jani</from>
                 <heading>Reminder</heading>
                 <body>Don't forget me this weekend!</body>
             </note>'''
     url = URL('http://www.w3af.com/')
     headers = Headers([('content-type', 'text/html')])
     response = HTTPResponse(200, body, headers, url, url, _id=1)
     request = FuzzableRequest(url, method='GET')
     self.plugin.grep(request, response)
     self.assertEqual(
         len(kb.kb.get('code_disclosure', 'code_disclosure')), 0)
Exemple #10
0
    def test_strange_headers_positive(self):
        body = 'Hello world'
        url = URL('http://www.w3af.com/')
        headers = Headers([('content-type', 'text/html'),
                           ('hello-world', 'yes!')])
        request = FuzzableRequest(url, method='GET')

        resp_positive = HTTPResponse(200, body, headers, url, url, _id=1)
        self.plugin.grep(request, resp_positive)

        infos = kb.kb.get('strange_headers', 'strange_headers')
        self.assertEquals(len(infos), 1)

        info = infos[0]
        self.assertEqual(info.get_name(), 'Strange header')
        self.assertEqual(info.get_url(), url)
Exemple #11
0
    def test_retrieve_csp_policies_with_special_policies_case01(self):
        '''
        Test case in which 2 policies are specified using special directives
        with empty value.
        '''
        header_value = "sandbox ; script-nonce "
        hrds = {CSP_HEADER_W3C: header_value}.items()
        csp_headers = Headers(hrds)

        http_response = HTTPResponse(200, '', csp_headers, self.url, self.url)
        policies = retrieve_csp_policies(http_response)

        self.assertEqual(len(policies), 2)
        self.assertEqual(len(policies[CSP_DIRECTIVE_SANDBOX]), 1)
        self.assertEqual(policies[CSP_DIRECTIVE_SANDBOX][0], "")
        self.assertEqual(len(policies[CSP_DIRECTIVE_SCRIPT_NONCE]), 1)
        self.assertEqual(policies[CSP_DIRECTIVE_SCRIPT_NONCE][0], "")
Exemple #12
0
def build_cors_request(url, origin_header_value):
    '''
    Method to generate a "GET" CORS HTTP request based on input context.

    :param url: a URL object object.
    :param origin_header_value: Value of the "ORIGIN" HTTP request header
                                  (if value is set to None then the "ORIGIN"
                                  header is skipped).
    :return: A fuzzable request that will be sent to @url and has
             @origin_header_value in the Origin header.
    '''
    headers = Headers()
    if origin_header_value is not None:
        headers["Origin"] = origin_header_value.strip()

    forged_req = FuzzableRequest(url, 'GET', headers=headers)
    return forged_req
Exemple #13
0
    def set_headers(self, headers):
        '''
        Sets the headers and also analyzes them in order to get the response
        mime type (text/html , application/pdf, etc).

        :param headers: The headers dict.
        '''
        # Fix lowercase in header names from HTTPMessage
        if isinstance(headers, httplib.HTTPMessage):
            self._headers = Headers()
            for header in headers.headers:
                key, value = header.split(':', 1)
                self._headers[key.strip()] = value.strip()
        else:
            self._headers = headers

        # Set the type, for easy access.
        self._doc_type = HTTPResponse.DOC_TYPE_OTHER
        find_word = lambda w: content_type.find(w) != -1

        content_type_hvalue, _ = self._headers.iget('content-type', None)

        # we need exactly content type but not charset
        if content_type_hvalue is not None:
            try:
                self._content_type = content_type_hvalue.split(';', 1)[0]
            except:
                msg = 'Invalid Content-Type value "%s" sent in HTTP response.'
                om.out.debug(msg % (content_type_hvalue, ))
            else:
                content_type = self._content_type.lower()

                # Set the doc_type
                if content_type.count('image'):
                    self._doc_type = HTTPResponse.DOC_TYPE_IMAGE

                elif content_type.count('pdf'):
                    self._doc_type = HTTPResponse.DOC_TYPE_PDF

                elif content_type.count('x-shockwave-flash'):
                    self._doc_type = HTTPResponse.DOC_TYPE_SWF

                elif any(
                        imap(find_word,
                             ('text', 'html', 'xml', 'txt', 'javascript'))):
                    self._doc_type = HTTPResponse.DOC_TYPE_TEXT_OR_HTML
Exemple #14
0
def new_no_content_resp(uri, add_id=False):
    '''
    Return a new NO_CONTENT HTTPResponse object.
    
    :param uri: URI string or request object
    '''
    no_content_response = HTTPResponse(NO_CONTENT,
                                       '',
                                       Headers(),
                                       uri,
                                       uri,
                                       msg='No Content')

    if add_id:
        no_content_response.id = consecutive_number_generator.inc()

    return no_content_response
Exemple #15
0
    def test_dump_case03(self):
        header_value = ''.join(chr(i) for i in xrange(256))

        expected = u'\r\n'.join([
            u'GET http://w3af.com/a/b/c.php HTTP/1.1',
            u'Hola: %s' % smart_unicode(header_value), u'', u''
        ])

        headers = Headers([(u'Hola', header_value)])

        #TODO: Note that I'm passing a dc to the FuzzableRequest and it's not
        # appearing in the dump. It might be a bug...
        fr = FuzzableRequest(self.url,
                             method='GET',
                             dc={u'a': ['b']},
                             headers=headers)
        self.assertEqual(fr.dump(), expected)
Exemple #16
0
    def test_clamav_empty(self, *args):
        body = ''
        url = URL('http://www.w3af.com/')
        headers = Headers([('content-type', 'text/html')])
        response = HTTPResponse(200, body, headers, url, url, _id=1)
        request = FuzzableRequest(url, method='GET')

        self.plugin.grep(request, response)

        # Let the worker pool wait for the clamd response, this is done by
        # the core when run in a real scan
        self.plugin.worker_pool.close()
        self.plugin.worker_pool.join()

        findings = kb.kb.get('clamav', 'malware')

        self.assertEqual(len(findings), 0, findings)
Exemple #17
0
    def test_analyze_cookies_with_httponly_case_sensitive_expires(self):
        body = ''
        url = URL('https://www.w3af.com/')
        headers = {
            'content-type':
            'text/html',
            'Set-Cookie':
            'name2=value2; Expires=Wed, 09-Jun-2021 10:18:14 GMT;Secure;HttpOnly'
        }
        headers = Headers(headers.items())
        response = HTTPResponse(200, body, headers, url, url, _id=1)
        request = FuzzableRequest(url, method='GET')

        self.plugin.grep(request, response)

        self.assertEqual(len(kb.kb.get('analyze_cookies', 'cookies')), 1)
        self.assertEqual(len(kb.kb.get('analyze_cookies', 'security')), 0)
Exemple #18
0
 def test_cache_control_correct_headers(self):
     '''
     Sensitive content with cache control headers so NO BUG is stored in KB.
     '''
     body = 'abc'
     url = URL('https://www.w3af.com/')
     headers = Headers([('content-type', 'text/html'),
                        ('Pragma', 'No-cache'),
                        ('Cache-Control', 'No-store')])
     request = FuzzableRequest(url, method='GET')
     resp = HTTPResponse(200, body, headers, url, url, _id=1)
     
     self.plugin.grep(request, resp)
     self.plugin.end()
     
     infos = kb.kb.get('cache_control', 'cache_control')
     self.assertEquals(len(infos), 0)
Exemple #19
0
    def test_object(self):
        body = '''header
        <OBJECT
          classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
          width="200" height="200">
          <PARAM name="code" value="Applet1.class">
        </OBJECT>
        footer'''
        url = URL('http://www.w3af.com/')
        headers = Headers([('content-type', 'text/html')])
        response = HTTPResponse(200, body, headers, url, url, _id=1)
        request = FuzzableRequest(url, method='GET')
        self.plugin.grep(request, response)

        self.assertEquals(len(kb.kb.get('objects', 'object')), 1)
        i = kb.kb.get('objects', 'object')[0]
        self.assertTrue('"object"' in i.get_desc())
Exemple #20
0
    def test_applet(self):
        body = '''header
        <APPLET code="XYZApp.class" codebase="html/" align="baseline"
            width="200" height="200">
            <PARAM name="model" value="models/HyaluronicAcid.xyz">
            No Java 2 SDK, Standard Edition v 1.4.2 support for APPLET!!
        </APPLET>
        footer'''
        url = URL('http://www.w3af.com/')
        headers = Headers([('content-type', 'text/html')])
        response = HTTPResponse(200, body, headers, url, url, _id=1)
        request = FuzzableRequest(url, method='GET')
        self.plugin.grep(request, response)

        self.assertEquals(len(kb.kb.get('objects', 'applet')), 1)
        i = kb.kb.get('objects', 'applet')[0]
        self.assertTrue('"applet"' in i.get_desc())
Exemple #21
0
    def test_from_dict(self):
        html = 'header <b>ABC</b>-<b>DEF</b>-<b>XYZ</b> footer'
        headers = Headers([('Content-Type', 'text/html')])
        orig_resp = self.create_resp(headers, html)

        msg = msgpack.dumps(orig_resp.to_dict())
        loaded_dict = msgpack.loads(msg)

        loaded_resp = HTTPResponse.from_dict(loaded_dict)

        self.assertEqual(orig_resp, loaded_resp)

        orig_resp.__dict__.pop('_body_lock')
        loaded_resp.__dict__.pop('_body_lock')

        self.assertEqual(orig_resp.__dict__.values(),
                         loaded_resp.__dict__.values())
Exemple #22
0
    def GET(self,
            uri,
            data=None,
            headers=Headers(),
            cache=False,
            grep=True,
            cookies=True,
            respect_size_limit=True):
        '''
        HTTP GET a URI using a proxy, user agent, and other settings
        that where previously set in opener_settings.py .

        :param uri: This is the URI to GET, with the query string included.
        :param data: Only used if the uri parameter is really a URL. The data
                     will be converted into a string and set as the URL object
                     query string before sending.
        :param headers: Any special headers that will be sent with this request
        :param cache: Should the library search the local cache for a response
                      before sending it to the wire?
        :param grep: Should grep plugins be applied to this request/response?
        :param cookies: Send stored cookies in request (or not)

        :return: An HTTPResponse object.
        '''
        if not isinstance(uri, URL):
            raise TypeError(
                'The uri parameter of ExtendedUrllib.GET() must be of '
                'url.URL type.')

        if not isinstance(headers, Headers):
            raise TypeError(
                'The header parameter of ExtendedUrllib.GET() must be of '
                'Headers type.')

        # Validate what I'm sending, init the library (if needed)
        self._init()

        if data:
            uri = uri.copy()
            uri.querystring = data

        req = HTTPRequest(uri, cookies=cookies, cache=cache)
        req = self._add_headers(req, headers)

        with raise_size_limit(respect_size_limit):
            return self._send(req, grep=grep)
Exemple #23
0
    def test_retrieve_csp_report_uri_yes(self):
        '''
        Test case in which site provides CSP report uri.
        '''
        hrds = {}
        hrds[CSP_HEADER_FIREFOX] = CSP_DIRECTIVE_OBJECT + " 'self'"
        hrds[CSP_HEADER_W3C_REPORT_ONLY] = CSP_DIRECTIVE_DEFAULT + \
            " 'self';" + CSP_DIRECTIVE_REPORT_URI + " http://example.com"
        hrds[CSP_HEADER_W3C] = CSP_DIRECTIVE_SCRIPT + " 'self';" + \
            CSP_DIRECTIVE_REPORT_URI + " /myrelativeuri"

        csp_headers = Headers(hrds.items())
        http_response = HTTPResponse(200, '', csp_headers, self.url, self.url)
        uri_set = retrieve_csp_report_uri(http_response)

        self.assertEqual(len(uri_set), 2)
        self.assertTrue("http://example.com" in uri_set)
        self.assertTrue("/myrelativeuri" in uri_set)
Exemple #24
0
 def test_cache_control_no_headers(self):
     '''
     Sensitive content without cache control headers so bug is stored in KB.
     '''
     body = 'abc'
     url = URL('https://www.w3af.com/')
     headers = Headers([('content-type', 'text/html')])
     request = FuzzableRequest(url, method='GET')
     resp = HTTPResponse(200, body, headers, url, url, _id=1)
     
     self.plugin.grep(request, resp)
     self.plugin.end()
     
     infos = kb.kb.get('cache_control', 'cache_control')
     self.assertEquals(len(infos), 1)
     
     info = infos[0]
     self.assertEqual(info.get_name(), 'Missing cache control for HTTPS content')
    def test_body_parse_form(self):
        body = '''<form action="/foo.bar" method="POST">
                    A: <input name="a" />
                    B: <input name="b" value="123" />
                  </form>'''
        headers = Headers([('content-type', 'text/html')])
        http_response = HTTPResponse(200, body, headers, self.url, self.url)

        post_request_lst = create_fuzzable_requests(http_response,
                                                    add_self=False)
        self.assertEqual(len(post_request_lst), 1)

        post_request = post_request_lst[0]
        self.assertEqual(post_request.get_url().url_string,
                         'http://www.w3af.com/foo.bar')
        self.assertEqual(post_request.get_data(), 'a=&b=123')
        self.assertEqual(post_request.get_method(), 'POST')
        self.assertFalse('content-type' in post_request.get_headers())
Exemple #26
0
    def test_image_with_image_content_type(self, *args):
        '''
        Verify that our plugins don't break when we send them an image.
        '''
        file_path = os.path.join('plugins', 'tests', 'grep', 'data',
                                 'w3af.png')
        body = file(file_path).read()
        hdrs = Headers({'Content-Type': 'image/png'}.items())
        response = HTTPResponse(200,
                                body,
                                hdrs,
                                self.url_inst,
                                self.url_inst,
                                _id=random.randint(1, 5000))
        request = FuzzableRequest(self.url_inst)

        for pinst in self._plugins:
            pinst.grep(request, response)
Exemple #27
0
    def test_retrieve_csp_policies_with_special_policies_case02(self):
        '''
        Test case in which 2 policies are specified using special directives
        with explicit values.
        '''
        header_value = "sandbox allow-forms allow-scripts ;"\
                       " script-nonce AABBCCDDEE"
        hrds = {CSP_HEADER_W3C: header_value}.items()
        csp_headers = Headers(hrds)

        http_response = HTTPResponse(200, '', csp_headers, self.url, self.url)
        policies = retrieve_csp_policies(http_response)

        self.assertEqual(len(policies), 2)
        self.assertEqual(len(policies[CSP_DIRECTIVE_SANDBOX]), 2)
        self.assertTrue("allow-forms" in policies[CSP_DIRECTIVE_SANDBOX])
        self.assertTrue("allow-scripts" in policies[CSP_DIRECTIVE_SANDBOX])
        self.assertEqual(len(policies[CSP_DIRECTIVE_SCRIPT_NONCE]), 1)
        self.assertEqual(policies[CSP_DIRECTIVE_SCRIPT_NONCE][0], "AABBCCDDEE")
Exemple #28
0
    def test_user_defined_regex(self):
        body = '<html><head><script>xhr = new XMLHttpRequest(); xhr.open(GET, "data.txt",  true);'
        url = URL('http://www.w3af.com/')
        headers = Headers([('content-type', 'text/html')])
        response = HTTPResponse(200, body, headers, url, url, _id=1)
        request = FuzzableRequest(url, method='GET')

        options = self.plugin.get_options()
        options['single_regex'].set_value('".*?"')
        self.plugin.set_options(options)

        self.plugin.grep(request, response)
        self.assertEquals(
            len(kb.kb.get('user_defined_regex', 'user_defined_regex')), 1)

        info_obj = kb.kb.get('user_defined_regex', 'user_defined_regex')[0]
        self.assertTrue(info_obj.get_desc().startswith(
            'User defined regular expression "'))
        self.assertIn('data.txt', info_obj.get_desc())
Exemple #29
0
    def test_response_body(self):
        body = 'hello user!'
        headers = Headers([('content-type', 'text/html')])
        response = HTTPResponse(200, body, headers, self.url, self.url, _id=1)

        option_list = self.plugin.get_options()
        option_list['expressions'].set_value('sb/user/notluser/')
        self.plugin.set_options(option_list)

        mod_request = self.plugin.mangle_request(self.request)
        mod_response = self.plugin.mangle_response(response)

        self.assertEqual(mod_request.get_headers(), self.request.get_headers())
        self.assertEqual(mod_response.get_headers(), response.get_headers())

        self.assertEqual(mod_request.get_uri(), self.request.get_uri())
        self.assertEqual(mod_response.get_uri(), response.get_uri())

        self.assertEqual(mod_response.get_body(), 'hello notluser!')
Exemple #30
0
    def test_no_code_disclosure(self, *args):
        body = """Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer
        eu lacus accumsan arcu fermentum euismod. Donec pulvinar porttitor
        tellus. Aliquam venenatis. Donec facilisis pharetra tortor.  In nec
        mauris eget magna consequat convallis. Nam sed sem vitae odio
        pellentesque interdum. Sed consequat viverra nisl. Suspendisse arcu
        metus, blandit quis, rhoncus <a>,</a> pharetra eget, velit. Mauris
        urna. Morbi nonummy molestie orci. Praesent nisi elit, fringilla ac,
        suscipit non, tristique vel, ma<?uris. Curabitur vel lorem id nisl porta
        adipiscing. Suspendisse eu lectus. In nunc. Duis vulputate tristique
        enim. Donec quis lectus a justo imperdiet tempus."""

        url = URL('http://www.w3af.com/')
        headers = Headers([('content-type', 'text/html')])
        response = HTTPResponse(200, body, headers, url, url, _id=1)
        request = FuzzableRequest(url, method='GET')
        self.plugin.grep(request, response)
        self.assertEqual(
            len(kb.kb.get('code_disclosure', 'code_disclosure')), 0)