Пример #1
0
def test_should_fail_fast(base_url: str, full_scan_mock: MockSpec,
                          capsys: CaptureFixture):

    common_args = {
        'base_url': base_url,
        'session_provider': lambda: full_scan_mock.session()
    }

    class FailFastException(Exception):
        pass

    class ErrorScanner(Scanner[str]):
        def __init__(self, **kwargs):
            super().__init__(result_type=WrapperType(str), **kwargs)

        def perform(self, **kwargs) -> (str, VulnFlag):
            raise FailFastException()

    ms = MasterScanner(scanners=[
        RealmScanner(**common_args, realms=['master', 'other']),
        WellKnownScanner(**common_args),
        ErrorScanner(**common_args),
        ClientScanner(**common_args, clients=['client1', 'client2']),
        LoginScanner(**common_args),
        SecurityConsoleScanner(**common_args),
        OpenRedirectScanner(**common_args),
        FormPostXssScanner(**common_args),
        NoneSignScanner(**common_args)
    ],
                       initial_values={
                           WrapperTypes.USERNAME_TYPE: {Username('admin')},
                           WrapperTypes.PASSWORD_TYPE: {Password('admin')}
                       },
                       fail_fast=True)

    with pytest.raises(FailFastException) as e:

        status = ms.start()

        assert status.has_error is True

        # TODO when vf was fixed
        # assert status.has_vulns is True

    captured = capsys.readouterr()

    print(captured.out)

    assert captured.err == ''

    assert 'Find realm master' in captured.out

    assert 'Public key for realm master : ' in captured.out

    assert "[+] WellKnownScanner - Find a well known for realm master" in captured.out
Пример #2
0
def test_perform(base_url: str, master_realm: Realm, other_realm: Realm,
                 capsys: CaptureFixture, well_known_list: List[WellKnown]):

    def assert0(**kwargs) -> bool:
        print(kwargs)
        return kwargs['params']['client_id'] in ['client1', 'client2']

    client_scanner = ClientScanner(clients=['client1', 'client2'], base_url=base_url,
                                   session_provider=lambda: MockSpec(
                                       get={
                                           'http://localhost:8080/auth/realms/master/client1':
                                               RequestSpec(response=MockResponse(status_code=200)),
                                           'http://localhost:8080/auth/realms/master/client2':
                                               RequestSpec(response=MockResponse(status_code=404)),

                                           'http://localhost:8080/auth/realms/master/protocol/openid-connect/auth':
                                               RequestSpec(response=MockResponse(302), assertion=assert0),
                                            'http://localhost:8080/realms/master/clients-registrations/default/client1':
                                                RequestSpec(response=MockResponse(200, response={'data': 'coucou'})),
                                           'http://localhost:8080/realms/master/clients-registrations/default/client2':
                                               RequestSpec(response=MockResponse(200, response={'data': 'coucou'}))
                                       }
                                   ).session())

    result, vf = client_scanner.perform(realm=master_realm, well_known=well_known_list[0])

    capture = capsys.readouterr()

    print(capture.out)
    print(capture.err)

    assert result == {Client('client1', 'http://localhost:8080/auth/realms/master/client1',
                                     client_registration=ClientConfig(name='client1',
                                                                      url='http://localhost:8080/realms/master/clients-registrations/default/client1',
                                                                      json={'data': 'coucou'}
                                                                      )
                                     ),
                              Client('client2', None,
                                     client_registration=ClientConfig(name='client2',
                                                                      url='http://localhost:8080/realms/master/clients-registrations/default/client2',
                                                                      json={'data': 'coucou'}
                                                                      )
                                     )}

    assert not vf.has_vuln

    assert 'Find a client for realm master: client1' in capture.out
Пример #3
0
def test_client_registration_scanner_should_not_register(master_realm: Realm,
                                                         well_known_master: WellKnown,
                                                         credential_set: Set[Credential],
                                                         well_known_json_master: dict):
    class TestRandomStr(RandomStr):

        def random_str(self) -> str:
            return '456789'

    class TestClientRegistrationScanner(ClientRegistrationScanner, TestRandomStr):
        pass

    session_provider = lambda: MockSpec(
        get={
            'http://localhost:8080/auth/realms/master/.well-known/openid-configuration': RequestSpec(
                MockResponse(status_code=200, response=well_known_json_master)
            ),
        },
        post={
            'http://localhost:8080/auth/realms/master/clients-registrations/openid-connect':
                RequestSpec(response=MockResponse(status_code=403),
                            assertion=check_request, assertion_value={'json': {
                        "application_type": "web",
                        "redirect_uris": [
                            "http://callback/callback"],
                        "client_name": "keycloak-client-456789",
                        "logo_uri": "http://callback/logo.png",
                        "jwks_uri": "http://callback/public_keys.jwks"
                    }}),
            'http://localhost:8080/auth/realms/master/protocol/openid-connect/token': RequestSpec(
                response=MockResponse(status_code=403))
        },

    ).session()

    mediator = Mediator([
        TestClientRegistrationScanner(['http://callback'], base_url='http://localhost:8080',
                                      session_provider=session_provider)
    ])

    mediator.send(WrapperTypes.REALM_TYPE, {master_realm})
    mediator.send(WrapperTypes.WELL_KNOWN_TYPE, {well_known_master})
    mediator.send(WrapperTypes.CREDENTIAL_TYPE, credential_set)

    assert mediator.scan_results.get(WrapperTypes.CLIENT_REGISTRATION) == set()
Пример #4
0
def test_client_registration_scanner_should_register(master_realm: Realm,
                                                     well_known_master: WellKnown,
                                                     credential_set: Set[Credential],
                                                     well_known_json_master: dict):
    class TestRandomStr(RandomStr):

        def random_str(self) -> str:
            return '456789'

    class TestClientRegistrationScanner(ClientRegistrationScanner, TestRandomStr):
        pass

    response = {
        "redirect_uris":
            ["http://localhost:8080/callback"],
        "token_endpoint_auth_method": "client_secret_basic",
        "grant_types": ["authorization_code", "refresh_token"],
        "response_types": ["code", "none"],
        "client_id": "539ce782-5d15-4256-a5fa-1a46609d056b",
        "client_secret": "c94f5fc0-0a04-4e2f-aec6-b1f5edad1d44",
        "client_name": "keycloak-client-456789",
        "scope": "address phone offline_access microprofile-jwt",
        "jwks_uri": "http://localhost:8080/public_keys.jwks",
        "subject_type": "pairwise",
        "request_uris": ["http://localhost:8080/rf.txt"],
        "tls_client_certificate_bound_access_tokens": False,
        "client_id_issued_at": 1622306364,
        "client_secret_expires_at": 0,
        "registration_client_uri": "http://localhost:8080/auth/realms/master/clients-registrations/openid-connect/539ce782-5d15-4256-a5fa-1a46609d056b",
        "backchannel_logout_session_required": False
    }

    session_provider = lambda: MockSpec(
        get={
            'http://localhost:8080/auth/realms/master/.well-known/openid-configuration': RequestSpec(
                MockResponse(status_code=200, response=well_known_json_master)
            ),
        },
        post={
            'http://localhost:8080/auth/realms/master/clients-registrations/openid-connect':
                RequestSpec(response=MockResponse(status_code=201, response=response),
                            assertion=check_request, assertion_value={'json': {
                        "application_type": "web",
                        "redirect_uris": [
                            "http://callback/callback"],
                        "client_name": "keycloak-client-456789",
                        "logo_uri": "http://callback/logo.png",
                        "jwks_uri": "http://callback/public_keys.jwks"
                    }})}).session()

    mediator = Mediator([
        TestClientRegistrationScanner(['http://callback'], base_url='http://localhost:8080',
                                      session_provider=session_provider)
    ])

    mediator.send(WrapperTypes.REALM_TYPE, {master_realm})
    mediator.send(WrapperTypes.WELL_KNOWN_TYPE, {well_known_master})
    mediator.send(WrapperTypes.CREDENTIAL_TYPE, credential_set)

    assert mediator.scan_results.get(WrapperTypes.CLIENT_REGISTRATION) == {ClientRegistration(
            'http://callback',
            name='keycloak-client-456789',
            url='http://localhost:8080/auth/realms/master/clients-registrations/openid-connect/539ce782-5d15-4256-a5fa-1a46609d056b',
            json=response
        )}
Пример #5
0
def full_scan_mock_session(full_scan_mock: MockSpec) -> Session:
    return full_scan_mock.session()
Пример #6
0
def full_scan_mock(master_realm_json, other_realm_json, well_known_json_master: dict,
                   well_known_json_other: dict, login_html_page: str) -> MockSpec:
    token_response = {
        'access_token': 'eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI3ODM4MGM2ZS1iODhmLTQ5NDQtOGRkZS03NTQyMDNkMjFhODEifQ.eyJleHAiOjE2MjE2NzU5NzIsImlhdCI6MTYyMTYzOTk3MiwianRpIjoiMGU2NDcxOTItMzU5ZS00NmU4LWFkYWQtNTQzNmQyNjMyZjA1IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjJjMTZhY2Y1LWMwOTYtNDg5ZC1iYjFjLTU4ZTc0ZTJiZjAzMiIsInR5cCI6IlNlcmlhbGl6ZWQtSUQiLCJzZXNzaW9uX3N0YXRlIjoiZWY3ZjNjZmItMDAzZS00YzViLWEzMWQtYmI0OGFhZjAzNzk3Iiwic3RhdGVfY2hlY2tlciI6ImtKNy05MURtNVEwVXktT1JfVlJnT1d5eF91Wkh3M0ZfczktTVdlUjZRTlEifQ.6yZvyGKEH0NXmLY8nKRQMLsMQYPXq5dYCsIF3LRiOxI',
        'refresh_token': 'eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI3ODM4MGM2ZS1iODhmLTQ5NDQtOGRkZS03NTQyMDNkMjFhODEifQ.eyJleHAiOjE2MjE2NzU5NzIsImlhdCI6MTYyMTYzOTk3MiwianRpIjoiMGU2NDcxOTItMzU5ZS00NmU4LWFkYWQtNTQzNmQyNjMyZjA1IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjJjMTZhY2Y1LWMwOTYtNDg5ZC1iYjFjLTU4ZTc0ZTJiZjAzMiIsInR5cCI6IlNlcmlhbGl6ZWQtSUQiLCJzZXNzaW9uX3N0YXRlIjoiZWY3ZjNjZmItMDAzZS00YzViLWEzMWQtYmI0OGFhZjAzNzk3Iiwic3RhdGVfY2hlY2tlciI6ImtKNy05MURtNVEwVXktT1JfVlJnT1d5eF91Wkh3M0ZfczktTVdlUjZRTlEifQ.6yZvyGKEH0NXmLY8nKRQMLsMQYPXq5dYCsIF3LRiOxI'
    }

    return MockSpec(get={
        'http://localhost:8080/auth/realms/master/.well-known/openid-configuration': RequestSpec(
            MockResponse(status_code=200, response=well_known_json_master)
        ),
        'http://localhost:8080/auth/realms/master': RequestSpec(
            MockResponse(status_code=200, response=master_realm_json)),
        'http://localhost:8080/auth/realms/other': RequestSpec(
            MockResponse(status_code=200, response=other_realm_json)),
        'http://localhost:8080/auth/realms/other/.well-known/openid-configuration': RequestSpec(
            MockResponse(status_code=200,
                         response=well_known_json_other)),
        'http://localhost:8080/auth/realms/master/client1': RequestSpec(
            MockResponse(status_code=200, response='coucou')),
        'http://localhost:8080/auth/realms/master/client2': RequestSpec(
            MockResponse(status_code=200, response='coucou')),
        'http://localhost:8080/auth/realms/other/client1': RequestSpec(
            MockResponse(status_code=200, response='coucou')),
        'http://localhost:8080/auth/realms/other/client2': RequestSpec(
            MockResponse(status_code=200, response='coucou')),
        'http://localhost:8080/auth/realms/master/clients-registrations/default/security-admin-console':
            RequestSpec(MockResponse(status_code=401, response={"error": "invalid_token",
                                                                "error_description": "Not authorized to view client. Not valid token or client credentials provided."})),
        'http://localhost:8080/auth/realms/other/clients-registrations/default/security-admin-console': RequestSpec(
            MockResponse(
                status_code=401, response={"error": "invalid_token",
                                           "error_description": "Not authorized to view client. Not valid token or client credentials provided."})),
        'http://localhost:8080/auth': RequestSpec(MockResponse(status_code=400)),
        'http://localhost:8080/auth/realms/master/protocol/openid-connect/auth': RequestSpec(MockResponse(200,
                                                                                                          response=login_html_page)),
        'http://localhost:8080/auth/realms/other/protocol/openid-connect/auth': RequestSpec(MockResponse(200,
                                                                                                         response=login_html_page)),
        'http://localhost:8080/auth/realms/master/protocol/openid-connect/auth?client_id=account-console&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fauth%2Frealms%2Fmaster%2Faccount%2F%23%2F&state=310f298c-f3d8-4c42-8ebc-44484febf84c&response_mode=fragment&response_type=code&scope=openid&nonce=a6be5274-15e4-4ffe-9905-ffb038b20a8e&code_challenge=Nd1svU3YNT0r6eWHkSmNeX_cxgUPQUVzPfZFXRWaJmY&code_challenge_method=S256':
            RequestSpec(MockResponse(
                200, login_html_page)),
        'http://localhost:8080/realms/master/clients-registrations/default/client1': RequestSpec(
            MockResponse(200, response={"id": "899e2dc1-5fc0-4eaf-bedb-f81a3f9e9313", "clientId": "admin-cli",
                                        "name": "${client_admin-cli}", "surrogateAuthRequired": False, "enabled": True,
                                        "alwaysDisplayInConsole": False, "clientAuthenticatorType": "client-secret",
                                        "redirectUris": [], "webOrigins": [], "notBefore": 0, "bearerOnly": False,
                                        "consentRequired": False, "standardFlowEnabled": False,
                                        "implicitFlowEnabled": False, "directAccessGrantsEnabled": False,
                                        "serviceAccountsEnabled": False, "publicClient": False,
                                        "frontchannelLogout": False, "protocol": "openid-connect", "attributes": {},
                                        "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": False,
                                        "nodeReRegistrationTimeout": 0,
                                        "defaultClientScopes": ["web-origins", "roles", "profile", "email"],
                                        "optionalClientScopes": ["address", "phone", "offline_access",
                                                                 "microprofile-jwt"]})
        ),
        'http://localhost:8080/realms/other/clients-registrations/default/client1': RequestSpec(
            MockResponse(200, response={"id": "899e2dc1-5fc0-4eaf-bedb-f81a3f9e9313", "clientId": "admin-cli",
                                        "name": "${client_admin-cli}", "surrogateAuthRequired": False, "enabled": True,
                                        "alwaysDisplayInConsole": False, "clientAuthenticatorType": "client-secret",
                                        "redirectUris": [], "webOrigins": [], "notBefore": 0, "bearerOnly": False,
                                        "consentRequired": False, "standardFlowEnabled": False,
                                        "implicitFlowEnabled": False, "directAccessGrantsEnabled": False,
                                        "serviceAccountsEnabled": False, "publicClient": False,
                                        "frontchannelLogout": False, "protocol": "openid-connect", "attributes": {},
                                        "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": False,
                                        "nodeReRegistrationTimeout": 0,
                                        "defaultClientScopes": ["web-origins", "roles", "profile", "email"],
                                        "optionalClientScopes": ["address", "phone", "offline_access",
                                                                 "microprofile-jwt"]})
        ),
        'http://localhost:8080/realms/master/clients-registrations/default/client2': RequestSpec(
            MockResponse(400)
        ),
        'http://localhost:8080/realms/other/clients-registrations/default/client2': RequestSpec(
            MockResponse(400)
        ),

    },
        post={
            'http://localhost:8080/master/token': RequestSpec(MockResponse(status_code=200, response=token_response)),
            'http://localhost:8080/auth/realms/master/protocol/openid-connect/token': RequestSpec(
                MockResponse(status_code=200,
                             response=token_response)),
            'http://localhost:8080/other/token': RequestSpec(MockResponse(status_code=200, response=token_response)),
            'http://localhost:8080/auth/realms/other/protocol/openid-connect/token': RequestSpec(
                MockResponse(status_code=200,
                             response=token_response)),
            'http://localhost:8080/auth/realms/master/login-actions/authenticate?session_code'
            '=bR4rBd0QNGsd_kGuqiyLEuYuY6FK3Lx9HCYJEltUQBk&execution=de13838a-ee3d-404e-b16d-b0d7aa320844&client_id'
            '=account-console&tab_id=GXMjAPR3DsQ':
                RequestSpec(MockResponse(
                    302, response=None, headers={'Location': '<openid location>'})),
            'http://localhost:8080/auth/realms/master/clients-registrations/openid-connect':
                RequestSpec(response=MockResponse(status_code=201, response={
                    "redirect_uris":
                        ["http://localhost:8080/callback"],
                    "token_endpoint_auth_method": "client_secret_basic",
                    "grant_types": ["authorization_code", "refresh_token"],
                    "response_types": ["code", "none"],
                    "client_id": "539ce782-5d15-4256-a5fa-1a46609d056b",
                    "client_secret": "c94f5fc0-0a04-4e2f-aec6-b1f5edad1d44",
                    "client_name": "keycloak-client-456789",
                    "scope": "address phone offline_access microprofile-jwt",
                    "jwks_uri": "http://localhost:8080/public_keys.jwks",
                    "subject_type": "pairwise",
                    "request_uris": ["http://localhost:8080/rf.txt"],
                    "tls_client_certificate_bound_access_tokens": False,
                    "client_id_issued_at": 1622306364,
                    "client_secret_expires_at": 0,
                    "registration_client_uri": "http://localhost:8080/auth/realms/master/clients-registrations/openid-connect/539ce782-5d15-4256-a5fa-1a46609d056b",
                    "backchannel_logout_session_required": False
                })),
            'http://localhost:8080/auth/realms/other/clients-registrations/openid-connect':
                RequestSpec(response=MockResponse(status_code=201, response={
                    "redirect_uris":
                        ["http://localhost:8080/callback"],
                    "token_endpoint_auth_method": "client_secret_basic",
                    "grant_types": ["authorization_code", "refresh_token"],
                    "response_types": ["code", "none"],
                    "client_id": "539ce782-5d15-4256-a5fa-1a46609d056b",
                    "client_secret": "c94f5fc0-0a04-4e2f-aec6-b1f5edad1d44",
                    "client_name": "keycloak-client-456789",
                    "scope": "address phone offline_access microprofile-jwt",
                    "jwks_uri": "http://localhost:8080/public_keys.jwks",
                    "subject_type": "pairwise",
                    "request_uris": ["http://localhost:8080/rf.txt"],
                    "tls_client_certificate_bound_access_tokens": False,
                    "client_id_issued_at": 1622306364,
                    "client_secret_expires_at": 0,
                    "registration_client_uri": "http://localhost:8080/auth/realms/other/clients-registrations/openid-connect/539ce782-5d15-4256-a5fa-1a46609d056b",
                    "backchannel_logout_session_required": False
                }))
        })