GraphQL Authorization Misconfiguration
GraphQL の認可設定の不備
概要
GraphQL の認可設定の不備(GraphQL Authorization Misconfiguration)は、GraphQL API がオペレーションおよびデータモデル全体で一貫して包括的なアクセス制御を実施できない場合に生じる、重大なセキュリティ脆弱性です。 この見落としにより、権限のないユーザーが意図された権限を超えて情報にアクセス、変更、または削除できるようになり、システム全体のセキュリティが危険にさらされる可能性があります。 この脆弱性の主な特徴としては、類似したデータに対する異なるクエリやミューテーションで認可チェックのレベルが異なるという一貫性のないアクセス制御、適切な制限なしに機密フィールドやオペレーションを公開する過度に寛容なスキーマ、およびリソースを大量に消費するクエリや過度にネストされたクエリを防ぐメカニズムが存在しない深さ制限の欠如が挙げられます。
影響
- 不正なデータへのアクセスと操作:
- 攻撃者は、ユーザーの個人データ、財務記録、機密のビジネス情報などの機密情報を取得する可能性があります。
-
悪意のあるユーザーが重要なデータを改ざんまたは削除し、システムの完全性とユーザーの信頼に影響を与える可能性があります。
-
潜在的な権限昇格:
- 設定に不備のあるクエリやミューテーションを悪用することで、攻撃者が管理者権限を取得する可能性があります。
-
システム内でのラテラルムーブメント(横展開)が可能になり、他の制限された領域へのアクセスが許可される可能性があります。
-
システムの完全性の侵害:
- データセット全体の信頼性と正確性が疑問視されます。
-
特に GDPR や CCPA などのデータ保護規制に関して、コンプライアンス違反が発生する可能性があります。
-
データの持ち出し:
- 巧妙に作成されたクエリを通じて、大規模なデータ窃取が可能になります。
-
競合情報やユーザーデータベースが検出されずに抽出される可能性があります。
-
評判へのダメージ:
- このような脆弱性が公に開示されると、ユーザーの信頼が失われ、法的結果を招く可能性があります。
コード例
class UserType(DjangoObjectType):
class Meta:
model = User
fields = ("id", "username", "email")
class OrganizationType(DjangoObjectType):
class Meta:
model = Organization
fields = ("id", "name", "users")
class Query(graphene.ObjectType):
all_users = graphene.List(UserType)
organization = graphene.Field(OrganizationType, id=graphene.ID(required=True))
def resolve_all_users(self, info):
user = info.context.user
if not user.is_authenticated:
raise graphene.GraphQLError("Authentication required")
return User.objects.all()
def resolve_organization(self, info, id):
try:
org = Organization.objects.get(id=id)
except Organization.DoesNotExist:
raise graphene.GraphQLError("Organization not found")
return org
Users Query ではアクセス制御が実装されていますが、Organization Query では実装されていないことに注意してください。
組織へのクエリによってネストされたユーザー属性が公開されるため、攻撃者はこれを使用して、直接クエリされた場合には拒否された情報にアクセスできます。
クエリの例:
# 安全なクエリ
query {
allUsers {
id
username
email
}
}
# 脆弱なクエリ
query {
organization(id: "123") {
id
name
users {
id
username
email
}
}
}
推奨事項
軽減のためのベストプラクティス
- サーバー側で一貫した認可を実装する:
- ミドルウェアまたはデコレータを使用して、アクセス制御を一律に適用します。
-
例:
@require_permission('admin') def resolve_sensitive_data(self, info): # 管理者のみがこのリゾルバーにアクセスできます pass -
フィールドレベルの権限を利用する:
- フィールドレベルでアクセス制御を定義および実施します。
-
graphene-django を使用した例:
class UserType(DjangoObjectType): class Meta: model = User fields = ('id', 'username', 'email') @staticmethod def resolve_email(parent, info): if info.context.user.has_permission('view_email'): return parent.email return None -
機密データにカスタムスカラーを使用する:
-
認可チェックが組み込まれたカスタムスカラー型を実装します。
-
イントロスペクションを無効化または制限する:
-
本番環境では、イントロスペクションを無効にするか、認証および認可されたユーザーのみに制限します。
-
定期的なセキュリティ監査とスキャン:
- GraphQL スキーマ、リゾルバ、およびアクセス制御メカニズムの徹底的なレビューを実施します。
これらの根本原因に対処し、堅牢な認可メカニズムを実装することで、開発者は GraphQL の認可設定の不備のリスクを大幅に軽減し、より安全な GraphQL API を構築できます。
リンク
標準
- CCPA:
- CCPA_1798_150
- CWE_TOP_25:
- CWE_862
- OWASP_ASVS_L3:
- V1_2_4
- V4_1_3
- V13_4_1
- V13_4_2
- SOC2_CONTROLS:
- CC_6_3