GraphQL

GraphQL - Medium

Trước tiên, chúng ta tạo account và thực hiện đăng nhập.

Thông thường để kiểm tra xem một trang web có khả năng bị khai thác GraphQL injection hay không, thì chúng ta sẽ kiểm tra xem có tồn tại đường dẫn:

  • /graphql

  • /grpahiql

  • /graphql.php

  • /graphql.console

Tham khảo: https://book.hacktricks.xyz/pentesting/pentesting-web/graphql

Sử dụng burpsuite, chúng ta kiểm tra trong HTTP history sẽ thấy một request tới /graphql dưới method là POST:

image

image

Trong hình có câu query để list ra id, slug, name, createAt của những bài post user có thể xem.

Mình sẽ chỉnh một tí ở câu query cho dễ nhìn:

image

Thử liệt kê tên của tất cả các types đang được sử dụng:

query={__schema{types{name,fields{name}}}}

image

Ở đây chúng ta thấy có 4 types chính là user, post, nude, comment.

Hiển thị chi tiết toàn bộ field và args cho từng field. Hiểu nôm na nó như việc chúng ta đang đi leak thông tin của các table tên bảng, tên cột trong SQL :

query IntrospectionQuery {__schema {queryType { name }mutationType { name }subscriptionType { name }types {...FullType}directives {\n        name\n        description\n        args {\n          ...InputValue\n        }}}}\n\n  fragment FullType on __Type {\n    kind\n    name\n    description\n    fields(includeDeprecated: true) {\n      name\n      description\n      args {\n        ...InputValue\n      }\n      type {\n        ...TypeRef\n      }\n      isDeprecated\n      deprecationReason\n    }\n    inputFields {\n      ...InputValue\n    }\n    interfaces {\n      ...TypeRef\n    }\n    enumValues(includeDeprecated: true) {\n      name\n      description\n      isDeprecated\n      deprecationReason\n    }\n    possibleTypes {\n      ...TypeRef\n    }\n  }\n\n  fragment InputValue on __InputValue {\n    name\n    description\n    type { ...TypeRef }\n    defaultValue\n  }\n\n  fragment TypeRef on __Type {\n    kind\n    name\n    ofType {\n      kind\n      name\n      ofType {\n        kind\n        name\n        ofType {\n          kind\n          name\n        }\n      }\n    }\n  }

Tham khảo: https://gist.github.com/craigbeck/b90915d49fda19d5b2b17ead14dcd6da

Chúng ta thấy ở trong nude code flag, khả năng cao là secret mà chúng ta cần tìm đang nằm ở đây:

image

Mình thử query vào nude xem sao nhưng không có quyền access:

image

Quan sát trong Comment chúng ta sẽ thấy có mutation createComment cho phép chúng ta tạo mới một comment.

Có một điều đáng lưu ý ở đây là ở trong args của comment chúng ta thấy có nude. Vậy nên chúng ta có thể tạo mới một comment, sau đó query tới nude trong comment và lấy flag mà không cần phải query trực tiếp vào nude:

Tạo mới một comment cần có: userId, postId, nudeId, comment (nội dung comment):

image

Xác định userId của mình:

image

PostId:

Ở đây có 3 post chúng ta có thể chọn một trong 3 post để tạo comment vào

image

Nude vì mình không biết flag đang nằm ở nudeId bao nhiêu nên mình sẽ để là 1:

mutation { createComment(userId:1,postId:1,nudeId:1,comment:\"hehe\"){comment,id}}

image

Bây giờ mình thử đi đọc comment vừa tạo, nhưng có một vấn đề là comment chỉ được đọc bởi admin, nên mình không thể đọc trực tiếp được:

image

Kiểm tra lại trong field post chúng ta sẽ thấy có comments, chứa tất cả comment của bài post. Vậy nên chúng ta sẽ đọc comment thông qua bài post.

Lúc nãy mình thực hiện comment vào bài post có id là 1 nên giờ mình sẽ đọc commnent từ bài post này ra:

image

Thành công đọc được comment và flag ở trong nude, nhưng thứ chúng ta cần tìm vẫn chưa có ở đây. Chứng tỏ flag không nằm trong nude có nudeId là 1.

Giờ mình sẽ thêm lại comment mới nhưng lúc này nudeId là 2:

image

Đến đây thì chúng ta sẽ có được flag cần tìm:

image

Last updated