Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GraphQLの関連タイプを辿る脆弱性

ham
October 04, 2021

 GraphQLの関連タイプを辿る脆弱性

GraphQLのedgeを辿ることで見えてはいけない情報が見えてしまう事象の説明資料

ham

October 04, 2021
Tweet

More Decks by ham

Other Decks in Technology

Transcript

  1. GraphQLのedgeを辿ることで
    見えてはいけない情報が
    見える脆弱性
    2021/10/4 LT
    ham

    View full-size slide

  2. 前提条件
    下記のようなUserとTeamというTypeがあるとします。
    Userは複数のチームに所属しており、Teamには複数のユーザーが所属しているとします。
    type User {
    id: ID!
    name: String!
    teams(afterなど): TeamConnection
    }
    type Team {
    id: ID!
    name: String!
    users(afterなど): UserConnection
    }

    View full-size slide

  3. 前提条件
    Teamを取得するQueryを定義します。
    type Query {
    team(teamId: ID!): Team!
    }
    このクエリーはアクセス制御されており、teamIdで指定したチームを閲覧許可された利用者のみが閲覧できるように制御
    しています。

    View full-size slide

  4. クエリー実行
    例えば下記のクエリーでTeamと所属Userを取得することができます。
    利用者がteamIdで指定したチームの閲覧権限がなければ取得できないのでアクセス制御も良さそうに見えます。
    query Team($teamId: ID!) {
    team(teamId, $teamId) {
    id
    name
    users {
    edges {
    node {
    id
    name
    }
    }
    }
    }
    }

    View full-size slide

  5. 次のクエリーではどうでしょうか?
    query Team($teamId: ID!) {
    team(teamId, $teamId) {
    users {
    edges {
    node {
    teams {
    edges {
    node {
    name
    users {...略}
    }
    }
    }
    }
    }
    }
    }
    }
    teamIdには閲覧できるチームを指定
    →アクセスOK
    指定したチームに他チームに所属しているユーザーが含まれている場合、
    そのユーザー経由で別チームの情報まで取得することができる。
    →トップ階層のアクセス制御だけでなく、関連 Typeのアクセス制御も考慮が
    必要

    View full-size slide

  6. 今後の方針(まだ迷っている...)
    ● DBカラム≒typeのように汎用的にtypeを作った場合、この脆弱性を埋め込
    んでしまう可能性が高い。
    ● クエリーごとにtypeを分ければ発生しないが似たtypeが乱立してしまう。
    ● Typeを何階層もまとめて取得したいケースはあまりないのではないか?とい
    う仮説のもと、次ページの方針でしばらく様子を見る。

    View full-size slide

  7. 今後の方針(まだ迷っている...)
    ● 親子関係の場合、親から子を参照するfieldのみ許可する。
    ● 親子関係以外の場合、fieldに指定するtypeはスカラー型だけのtypeとす
    る。さらに先のtypeを取得したい場合は別途クエリーを実行する。
    type Team {
    id: ID!
    name: String!
    users(afterなど): UserConnection
    }
    UserConnectionには別typeのfieldは定義しない。
    もしUserに紐づくtypeを取得したい場合は、別途 User主
    体のクエリーを実行する。

    View full-size slide