Brute Force Login Using Alias Batching in GraphQL API
Brute Force Login Using Alias Batching in GraphQL API
Description
Brute Force Login Using Alias Batching in GraphQL involves an attacker leveraging the alias feature to automate login attempts, making it easier to submit numerous credential combinations in a single query.
In GraphQL, aliases allow clients to send multiple versions of the same query under different names. Attackers exploit this by batching login requests within a single query using different alias names for each attempt. This can lead to an efficient brute force attack, bypassing traditional rate-limiting protections and overwhelming the authentication system with login attempts.
Example:
query loginBatch {
login1: login(username: "user1", password: "password1") { token }
login2: login(username: "user2", password: "password2") { token }
login3: login(username: "user3", password: "password3") { token }
...
}
Recommendation
To mitigate the risk of Brute Force Login Using Alias Batching attacks, consider implementing the following measures:
-
Limit Aliases: Configure server-side limits on the number of aliases allowed in a single GraphQL query. You can configure tools like GraphQL Armor to limit aliases and prevent overloading.
-
Implement CAPTCHA: Introduce CAPTCHA or other user verification mechanisms to challenge users after a certain number of failed login attempts, adding an additional layer of protection.
// Configuring rate limiting and alias limits for a GraphQL server
const express = require('express');
const rateLimit = require('express-rate-limit');
const { ApolloServer, gql } = require('apollo-server-express');
const { GraphQLArmorConfig } = require('graphql-armor');
const app = express();
// Rate limit for login attempts
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 requests per windowMs
message: "Too many login attempts, please try again later."
});
// Define your GraphQL schema
const typeDefs = gql`
type Query {
login(username: String!, password: String!): String
}
`;
// Implement the alias limit configuration
GraphQLArmorConfig({
maxAliases: {
enabled: true,
n: 20, // Set the maximum number of aliases allowed per query
onAccept: [],
onReject: [],
propagateOnRejection: true,
}
});
const server = new ApolloServer({ typeDefs, resolvers });
// Apply rate limiter middleware
app.use('/graphql', loginLimiter);
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () =>
console.log(`Server ready at http://localhost:4000${server.graphqlPath}`)
);
import graphql
from graphql.language import ast
from graphql.language import parser
from settings import api
def validate_aliases(query: str) -> None:
"""
This validation prevents the execution of queries containing an excessive
number of aliases to prevent server overload.
"""
class AliasesParser(parser.Parser):
def parse_aliases(self) -> list[ast.FieldNode]:
aliases = 0
while self.peek(graphql.TokenKind.NAME):
aliases += 1
if aliases > api.API_MAX_ALIASES:
raise graphql.GraphQLError("Exception - Max aliases exceeded")
self.parse_field()
return []
ast_parser = AliasesParser(query)
ast_parser.parse_document()
Links
Standards
- PCI_STANDARDS:
- REQ_6_2
- REQ_6_4
- REQ_11_3
- OWASP_ASVS_L3:
- V13_4_1
- SOC2_CONTROLS:
- CC_2_1
- CC_4_1
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5
- CC_9_1