Giter Site home page Giter Site logo

graphql-cop's Introduction

GraphQL Cop - Security Audit Utility for GraphQL

GraphQL Cop

About

GraphQL Cop is a small Python utility to run common security tests against GraphQL APIs. GraphQL Cop is perfect for running CI/CD checks in GraphQL. It is lightweight, and covers interesting security issues in GraphQL.

GraphQL Cop allows you to reproduce the findings by providing cURL commands upon any identified vulnerabilities.

Requirements

  • Python3
  • Requests Library

Detections

  • Alias Overloading (DoS)
  • Batch Queries (DoS)
  • GET based Queries (CSRF)
  • POST based Queries using urlencoded payloads (CSRF)
  • GraphQL Tracing / Debug Modes (Info Leak)
  • Field Duplication (DoS)
  • Field Suggestions (Info Leak)
  • GraphiQL (Info Leak)
  • Introspection (Info Leak)
  • Directives Overloading (DoS)
  • Circular Query using Introspection (DoS)
  • Mutation support over GET methods (CSRF)

Usage

$ python graphql-cop.py -h

Usage: graphql-cop.py -t http://example.com -o json

Options:
  -h, --help            show this help message and exit
  -t URL, --target=URL  target url with the path - if a GraphQL path is not
                        provided, GraphQL Cop will iterate through a series of
                        common GraphQL paths
  -H HEADER, --header=HEADER
                        Append Header(s) to the request '{"Authorization":
                        "Bearer eyjt"}' - Use multiple -H for additional
                        Headers
  -o FORMAT, --output=FORMAT
                        json
  -f, --force           Forces a scan when GraphQL cannot be detected
  -d, --debug           Append a header with the test name for debugging
  -x PROXY, --proxy=PROXY
                        HTTP(S) proxy URL in the form
                        http://user:pass@host:port
  -v, --version         Print out the current version and exit.

Test a website

$ python3 graphql-cop.py -t https://mywebsite.com/graphql

                GraphQL Cop 1.1
           Security Auditor for GraphQL
            Dolev Farhi & Nick Aleks

Starting...
[HIGH] Introspection Query Enabled (Information Leakage)
[LOW] GraphQL Playground UI (Information Leakage)
[HIGH] Alias Overloading with 100+ aliases is allowed (Denial of Service)
[HIGH] Queries are allowed with 1000+ of the same repeated field (Denial of Service)

Test a website, dump to a parse-able JSON output, cURL reproduction command

python3 graphql-cop.py -t https://mywebsite.com/graphql -o json

 {'curl_verify': 'curl -X POST -H "User-Agent: graphql-cop/1.2" -H '
                 '"Accept-Encoding: gzip, deflate" -H "Accept: */*" -H '
                 '"Connection: keep-alive" -H "Content-Length: 33" -H '
                 '"Content-Type: application/json" -d \'{"query": "query { '
                 '__typename }"}\' \'http://localhost:5013/graphql\'',
  'description': 'Tracing is Enabled',
  'impact': 'Information Leakage',
  'result': False,
  'severity': 'INFO',
  'color': 'green',
  'title': 'Trace Mode'},
 {'curl_verify': 'curl -X POST -H "User-Agent: graphql-cop/1.2" -H '
                 '"Accept-Encoding: gzip, deflate" -H "Accept: */*" -H '
                 '"Connection: keep-alive" -H "Content-Length: 64" -H '
                 '"Content-Type: application/json" -d \'{"query": "query { '
                 '__typename @aa@aa@aa@aa@aa@aa@aa@aa@aa@aa }"}\' '
                 "'http://localhost:5013/graphql'",
  'description': 'Multiple duplicated directives allowed in a query',
  'impact': 'Denial of Service',
  'result': True,
  'severity': 'HIGH',
  'color': 'red',
  'title': 'Directive Overloading'}]

Test a website using graphql-cop through a proxy (e.g. Burp Suite listening on 127.0.0.1:8080) with custom headers (e.g. Authorization):

$ python3 graphql-cop.py -t https://mywebsite.com/graphql --proxy=http://127.0.0.1:8080 --header '{"Authorization": "Bearer token_here"}'

                GraphQL Cop 1.2
           Security Auditor for GraphQL
            Dolev Farhi & Nick Aleks

Starting...
[HIGH] Introspection Query Enabled (Information Leakage)
[LOW] GraphQL Playground UI (Information Leakage)
[HIGH] Alias Overloading with 100+ aliases is allowed (Denial of Service)
[HIGH] Queries are allowed with 1000+ of the same repeated field (Denial of Service)

graphql-cop's People

Contributors

darksilenxe avatar dolevf avatar fabaff avatar halfluke avatar hd421 avatar joanbono avatar mjfwebb avatar n3rada avatar petermosmans avatar sp3nx0r avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

graphql-cop's Issues

Stack trace discovery

Hi Dolev,

I've just found this new tool of yours and it looks pretty cool!
I've tested it on an assessment I had at work and I've found minor things that could be improved - of course it works perfectly on dvga!
I'll see if I can submit some little PRs if I find the time

Quick question: looking at info_trace_mode.py, I am not able to understand what it looks for in order to decide if trace mode is enable.
Would you mind to explain?
I tried to alter the related query to:
{"query": "query { __typenaaame }"}

and I get on dvga:
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
Content-Length: 117
Date: Fri, 19 Aug 2022 18:53:39 GMT

{"errors":[{"message":"Cannot query field "__typenaaame" on type "Query".","locations":[{"line":1,"column":9}]}]}

But it's still not flagged as an issue.
I am not sure how these lines work, to be honest:
try:
if gql_response.json().get('errors', {}).get('extensions', {}).get('tracing'):
res['result'] = True
elif gql_response.json().get('errors', {}).get('extensions', {}).get('exception', None):
res['result'] = True
elif 'stacktrace' in str(gql_response.json()).lower():
res['result'] = True
except:
pass

Thank you for another awesome tool and for dvga v2!

No module Found Error

I tried to run python graphql-cop.py , but it throws error like this

Traceback (most recent call last):
File "graphql-cop.py", line 9, in
from lib.tests.info_field_suggestions import field_suggestions
ModuleNotFoundError: No module named 'lib.tests'

JSON output format is incorrect

The JSON output when using the -o json option is invalid.

A snippet from the very start of the output:

{'result': False, ...

This should look like this:

{"result": false, ...

I'll create a PR ๐Ÿ˜ƒ

Tag the source

It would be very helpful if you could add tags. This would make it easier to keep track and include graphql-cop into distributions.

Thanks

Using graphql-cop as package

@dolevf ,
In continuation with the issue earlier discussed : #27

We are planning to use the library in our org. But it requires licensing details and also needs to be available as a package as downloading public git repo's are not allowed. So any plan to package and publish it as it would be helpful

Aswathy

Doesn't run graphql-cop.py

I tried several times both on local and real URLs but did not succeed. The error is like the following.

Ps: the project is on and lives in port 1003.

x@Mac graphql-cop % python3 graphql-cop.py -t http://192.168.1.2:1003/graphql
Traceback (most recent call last):
  File "/path/to/folder/graphql-cop/graphql-cop.py", line 64, in <module>
    if field_suggestions(url, proxy, HEADERS):
TypeError: field_suggestions() takes 1 positional argument but 3 were given

Failing to find GraphQL

The following code at line 87:

for path in paths:
    if not is_graphql(path, proxy, HEADERS):
        print(path, 'does not seem to be running GraphQL.')
        continue
    for test in tests:
        json_output.append(test(path, proxy, HEADERS))

Is not finding graphql endpoints that are clearly present.

Screenshot 2022-11-01 092015

Screenshot 2022-11-01 091729

If I comment out the if not is_graphql statement and run the tests, the tests are successful.

image

Screenshot 2022-11-01 092305

I cannot run graphql-cop

Every time I run the command python3 graphql-cop -t {target IP} i get this output. I am not sure what to do please advise.

Traceback (most recent call last):
File "/home/hapihacker/tools/graphql-cop/graphql-cop.py", line 101, in
json_output.append(test(path, proxy, HEADERS, options.debug_mode))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/hapihacker/tools/graphql-cop/lib/tests/dos_field_duplication.py", line 22, in field_duplication
res['curl_verify'] = curlify(gql_response)
^^^^^^^^^^^^^^^^^^^^^
File "/home/hapihacker/tools/graphql-cop/lib/utils.py", line 9, in curlify
req = obj.request
^^^^^^^^^^^
AttributeError: 'dict' object has no attribute 'request'

Wondering about the Accept header

Hi Doleh,

do you think graphql-cop should use the Accept: application/json header by default instead of */* ?
As I mentioned previously, the environment where I tested would immediately error out if the Accept header was not application/json.

Additionally, have you noticed that running it against DVGA does not return the GraphiQL IDE finding unless Accept is set to text/html ?
We can override the header with -H, but I was thinking of setting it by default in the info_graphiql.py check.
Two lines of codes for a PR: one before the check to set it and one before the end to remove it, if you want :)

License statement

Currently there is no license statement. Could you please add a LICENSE file that contains the license text. Shipping the LICENSE file is a requirement for some distributions (e.g., Fedora).

Thanks.

Module Not Found Error

While attempting to run the script, I received the following error: ModuleNotFoundError: No module named 'lib.tests'. After reviewing the lib and tests directory I noticed you're missing a init.py file in both directories. After adding the init.py file, the script runs as expected. I assuming this is broken for a reason?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.