hasura / graphql-engine

Blazing fast, instant realtime GraphQL APIs on your DB with fine grained access control, also trigger webhooks on database events.
https://hasura.io
Apache License 2.0
31.04k stars 2.76k forks source link

Security: unrestricted access in jwt mode using HASURA_GRAPHQL_UNAUTHORIZED_ROLE="public" #5501

Closed ChristianHohlfeld closed 4 years ago

ChristianHohlfeld commented 4 years ago

I'm using grapqhl in jwt mode using HASURA_GRAPHQL_JWT_SECRET and jwk uri. HASURA_GRAPHQL_ADMIN_SECRET is also set. If I set HASURA_GRAPHQL_UNAUTHORIZED_ROLE to "public" I can download the entire graphql schema without authorization headers and without using the admin secret as request headers. If I change it back to HASURA_GRAPHQL_UNAUTHORIZED_ROLE="anonymous" the request gets blocked.

In both cases the grapqhl endpoint can be queried with a schema introspection query, which should not be allowed when jwt mode is active without using any authorization headers in the request. Query used:

{ __schema { types { name } } } Thanks!

tirumaraiselvan commented 4 years ago

Hi @ChristianHohlfeld

When you have HASURA_GRAPHQL_UNAUTHORIZED_ROLE set, it doesn't need any auth token (think of it as unauthenticated role). So any request which doesn't have valid auth headers, will be given this role.

ChristianHohlfeld commented 4 years ago

I know, that's how I'm using it. But if I set the role ( HASURA_GRAPHQL_UNAUTHORIZED_ROLE ) to "public", then the entire endpoint is open to all requests without any authentication checks whatsoever. Full access, no checks by hasura (jwt and secret getting skipped).

tirumaraiselvan commented 4 years ago

@ChristianHohlfeld Do you have a role called "public" defined on your schema? If yes, what kind of access permissions are defined for that role?

A quick way to check this is via Show Permissions Summary button on the Data page.

Screen Shot 2020-08-02 at 9 42 19 AM

If you do have a role called "public" and this is set as unauthenticated role, then the introspection query will return a schema which is accessible by the role (without needing any auth headers).

ChristianHohlfeld commented 4 years ago

@tirumaraiselvan I got a role that is public like you mentioned in the screenshot. So does this mean if I use HASURA_GRAPHQL_UNAUTHORIZED_ROLE="public", the entire endpoint is open, is this correct? I can even query and download the schema if the role is named like the database schema ("public"). Is this intentional? Thanks for your response!

Great work by the way, awesome tool!

tirumaraiselvan commented 4 years ago

@ChristianHohlfeld Yes, it is valid to query from the endpoint as an "unauthenticated" user and you will be regarded as the "public" role (as this is what you have set via HASURA_GRAPHQL_UNAUTHORIZED_ROLE) . Now, what you expose in the "public" role is totally upto you, it based on the rules that you have defined for that role. By default, all roles are deny-all (including unauthorized role) and only that part of schema is visible (say via introspection query) for which you have given the role explicit permissions.

In other words, Hasura has role based schemas. The schema for each role is generated by inferring the permission rules for that role: https://hasura.io/docs/1.0/graphql/manual/auth/authorization/roles-variables.html#roles

If you don't want unauthenticated access, then you can just remove HASURA_GRAPHQL_UNAUTHORIZED_ROLE from your configuration. Then the endpoint can't be queried without having valid auth headers.

ChristianHohlfeld commented 4 years ago

I checked again and you're right. I had only one table which had a role "public" so it looked to me like the whole schema was exposed. You can close this as I can no longer see any issues relating secuirity and UNAUTHORIZED_ROLE. If I come across an issue I will open up again. Thank's for your fast response, great team, great service and awesome software!