WedX - журнал о программировании и компьютерных науках

Предотвращение эксплойта утечки данных о взаимоотношениях с помощью graphql

Как сделать так, чтобы люди не запрашивали отношения между объектами, которые они не должны видеть в graphql?

Например, предположим, что у нас есть следующая модель данных.

type Board {
    id: ID! @unique
    name: String!
    boardUserRoles: [BoardUserRole!]!
}

type BoardUserRole {
    id: ID! @unique
    board: Board!
    user: User!
    role: BoardRole!
}

type User {
    id: ID! @unique
    tasks: [Task!]!
    userName: String! @unique
    boardUserRoles: [BoardUserRole!]!
}

Это настройка, в которой есть пользователи, которые имеют доступ к определенным доскам. И BoardUserRole определяет, какую роль играет пользователь для конкретной таблицы.

Теперь я захожу и запрашиваю доску, на которую у меня есть разрешение, и смотрю на ее название.

query {
    board(where: {id: "3"}) {
        id
        name
    }
}

Это прекрасно. Однако я могу связаться с другими пользователями системы и увидеть задачи, которые у них есть, если я изменю запрос. Я могу видеть все, что связано с этим пользователем.

query {
    board(where: {id: "3"}) {
        id
        name
        boardUserRoles {
            user {
                tasks
            }
        }
    }
}

Как защитить себя от запросов такого типа?


  • это серьезный вопрос? это похоже на «У меня есть таблица sql с паролем - как не показывать их с помощью select» - API просто не должен возвращать данные, у которых нет прав. Неважно, что это sql, rest, graphql или что угодно. Проверить документы Prisma? 11.08.2018
  • @xadm да. Серьезный. Возможно, я что-то неправильно понимаю, но если у пользователя есть доступ к доске 3, как бы вы помешали ему использовать остальную схему для обхода графа для доступа к другим данным? Вы делаете это очевидным, поэтому, пожалуйста, дайте мне знать, о чем вы думаете. Я прочитал Prisma, Apollo и graphql и ничего не нашел о том, как запретить кому-либо запрашивать весь граф в одном запросе. Я знаю способ сделать это, переопределив info, который поступает на преобразователь, только с теми данными, которые я хочу, чтобы они получали, но я не хочу лишать пользователей этой возможности. 11.08.2018
  • В graphql вы можете иметь безопасность на уровне поля. It doesn't matter it's traversing or simple query - резолвер всегда беру отдельно. Вы должны ограничить возвращаемые поля, когда у пользователя нет разрешения. F.e. не показывать некоторые данные, не обновлять содержимое сообщения, если вы не являетесь автором или модератором ... 2-секундный поиск в Google: github.com/prismagraphql/prisma/issues/1768, директивы разрешений prisma ... 11.08.2018
  • @xadm, это действительно хорошие книги, я считаю, что это именно то, что я ищу. Подробнее об этом в понедельник. Ty 11.08.2018

Ответы:


1

С помощью @xadm. Мне удалось собрать решение, которое идеально мне подошло.

После прочтения этой статьи о том, как работает выполнение запроса . Я понял, как писать преобразователи полей. Преобразователь полей позволяет мне определять, как именно разрешается конкретное поле. Я сделал преобразователь полей для Board: boardUserRoles.

Вот мой преобразователь поля.

Board: {
    boardUserRoles: async (parent: Board, args, ctx, info) => {
        // getting user id from header.
        const userId: string = VerificationHelper.getUserId(ctx);

        // Verifying role of user.
        return VerificationHelper.verifyRole(userId, ["ADMIN"], ctx).pipe(
            map(
                (result: boolean) => {
                    // If the user has an admin role, show the roles
                    if (result) {
                        return parent.boardUserRoles;
                    // If not, map the results to undefined
                    } else {
                        return undefined;
                    }
                }
            )
        ).toPromise();
    }
}

Затем я добавил этот преобразователь в свой список преобразователей при создании graphql.

const server: GraphQLServer = new GraphQLServer({
    typeDefs: "src/schema.graphql",
    resolvers: {
        Query: QueryResolvers,
        Mutation: MutationResolvers,
        Subscription: SubscriptionResolvers,
        ...FieldResolvers, // A file that contains all my field resolvers.
        AuthPayload
    },
    context: (req: any) => ({
        ...req,
        prisma: new Prisma({
            typeDefs: "src/generated/prisma.graphql",
            endpoint: endpoint()
        })
    })
});

Это очень простой преобразователь полей. Он проверяет роль пользователя и определяет, следует ли скрывать данные или отображать данные. Я просмотрел всю свою схему и нашел другие эксплойты данных. Я исправил те, которые нашел с помощью преобразователей полей, и теперь все работает отлично.

Спасибо за помощь @xadm, ваши ссылки указали мне правильное направление.

14.08.2018
  • Замечательно! ???? Дайте мне знать, если у вас возникнут другие вопросы по Prisma. 14.08.2018
  • @nburk Подойдет, изучаю graphql прямо сейчас и получаю от этого удовольствие. Предпочитаете его прямо сейчас обычному restAPI. 14.08.2018

  • 2

    При использовании Prisma вы можете изменять структуры данных, которые доступны вашим клиентским приложениям, переопределив тип в схеме приложения.

    Определения SDL, которые вы показываете в своем вопросе, мне кажутся моделью данных Prisma. Я предполагаю, что у вас также есть сервер API (возможно, реализованный с помощью graphl-yoga или apollo-server), который предоставляет API GraphQL, который будет использоваться вашими клиентскими приложениями. Назовем схему GraphQL, определяющую этот API, схемой приложения. Внутри схемы приложения вы можете переопределить типы из вашей модели данных так, как вы хотите предоставить их своим клиентам.

    Вот простой пример:

    Предположим, у вас есть следующий User тип в вашей модели данных Prisma:

    type User {
      id: ID! @unique
      email: String! @unique
      password: String!
      name: String!
      posts: [Post!]!
    }
    

    Теперь вы не хотите раскрывать password своим клиентам. Итак, что вы можете сделать, так это переопределить тип User таким образом, чтобы ваши клиенты могли получить к нему доступ. Вот как вы можете определить его в схеме приложения (часто называемой schema.graphql):

    type User {
      id: ID!
      email: String!
      name: String!
      posts: [Post!]!
    }
    

    Вы можете найти работающую версию этого примера здесь . Кроме того, если вас смущает терминология схемы приложения и модели данных, я рекомендую вам прочитать эта часть документации Prisma.

    14.08.2018
  • Я полностью понимаю, о чем вы говорите. Я не знал, что могу переопределить свои типы в schema.graphql. Я думал, что это предназначено только для резольверов. Это проницательно, но не решение моей проблемы. Мне нужно, чтобы определенные вещи были открыты на основании авторизации. Я разобрался и опубликую свое решение через несколько минут. Спасибо! 14.08.2018
  • Новые материалы

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]