Exemplo n.º 1
0
    def test_fuzzable_request(self):
        dl = DiskList()

        uri = URL('http://w3af.org/?id=2')
        qsr1 = HTTPQSRequest(uri,
                             method='GET',
                             headers=Headers([('Referer', 'http://w3af.org/')
                                              ]))

        uri = URL('http://w3af.org/?id=3')
        qsr2 = HTTPQSRequest(uri,
                             method='OPTIONS',
                             headers=Headers([('Referer', 'http://w3af.org/')
                                              ]))

        uri = URL('http://w3af.org/?id=7')
        qsr3 = HTTPQSRequest(uri,
                             method='FOO',
                             headers=Headers([('Referer', 'http://w3af.org/')
                                              ]))

        dl.append(qsr1)
        dl.append(qsr2)

        self.assertEqual(dl[0], qsr1)
        self.assertEqual(dl[1], qsr2)
        self.assertFalse(qsr3 in dl)
        self.assertTrue(qsr2 in dl)
Exemplo n.º 2
0
    def test_remove_table_then_add(self):
        disk_list = DiskList()
        disk_list.append(1)

        disk_list.cleanup()

        self.assertRaises(AssertionError, disk_list.append, 1)
Exemplo n.º 3
0
    def test_to_unicode(self):
        dl = DiskList()
        dl.append(1)
        dl.append(2)
        dl.append(3)

        self.assertEqual(unicode(dl), u'<DiskList [1, 2, 3]>')
Exemplo n.º 4
0
    def test_specific_serializer_with_http_response(self):
        #
        #   This test runs in 26.42 seconds on my workstation
        #
        body = '<html><a href="http://moth/abc.jsp">test</a></html>'
        headers = Headers([('Content-Type', 'text/html')])
        url = URL('http://w3af.com')
        response = HTTPResponse(200, body, headers, url, url, _id=1)

        def dump(http_response):
            return msgpack.dumps(http_response.to_dict(),
                                 use_bin_type=True)

        def load(serialized_object):
            data = msgpack.loads(serialized_object, raw=False)
            return HTTPResponse.from_dict(data)

        count = 30000
        dl = DiskList(dump=dump, load=load)

        for i in xrange(0, count):
            # This tests the serialization
            dl.append(response)

            # This tests the deserialization
            _ = dl[i]
Exemplo n.º 5
0
    def test_specific_serializer_with_http_response(self):
        #
        #   This test runs in 26.42 seconds on my workstation
        #
        body = '<html><a href="http://moth/abc.jsp">test</a></html>'
        headers = Headers([('Content-Type', 'text/html')])
        url = URL('http://w3af.com')
        response = HTTPResponse(200, body, headers, url, url, _id=1)

        def dump(http_response):
            return msgpack.dumps(http_response.to_dict(), use_bin_type=True)

        def load(serialized_object):
            data = msgpack.loads(serialized_object, raw=False)
            return HTTPResponse.from_dict(data)

        count = 30000
        dl = DiskList(dump=dump, load=load)

        for i in xrange(0, count):
            # This tests the serialization
            dl.append(response)

            # This tests the deserialization
            _ = dl[i]
Exemplo n.º 6
0
    def test_remove_table_then_add(self):
        disk_list = DiskList()
        disk_list.append(1)

        disk_list.cleanup()

        self.assertRaises(AssertionError, disk_list.append, 1)
Exemplo n.º 7
0
 def test_to_unicode(self):
     dl = DiskList()
     dl.append(1)
     dl.append(2)
     dl.append(3)
     
     self.assertEqual(unicode(dl), u'<DiskList [1, 2, 3]>')
Exemplo n.º 8
0
class RESTAPIOutput(OutputPlugin):
    """
    Store all log messages on a DiskList

    :author: Andres Riancho ([email protected])
    """
    def __init__(self):
        super(RESTAPIOutput, self).__init__()
        self.log = DiskList(table_prefix='RestApiScanLog')
        self.log_id = -1

    def get_log_id(self):
        self.log_id += 1
        return self.log_id

    def debug(self, msg_string, new_line=True):
        """
        This method is called from the output object. The output object was
        called from a plugin or from the framework. This method should take an
        action for debug messages.
        """
        m = Message(DEBUG, self._clean_string(msg_string), self.get_log_id())
        self.log.append(m)

    def information(self, msg_string, new_line=True):
        """
        This method is called from the output object. The output object was
        called from a plugin or from the framework. This method should take an
        action for informational messages.
        """
        m = Message(INFORMATION, self._clean_string(msg_string),
                    self.get_log_id())
        self.log.append(m)

    def error(self, msg_string, new_line=True):
        """
        This method is called from the output object. The output object was
        called from a plugin or from the framework. This method should take an
        action for error messages.
        """
        m = Message(ERROR, self._clean_string(msg_string), self.get_log_id())
        self.log.append(m)

    def vulnerability(self, msg_string, new_line=True, severity=MEDIUM):
        """
        This method is called from the output object. The output object was
        called from a plugin or from the framework. This method should take an
        action when a vulnerability is found.
        """
        m = Message(VULNERABILITY, self._clean_string(msg_string),
                    self.get_log_id())
        m.set_severity(severity)
        self.log.append(m)

    def console(self, msg_string, new_line=True):
        """
        This method is used by the w3af console to print messages to the outside
        """
        m = Message(CONSOLE, self._clean_string(msg_string), self.get_log_id())
        self.log.append(m)
Exemplo n.º 9
0
class content_sniffing(GrepPlugin):
    """
    Check if all responses have X-Content-Type-Options header set

    :author: Andres Riancho ([email protected])
    """
    def __init__(self):
        super(content_sniffing, self).__init__()
        self._vuln_count = 0
        self._vulns = DiskList(table_prefix='content_sniffing')
        self._ids = DiskList(table_prefix='content_sniffing')

    def grep(self, request, response):
        """
        Check if all responses have X-Content-Type-Options header set

        :param request: The HTTP request object.
        :param response: The HTTP response object
        :return: None, all results are saved in the kb.
        """
        if self._vuln_count > MAX_REPORTS:
            return

        ct_options_value, _ = response.get_headers().iget(
            CT_OPTIONS_HEADER, None)
        if ct_options_value is not None:
            if ct_options_value.strip().lower() == NOSNIFF:
                return

        self._vuln_count += 1

        if response.get_url() not in self._vulns:
            self._vulns.append(response.get_url())
            self._ids.append(response.id)

    def end(self):
        if not self._vuln_count:
            return

        response_ids = [_id for _id in self._ids]

        desc = 'Some URLs returned an HTTP response without the' \
               ' recommended HTTP header X-Content-Type-Options.' \
               'The list of vulnerable URLs is:\n\n - %s'
        desc %= ' - '.join([str(url) + '\n' for url in self._vulns])

        v = Vuln('Missing X-Content-Type-Options header', desc, severity.LOW,
                 response_ids, self.get_name())

        self.kb_append_uniq_group(self,
                                  'content_sniffing',
                                  v,
                                  group_klass=CTSniffingInfoSet)

    def get_long_desc(self):
        """
        :return: A DETAILED description of the plugin functions and features.
        """
        return """
Exemplo n.º 10
0
    def test_slice_all(self):
        disk_list = DiskList()
        disk_list.append("1")
        disk_list.append("2")

        dl_copy = disk_list[:]
        self.assertIn("1", dl_copy)
        self.assertIn("2", dl_copy)
Exemplo n.º 11
0
    def test_slice_all(self):
        disk_list = DiskList()
        disk_list.append('1')
        disk_list.append('2')

        dl_copy = disk_list[:]
        self.assertIn('1', dl_copy)
        self.assertIn('2', dl_copy)
Exemplo n.º 12
0
 def test_slice_all(self):
     disk_list = DiskList()
     disk_list.append('1')
     disk_list.append('2')
     
     dl_copy = disk_list[:]
     self.assertIn('1', dl_copy)
     self.assertIn('2', dl_copy)
Exemplo n.º 13
0
    def test_slice_greater_than_length(self):
        disk_list = DiskList()
        disk_list.append('1')
        disk_list.append('2')

        dl_copy = disk_list[:50]
        self.assertIn('1', dl_copy)
        self.assertIn('2', dl_copy)
        self.assertEqual(2, len(dl_copy))
Exemplo n.º 14
0
    def test_slice_greater_than_length(self):
        disk_list = DiskList()
        disk_list.append('1')
        disk_list.append('2')

        dl_copy = disk_list[:50]
        self.assertIn('1', dl_copy)
        self.assertIn('2', dl_copy)
        self.assertEqual(2, len(dl_copy))
Exemplo n.º 15
0
    def test_sorted(self):
        dl = DiskList()

        dl.append("abc")
        dl.append("def")
        dl.append("aaa")

        sorted_dl = sorted(dl)

        self.assertEqual(["aaa", "abc", "def"], sorted_dl)
Exemplo n.º 16
0
    def test_slice_first_N(self):
        disk_list = DiskList()
        disk_list.append("1")
        disk_list.append("2")
        disk_list.append("3")

        dl_copy = disk_list[:1]
        self.assertIn("1", dl_copy)
        self.assertNotIn("2", dl_copy)
        self.assertNotIn("3", dl_copy)
Exemplo n.º 17
0
    def test_urlobject(self):
        dl = DiskList()

        dl.append(URL('http://w3af.org/?id=2'))
        dl.append(URL('http://w3af.org/?id=3'))

        self.assertEqual(dl[0], URL('http://w3af.org/?id=2'))
        self.assertEqual(dl[1], URL('http://w3af.org/?id=3'))
        self.assertFalse(URL('http://w3af.org/?id=4') in dl)
        self.assertTrue(URL('http://w3af.org/?id=2') in dl)
Exemplo n.º 18
0
 def test_slice_first_N(self):
     disk_list = DiskList()
     disk_list.append('1')
     disk_list.append('2')
     disk_list.append('3')
     
     dl_copy = disk_list[:1]
     self.assertIn('1', dl_copy)
     self.assertNotIn('2', dl_copy)
     self.assertNotIn('3', dl_copy)
Exemplo n.º 19
0
    def test_sorted(self):
        dl = DiskList()

        dl.append('abc')
        dl.append('def')
        dl.append('aaa')

        sorted_dl = sorted(dl)

        self.assertEqual(['aaa', 'abc', 'def'], sorted_dl)
Exemplo n.º 20
0
    def test_sorted(self):
        dl = DiskList()

        dl.append('abc')
        dl.append('def')
        dl.append('aaa')

        sorted_dl = sorted(dl)

        self.assertEqual(['aaa', 'abc', 'def'], sorted_dl)
Exemplo n.º 21
0
    def test_slice_first_N(self):
        disk_list = DiskList()
        disk_list.append('1')
        disk_list.append('2')
        disk_list.append('3')

        dl_copy = disk_list[:1]
        self.assertIn('1', dl_copy)
        self.assertNotIn('2', dl_copy)
        self.assertNotIn('3', dl_copy)
Exemplo n.º 22
0
    def test_urlobject(self):
        dl = DiskList()

        dl.append(URL('http://w3af.org/?id=2'))
        dl.append(URL('http://w3af.org/?id=3'))

        self.assertEqual(dl[0], URL('http://w3af.org/?id=2'))
        self.assertEqual(dl[1], URL('http://w3af.org/?id=3'))
        self.assertFalse(URL('http://w3af.org/?id=4') in dl)
        self.assertTrue(URL('http://w3af.org/?id=2') in dl)
Exemplo n.º 23
0
    def test_reverse_iteration(self):
        dl = DiskList()
        dl.append(1)
        dl.append(2)
        dl.append(3)

        reverse_iter_res = []
        for i in reversed(dl):
            reverse_iter_res.append(i)

        self.assertEqual(reverse_iter_res, [3, 2, 1])
Exemplo n.º 24
0
    def test_getitem_negative(self):
        dl = DiskList()

        dl.append('a')
        dl.append('b')
        dl.append('c')

        self.assertEqual(dl[-1], 'c')
        self.assertEqual(dl[-2], 'b')
        self.assertEqual(dl[-3], 'a')
        self.assertRaises(IndexError, dl.__getitem__, -4)
Exemplo n.º 25
0
    def test_clear(self):
        dl = DiskList()

        dl.append('a')
        dl.append('b')

        self.assertEqual(len(dl), 2)

        dl.clear()

        self.assertEqual(len(dl), 0)
Exemplo n.º 26
0
    def test_extend(self):
        dl = DiskList()

        dl.append('a')
        dl.extend([1, 2, 3])

        self.assertEqual(len(dl), 4)
        self.assertEqual(dl[0], 'a')
        self.assertEqual(dl[1], 1)
        self.assertEqual(dl[2], 2)
        self.assertEqual(dl[3], 3)
Exemplo n.º 27
0
    def test_getitem_negative(self):
        dl = DiskList()

        dl.append('a')
        dl.append('b')
        dl.append('c')

        self.assertEqual(dl[-1], 'c')
        self.assertEqual(dl[-2], 'b')
        self.assertEqual(dl[-3], 'a')
        self.assertRaises(IndexError, dl.__getitem__, -4)
Exemplo n.º 28
0
    def test_extend(self):
        dl = DiskList()

        dl.append('a')
        dl.extend([1, 2, 3])

        self.assertEqual(len(dl), 4)
        self.assertEqual(dl[0], 'a')
        self.assertEqual(dl[1], 1)
        self.assertEqual(dl[2], 2)
        self.assertEqual(dl[3], 3)
Exemplo n.º 29
0
    def test_clear(self):
        dl = DiskList()

        dl.append('a')
        dl.append('b')

        self.assertEqual(len(dl), 2)

        dl.clear()

        self.assertEqual(len(dl), 0)
Exemplo n.º 30
0
    def test_reverse_iteration(self):
        dl = DiskList()
        dl.append(1)
        dl.append(2)
        dl.append(3)

        reverse_iter_res = []
        for i in reversed(dl):
            reverse_iter_res.append(i)

        self.assertEqual(reverse_iter_res, [3, 2, 1])
Exemplo n.º 31
0
    def test_getitem_negative(self):
        dl = DiskList()

        dl.append("a")
        dl.append("b")
        dl.append("c")

        self.assertEqual(dl[-1], "c")
        self.assertEqual(dl[-2], "b")
        self.assertEqual(dl[-3], "a")
        self.assertRaises(IndexError, dl.__getitem__, -4)
Exemplo n.º 32
0
    def test_ordered_iter(self):
        dl = DiskList()

        dl.append("abc")
        dl.append("def")
        dl.append("aaa")

        sorted_dl = []
        for i in dl.ordered_iter():
            sorted_dl.append(i)

        self.assertEqual(["aaa", "abc", "def"], sorted_dl)
Exemplo n.º 33
0
    def test_ordered_iter(self):
        dl = DiskList()

        dl.append('abc')
        dl.append('def')
        dl.append('aaa')

        sorted_dl = []
        for i in dl.ordered_iter():
            sorted_dl.append(i)

        self.assertEqual(['aaa', 'abc', 'def'], sorted_dl)
Exemplo n.º 34
0
    def test_ordered_iter(self):
        dl = DiskList()

        dl.append('abc')
        dl.append('def')
        dl.append('aaa')

        sorted_dl = []
        for i in dl.ordered_iter():
            sorted_dl.append(i)

        self.assertEqual(['aaa', 'abc', 'def'], sorted_dl)
Exemplo n.º 35
0
    def test_no_specific_serializer_with_string(self):
        #
        #   This test runs in ~5.1 seconds on my workstation
        #
        count = 30000
        dl = DiskList()

        for i in xrange(0, count):
            i_str = str(i)

            # This tests the serialization
            dl.append(i_str)

            # This tests the deserialization
            _ = dl[i]
Exemplo n.º 36
0
    def test_no_specific_serializer_with_string(self):
        #
        #   This test runs in ~5.1 seconds on my workstation
        #
        count = 30000
        dl = DiskList()

        for i in xrange(0, count):
            i_str = str(i)

            # This tests the serialization
            dl.append(i_str)

            # This tests the deserialization
            _ = dl[i]
Exemplo n.º 37
0
    def test_len(self):
        dl = DiskList()

        for i in xrange(0, 100):
            _ = dl.append(i)

        self.assertEqual(len(dl) == 100, True)
Exemplo n.º 38
0
    def test_len(self):
        dl = DiskList()

        for i in xrange(0, 100):
            _ = dl.append(i)

        self.assertEqual(len(dl), 100)
Exemplo n.º 39
0
    def test_no_specific_serializer_with_http_response(self):
        #
        #   This test runs in 28.14 seconds on my workstation
        #
        body = '<html><a href="http://moth/abc.jsp">test</a></html>'
        headers = Headers([('Content-Type', 'text/html')])
        url = URL('http://w3af.com')
        response = HTTPResponse(200, body, headers, url, url, _id=1)

        count = 30000
        dl = DiskList()

        for i in xrange(0, count):
            # This tests the serialization
            dl.append(response)

            # This tests the deserialization
            _ = dl[i]
Exemplo n.º 40
0
    def test_specific_serializer_with_string(self):
        #
        #   This test runs in ~5.0 seconds on my workstation
        #
        #   It seems that cPickle takes almost no time to serialize
        #   a simple string.
        #
        count = 30000
        dl = DiskList(load=lambda x: x, dump=lambda x: x)

        for i in xrange(0, count):
            i_str = str(i)

            # This tests the serialization
            dl.append(i_str)

            # This tests the deserialization
            _ = dl[i]
Exemplo n.º 41
0
    def test_no_specific_serializer_with_http_response(self):
        #
        #   This test runs in 28.14 seconds on my workstation
        #
        body = '<html><a href="http://moth/abc.jsp">test</a></html>'
        headers = Headers([('Content-Type', 'text/html')])
        url = URL('http://w3af.com')
        response = HTTPResponse(200, body, headers, url, url, _id=1)

        count = 30000
        dl = DiskList()

        for i in xrange(0, count):
            # This tests the serialization
            dl.append(response)

            # This tests the deserialization
            _ = dl[i]
Exemplo n.º 42
0
    def test_specific_serializer_with_string(self):
        #
        #   This test runs in ~5.0 seconds on my workstation
        #
        #   It seems that cPickle takes almost no time to serialize
        #   a simple string.
        #
        count = 30000
        dl = DiskList(load=lambda x: x,
                      dump=lambda x: x)

        for i in xrange(0, count):
            i_str = str(i)

            # This tests the serialization
            dl.append(i_str)

            # This tests the deserialization
            _ = dl[i]
Exemplo n.º 43
0
    def test_fuzzable_request(self):
        dl = DiskList()

        uri = URL("http://w3af.org/?id=2")
        qsr1 = FuzzableRequest(uri, method="GET", headers=Headers([("Referer", "http://w3af.org/")]))

        uri = URL("http://w3af.org/?id=3")
        qsr2 = FuzzableRequest(uri, method="OPTIONS", headers=Headers([("Referer", "http://w3af.org/")]))

        uri = URL("http://w3af.org/?id=7")
        qsr3 = FuzzableRequest(uri, method="FOO", headers=Headers([("Referer", "http://w3af.org/")]))

        dl.append(qsr1)
        dl.append(qsr2)

        self.assertEqual(dl[0], qsr1)
        self.assertEqual(dl[1], qsr2)
        self.assertFalse(qsr3 in dl)
        self.assertTrue(qsr2 in dl)
Exemplo n.º 44
0
    def test_int(self):
        dl = DiskList()

        for i in xrange(0, 1000):
            _ = dl.append(i)

        for i in xrange(0, 1000 / 2):
            r = random.randint(0, 1000 - 1)
            self.assertEqual(r in dl, True)

        for i in xrange(0, 1000 / 2):
            r = random.randint(1000, 1000 * 2)
            self.assertEqual(r in dl, False)
Exemplo n.º 45
0
    def test_int(self):
        dl = DiskList()

        for i in xrange(0, 1000):
            _ = dl.append(i)

        for i in xrange(0, 1000 / 2):
            r = random.randint(0, 1000 - 1)
            self.assertEqual(r in dl, True)

        for i in xrange(0, 1000 / 2):
            r = random.randint(1000, 1000 * 2)
            self.assertEqual(r in dl, False)
Exemplo n.º 46
0
    def test_string(self):
        dl = DiskList()

        for i in xrange(0, 1000):
            rnd = ''.join(random.choice(string.letters) for i in xrange(40))
            _ = dl.append(rnd)

        self.assertEqual(rnd in dl, True)

        for i in string.letters:
            self.assertNotIn(i, dl)

        self.assertIn(rnd, dl)
Exemplo n.º 47
0
    def test_string(self):
        dl = DiskList()

        for i in xrange(0, 1000):
            rnd = ''.join(random.choice(string.letters) for i in xrange(40))
            _ = dl.append(rnd)

        self.assertEqual(rnd in dl, True)

        for i in string.letters:
            self.assertNotIn(i, dl)

        self.assertIn(rnd, dl)
Exemplo n.º 48
0
    def test_fuzzable_request(self):
        dl = DiskList()

        uri = URL('http://w3af.org/?id=2')
        qsr1 = FuzzableRequest(uri, method='GET', headers=Headers(
            [('Referer', 'http://w3af.org/')]))

        uri = URL('http://w3af.org/?id=3')
        qsr2 = FuzzableRequest(uri, method='OPTIONS', headers=Headers(
            [('Referer', 'http://w3af.org/')]))

        uri = URL('http://w3af.org/?id=7')
        qsr3 = FuzzableRequest(uri, method='FOO', headers=Headers(
            [('Referer', 'http://w3af.org/')]))

        dl.append(qsr1)
        dl.append(qsr2)

        self.assertEqual(dl[0], qsr1)
        self.assertEqual(dl[1], qsr2)
        self.assertFalse(qsr3 in dl)
        self.assertTrue(qsr2 in dl)
Exemplo n.º 49
0
    def test_unicode(self):
        dl = DiskList()

        dl.append(u"à")
        dl.append(u"המלצת השבוע")
        dl.append([u"à"])

        self.assertEqual(dl[0], u"à")
        self.assertEqual(dl[1], u"המלצת השבוע")
        self.assertEqual(dl[2], [u"à"])
Exemplo n.º 50
0
    def test_unicode(self):
        dl = DiskList()

        dl.append(u'à')
        dl.append(u'המלצת השבוע')
        dl.append([u'à', ])

        self.assertEqual(dl[0], u'à')
        self.assertEqual(dl[1], u'המלצת השבוע')
        self.assertEqual(dl[2], [u'à', ])
Exemplo n.º 51
0
    def test_getitem(self):
        dl = DiskList()

        dl.append('a')
        dl.append(1)
        dl.append([3, 2, 1])

        self.assertEqual(dl[0], 'a')
        self.assertEqual(dl[1], 1)
        self.assertEqual(dl[2], [3, 2, 1])
        self.assertRaises(IndexError, dl.__getitem__, 3)
Exemplo n.º 52
0
    def test_getitem(self):
        dl = DiskList()

        dl.append('a')
        dl.append(1)
        dl.append([3, 2, 1])

        self.assertEqual(dl[0], 'a')
        self.assertEqual(dl[1], 1)
        self.assertEqual(dl[2], [3, 2, 1])
        self.assertRaises(IndexError, dl.__getitem__, 3)
Exemplo n.º 53
0
    def test_getitem(self):
        dl = DiskList()

        dl.append('a')
        dl.append(1)
        dl.append([3, 2, 1])

        self.assertEqual(dl[0] == 'a', True)
        self.assertEqual(dl[1] == 1, True)
        self.assertEqual(dl[2] == [3, 2, 1], True)
        self.assertRaises(IndexError, dl.__getitem__, 3)
Exemplo n.º 54
0
    def test_unicode(self):
        dl = DiskList()

        dl.append(u'à')
        dl.append(u'המלצת השבוע')
        dl.append([
            u'à',
        ])

        self.assertEqual(dl[0], u'à')
        self.assertEqual(dl[1], u'המלצת השבוע')
        self.assertEqual(dl[2], [
            u'à',
        ])
Exemplo n.º 55
0
    def test_pickle(self):
        dl = DiskList()

        dl.append('a')
        dl.append(1)
        dl.append([3, 2, 1])

        values = []
        for i in dl:
            values.append(i)

        self.assertEqual(values[0], 'a')
        self.assertEqual(values[1], 1)
        self.assertEqual(values[2], [3, 2, 1])
Exemplo n.º 56
0
    def test_pickle(self):
        dl = DiskList()

        dl.append('a')
        dl.append(1)
        dl.append([3, 2, 1])

        values = []
        for i in dl:
            values.append(i)

        self.assertEqual(values[0] == 'a', True)
        self.assertEqual(values[1] == 1, True)
        self.assertEqual(values[2] == [3, 2, 1], True)
Exemplo n.º 57
0
class _LineScroller(gtk.TextView, MessageConsumer):
    """The text view of the Messages window.

    :author: Facundo Batista <facundobatista =at= taniquetil.com.ar>
    """
    def __init__(self, scroll_bar, active_filter, possible):
        """
        :param scroll_bar: Gtk Vertical Scrollbar object
        :param active_filter: the filter active at startup.
        :param possible: all filter keys
        """
        gtk.TextView.__init__(self)
        MessageConsumer.__init__(self)
        
        self.set_editable(False)
        self.set_cursor_visible(False)
        self.set_wrap_mode(gtk.WRAP_WORD)
        self.textbuffer = self.get_buffer()
        self.show()
        self.possible = set(possible)
        self.active_filter = active_filter
        self.text_position = 0
        
        self.all_messages = DiskList()
        
        # scroll bar
        self.freeze_scrollbar = False
        scroll_bar.connect("value-changed", self.scroll_changed)

        # colors
        self.textbuffer.create_tag("red-fg", foreground="red")
        self.textbuffer.create_tag("blue-fg", foreground="blue")
        self.textbuffer.create_tag("brown-fg", foreground="brown")
        self.bg_colors = {
            "vulnerability": "red-fg",
            "information": "blue-fg",
            "error": "brown-fg",
        }

    def filter(self, filtinfo):
        """Applies a different filter to the textview.

        :param filtinfo: the new filter
        """
        self.active_filter = filtinfo
        textbuff = self.textbuffer
        textbuff.set_text("")
        for (mtype, text) in self.all_messages:
            if mtype in filtinfo:
                colortag = self.bg_colors[mtype]
                iterl = textbuff.get_end_iter()
                textbuff.insert_with_tags_by_name(iterl, text, colortag)
        self.scroll_to_end()

    def handle_message(self, msg):
        """Adds a message to the textview.

        :param msg: The message to add to the textview
        @returns: None
        """
        yield super(_LineScroller, self).handle_message(msg)

        textbuff = self.textbuffer
                
        text = "[%s] %s\n" % (msg.get_time(), msg.get_msg())
        mtype = msg.get_type()

        # only store it if it's of one of the possible filtered
        if mtype in self.possible:

            # store it
            self.all_messages.append((mtype, text))
            antpos = self.text_position
            self.text_position += len(text)
    
            if mtype in self.active_filter:
                iterl = textbuff.get_end_iter()
                colortag = self.bg_colors[mtype]
                textbuff.insert_with_tags_by_name(iterl, text, colortag)
                self.scroll_to_end()

    def scroll_to_end(self):
        if not self.freeze_scrollbar:
            self.scroll_to_mark(self.textbuffer.get_insert(), 0)

    def scroll_changed(self, vscrollbar):
        """Handle scrollbar's "value-changed" signal.

        Figure out if the scroll should be frozen. If the adjustment's value
        is not in the last page's range => means it was moved up =>
        the scroll bar should be stopped.
        """
        adj = vscrollbar.get_adjustment()
        self.freeze_scrollbar = \
            False if adj.value >= (adj.upper - adj.page_size) else True
Exemplo n.º 58
0
class generic(AuditPlugin):
    """
    Find all kind of bugs without using a fixed database of errors.
    :author: Andres Riancho ([email protected])
    """

    ERROR_STRINGS = ['d\'kc"z\'gj\'\"**5*(((;-*`)', '']

    def __init__(self):
        AuditPlugin.__init__(self)

        #   Internal variables
        self._potential_vulns = DiskList(table_prefix='generic')

        #   User configured variables
        self._diff_ratio = 0.30

    def audit(self, freq, orig_response):
        """
        Find all kind of bugs without using a fixed database of errors.

        :param freq: A FuzzableRequest
        """
        # First, get the original response and create the mutants
        mutants = create_mutants(freq, [
            '',
        ], orig_resp=orig_response)

        for m in mutants:

            # First I check that the current modified parameter in the mutant
            # doesn't have an already reported vulnerability. I don't want to
            # report vulnerabilities more than once.
            if (m.get_url(), m.get_token_name()) in self._potential_vulns:
                continue

            # Now, we request the limit (something that doesn't exist)
            # If http://localhost/a.php?b=1
            #   * Then I should request b=12938795 (random number)
            #
            # If http://localhost/a.php?b=abc
            #   * Then I should request b=hnv98yks (random alnum)
            limit_response = self._get_limit_response(m)

            # Now I request something that could generate an error
            # If http://localhost/a.php?b=1
            #   * Then I should request b=d'kcz'gj'"**5*(((*)
            #
            # If http://localhost/a.php?b=abc
            #   * Then I should request b=d'kcz'gj'"**5*(((*)
            #
            # I also try to trigger errors by sending empty strings
            #     If http://localhost/a.php?b=1 ; then I should request b=
            #     If http://localhost/a.php?b=abc ; then I should request b=
            for error_string in self.ERROR_STRINGS:

                m.set_token_value(error_string)
                error_response = self._uri_opener.send_mutant(m)

                # Now I compare responses
                self._analyze_responses(orig_response, limit_response,
                                        error_response, m)

    def _analyze_responses(self, orig_resp, limit_response, error_response,
                           mutant):
        """
        Analyze responses; if error_response doesn't look like orig_resp nor
        limit_response, then we have a vuln.

        :return: None
        """
        original_to_error = relative_distance(orig_resp.get_body(),
                                              error_response.get_body())
        limit_to_error = relative_distance(limit_response.get_body(),
                                           error_response.get_body())
        original_to_limit = relative_distance(limit_response.get_body(),
                                              orig_resp.get_body())

        ratio = self._diff_ratio + (1 - original_to_limit)

        if original_to_error < ratio and limit_to_error < ratio:
            # Maybe the limit I requested wasn't really a non-existent one
            # (and the error page really found the limit),
            # let's request a new limit (one that hopefully doesn't exist)
            # in order to remove some false positives
            limit_response2 = self._get_limit_response(mutant)

            id_list = [orig_resp.id, limit_response.id, error_response.id]

            if relative_distance(
                    limit_response2.get_body(),
                    limit_response.get_body()) > 1 - self._diff_ratio:
                # The two limits are "equal"; It's safe to suppose that we have
                # found the limit here and that the error string really produced
                # an error
                self._potential_vulns.append(
                    (mutant.get_url(), mutant.get_token_name(), mutant,
                     id_list))

    def _get_limit_response(self, mutant):
        """
        We request the limit (something that doesn't exist)
            - If http://localhost/a.php?b=1
                then I should request b=12938795 (random number)
            - If http://localhost/a.php?b=abc
                then I should request b=hnv98yks (random alnum)

        :return: The limit response object
        """
        mutant_copy = mutant.copy()

        is_digit = mutant.get_token_original_value().isdigit()
        value = rand_number(length=8) if is_digit else rand_alnum(length=8)
        mutant_copy.set_token_value(value)
        limit_response = self._uri_opener.send_mutant(mutant_copy)

        return limit_response

    def end(self):
        """
        This method is called when the plugin wont be used anymore.
        """
        all_findings = kb.kb.get_all_findings()

        for url, variable, mutant, id_list in self._potential_vulns:
            for info in all_findings:
                if info.get_token_name() == variable and info.get_url() == url:
                    break
            else:
                desc = 'An unhandled error, which could potentially translate' \
                       ' to a vulnerability, was found at: %s'
                desc = desc % mutant.found_at()

                v = Vuln.from_mutant('Unhandled error in web application',
                                     desc, severity.LOW, id_list,
                                     self.get_name(), mutant)

                self.kb_append_uniq(self, 'generic', v)

        self._potential_vulns.cleanup()

    def get_options(self):
        """
        :return: A list of option objects for this plugin.
        """
        ol = OptionList()

        d = 'If two strings have a diff ratio less than diff_ratio, then they'\
            '  are really different.'
        o = opt_factory('diff_ratio', self._diff_ratio, d, 'float')
        ol.add(o)

        return ol

    def set_options(self, options_list):
        """
        This method sets all the options that are configured using the user
        interface generated by the framework using the result of get_options().

        :param options_list: A dictionary with the options for the plugin.
        :return: No value is returned.
        """
        self._diff_ratio = options_list['diff_ratio'].get_value()

    def get_long_desc(self):
        """
        :return: A DETAILED description of the plugin functions and features.
        """
        return """
Exemplo n.º 59
0
class html_file(OutputPlugin):
    """
    Generate HTML report with identified vulnerabilities and log messages.

    :author: Andres Riancho (([email protected]))
    """
    def __init__(self):
        OutputPlugin.__init__(self)

        # Internal variables
        self._initialized = False
        self._additional_info = DiskList(table_prefix='html_file')
        self._enabled_plugins = {}
        self.template_root = os.path.join(ROOT_PATH, 'plugins', 'output',
                                          'html_file', 'templates')

        # User configured parameters
        self._verbose = False
        self._output_file_name = './report.html'
        self._template = os.path.join(self.template_root, 'complete.html')

    def debug(self, message, new_line=True):
        """
        This method is called from the output object. The output object was
        called from a plugin or from the framework. This method should take
        an action for debug messages.
        """
        if self._verbose:
            to_print = self._clean_string(message)
            self._append_additional_info(to_print, 'debug')

    def do_nothing(self, *args, **kwargs):
        pass

    information = vulnerability = do_nothing

    def error(self, message, new_line=True):
        """
        This method is called from the output object. The output object was
        called from a plugin or from the framework. This method should take
        an action for error messages.
        """
        to_print = self._clean_string(message)
        self._append_additional_info(to_print, 'error')

    def console(self, message, new_line=True):
        """
        This method is used by the w3af console to print messages to the
        outside.
        """
        to_print = self._clean_string(message)
        self._append_additional_info(to_print, 'console')

    def _append_additional_info(self, message, msg_type):
        """
        Add a message to the debug table.

        :param message: The message to add to the table. It's in HTML.
        :param msg_type: The type of message
        """
        now = time.localtime(time.time())
        the_time = time.strftime("%c", now)
        self._additional_info.append((the_time, msg_type, message))

    def set_options(self, option_list):
        """
        Sets the Options given on the OptionList to self. The options are the
        result of a user entering some data on a window that was constructed
        using the XML Options that was retrieved from the plugin using
        get_options()

        This method MUST be implemented on every plugin.

        :return: No value is returned.
        """
        self._output_file_name = option_list['output_file'].get_value()
        self._verbose = option_list['verbose'].get_value()

    def get_options(self):
        """
        :return: A list of option objects for this plugin.
        """
        ol = OptionList()

        d = 'The path to the HTML template used to render the report.'
        o = opt_factory('template', self._template, d, INPUT_FILE)
        ol.add(o)

        d = 'File name where this plugin will write to'
        o = opt_factory('output_file', self._output_file_name, d, OUTPUT_FILE)
        ol.add(o)

        d = 'True if debug information will be appended to the report.'
        o = opt_factory('verbose', self._verbose, d, 'boolean')
        ol.add(o)

        return ol

    def log_enabled_plugins(self, plugins_dict, options_dict):
        """
        This method is called from the output manager object. This method
        should take an action for the enabled plugins and their configuration.
        Usually, write the info to a file or print it somewhere.

        :param plugins_dict: A dict with all the plugin types and the
                                enabled plugins for that type of plugin.
        :param options_dict: A dict with the options for every plugin.
        """
        self._enabled_plugins = {}

        # TODO: Improve so it contains the plugin configuration too
        for plugin_type, enabled in plugins_dict.iteritems():
            self._enabled_plugins[plugin_type] = enabled

    def end(self):
        """
        This method is called when the scan has finished, we perform these
        main tasks:
            * Get the target URLs
            * Get the enabled plugins
            * Get the vulnerabilities and infos from the KB
            * Get the debug data
            * Send all the data to jinja2 for rendering the template

        """
        target_urls = [t.url_string for t in cf.cf.get('targets')]
        target_domain = cf.cf.get('target_domains')[0]
        enabled_plugins = self._enabled_plugins
        findings = kb.kb.get_all_findings()
        debug_log = ((t, l, smart_unicode(m))
                     for (t, l, m) in self._additional_info)
        known_urls = kb.kb.get_all_known_urls()

        context = {
            'target_urls': target_urls,
            'target_domain': target_domain,
            'enabled_plugins': enabled_plugins,
            'findings': findings,
            'debug_log': debug_log,
            'known_urls': known_urls
        }

        # The file was verified to exist when setting the plugin configuration
        template_fh = file(os.path.expanduser(self._template), 'r')
        output_fh = file(os.path.expanduser(self._output_file_name), 'w')

        self._render_html_file(template_fh, context, output_fh)

    def _render_html_file(self, template_fh, context, output_fh):
        """
        Renders the HTML file using the configured template. Separated as a
        method to be able to easily test.

        :param context: A dict containing target urls, enabled plugins, etc.
        :return: True on successful rendering
        """
        severity_icon = functools.partial(get_severity_icon,
                                          self.template_root)

        env_config = {
            'undefined': StrictUndefined,
            'trim_blocks': True,
            'autoescape': True,
            'lstrip_blocks': True
        }

        try:
            jinja2_env = Environment(**env_config)
        except TypeError:
            # Kali uses a different jinja2 version, which doesn't have the same
            # Environment kwargs, so we first try with the version we expect
            # to have available, and then if it doesn't work apply this
            # workaround for Kali
            #
            # https://github.com/andresriancho/w3af/issues/9552
            env_config.pop('lstrip_blocks')
            jinja2_env = Environment(**env_config)

        jinja2_env.filters['render_markdown'] = render_markdown
        jinja2_env.filters['request'] = request_dump
        jinja2_env.filters['response'] = response_dump
        jinja2_env.filters['severity_icon'] = severity_icon
        jinja2_env.filters['severity_text'] = get_severity_text
        jinja2_env.globals['get_current_date'] = get_current_date
        jinja2_env.loader = FileSystemLoader(self.template_root)

        template = jinja2_env.from_string(template_fh.read())

        try:
            rendered_output = template.render(context)
        except Exception, e:
            msg = u'Failed to render html report template. Exception: "%s"'
            om.out.error(msg % e)
            return False
        finally:
Exemplo n.º 60
0
class cache_control(GrepPlugin):
    """
    Grep every page for Pragma and Cache-Control headers.

    :author: Andres Riancho ([email protected])
    """
    
    SAFE_CONFIG = {'pragma': 'no-cache',
                   'cache-control': 'no-store'}
    
    def __init__(self):
        GrepPlugin.__init__(self)

        self._total_count = 0
        self._vuln_count = 0
        self._vulns = DiskList()
        self._ids = DiskList()

    def grep(self, request, response):
        if response.is_image() or response.is_swf():
            return

        elif response.get_url().get_protocol() == 'http':
            return

        elif response.get_code() > 300\
        and response.get_code() < 310:
            return
        
        elif response.body == '':
            return
        
        else:
            self._total_count += 1
    
            cache_control_settings = self._get_cache_control(response)
            self._analyze_cache_control(cache_control_settings, response)
    
    def _get_cache_control(self, response):
        """
        :param response: The http response we want to extract the information
                         from.
        :return: A list with the headers and meta tag information used to
                 configure the browser cache control.
        """
        res = []

        cache_control_headers = self.SAFE_CONFIG.keys()
        headers = response.get_headers()
        
        for _type in cache_control_headers:
            header_value, _ = headers.iget(_type, None)
            if header_value is not None:
                res.append(CacheSettings(_type, header_value.lower()))
                
        try:
            doc_parser = parser_cache.dpc.get_document_parser_for(response)
        except BaseFrameworkException:
            pass
        else:
            for meta_tag in doc_parser.get_meta_tags():
                header_name = meta_tag.get('http-equiv', None)
                header_value = meta_tag.get('content', None)
                if header_name is not None and header_value is not None:
                    header_name = header_name.lower()
                    header_value = header_value.lower()
                    if header_name in cache_control_headers:
                        res.append(CacheSettings(header_name, header_value))
        
        return res

    def _analyze_cache_control(self, cache_control_settings, response):
        """
        Analyze the cache control settings set in headers and meta tags,
        store the information to report the vulnerabilities.
        """
        received_headers = set()
        
        for cache_setting in cache_control_settings:
            expected_header = self.SAFE_CONFIG[cache_setting.type]
            received_header = cache_setting.value.lower()
            received_headers.add(cache_setting.type)
            if expected_header not in received_header:
                # The header has an incorrect value
                self.is_vuln(response)
                return
        
        if len(received_headers) != len(self.SAFE_CONFIG):
            # No cache control header found
            self.is_vuln(response)
    
    def is_vuln(self, response):
        self._vuln_count += 1
        if response.get_url() not in self._vulns:
            self._vulns.append(response.get_url())
            self._ids.append(response.id)
    
    def end(self):
        # If all URLs implement protection, don't report anything.
        if not self._vuln_count:
            return

        # If none of the URLs implement protection, simply report
        # ONE vulnerability that says that.
        if self._total_count == self._vuln_count:
            desc = 'The whole target web application has no protection (Pragma'\
                   ' and Cache-Control headers) against sensitive content'\
                   ' caching.'
            
        # If most of the URLs implement the protection but some
        # don't, report ONE vulnerability saying: "Most are protected, but x, y
        # are not.
        if self._total_count > self._vuln_count:
            desc = 'Some URLs have no protection (Pragma and Cache-Control'\
                   ' headers) against sensitive content caching. Among them:\n'
            desc += ' '.join([str(url) + '\n' for url in self._vulns])
        
        response_ids = [_id for _id in self._ids]
        
        v = Vuln('Missing cache control for HTTPS content', desc,
                 severity.LOW, response_ids, self.get_name())
        
        self.kb_append_uniq(self, 'cache_control', v, 'URL')
        
        self._vulns.cleanup()
        self._ids.cleanup()

    def get_long_desc(self):
        return """\