Beispiel #1
0
class TestFoundHttpsAFD(TestFoundAFD):

    target_url = 'https://httpretty/'

    MOCK_RESPONSES = [MockResponse(target_url, 'Home page'),
                      MockResponse(BAD_SIG_URI, 'Blocked by WAF'),
                      MockResponse(re.compile(target_url + '.*'), 'Another page')]
Beispiel #2
0
class TestJSONDoblequotesFiltered(PluginTest):

    target_url = 'http://json-filtered/?q=rfd'

    MOCK_RESPONSES = [
              MockResponse(url='http://json-filtered/%3B/w3af.cmd%3B/w3af.cmd?q=rfd',
                           body='message "w3afExecToken"',
                           content_type='text/json',
                           method='GET', status=200),
              MockResponse(url='http://json-filtered/%3B/w3af.cmd%3B/w3af.cmd?'
                               'q=w3afExecToken',
                           body='    {"a":"w3afExecToken","b":"b"}',
                           content_type='text/json',
                           method='GET', status=200),
              MockResponse(url='http://json-filtered/%3B/w3af.cmd%3B/w3af.cmd?'
                               'q=w3afExecToken%22%26%7C%0A',
                           body='    {"a":"w3afExecToken&|\n","b":"b"}',
                           content_type='application/javascript',
                           method='GET', status=200),
              ]

    def test_not_found_json(self):
        cfg = RUN_CONFIG['cfg']
        self._scan(self.target_url, cfg['plugins'])
        vulns = self.kb.get('rfd', 'rfd')
        self.assertEquals(0, len(vulns))
class TestGlobalRedirectBasic(PluginTest):

    target_url = 'http://httpretty'

    MOCK_RESPONSES = [
        MockResponse('http://httpretty/',
                     '<a href="/redir?target=">redirect</a>'),
        MockResponse('http://httpretty/redir?target=', 'No redirect'),
        MockResponse('http://httpretty/redir?target=http://www.w3af.org/',
                     status=302,
                     headers={'Location': 'https://www.w3af.org/'},
                     body='')
    ]

    def test_original_response_has_no_redirect(self):
        cfg = SCAN_CONFIG['cfg']
        cfg['target'] = self.target_url

        self._scan(cfg['target'], cfg['plugins'])

        vulns = self.kb.get('global_redirect', 'global_redirect')
        expected = [('redir', 'target')]

        self.assertAllVulnNamesEqual('Insecure redirection', vulns)
        self.assertExpectedVulnsFound(expected, vulns)
Beispiel #4
0
class TestJSONP(PluginTest):

    target_url = 'http://jsonp/?callback=rfd'

    MOCK_RESPONSES = [
        MockResponse(url='http://jsonp/%3B/w3af.cmd%3B/w3af.cmd?callback'
                     '=rfd',
                     body='    rfd({ "Result": '
                     '{ "Timestamp": 1417601045 } }) ',
                     content_type='application/javascript',
                     method='GET',
                     status=200),
        MockResponse(url='http://jsonp/%3B/w3af.cmd%3B/w3af.cmd?callback'
                     '=w3afExecToken',
                     body='    w3afExecToken({ "Result": '
                     '{ "Timestamp": 1417601045 } }) ',
                     content_type='application/javascript',
                     method='GET',
                     status=200),
    ]

    def test_found_jsonp(self):
        cfg = RUN_CONFIG['cfg']
        self._scan(self.target_url, cfg['plugins'])
        vulns = self.kb.get('rfd', 'rfd')
        self.assertEquals(1, len(vulns))
class TestGlobalRedirectBasicWithMetaRedir(PluginTest):

    target_url = 'http://httpretty'

    MOCK_RESPONSES = [
        MockResponse('http://httpretty/',
                     '<a href="/redir?target=">redirect</a>'),
        MockResponse('http://httpretty/redir?target=',
                     '<meta http-equiv="refresh" content="0; url=">'),
        MockResponse(
            'http://httpretty/redir?target=http://www.w3af.org/',
            body=
            '<meta http-equiv="refresh" content="0; url=http://www.w3af.org/">'
        )
    ]

    def test_original_response_has_meta_redirect(self):
        cfg = SCAN_CONFIG['cfg']
        cfg['target'] = self.target_url

        self._scan(cfg['target'], cfg['plugins'])

        vulns = self.kb.get('global_redirect', 'global_redirect')
        expected = [('redir', 'target')]

        self.assertAllVulnNamesEqual('Insecure redirection', vulns)
        self.assertExpectedVulnsFound(expected, vulns)
class TestSerializedObjectIntegration(PluginTest):

    target_url = 'http://mock/'

    html = ('<form action="/form" method="GET">'
            '<input type="hidden" name="viewstate" value="%s">'
            '</form>'
            % base64.b64encode(SERIALIZED_PHP_OBJECTS[0]))

    MOCK_RESPONSES = [MockResponse(url='http://mock/',
                                   body=html,
                                   method='GET', status=200),

                      MockResponse(url='http://mock/form',
                                   body='Ok',
                                   method='GET', status=200)]

    def test_vuln_found(self):
        self._scan(self.target_url, RUN_CONFIGS['cfg']['plugins'])

        vulns = self.kb.get('serialized_object',
                            'serialized_object')

        expected_vulns = {('Serialized object',
                           u'A total of 1 HTTP requests contained a serialized object'
                           u' in the parameter with name "viewstate". The first ten'
                           u' matching URLs are:\n - http://mock/form\n')}

        vulns_set = set()

        for vuln in vulns:
            desc = vuln.get_desc(with_id=False)
            vulns_set.add((vuln.get_name(), desc))

        self.assertEqual(expected_vulns, vulns_set)
Beispiel #7
0
class TestDeadLock(PluginTest):
    """
    This test reproduces a lock that I've found while debugging #5834, as far as
    I know, it has nothing to do with #5834 itself.

    I tried, but was unable to make this test fail when the dead-lock is found,
    instead when the dead-lock is found the test will "hang", CI will timeout,
    and in your workstation you'll have to manually kill it.
    """
    target_url = 'http://mock/'

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {
                'crawl': (PluginConfig('web_spider'), )
            }
        }
    }

    TEST_ROOT = os.path.join(ROOT_PATH, 'plugins', 'tests', 'crawl',
                             'web_spider', '5834')

    INDEX_HTML = file(os.path.join(TEST_ROOT, 'index.html')).read()

    MOCK_RESPONSES = [
        MockResponse('http://mock/', INDEX_HTML),
        MockResponse('http://mock/', 'Thanks.', method='POST')
    ]

    def test_no_lock(self):
        cfg = self._run_configs['cfg']
        self._scan(cfg['target'], cfg['plugins'])
Beispiel #8
0
class TestAFDShortResponses(PluginTest):

    target_url = 'http://httpretty/'

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {'infrastructure': (PluginConfig('afd'),)}
        }
    }

    MOCK_RESPONSES = [MockResponse(target_url, 'hello world'),
                      MockResponse(BAD_SIG_URI, MOD_SECURITY_ANSWER, status=403),
                      MockResponse(re.compile(target_url + '\?.*'), 'hello world')]

    def test_afd_found(self):
        cfg = self._run_configs['cfg']
        self._scan(self.target_url, cfg['plugins'])

        infos = self.kb.get('afd', 'afd')

        self.assertEqual(len(infos), 1, infos)
        info = infos[0]

        self.assertEqual(info.get_name(), 'Active filter detected')
        values = [u.url_string.split('=')[1] for u in info['filtered']]

        self.assertIn('../../../../etc/passwd', set(values), values)
Beispiel #9
0
class TestFoundHttpsAFD(TestFoundAFD):
    target_url = 'https://httpretty/'

    MOCK_RESPONSES = [
        MockResponse(target_url, 'PASS'),
        MockResponse(BAD_SIG_URI, 'FAIL')
    ]
Beispiel #10
0
class TestFoundAFD(PluginTest):

    target_url = 'http://httpretty/'

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {
                'infrastructure': (PluginConfig('afd'), )
            }
        }
    }

    MOCK_RESPONSES = [
        MockResponse('/', 'PASS'),
        MockResponse(BAD_SIG_URI, 'FAIL')
    ]

    def test_afd_found_http(self):
        cfg = self._run_configs['cfg']
        self._scan(self.target_url, cfg['plugins'])

        infos = self.kb.get('afd', 'afd')

        self.assertEqual(len(infos), 1, infos)
        info = infos[0]

        self.assertEqual(info.get_name(), 'Active filter detected')
        values = [u.url_string.split('=')[1] for u in info['filtered']]

        self.assertIn('../../../../etc/passwd', set(values), values)
Beispiel #11
0
class TestPaymentWebHookFinderPOST(PluginTest):
    target_url = 'http://httpretty/'

    MOCK_RESPONSES = [
        MockResponse('http://httpretty/',
                     body='index home page',
                     method='GET',
                     status=200),
        MockResponse('http://httpretty/cgi-bin/paymentsuccessful.cgi',
                     body='hidden',
                     method='POST',
                     status=200),
        MockResponse('http://httpretty/.*',
                     body='Not found',
                     method='POST',
                     status=404),
    ]

    _run_config = {
        'target': target_url,
        'plugins': {
            'crawl': (PluginConfig('payment_webhook_finder'), )
        }
    }

    def test_find_using_POST(self):
        fill_kb_with_cgi_urls(self.target_url, self.kb.add_url)

        self._scan(self._run_config['target'], self._run_config['plugins'])

        urls = self.kb.get_all_known_urls()
        urls = [url.url_string for url in urls]

        self.assertIn(self.target_url + 'cgi-bin/paymentsuccessful.cgi', urls)
Beispiel #12
0
class TestUserDir(PluginTest):

    target_url = 'http://httpretty/'

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {'crawl': (PluginConfig('user_dir'),)}
        }
    }

    MOCK_RESPONSES = [MockResponse('/~www/', 'www user home directory.'),
                      MockResponse('/~kmem/', 'kmem user home directory.'),
                      MockResponse('/xfs/', 'home sweet home')]

    EXPECTED_RESULTS = {('Web user home directory', 'http://httpretty/~www/'),
                        ('Web user home directory', 'http://httpretty/~kmem/'),
                        ('Web user home directory', 'http://httpretty/xfs/'),
                        ('Identified installed application', 'http://httpretty/xfs/'),
                        ('Fingerprinted operating system', 'http://httpretty/~kmem/')}

    def test_fuzzer_user(self):
        # Don't enable dependencies
        self.w3afcore.plugins.resolve_dependencies = Mock()

        cfg = self._run_configs['cfg']
        self._scan(cfg['target'], cfg['plugins'])

        users = self.kb.get('user_dir', 'users')
        scan_results = set([(i.get_name(), i.get_url().url_string) for i in users])

        self.assertEqual(self.EXPECTED_RESULTS, scan_results)
Beispiel #13
0
class TestFormAuthFailedLoginMatchWithStaticLargeResponse(GenericFormAuthTest):

    target_url = u'http://w3af.org/'
    login_url = u'http://w3af.org/login'

    FORM = ('<form method="POST" action="/login">'
            '    <input name="username" type="text" />'
            '    <input name="password" type="password" />'
            '    <input name="submit" type="submit" />'
            '</form>')

    HEADER = 'abc <b>def</b> xyz'.join('\n' for _ in xrange(100))
    FOOTER = 'abc <b>def</b> xyz'.join('\n' for _ in xrange(100))

    def request_callback(self, request, uri, response_headers):
        response_headers['content-type'] = 'text/html'

        username = request.parsed_body.get('username', [''])[0]
        password = request.parsed_body.get('password', [''])[0]

        klass = TestFormAuthFailedLoginMatchWithStaticLargeResponse

        if username == 'admin' and password == 'admin':
            body = '%s\n%s\n%s' % (klass.HEADER,
                                   'Success, redirecting to the home page... <a href="/home">home<a>',
                                   klass.FOOTER)
        else:
            body = klass.HEADER + '\nFail\n' + klass.FOOTER

        return 200, response_headers, body

    MOCK_RESPONSES = [
              MockResponse(url=target_url,
                           body=FORM,
                           status=200,
                           method='GET',
                           content_type='text/html'),

              MockResponse(url=login_url,
                           body=request_callback,
                           method='POST',
                           content_type='text/html',
                           status=200),

    ]

    def test_found_credentials(self):
        self._scan(self.target_url, self.basic_config)

        # Assert the general results
        vulns = self.kb.get('form_auth', 'auth')
        self.assertEquals(len(vulns), 1)

        vuln = vulns[0]

        self.assertEquals(vuln.get_name(), 'Guessable credentials')
        self.assertEquals(vuln.get_url().url_string, self.login_url)
        self.assertEquals(vuln['user'], 'admin')
        self.assertEquals(vuln['pass'], 'admin')
Beispiel #14
0
class TestRetireJS(PluginTest):

    target_url = 'http://httpretty'

    # This is a vulnerable version of JQuery
    JQUERY_VULN = os.path.join(ROOT_PATH, 'plugins', 'tests', 'grep',
                               'retirejs', 'jquery.js')

    INDEX = '<html><script src="/js/jquery.js"></script></html>'

    MOCK_RESPONSES = [
        MockResponse('http://httpretty/', body=INDEX, method='GET',
                     status=200),
        MockResponse('http://httpretty/js/jquery.js',
                     body=file(JQUERY_VULN).read(),
                     method='GET',
                     status=200),
    ]

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {
                'grep': (PluginConfig('retirejs'), ),
                'crawl':
                (PluginConfig('web_spider',
                              ('only_forward', True, PluginConfig.BOOL)), )
            }
        }
    }

    def test_is_vulnerable_detected(self):
        cfg = self._run_configs['cfg']
        self._scan(cfg['target'], cfg['plugins'])

        vulns = self.kb.get('retirejs', 'js')

        self.assertEqual(len(vulns), 1, vulns)

        vuln = vulns[0]

        self.assertEqual(vuln.get_name(),
                         'Vulnerable JavaScript library in use')
        self.assertEqual(vuln.get_url().url_string,
                         'http://httpretty/js/jquery.js')

        expected_desc = (
            u'A JavaScript library with known vulnerabilities was'
            u' identified at http://httpretty/js/jquery.js. The'
            u' library was identified as "jquery" version 1.11.0'
            u' and has these known vulnerabilities:\n'
            u'\n'
            u' - 3rd party CORS request may execute\n'
            u' - parseHTML() executes scripts in event handlers\n'
            u'\n'
            u'Consider updating to the latest stable release of the'
            u' affected library.')
        self.assertEqual(vuln.get_desc(with_id=False), expected_desc)
Beispiel #15
0
class TestDetailedRedirect(PluginTest):

    target_url = 'http://mock/auth/'

    auth_url = URL(target_url + 'login_form.py')
    check_url = URL(target_url + 'verify.py')
    check_string = 'Logged in'
    data_format = '%u=%U&%p=%P&Login=Login'

    MOCK_RESPONSES = [
        MockResponse('http://mock/auth/login_form.py',
                     '',
                     status=302,
                     headers={'Location': '/confirm/?token=123'},
                     method='POST'),
        MockResponse('http://mock/confirm/?token=123',
                     'Login success',
                     status=302,
                     headers={'Location': '/auth/home.py'}),
        MockResponse('http://mock/auth/home.py', 'Home page'),
        MockResponse('http://mock/auth/verify.py', 'Not logged in')
    ]

    _run_config = {
        'target': target_url,
        'plugins': {
            'audit': (PluginConfig('xss'), ),
            'auth': (PluginConfig(
                'detailed',
                ('username', '*****@*****.**', PluginConfig.STR),
                ('password', 'passw0rd', PluginConfig.STR),
                ('username_field', 'username', PluginConfig.STR),
                ('password_field', 'password', PluginConfig.STR),
                ('data_format', data_format, PluginConfig.STR),
                ('auth_url', auth_url, PluginConfig.URL),
                ('method', 'POST', PluginConfig.STR),
                ('check_url', check_url, PluginConfig.URL),
                ('check_string', check_string, PluginConfig.STR),
                ('follow_redirects', True, PluginConfig.BOOL),
            ), ),
        }
    }

    def test_redirect_login(self):
        self._scan(self._run_config['target'], self._run_config['plugins'])

        all_paths = set()
        for request in httpretty.latest_requests:
            all_paths.add(request.path)

        # Followed two redirects
        self.assertIn('/confirm/?token=123', all_paths)
        self.assertIn('/auth/home.py', all_paths)

        # Send the POST to login
        self.assertIn('/auth/login_form.py', all_paths)
Beispiel #16
0
class TestPHPEggs(PluginTest):

    target_url = 'http://mock/'
    MOCK_RESPONSES = [
        MockResponse('http://mock/?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000',
                     '1'),
        MockResponse('http://mock/?=PHPE9568F34-D428-11d2-A769-00AA001ACF42',
                     '2',
                     content_type='image/png'),
        MockResponse('http://mock/?=PHPE9568F35-D428-11d2-A769-00AA001ACF42',
                     '3',
                     content_type='image/png'),
        MockResponse('http://mock/?=PHPE9568F36-D428-11d2-A769-00AA001ACF42',
                     '4',
                     content_type='image/png')
    ]

    _run_configs = {
        'cfg': {
            'target': None,
            'plugins': {
                'infrastructure': (PluginConfig('php_eggs'), )
            }
        }
    }

    def test_php_eggs_fingerprinted(self):
        cfg = self._run_configs['cfg']

        with patch('w3af.plugins.infrastructure.php_eggs.md5_hash') as md5mock:

            def side_effect(body):
                return {
                    '1': 'a4c057b11fa0fba98c8e26cd7bb762a8',
                    '2': 'c48b07899917dfb5d591032007041ae3',
                    '3': 'fb3bbd9ccc4b3d9e0b3be89c5ff98a14',
                    '4': '7675f1d01c927f9e6a4752cf182345a2'
                }.get(body)

            md5mock.side_effect = side_effect
            self._scan(self.target_url, cfg['plugins'])

        eggs = self.kb.get('php_eggs', 'eggs')
        self.assertEqual(len(eggs), 4, eggs)

        for egg in eggs:
            self.assertIn('PHP Egg', egg.get_name())

        php_version = self.kb.get('php_eggs', 'version')
        self.assertEqual(len(php_version), 1, php_version)

        php_version = php_version[0]
        self.assertEqual(php_version['version'], [u'5.3.2', u'5.3.1'])
Beispiel #17
0
class TestRegexOutputFromUpload(TestParseOutputFromUpload):

    target_url = u'http://w3af.org/'

    FORM = """\
          <form enctype="multipart/form-data" action="upload" method="POST">
              <input type="hidden" name="MAX_FILE_SIZE" value="10000000" />
              Choose a file to upload: <input name="uploadedfile" type="file" /><br />
              <input type="submit" value="Upload File" />
          </form>
          """

    RESULT = "Thanks for uploading your file to <pre>../../hackable/uploads/mockname.png</pre>"

    FILE_CONTENT_RAND = 'w3af.core.data.fuzzer.utils.rand_alnum'
    IMAGE_CONTENT = 'PNG' + 'B' * 239

    FILENAME_RAND_ALPHA = 'w3af.core.data.constants.file_templates.file_templates.rand_alpha'

    MOCK_RESPONSES = [
        MockResponse(url=target_url,
                     body=FORM,
                     content_type='text/html',
                     method='GET',
                     status=200),
        MockResponse(url=target_url + 'upload',
                     body=RESULT,
                     content_type='text/html',
                     method='POST',
                     status=200),
        MockResponse(url=target_url + 'hackable/uploads/mockname.png',
                     body=IMAGE_CONTENT,
                     content_type='image/png',
                     method='GET',
                     status=200),
    ]

    def test_parse_response(self):
        with patch(self.FILENAME_RAND_ALPHA) as rand_alpha_mock:
            rand_alpha_mock.return_value = 'mockname'

            with patch(self.FILE_CONTENT_RAND) as rand_alnum_mock:
                rand_alnum_mock.return_value = 'B' * 239

                cfg = self._run_configs['cfg']
                self._scan(cfg['target'], cfg['plugins'])

        fu_vulns = self.kb.get('file_upload', 'file_upload')
        self.assertEquals(1, len(fu_vulns))

        v = fu_vulns[0]
        self.assertEquals(v.get_name(), 'Insecure file upload')
        self.assertEquals(str(v.get_url().get_domain_path()), self.target_url)
Beispiel #18
0
class TestAutocomplete(PluginTest):
    target_url = 'http://w3af.org/'

    login_form_url = URL(target_url + 'login_form.py')
    login_post_handler_url = URL(target_url + 'login_post.py')

    check_url = URL(target_url + 'admin')
    check_string = 'Logged in'

    MOCK_RESPONSES = [
                      MockResponse('http://w3af.org/login_form.py',
                                   HTML_LOGIN_FORM,
                                   status=200,
                                   method='GET',
                                   headers={'Set-Cookie': '__csrf=09876xyzxyz'}),

                      LoginMockResponse('http://w3af.org/login_post.py',
                                        '',
                                        method='POST'),

                      SessionCheckMockResponse('http://w3af.org/admin', ''),

                      MockResponse('http://w3af.org/unittest',
                                   'Success',
                                   status=200,
                                   method='GET')
                      ]

    _run_config = {
        'target': target_url,
        'plugins': {
            'audit': (PluginConfig('xss'),),
            'auth': (PluginConfig('autocomplete',
                                  ('username', USER, PluginConfig.STR),
                                  ('password', PASS, PluginConfig.STR),
                                  ('login_form_url', login_form_url, PluginConfig.URL),
                                  ('check_url', check_url, PluginConfig.URL),
                                  ('check_string', check_string, PluginConfig.STR)),),
        }
    }

    def test_find_form_submit_csrf_token(self):
        self._scan(self._run_config['target'], self._run_config['plugins'])

        all_paths = set()
        for request in httpretty.latest_requests:
            all_paths.add(request.path)

        self.assertIn('/login_form.py', all_paths)
        self.assertIn('/login_post.py', all_paths)
        self.assertIn('/admin', all_paths)

        self.assertTrue(SUCCESS)
Beispiel #19
0
class TestFormExclusions(PluginTest):
    """
    This is an integration test for form exclusions

    :see: https://github.com/andresriancho/w3af/issues/15161
    """
    target_url = 'http://mock/'

    scan_config = {
        'target': target_url,
        'plugins': {
            'crawl': (PluginConfig('web_spider'), )
        }
    }

    MOCK_RESPONSES = [
        MockResponse(
            'http://mock/', '<html>'
            ''
            '<form action="/out/" method="POST">'
            '<input name="x" /></form>'
            ''
            '<form action="/in/" method="POST">'
            '<input name="x" /></form>'
            ''
            '</html>'),
        MockResponse('http://mock/out/', 'Thanks.', method='POST'),
        MockResponse('http://mock/in/', 'Thanks.', method='POST')
    ]

    def test_form_exclusions(self):
        user_value = '[{"action": "/out.*"}]'
        cf.cf.save('form_id_list', FormIDMatcherList(user_value))
        cf.cf.save('form_id_action', EXCLUDE)

        self._scan(self.scan_config['target'], self.scan_config['plugins'])

        # Define the expected/desired output
        expected_files = ['', '/in/']
        expected_urls = set(
            URL(self.target_url).url_join(end).url_string
            for end in expected_files)

        # pylint: disable=E1101
        # Pylint fails to detect the object types that come out of the KB
        urls = self.kb.get_all_known_urls()
        found_urls = set(str(u).decode('utf-8') for u in urls)

        self.assertEquals(found_urls, expected_urls)

        # revert any changes to the default so we don't affect other tests
        cf.cf.save('form_id_list', FormIDMatcherList('[]'))
        cf.cf.save('form_id_action', EXCLUDE)
Beispiel #20
0
class TestFormAuthFailedLoginMatchTrivial(GenericFormAuthTest):

    target_url = u'http://w3af.org/'
    login_url = u'http://w3af.org/login'

    FORM = ('<form method="POST" action="/login">'
            '    <input name="username" type="text" />'
            '    <input name="password" type="password" />'
            '    <input name="submit" type="submit" />'
            '</form>')

    def request_callback(self, request, uri, response_headers):
        response_headers['content-type'] = 'text/html'

        username = request.parsed_body.get('username', [''])[0]
        password = request.parsed_body.get('password', [''])[0]

        if username == 'admin' and password == 'admin':
            body = 'Welcome Mr. Admin'
        else:
            body = 'Fail'

        return 200, response_headers, body

    MOCK_RESPONSES = [
              MockResponse(url=target_url,
                           body=FORM,
                           status=200,
                           method='GET',
                           content_type='text/html'),

              MockResponse(url=login_url,
                           body=request_callback,
                           method='POST',
                           content_type='text/html',
                           status=200),

    ]

    def test_found_credentials(self):
        self._scan(self.target_url, self.basic_config)

        # Assert the general results
        vulns = self.kb.get('form_auth', 'auth')
        self.assertEquals(len(vulns), 1)

        vuln = vulns[0]

        self.assertEquals(vuln.get_name(), 'Guessable credentials')
        self.assertEquals(vuln.get_url().url_string, self.login_url)
        self.assertEquals(vuln['user'], 'admin')
        self.assertEquals(vuln['pass'], 'admin')
Beispiel #21
0
class TestFrontpage(PluginTest):

    target_url = 'http://httpretty'

    FRONTPAGE_BODY = ('FPVersion="1.2.3"\n'
                      'FPAdminScriptUrl="/admin"\n'
                      'FPAuthorScriptUrl="/author"\n')

    MOCK_RESPONSES = [
        MockResponse('http://httpretty/_vti_inf.html',
                     body=FRONTPAGE_BODY,
                     method='GET',
                     status=200),
        MockResponse('http://httpretty/author',
                     body='',
                     method='POST',
                     status=200),
        MockResponse('http://httpretty/AAAAAA.html',
                     body='AAAAAA.html'[::-1],
                     method='GET',
                     status=200),
    ]

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {
                'infrastructure': (PluginConfig('frontpage_version'), ),
                'audit': (PluginConfig('frontpage'), )
            }
        }
    }

    def test_upload(self):
        cfg = self._run_configs['cfg']

        with patch(
                'w3af.plugins.audit.frontpage.rand_alpha') as rand_alpha_mock:
            rand_alpha_mock.side_effect = ['AAAAAA']
            self._scan(cfg['target'], cfg['plugins'])

        vulns = self.kb.get('frontpage', 'frontpage')

        self.assertEqual(len(vulns), 1, vulns)

        vuln = vulns[0]

        self.assertEqual(vuln.get_url().url_string,
                         'http://httpretty/AAAAAA.html')
        self.assertEqual(vuln.get_name(),
                         'Insecure Frontpage extensions configuration')
class TestHTAccessFalsePositiveGeneric(PluginTest):
    target_url = 'http://httpretty-mock/'

    MOCK_RESPONSES = [
        MockResponse('/', 'Bad credentials', method='GET', status=401),
        MockResponse('/', 'Bad credentials', method='POST', status=403)
    ]

    def test_false_positive(self):
        cfg = RUN_CONFIG['cfg']
        self._scan(self.target_url, cfg['plugins'])
        vulns = self.kb.get('htaccess_methods', 'auth')

        self.assertEquals(0, len(vulns))
Beispiel #23
0
class TestRelativePathsIn404(PluginTest):
    """
    This test reproduces the issue #5834 which generates an endless crawl loop

    :see: https://github.com/andresriancho/w3af/issues/5834
    """
    target_url = 'http://mock/'

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {
                'crawl': (PluginConfig('web_spider'), )
            }
        }
    }

    TEST_ROOT = os.path.join(ROOT_PATH, 'plugins', 'tests', 'crawl',
                             'web_spider', '5834')

    GALERIA_HTML = file(os.path.join(TEST_ROOT, 'galeria-root.html')).read()
    INDEX_HTML = file(os.path.join(TEST_ROOT, 'index.html')).read()

    MOCK_RESPONSES = [
        MockResponse(re.compile('http://mock/galeria/.*'), GALERIA_HTML),
        MockResponse('/', 'Thanks.', method='POST'),
        MockResponse('/', INDEX_HTML)
    ]

    def test_crawl_404_relative(self):
        cfg = self._run_configs['cfg']
        self._scan(cfg['target'], cfg['plugins'])

        # Define the expected/desired output
        expected_files = [
            '', '/galeria/', '/galeria/assets/ico/', '/i18n/setlang/',
            '/galeria/assets/ico/tel:982560987', '/reserva/resumen/'
        ]
        expected_urls = set(
            URL(self.target_url).url_join(end).url_string
            for end in expected_files)

        # pylint: disable=E1101
        # Pylint fails to detect the object types that come out of the KB
        urls = self.kb.get_all_known_urls()
        found_urls = set(str(u).decode('utf-8') for u in urls)

        self.assertEquals(found_urls, expected_urls)
class TestEventValidationGrouping(PluginTest):

    target_url = 'http://mock/'

    html = ('<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"'
            ' value="/wEPDwUKLTMyNjg0MDc1MWQYAQUeX19Db250cm9sc1JlcXVpcmVQb3'
            'N0QmFja0tleV9fFgEFIGJwJF8kY3RsMDAkXyRicyRfJHdzJF8kU2VhcmNoQm94'
            'bxUzDQVBRPB2cN8nnSmNhVZ6WX0=" />')

    MOCK_RESPONSES = [
        MockResponse(url='http://mock/',
                     body='<a href="/1">1</a>'
                     '<a href="/2">2</a>',
                     method='GET',
                     status=200),
        MockResponse(url='http://mock/1', body=html, method='GET', status=200),
        MockResponse(url='http://mock/2', body=html, method='GET', status=200)
    ]

    def test_grouped_vulnerabilities(self):
        self._scan(self.target_url, RUN_CONFIGS['cfg']['plugins'])

        vulns = self.kb.get('dot_net_event_validation',
                            'dot_net_event_validation')

        expected_vulns = {
            ('.NET Event Validation is disabled',
             u'The application contains 2 unique URLs which have'
             u' .NET Event Validation disabled. This programming'
             u' / configuration error should be manually'
             u' verified. The first two vulnerable URLs are:\n'
             u' - http://mock/2\n - http://mock/1\n'),
            ('.NET ViewState encryption is disabled',
             u'The application contains 2 unique URLs with .NET'
             u' ViewState encryption disabled. This programming'
             u' / configuration error can be exploited to decode'
             u' and inspect the ViewState contents. The first two'
             u' vulnerable URLs are:\n - http://mock/2\n'
             u' - http://mock/1\n')
        }

        vulns_set = set()

        for vuln in vulns:
            desc = vuln.get_desc(with_id=False)
            vulns_set.add((vuln.get_name(), desc))

        self.assertEqual(expected_vulns, vulns_set)
Beispiel #25
0
class TestPHPInfo516(PluginTest):

    target_url = 'http://httpretty/'

    PHPINFO = os.path.join(ROOT_PATH, 'plugins', 'tests', 'crawl', 'phpinfo',
                           'phpinfo-5.1.6.html')

    MOCK_RESPONSES = [
        MockResponse('http://httpretty/',
                     body='index home page',
                     method='GET',
                     status=200),
        MockResponse('http://httpretty/phpversion.php',
                     body=file(PHPINFO).read(),
                     method='GET',
                     status=200),
    ]

    _run_config = {
        'target': target_url,
        'plugins': {
            'crawl': (PluginConfig('phpinfo'), )
        }
    }

    def test_phpinfo(self):
        self._scan(self._run_config['target'], self._run_config['plugins'])

        urls = self.kb.get_all_known_urls()
        urls = [url.url_string for url in urls]

        self.assertIn(self.target_url + 'phpversion.php', urls)

        infos = self.kb.get('phpinfo', 'phpinfo')
        self.assertTrue(len(infos) > 5, infos)

        info_urls = [i.get_url().url_string for i in infos]
        self.assertIn(self.target_url + 'phpversion.php', info_urls)

        found_infos = set([i.get_name() for i in infos])

        expected_infos = {
            'PHP register_globals: On', 'PHP expose_php: On',
            'PHP session.hash_function:md5', 'phpinfo() file found'
        }

        for expected_info in expected_infos:
            self.assertIn(expected_info, found_infos)
Beispiel #26
0
class TestOpenAPIFindsSpecInOtherDirectory2(PluginTest):
    target_url = 'http://w3af.org/a/b/c/'

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {
                'crawl': (PluginConfig('open_api'), )
            }
        }
    }

    MOCK_RESPONSES = [
        MockResponse('http://w3af.org/a/openapi.json',
                     NestedModel().get_specification())
    ]

    def test_auth_warning_raised(self):
        cfg = self._run_configs['cfg']
        self._scan(cfg['target'], cfg['plugins'])

        #
        # Since we configured authentication we should only get one of the Info
        #
        infos = self.kb.get('open_api', 'open_api')
        self.assertEqual(len(infos), 2, infos)

        info_i = infos[0]
        self.assertEqual(info_i.get_name(), 'Open API specification found')
Beispiel #27
0
class TestUnSSL(PluginTest):
    target_url = 'http://httpretty/'

    # This mocked response will be returned for both http and https
    MOCK_RESPONSES = [MockResponse('/', 'foo bar spam', )]

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {
                'audit': (PluginConfig('un_ssl'),),
            }
        }
    }

    def setUp(self):
        super(TestUnSSL, self).setUp()
        self._register_httpretty_uri('https', 'httpretty', 443)

    def test_found_unssl(self):
        cfg = self._run_configs['cfg']
        self._scan(cfg['target'], cfg['plugins'])

        vulns = self.kb.get('un_ssl', 'un_ssl')
        self.assertEquals(1, len(vulns))

        # Now some tests around specific details of the found vuln
        vuln = vulns[0]
        self.assertEquals(vuln.get_name(), 'Secure content over insecure channel')
        self.assertEquals(vuln.get_url().url_string, 'http://httpretty/')
Beispiel #28
0
class TestOpenAPIRaisesWarningIfNoAuth(PluginTest):
    target_url = 'http://w3af.org/'

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {
                'crawl': (PluginConfig('open_api'), )
            }
        }
    }

    MOCK_RESPONSES = [
        MockResponse('http://w3af.org/openapi.json',
                     NestedModel().get_specification(),
                     content_type='application/json')
    ]

    def test_auth_warning_raised(self):
        cfg = self._run_configs['cfg']
        self._scan(cfg['target'], cfg['plugins'])

        #
        # Since we configured authentication we should only get one of the Info
        #
        infos = self.kb.get('open_api', 'open_api')
        self.assertEqual(len(infos), 2, infos)

        info_i = infos[0]
        self.assertEqual(info_i.get_name(), 'Open API specification found')

        info_i = infos[1]
        self.assertEqual(info_i.get_name(), 'Open API missing credentials')
Beispiel #29
0
class TestServerStatus(PluginTest):
    target_url = 'http://httpretty-mock/'

    MOCK_RESPONSES = [
        MockResponse('/server-status',
                     '<dl><dt>Server Version: Apache/2.2.9 (Unix)</dt>'),
    ]

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {
                'infrastructure': (PluginConfig('server_status'), )
            }
        }
    }

    def test_find_server(self):
        cfg = self._run_configs['cfg']
        self._scan(cfg['target'], cfg['plugins'])

        server = self.kb.get('server_status', 'server')

        self.assertEqual(len(server), 1, server)
        self.assertTrue(
            'remote server version: "Apache/2.' in server[0].get_desc(),
            server[0].get_desc())
Beispiel #30
0
class TestUserDir(PluginTest):

    target_url = 'http://moth/'

    _run_configs = {
        'cfg': {
            'target': target_url,
            'plugins': {
                'crawl': (PluginConfig('user_dir'), )
            }
        }
    }

    MOCK_RESPONSES = [MockResponse('/~www/', 'www user home directory.')]

    def test_fuzzer_user(self):
        # Don't enable dependencies
        self.w3afcore.plugins.resolve_dependencies = Mock()

        cfg = self._run_configs['cfg']
        self._scan(cfg['target'], cfg['plugins'])

        users = self.kb.get('user_dir', 'users')

        self.assertEqual(len(users), 1, users)

        user = users[0]

        self.assertTrue(user.get_name().startswith('Web user home directory'))
        self.assertEquals(user.get_url().url_string, 'http://moth/~www/')