Exemple #1
0
class TestExtendedUrllibProxy(unittest.TestCase):

    MOTH_MESSAGE = '<title>moth: vulnerable web application</title>'

    def setUp(self):
        self.uri_opener = ExtendedUrllib()

        # Start the proxy daemon
        self._proxy = Proxy('127.0.0.1', 0, ExtendedUrllib(), w3afProxyHandler)
        self._proxy.start()
        self._proxy.wait_for_start()

        port = self._proxy.get_port()

        # Configure the proxy
        settings = OpenerSettings()
        options = settings.get_options()
        proxy_address_opt = options['proxy_address']
        proxy_port_opt = options['proxy_port']

        proxy_address_opt.set_value('127.0.0.1')
        proxy_port_opt.set_value(port)

        settings.set_options(options)
        self.uri_opener.settings = settings

    def tearDown(self):
        self.uri_opener.end()

    def test_http_default_port_via_proxy(self):
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

    def test_http_port_specification_via_proxy(self):
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

    def test_https_via_proxy(self):
        TODO = 'Skip this test because of a strange bug with the extended'\
               ' url library and w3af\'s local proxy daemon. More info here:'\
               ' https://github.com/andresriancho/w3af/issues/183'
        raise SkipTest(TODO)

        url = URL(get_moth_https())
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

    def test_offline_port_via_proxy(self):
        url = URL('http://127.0.0.1:8181/')
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertEqual(http_response.get_code(), 400)

    def test_POST_via_proxy(self):
        url = URL(get_moth_http('/audit/xss/simple_xss_form.py'))
        http_response = self.uri_opener.POST(url,
                                             data='text=123456abc',
                                             cache=False)
        self.assertIn('123456abc', http_response.body)
Exemple #2
0
class TestXUrllib(unittest.TestCase):

    MOTH_MESSAGE = '<title>moth: vulnerable web application</title>'

    def setUp(self):
        self.uri_opener = ExtendedUrllib()

    def tearDown(self):
        self.uri_opener.end()

    def test_basic(self):
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url, cache=False)

        self.assertIn(self.MOTH_MESSAGE, http_response.body)

        self.assertGreaterEqual(http_response.id, 1)
        self.assertNotEqual(http_response.id, None)

    def test_cache(self):
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

    def test_qs_params(self):
        url = URL(get_moth_http('/audit/xss/simple_xss.py?text=123456abc'))
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn('123456abc', http_response.body)

        url = URL(get_moth_http('/audit/xss/simple_xss.py?text=root:x:0'))
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn('root:x:0', http_response.body)

    def test_POST(self):
        url = URL(get_moth_http('/audit/xss/simple_xss_form.py'))

        data = URLEncodedForm()
        data['text'] = ['123456abc']

        http_response = self.uri_opener.POST(url, data, cache=False)
        self.assertIn('123456abc', http_response.body)

    def test_POST_special_chars(self):
        url = URL(get_moth_http('/audit/xss/simple_xss_form.py'))
        test_data = u'abc<def>"-á-'

        data = URLEncodedForm()
        data['text'] = [test_data]

        http_response = self.uri_opener.POST(url, data, cache=False)
        self.assertIn(test_data, http_response.body)

    def test_unknown_url(self):
        url = URL('http://longsitethatdoesnotexistfoo.com/')
        self.assertRaises(ScanMustStopOnUrlError, self.uri_opener.GET, url)

    def test_url_port_closed(self):
        # TODO: Change 2312 by an always closed/non-http port
        url = URL('http://127.0.0.1:2312/')
        self.assertRaises(ScanMustStopOnUrlError, self.uri_opener.GET, url)

    def test_url_port_not_http(self):
        upper_daemon = UpperDaemon(EmptyTCPHandler)
        upper_daemon.start()
        upper_daemon.wait_for_start()

        port = upper_daemon.get_port()

        url = URL('http://127.0.0.1:%s/' % port)
        self.assertRaises(ScanMustStopOnUrlError, self.uri_opener.GET, url)

    def test_url_port_not_http_many(self):
        upper_daemon = UpperDaemon(EmptyTCPHandler)
        upper_daemon.start()
        upper_daemon.wait_for_start()

        port = upper_daemon.get_port()

        url = URL('http://127.0.0.1:%s/' % port)
        for _ in xrange(MAX_ERROR_COUNT):
            try:
                self.uri_opener.GET(url)
            except ScanMustStopByUnknownReasonExc:
                self.assertTrue(False, 'Not expecting this exception type.')
            except ScanMustStopOnUrlError:
                self.assertTrue(True)
            except ScanMustStopException:
                self.assertTrue(True)
                break
        else:
            self.assertTrue(False)

    def test_timeout(self):
        upper_daemon = UpperDaemon(TimeoutTCPHandler)
        upper_daemon.start()
        upper_daemon.wait_for_start()

        port = upper_daemon.get_port()

        url = URL('http://127.0.0.1:%s/' % port)

        self.uri_opener.settings.set_timeout(1)

        self.assertRaises(ScanMustStopOnUrlError, self.uri_opener.GET, url)

        self.uri_opener.settings.set_default_values()

    def test_timeout_many(self):
        upper_daemon = UpperDaemon(TimeoutTCPHandler)
        upper_daemon.start()
        upper_daemon.wait_for_start()

        port = upper_daemon.get_port()

        self.uri_opener.settings.set_timeout(1)

        url = URL('http://127.0.0.1:%s/' % port)

        for _ in xrange(MAX_ERROR_COUNT):
            try:
                self.uri_opener.GET(url)
            except ScanMustStopByUnknownReasonExc:
                self.assertTrue(False, 'Not expecting this exception type.')
            except ScanMustStopOnUrlError:
                self.assertTrue(True)
            except ScanMustStopException:
                self.assertTrue(True)
                break
        else:
            self.assertTrue(False)

        self.uri_opener.settings.set_default_values()

    def test_ignore_errors(self):
        upper_daemon = UpperDaemon(TimeoutTCPHandler)
        upper_daemon.start()
        upper_daemon.wait_for_start()

        port = upper_daemon.get_port()

        self.uri_opener.settings.set_timeout(1)
        self.uri_opener._retry = Mock()

        url = URL('http://127.0.0.1:%s/' % port)

        try:
            self.uri_opener.GET(url, ignore_errors=True)
        except ScanMustStopOnUrlError:
            self.assertEqual(self.uri_opener._retry.call_count, 0)
        else:
            self.assertTrue(False, 'Exception not raised')

        self.uri_opener.settings.set_default_values()

    def test_stop(self):
        self.uri_opener.stop()
        url = URL(get_moth_http())
        self.assertRaises(ScanMustStopByUserRequest, self.uri_opener.GET, url)

    def test_pause_stop(self):
        self.uri_opener.pause(True)
        self.uri_opener.stop()
        url = URL(get_moth_http())
        self.assertRaises(ScanMustStopByUserRequest, self.uri_opener.GET, url)

    def test_pause(self):
        output = Queue.Queue()
        self.uri_opener.pause(True)

        def send(uri_opener, output):
            url = URL(get_moth_http())
            try:
                http_response = uri_opener.GET(url)
                output.put(http_response)
            except:
                output.put(None)

        th = Process(target=send, args=(self.uri_opener, output))
        th.daemon = True
        th.start()

        self.assertRaises(Queue.Empty, output.get, True, 2)

    def test_pause_unpause(self):
        output = Queue.Queue()
        self.uri_opener.pause(True)

        def send(uri_opener, output):
            url = URL(get_moth_http())
            try:
                http_response = uri_opener.GET(url)
                output.put(http_response)
            except:
                output.put(None)

        th = Process(target=send, args=(self.uri_opener, output))
        th.daemon = True
        th.start()

        self.assertRaises(Queue.Empty, output.get, True, 2)

        self.uri_opener.pause(False)

        http_response = output.get()
        self.assertNotIsInstance(http_response, types.NoneType,
                                 'Error in send thread.')

        th.join()

        self.assertEqual(http_response.get_code(), 200)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

    def test_removes_cache(self):
        url = URL(get_moth_http())
        self.uri_opener.GET(url, cache=False)

        # Please note that this line, together with the tearDown() act as
        # a test for a "double call to end()".
        self.uri_opener.end()

        db_fmt = 'db_unittest-%s'
        trace_fmt = 'db_unittest-%s_traces/'
        temp_dir = get_temp_dir()

        for i in xrange(100):
            test_db_path = os.path.join(temp_dir, db_fmt % i)
            test_trace_path = os.path.join(temp_dir, trace_fmt % i)
            self.assertFalse(os.path.exists(test_db_path), test_db_path)
            self.assertFalse(os.path.exists(test_trace_path), test_trace_path)

    def test_special_char_header(self):
        url = URL(get_moth_http('/core/headers/echo-headers.py'))
        header_content = u'name=ábc'
        headers = Headers([('Cookie', header_content)])
        http_response = self.uri_opener.GET(url, cache=False, headers=headers)
        self.assertIn(header_content, http_response.body)
Exemple #3
0
class TestXUrllib(unittest.TestCase):

    MOTH_MESSAGE = '<title>moth: vulnerable web application</title>'

    def setUp(self):
        self.uri_opener = ExtendedUrllib()

    def tearDown(self):
        self.uri_opener.end()

    def test_basic(self):
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url, cache=False)

        self.assertIn(self.MOTH_MESSAGE, http_response.body)

        self.assertGreaterEqual(http_response.id, 1)
        self.assertNotEqual(http_response.id, None)

    def test_cache(self):
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

    def test_qs_params(self):
        url = URL(get_moth_http('/audit/xss/simple_xss.py?text=123456abc'))
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn('123456abc', http_response.body)

        url = URL(get_moth_http('/audit/xss/simple_xss.py?text=root:x:0'))
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn('root:x:0', http_response.body)

    def test_post(self):
        url = URL(get_moth_http('/audit/xss/simple_xss_form.py'))

        data = URLEncodedForm()
        data['text'] = ['123456abc']

        http_response = self.uri_opener.POST(url, data, cache=False)
        self.assertIn('123456abc', http_response.body)

    def test_post_special_chars(self):
        url = URL(get_moth_http('/audit/xss/simple_xss_form.py'))
        test_data = u'abc<def>"-á-'

        data = URLEncodedForm()
        data['text'] = [test_data]

        http_response = self.uri_opener.POST(url, data, cache=False)
        self.assertIn(test_data, http_response.body)

    def test_unknown_domain(self):
        url = URL('http://longsitethatdoesnotexistfoo.com/')
        self.assertRaises(HTTPRequestException, self.uri_opener.GET, url)

    def test_file_proto(self):
        url = URL('file://foo/bar.txt')
        self.assertRaises(HTTPRequestException, self.uri_opener.GET, url)

    def test_url_port_closed(self):
        # TODO: Change 2312 by an always closed/non-http port
        url = URL('http://127.0.0.1:2312/')
        self.assertRaises(HTTPRequestException, self.uri_opener.GET, url)

    def test_url_port_not_http(self):
        upper_daemon = UpperDaemon(EmptyTCPHandler)
        upper_daemon.start()
        upper_daemon.wait_for_start()

        port = upper_daemon.get_port()

        url = URL('http://127.0.0.1:%s/' % port)

        try:
            self.uri_opener.GET(url)
        except HTTPRequestException, hre:
            self.assertEqual(hre.value, "Bad HTTP response status line: ''")
        else:
Exemple #4
0
class TestXUrllib(unittest.TestCase):

    MOTH_MESSAGE = '<title>moth: vulnerable web application</title>'
    MOCK_URL = 'http://www.w3af.org/'

    def setUp(self):
        self.uri_opener = ExtendedUrllib()

    def tearDown(self):
        self.uri_opener.end()
        httpretty.reset()

    def test_basic(self):
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url, cache=False)

        self.assertIn(self.MOTH_MESSAGE, http_response.body)

        self.assertGreaterEqual(http_response.id, 1)
        self.assertNotEqual(http_response.id, None)

    def test_basic_ssl(self):
        url = URL(get_moth_https())
        http_response = self.uri_opener.GET(url, cache=False)

        self.assertIn(self.MOTH_MESSAGE, http_response.body)

        self.assertGreaterEqual(http_response.id, 1)
        self.assertNotEqual(http_response.id, None)

    def test_cache(self):
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

    def test_qs_params(self):
        url = URL(get_moth_http('/audit/xss/simple_xss.py?text=123456abc'))
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn('123456abc', http_response.body)

        url = URL(get_moth_http('/audit/xss/simple_xss.py?text=root:x:0'))
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn('root:x:0', http_response.body)

    @httpretty.activate
    def test_GET_with_post_data(self):
        httpretty.register_uri(httpretty.GET,
                               self.MOCK_URL,
                               body=self.MOTH_MESSAGE,
                               status=200)

        mock_url = URL(self.MOCK_URL)
        data = 'abc=123&def=456'
        response = self.uri_opener.GET(mock_url, data=data)

        # Check the response
        self.assertEqual(response.get_code(), 200)
        self.assertEqual(response.get_body(), self.MOTH_MESSAGE)

        # And use httpretty to check the request
        self.assertEqual(httpretty.last_request().method, 'GET')

        request_headers = httpretty.last_request().headers
        self.assertIn('content-length', request_headers)
        self.assertEqual(str(len(data)), request_headers['content-length'])

        self.assertEqual(httpretty.last_request().body, data)
        self.assertEqual(httpretty.last_request().path, '/')

    @httpretty.activate
    def test_GET_with_post_data_and_qs(self):
        httpretty.register_uri(httpretty.GET,
                               self.MOCK_URL,
                               body=self.MOTH_MESSAGE,
                               status=200)

        qs = '?qs=1'
        mock_url = URL(self.MOCK_URL + qs)
        data = 'abc=123&def=456'
        response = self.uri_opener.GET(mock_url, data=data)

        # Check the response
        self.assertEqual(response.get_code(), 200)
        self.assertEqual(response.get_body(), self.MOTH_MESSAGE)

        # And use httpretty to check the request
        self.assertEqual(httpretty.last_request().method, 'GET')

        request_headers = httpretty.last_request().headers
        self.assertIn('content-length', request_headers)
        self.assertEqual(str(len(data)), request_headers['content-length'])

        self.assertEqual(httpretty.last_request().body, data)
        self.assertEqual(httpretty.last_request().path, '/' + qs)

    def test_post(self):
        url = URL(get_moth_http('/audit/xss/simple_xss_form.py'))

        data = URLEncodedForm()
        data['text'] = ['123456abc']

        http_response = self.uri_opener.POST(url, data, cache=False)
        self.assertIn('123456abc', http_response.body)

    def test_post_special_chars(self):
        url = URL(get_moth_http('/audit/xss/simple_xss_form.py'))
        test_data = u'abc<def>"-á-'

        data = URLEncodedForm()
        data['text'] = [test_data]

        http_response = self.uri_opener.POST(url, data, cache=False)
        self.assertIn(test_data, http_response.body)

    def test_unknown_domain(self):
        url = URL('http://longsitethatdoesnotexistfoo.com/')
        self.assertRaises(HTTPRequestException, self.uri_opener.GET, url)

    def test_file_proto(self):
        url = URL('file://foo/bar.txt')
        self.assertRaises(HTTPRequestException, self.uri_opener.GET, url)

    def test_url_port_closed(self):
        # TODO: Change 2312 by an always closed/non-http port
        url = URL('http://127.0.0.1:2312/')
        self.assertRaises(HTTPRequestException, self.uri_opener.GET, url)

    def test_url_port_not_http(self):
        upper_daemon = UpperDaemon(EmptyTCPHandler)
        upper_daemon.start()
        upper_daemon.wait_for_start()

        port = upper_daemon.get_port()

        url = URL('http://127.0.0.1:%s/' % port)

        try:
            self.uri_opener.GET(url)
        except HTTPRequestException, hre:
            self.assertEqual(hre.value, "Bad HTTP response status line: ''")
        else:
Exemple #5
0
class TestExtendedUrllibProxy(unittest.TestCase):

    MOTH_MESSAGE = '<title>moth: vulnerable web application</title>'

    def setUp(self):
        self.uri_opener = ExtendedUrllib()

        # Start the proxy daemon
        self._proxy = Proxy('127.0.0.2', 0, ExtendedUrllib(), ProxyHandler)
        self._proxy.start()
        self._proxy.wait_for_start()

        port = self._proxy.get_port()

        # Configure the proxy
        settings = OpenerSettings()
        options = settings.get_options()
        proxy_address_opt = options['proxy_address']
        proxy_port_opt = options['proxy_port']

        proxy_address_opt.set_value('127.0.0.2')
        proxy_port_opt.set_value(port)

        settings.set_options(options)
        self.uri_opener.settings = settings

    def tearDown(self):
        self.uri_opener.end()

    def test_http_default_port_via_proxy(self):
        # TODO: Write this test
        pass

    def test_http_port_specification_via_proxy(self):
        self.assertEqual(self._proxy.total_handled_requests, 0)

        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url, cache=False)

        self.assertIn(self.MOTH_MESSAGE, http_response.body)
        self.assertEqual(self._proxy.total_handled_requests, 1)

    def test_https_via_proxy(self):
        self.assertEqual(self._proxy.total_handled_requests, 0)

        url = URL(get_moth_https())
        http_response = self.uri_opener.GET(url, cache=False)

        self.assertIn(self.MOTH_MESSAGE, http_response.body)
        self.assertEqual(self._proxy.total_handled_requests, 1)

    def test_offline_port_via_proxy(self):
        url = URL('http://127.0.0.1:8181/')
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertEqual(http_response.get_code(), 500)
        self.assertIn('Connection refused', http_response.body)

    def test_POST_via_proxy(self):
        url = URL(get_moth_http('/audit/xss/simple_xss_form.py'))
        http_response = self.uri_opener.POST(url,
                                             data='text=123456abc',
                                             cache=False)
        self.assertIn('123456abc', http_response.body)
Exemple #6
0
class TestXUrllib(unittest.TestCase):

    MOTH_MESSAGE = '<title>moth: vulnerable web application</title>'
    MOCK_URL = 'http://www.w3af.org/'

    def setUp(self):
        self.uri_opener = ExtendedUrllib()

    def tearDown(self):
        self.uri_opener.end()
        httpretty.reset()

    def test_basic(self):
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url, cache=False)

        self.assertIn(self.MOTH_MESSAGE, http_response.body)

        self.assertGreaterEqual(http_response.id, 1)
        self.assertNotEqual(http_response.id, None)

    def test_basic_ssl(self):
        url = URL(get_moth_https())
        http_response = self.uri_opener.GET(url, cache=False)

        self.assertIn(self.MOTH_MESSAGE, http_response.body)

        self.assertGreaterEqual(http_response.id, 1)
        self.assertNotEqual(http_response.id, None)

    def test_github_ssl(self):
        url = URL(
            'https://raw.githubusercontent.com/RetireJS/retire.js/master/repository/jsrepository.json'
        )

        http_response = self.uri_opener.GET(url,
                                            cache=False,
                                            binary_response=True,
                                            respect_size_limit=False)

        self.assertIn('jquery', http_response.body)

        self.assertGreaterEqual(http_response.id, 1)
        self.assertNotEqual(http_response.id, None)

    def test_cache(self):
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

    def test_qs_params(self):
        url = URL(get_moth_http('/audit/xss/simple_xss.py?text=123456abc'))
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn('123456abc', http_response.body)

        url = URL(get_moth_http('/audit/xss/simple_xss.py?text=root:x:0'))
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertIn('root:x:0', http_response.body)

    @httpretty.activate
    def test_GET_with_post_data(self):
        httpretty.register_uri(httpretty.GET,
                               self.MOCK_URL,
                               body=self.MOTH_MESSAGE,
                               status=200)

        mock_url = URL(self.MOCK_URL)
        data = 'abc=123&def=456'
        response = self.uri_opener.GET(mock_url, data=data)

        # Check the response
        self.assertEqual(response.get_code(), 200)
        self.assertEqual(response.get_body(), self.MOTH_MESSAGE)

        # And use httpretty to check the request
        self.assertEqual(httpretty.last_request().method, 'GET')

        request_headers = httpretty.last_request().headers
        self.assertIn('content-length', request_headers)
        self.assertEqual(str(len(data)), request_headers['content-length'])

        self.assertEqual(httpretty.last_request().body, data)
        self.assertEqual(httpretty.last_request().path, '/')

    @httpretty.activate
    def test_GET_with_post_data_and_qs(self):
        httpretty.register_uri(httpretty.GET,
                               self.MOCK_URL,
                               body=self.MOTH_MESSAGE,
                               status=200)

        qs = '?qs=1'
        mock_url = URL(self.MOCK_URL + qs)
        data = 'abc=123&def=456'
        response = self.uri_opener.GET(mock_url, data=data)

        # Check the response
        self.assertEqual(response.get_code(), 200)
        self.assertEqual(response.get_body(), self.MOTH_MESSAGE)

        # And use httpretty to check the request
        self.assertEqual(httpretty.last_request().method, 'GET')

        request_headers = httpretty.last_request().headers
        self.assertIn('content-length', request_headers)
        self.assertEqual(str(len(data)), request_headers['content-length'])

        self.assertEqual(httpretty.last_request().body, data)
        self.assertEqual(httpretty.last_request().path, '/' + qs)

    def test_post(self):
        url = URL(get_moth_http('/audit/xss/simple_xss_form.py'))

        data = URLEncodedForm()
        data['text'] = ['123456abc']

        http_response = self.uri_opener.POST(url, data, cache=False)
        self.assertIn('123456abc', http_response.body)

    def test_post_special_chars(self):
        url = URL(get_moth_http('/audit/xss/simple_xss_form.py'))
        test_data = u'abc<def>"-á-'

        data = URLEncodedForm()
        data['text'] = [test_data]

        http_response = self.uri_opener.POST(url, data, cache=False)
        self.assertIn(test_data, http_response.body)

    def test_unknown_domain(self):
        url = URL('http://longsitethatdoesnotexistfoo.com/')
        self.assertRaises(HTTPRequestException, self.uri_opener.GET, url)

    def test_file_proto(self):
        url = URL('file://foo/bar.txt')
        self.assertRaises(HTTPRequestException, self.uri_opener.GET, url)

    def test_url_port_closed(self):
        # TODO: Change 2312 by an always closed/non-http port
        url = URL('http://127.0.0.1:2312/')
        self.assertRaises(HTTPRequestException, self.uri_opener.GET, url)

    def test_url_port_not_http(self):
        upper_daemon = UpperDaemon(EmptyTCPHandler)
        upper_daemon.start()
        upper_daemon.wait_for_start()

        port = upper_daemon.get_port()

        url = URL('http://127.0.0.1:%s/' % port)

        try:
            self.uri_opener.GET(url)
        except HTTPRequestException as hre:
            self.assertEqual(hre.value, "Bad HTTP response status line: ''")
        else:
            self.assertTrue(False, 'Expected HTTPRequestException.')

    def test_url_port_not_http_many(self):
        upper_daemon = UpperDaemon(EmptyTCPHandler)
        upper_daemon.start()
        upper_daemon.wait_for_start()

        port = upper_daemon.get_port()

        self.uri_opener.settings.set_max_http_retries(0)

        url = URL('http://127.0.0.1:%s/' % port)
        http_request_e = 0
        scan_must_stop_e = 0

        for _ in xrange(MAX_ERROR_COUNT):
            try:
                self.uri_opener.GET(url)
            except HTTPRequestException:
                http_request_e += 1
            except ScanMustStopException as smse:
                scan_must_stop_e += 1
                break
            except Exception as e:
                msg = 'Not expecting "%s".'
                self.assertTrue(False, msg % e.__class__.__name__)

        self.assertEqual(scan_must_stop_e, 1)
        self.assertEqual(http_request_e, 9)

    def test_get_wait_time(self):
        """
        Asserts that all the responses coming out of the extended urllib have a
        get_wait_time different from the default.
        """
        url = URL(get_moth_http())
        http_response = self.uri_opener.GET(url, cache=False)
        self.assertNotEqual(http_response.get_wait_time(), DEFAULT_WAIT_TIME)

    def test_ssl_tls_1_0(self):
        ssl_daemon = RawSSLDaemon(Ok200Handler, ssl_version=ssl.PROTOCOL_TLSv1)
        ssl_daemon.start()
        ssl_daemon.wait_for_start()

        port = ssl_daemon.get_port()

        url = URL('https://127.0.0.1:%s/' % port)

        resp = self.uri_opener.GET(url)
        self.assertEqual(resp.get_body(), Ok200Handler.body)

    def test_ssl_v23(self):
        # https://bugs.kali.org/view.php?id=2160
        if not hasattr(ssl, 'PROTOCOL_SSLv23'):
            return

        ssl_daemon = RawSSLDaemon(Ok200Handler,
                                  ssl_version=ssl.PROTOCOL_SSLv23)
        ssl_daemon.start()
        ssl_daemon.wait_for_start()

        port = ssl_daemon.get_port()

        url = URL('https://127.0.0.1:%s/' % port)

        resp = self.uri_opener.GET(url)
        self.assertEqual(resp.get_body(), Ok200Handler.body)

    def test_ssl_v3(self):
        # https://bugs.kali.org/view.php?id=2160
        if not hasattr(ssl, 'PROTOCOL_SSLv3'):
            return

        # pylint: disable=E1101
        ssl_daemon = RawSSLDaemon(Ok200Handler, ssl_version=ssl.PROTOCOL_SSLv3)
        ssl_daemon.start()
        ssl_daemon.wait_for_start()
        # pylint: disable=E1101

        port = ssl_daemon.get_port()

        url = URL('https://127.0.0.1:%s/' % port)

        resp = self.uri_opener.GET(url)
        self.assertEqual(resp.get_body(), Ok200Handler.body)

    @attr('internet')
    @attr('ci_fails')
    def test_ssl_sni(self):
        """
        Test is our HTTP client supports SSL SNI
        """
        url = URL('https://sni.velox.ch/')

        resp = self.uri_opener.GET(url)
        self.assertIn('<strong>Great!', resp.get_body())

    def test_ssl_fail_when_requesting_http(self):
        http_daemon = UpperDaemon(Ok200Handler)
        http_daemon.start()
        http_daemon.wait_for_start()

        port = http_daemon.get_port()

        # Note that here I'm using httpS <<---- "S" and that I've started an
        # HTTP server. We should get an exception
        url = URL('https://127.0.0.1:%s/' % port)

        self.assertRaises(HTTPRequestException, self.uri_opener.GET, url)

    def test_ssl_fail_when_requesting_moth_http(self):
        """
        https://github.com/andresriancho/w3af/issues/7989

        This test takes considerable time to run since it needs to timeout the
        SSL connection for each SSL protocol
        """
        # Note that here I'm using httpS <<---- "S" and that I'm connecting to
        # the net location (host:port) of an HTTP server.
        http_url = URL(get_moth_http())
        test_url = URL('https://%s' % http_url.get_net_location())

        self.uri_opener.settings.set_max_http_retries(0)

        self.assertRaises(HTTPRequestException,
                          self.uri_opener.GET,
                          test_url,
                          timeout=1)

    def test_stop(self):
        self.uri_opener.stop()
        url = URL(get_moth_http())
        self.assertRaises(ScanMustStopByUserRequest, self.uri_opener.GET, url)

    def test_pause_stop(self):
        self.uri_opener.pause(True)
        self.uri_opener.stop()
        url = URL(get_moth_http())
        self.assertRaises(ScanMustStopByUserRequest, self.uri_opener.GET, url)

    def test_pause(self):
        output = Queue.Queue()
        self.uri_opener.pause(True)

        def send(uri_opener, output):
            url = URL(get_moth_http())
            try:
                http_response = uri_opener.GET(url)
                output.put(http_response)
            except:
                output.put(None)

        th = Process(target=send, args=(self.uri_opener, output))
        th.daemon = True
        th.start()

        self.assertRaises(Queue.Empty, output.get, True, 2)

    def test_pause_unpause(self):
        output = Queue.Queue()
        self.uri_opener.pause(True)

        def send(uri_opener, output):
            url = URL(get_moth_http())
            try:
                http_response = uri_opener.GET(url)
                output.put(http_response)
            except:
                output.put(None)

        th = Process(target=send, args=(self.uri_opener, output))
        th.daemon = True
        th.start()

        self.assertRaises(Queue.Empty, output.get, True, 2)

        self.uri_opener.pause(False)

        http_response = output.get()
        self.assertNotIsInstance(http_response, types.NoneType,
                                 'Error in send thread.')

        th.join()

        self.assertEqual(http_response.get_code(), 200)
        self.assertIn(self.MOTH_MESSAGE, http_response.body)

    def test_removes_cache(self):
        url = URL(get_moth_http())
        self.uri_opener.GET(url, cache=False)

        # Please note that this line, together with the tearDown() act as
        # a test for a "double call to end()".
        self.uri_opener.end()

        db_fmt = 'db_unittest-%s'
        trace_fmt = 'db_unittest-%s_traces/'
        temp_dir = get_temp_dir()

        for i in xrange(100):
            test_db_path = os.path.join(temp_dir, db_fmt % i)
            test_trace_path = os.path.join(temp_dir, trace_fmt % i)
            self.assertFalse(os.path.exists(test_db_path), test_db_path)
            self.assertFalse(os.path.exists(test_trace_path), test_trace_path)

    def test_special_char_header(self):
        url = URL(get_moth_http('/core/headers/echo-headers.py'))
        header_content = u'name=ábc'
        headers = Headers([('Cookie', header_content)])
        http_response = self.uri_opener.GET(url, cache=False, headers=headers)
        self.assertIn(header_content, http_response.body)

    def test_bad_file_descriptor_8125_local(self):
        """
        8125 is basically an issue with the way HTTP SSL connections handle the
        Connection: Close header.

        :see: https://github.com/andresriancho/w3af/issues/8125
        """
        raw_http_response = ('HTTP/1.1 200 Ok\r\n'
                             'Connection: close\r\n'
                             'Content-Type: text/html\r\n'
                             'Content-Length: 3\r\n\r\nabc')
        certfile = os.path.join(ROOT_PATH, 'plugins', 'tests', 'audit',
                                'certs', 'invalid_cert.pem')
        port = get_unused_port()

        s = SSLServer('localhost',
                      port,
                      certfile,
                      http_response=raw_http_response)
        s.start()

        body = 'abc'
        mock_url = 'https://localhost:%s/' % port
        url = URL(mock_url)
        http_response = self.uri_opener.GET(url, cache=False)

        self.assertEqual(body, http_response.body)
        s.stop()

        # This error is expected, it's generated when the xurllib negotiates
        # the different SSL protocols with the server
        self.assertEqual(set([e.strerror for e in s.errors]),
                         {'Bad file descriptor'})

    def test_rate_limit_high(self):
        self.rate_limit_generic(500, 0.009, 0.4)

    def test_rate_limit_low(self):
        self.rate_limit_generic(1, 1, 2.2)

    def test_rate_limit_zero(self):
        self.rate_limit_generic(0, 0.005, 0.4)

    @httpretty.activate
    def rate_limit_generic(self, max_requests_per_second, _min, _max):
        mock_url = 'http://mock/'
        url = URL(mock_url)
        httpretty.register_uri(httpretty.GET, mock_url, body='Body')

        start_time = time.time()

        with patch.object(self.uri_opener.settings,
                          'get_max_requests_per_second') as mrps_mock:
            mrps_mock.return_value = max_requests_per_second

            self.uri_opener.GET(url, cache=False)
            self.uri_opener.GET(url, cache=False)

        httpretty.reset()

        end_time = time.time()
        elapsed_time = end_time - start_time
        self.assertGreaterEqual(elapsed_time, _min)
        self.assertLessEqual(elapsed_time, _max)
Exemple #7
0
class TestMultipartPostUpload(unittest.TestCase):
    """
    In the new architecture I've been working on, the HTTP requests are almost
    completely created by serializing two objects:
        * FuzzableRequest
        * DataContainer (stored in FuzzableRequest._post_data)

    There is a special DataContainer sub-class for MultipartPost file uploads
    called MultipartContainer, which holds variables and files and when
    serialized will be encoded as multipart.

    These test cases try to make sure that the file upload feature works by
    sending a POST request with a MultipartContainer to moth.
    """
    MOTH_FILE_UP_URL = URL(get_moth_http('/core/file_upload/upload.py'))

    def setUp(self):
        self.opener = ExtendedUrllib()

    def tearDown(self):
        self.opener.end()

    def test_multipart_without_file(self):
        form_params = FormParameters()
        form_params.add_field_by_attr_items([('name', 'uploadedfile')])
        form_params['uploadedfile'][0] = 'this is not a file'
        form_params.add_field_by_attr_items([('name', 'MAX_FILE_SIZE'),
                                             ('type', 'hidden'),
                                             ('value', '10000')])

        mpc = MultipartContainer(form_params)

        resp = self.opener.POST(self.MOTH_FILE_UP_URL,
                                data=str(mpc),
                                headers=Headers(mpc.get_headers()))

        self.assertNotIn('was successfully uploaded', resp.get_body())

    def test_file_upload(self):
        temp = tempfile.mkstemp(suffix=".tmp")
        os.write(temp[0], 'file content')

        _file = open(temp[1], "rb")
        self.upload_file(_file)

    def test_stringio_upload(self):
        _file = NamedStringIO('file content', name='test.txt')
        self.upload_file(_file)

    def upload_file(self, _file):
        form_params = FormParameters()
        form_params.add_field_by_attr_items([('name', 'uploadedfile')])
        form_params.add_field_by_attr_items([('name', 'MAX_FILE_SIZE'),
                                             ('type', 'hidden'),
                                             ('value', '10000')])

        mpc = MultipartContainer(form_params)
        mpc['uploadedfile'][0] = _file

        resp = self.opener.POST(self.MOTH_FILE_UP_URL,
                                data=str(mpc),
                                headers=Headers(mpc.get_headers()))

        self.assertIn('was successfully uploaded', resp.get_body())

    def test_upload_file_using_fuzzable_request(self):
        form_params = FormParameters()
        form_params.add_field_by_attr_items([('name', 'uploadedfile')])
        form_params['uploadedfile'][0] = NamedStringIO('file content',
                                                       name='test.txt')
        form_params.add_field_by_attr_items([('name', 'MAX_FILE_SIZE'),
                                             ('type', 'hidden'),
                                             ('value', '10000')])

        mpc = MultipartContainer(form_params)

        freq = FuzzableRequest(self.MOTH_FILE_UP_URL,
                               post_data=mpc,
                               method='POST')

        resp = self.opener.send_mutant(freq)

        self.assertIn('was successfully uploaded', resp.get_body())