Brute Force Login Using Alias Batching in GraphQL API
GraphQL APIでのエイリアスバッチ処理を使用したブルートフォースログイン
概要
GraphQLにおけるエイリアスバッチ処理を使用したブルートフォースログインとは、攻撃者がエイリアス機能を利用してログイン試行を自動化し、単一のクエリで多数の認証情報の組み合わせを簡単に送信できるようにする攻撃です。
GraphQLでは、エイリアスを使用すると、クライアントは同じクエリの複数のバージョンを異なる名前で送信できます。攻撃者は、試行ごとに異なるエイリアス名を使用して、単一のクエリ内でログインリクエストをバッチ処理することでこれを悪用します。これにより、従来のレート制限による保護を回避し、ログイン試行で認証システムを圧倒する、効率的なブルートフォース攻撃につながる可能性があります。
例:
query loginBatch {
login1: login(username: "user1", password: "password1") { token }
login2: login(username: "user2", password: "password2") { token }
login3: login(username: "user3", password: "password3") { token }
...
}
推奨事項
エイリアスバッチ処理を使用したブルートフォースログイン攻撃のリスクを軽減するには、次の対策の実装を検討してください。
-
エイリアスの制限:単一のGraphQLクエリで許可されるエイリアスの数にサーバー側の制限を構成します。GraphQL Armorなどのツールを設定して、エイリアスを制限し、過負荷を防ぐことができます。
-
CAPTCHAの実装:CAPTCHAまたはその他のユーザー検証メカニズムを導入して、一定回数ログインに失敗した後にユーザーにチャレンジを提示し、保護レイヤーを追加します。
// 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()
リンク
基準
- 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
- HIPAA_CONTROLS:
- SECURITY221
- SECURITY212
- SECURITY213