Description
Hi guys we are facing pen testing now. We got some vulnerabilities and almost all of them were solved by using in-built validators but one of them is still present
[HIGH] Directive Overloading - Multiple duplicated directives allowed in a query (Denial of Service - /graphql)
Script example how to break the system:
curl --path-as-is -i -s -k -X $'POST'
-H $'Host: api-acc.expoze.app'
-H $'User-Agent: graphql-cop/1.13'
-H $'Accept-Encoding: gzip, deflate, br'
-H $'Accept: /'
-H $'Content-Length: 98612'
-H $'Content-Type: application/json'
-o /dev/null
-w "Time elapsed: %{time_total} seconds\nResponse size: %{size_download} bytes\n"
--data-binary $'{"query": "query cop { __typename @aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@aa@[email protected]}", "operationName": "cop"}'
$'https://api-acc.expoze.app/graphql'
I tried to use custom validator
`<?php
namespace App\GraphQL\Rule;
use GraphQL\Error\Error;
use GraphQL\Language\AST\DirectiveNode;
use GraphQL\Language\AST\OperationDefinitionNode;
use GraphQL\Language\AST\NodeKind;
use GraphQL\Validator\QueryValidationContext;
use GraphQL\Validator\Rules\ValidationRule;
use GraphQL\Validator\SDLValidationContext;
class LimitDirectivesAndAliases extends ValidationRule
{
// Set your desired directive limit
private const MAX_DIRECTIVES = 10;
public function getSDLVisitor(SDLValidationContext $context): array
{
return [
NodeKind::OPERATION_DEFINITION => [
'leave' => function (OperationDefinitionNode $operation) use ($context): void {
$seenDirectives = [];
foreach ($operation->directives as $directive) {
$directiveName = $directive->name->value;
// Count the occurrences of each directive
if (!isset($seenDirectives[$directiveName])) {
$seenDirectives[$directiveName] = 0;
}
$seenDirectives[$directiveName]++;
// Report an error if the directive exceeds the max allowed
if ($seenDirectives[$directiveName] > self::MAX_DIRECTIVES) {
$context->reportError(
new Error(
sprintf(
'The directive "@%s" may be used only %d times per operation.',
$directiveName,
self::MAX_DIRECTIVES
),
[$directive]
)
);
}
}
}
]
];
}
}
`
getVisitor(QueryValidationContext $context) - also is not working
but problem is still there. I am lost a bit. May be it is known issue and you have some built in solutions how to solve it. Or probably I misunderstood smth. I really hope you can help me here coz clients wait and I am crying :) Thank you in advance :)
This is rules used:
` // Configure Query Complexity
$maxQueryComplexity = 100; // Set your desired complexity limit
DocumentValidator::addRule(new QueryComplexity($maxQueryComplexity));
// Configure Query Depth
$maxDepth = 10; // Set your desired depth limit
DocumentValidator::addRule(new QueryDepth($maxDepth));
// Disable Introspection
DocumentValidator::addRule(new DisableIntrospection(DisableIntrospection::ENABLED));
DocumentValidator::addRule(new UniqueDirectivesPerLocation());
DocumentValidator::addRule(new UniqueDirectiveNames());
DocumentValidator::addRule(new LimitDirectivesAndAliases());`