Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New CS: GraphQL #434

Merged
merged 29 commits into from
Oct 30, 2020
Merged
Changes from 5 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ca64aac
Merge pull request #1 from OWASP/master
bigshebang Jun 17, 2020
c32fd1e
feat: add first draft of GraphQL Cheat Sheet
bigshebang Jun 18, 2020
904b814
chore: fix formatting to match guidelines
bigshebang Jun 18, 2020
d67346a
chore: md clean up
ThunderSon Jun 20, 2020
bf8ccf8
chore: header tweaks
ThunderSon Jun 20, 2020
5d0c975
revision 1 based on feedback
bigshebang Aug 16, 2020
6b41373
Add ORM/ORD feedback from PauloASilva
bigshebang Aug 19, 2020
b6fc880
Add tool vs API feedback from PauloASilva
bigshebang Aug 19, 2020
0166339
Adding DoS change from PauloASilva
bigshebang Aug 23, 2020
b025b22
Another DoS change from PauloASilva
bigshebang Aug 23, 2020
0547d00
Add missing parenthesis to link
bigshebang Aug 23, 2020
045a21f
adding real content for OS DoS placeholders
bigshebang Sep 2, 2020
0b3844a
added an example attack query for amount limiting
bigshebang Sep 2, 2020
506a287
touched up the DoS section a bit
bigshebang Sep 2, 2020
c483d37
rearranging IDOR to be under the access control section
bigshebang Oct 5, 2020
c734132
Important wording fix from PauloASilva
bigshebang Oct 6, 2020
934c422
IDOR clarification from PauloASilva
bigshebang Oct 6, 2020
c86ef61
move content to new insecure defaults section
bigshebang Oct 8, 2020
5fa8cb1
Merge branch 'new-CS_421' of github.com:bigshebang/CheatSheetSeries i…
bigshebang Oct 8, 2020
2613cf6
add content for batch attacks; clean up other loose ends
bigshebang Oct 12, 2020
d43e786
Add batching attack mitigation for DOS attacks, from Paulo
bigshebang Oct 14, 2020
5afd00a
add content changes/additions per Paulo's suggestions
bigshebang Oct 14, 2020
d891cc6
Fix wording and add proper input validation CS link
bigshebang Oct 23, 2020
4092bbe
Letting ThunderSon fix up some javascript
bigshebang Oct 23, 2020
67d47bb
changes based on ThunderSon's feedback
bigshebang Oct 23, 2020
2f8b358
Update cheatsheets_draft/GraphQL_Cheat_Sheet.md
bigshebang Oct 23, 2020
5d865f5
fixing remaining CS links
bigshebang Oct 23, 2020
3f960b1
changing WSTG from latest to stable
bigshebang Oct 23, 2020
dc5486a
Fixing javascript code snippet
bigshebang Oct 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
128 changes: 128 additions & 0 deletions cheatsheets_draft/GraphQL_Cheat_Sheet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# GraphQL Cheat Sheet

## Introduction

- Strict input validation is highly recommended and easy
bigshebang marked this conversation as resolved.
Show resolved Hide resolved
- Expensive queries can easily lead to a denial of service, but defending against this is not simple
- It can be tricky and is very important to implement proper access control (authorization)
- Common attacks become much more likely if input from external parties is directly ingested by the service

## Common Attacks

- Injection
- [SSRF](https://portswigger.net/web-security/ssrf) (also [CRLF](https://owasp.org/www-community/vulnerabilities/CRLF_Injection) [injection](https://www.acunetix.com/websitesecurity/crlf-injection/) or [Request](https://portswigger.net/web-security/request-smuggling) [Smuggling](https://www.pentestpartners.com/security-blog/http-request-smuggling-a-how-to/))
- [SQL](https://portswigger.net/web-security/sql-injection) [injection](https://owasp.org/www-community/attacks/SQL_Injection)
- [DoS](https://owasp.org/www-community/attacks/Denial_of_Service) ([Denial of Service](https://www.cloudflare.com/learning/ddos/glossary/denial-of-service/))
- [IDOR](https://portswigger.net/web-security/access-control/idor)
bigshebang marked this conversation as resolved.
Show resolved Hide resolved
- Abuse of improper/excessive access

## Best Practices and Recommendations

### Input Validation

Adding strict input validation can help prevent against SSRF, SQL injection, and DoS. The main design for GraphQL is that an identifier is given and the backend has a number of fetchers making HTTP, DB, or other calls. This means that user input will be included in HTTP requests, DB queries, or other requests/calls and there is opportunity for injection that could lead to SSRF or SQL injection. Some pages that may be helpful here are OWASP Cheat Sheets for generic [Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html) or [Java Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet_in_Java.html).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest to avoid narrowing injections to SQL injection, since GraphQL is widely used with NoSQL databases.
I am afraid someone reading this may think: "I am not using SQL so I am safe". We shall not neglect LDAP queries, OS commands, XML parsers, and ORM/ODM injections.

Linking to API8:2019 Injection makes sense since:

  1. we describe real API attacker scenarios
  2. there's a "How To Prevent" section

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I very much agree with this feedback! But as I work on this rewrite, I have a problem calling out "ORM injection" as an issue. I have less experience with ORMs so maybe I'm off base here, but it seems to me that when a developer uses an ORM properly it will parameterize their queries and prevent injection entirely. Where devs would get into trouble is using functionality of an ORM that allows for non-parameterized queries like raw query execution/manipulation or similar.

So I think calling it "ORM injection" isn't really accurate; it's actually just plain old SQL injection but using an ORM, which is just a different driver/connection than is traditionally used. Instead I think the advice to devs should be to use parameterized queries with their ORM and not to use their ORM to mess with raw queries.

Any thoughts on that? We don't necessarily need to agree on terminology of whether ORM injection is its own attack, but we should agree on the recommendation to devs using ORMs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point.

The ORM Injection is a little different from a plain SQL Injection, since the attacker will target the ORM itself or the SQL generated by the ORM, instead of the DBMS.

A developer may choose an ORM that offers parameterized queries as well as a fluent querying API to programmatically build queries (example). Although the parameterized queries API is safe, attackers may trick the ORM to generate unsafe SQL.

Any thoughts on that? We don't necessarily need to agree on terminology of whether ORM injection is its own attack, but we should agree on the recommendation to devs using ORMs.

I am OK recommending ORMs/ODMs as long as we add something like: "ORMs/ODMs may introduce other issues such as ORM Injection: always audit your dependencies."

Copy link

@inonshk inonshk Aug 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to add one more point: when exploiting SSRF, we don't really break or the change the syntax of any command/query/code.
Hence, I wouldn't say that SSRF is a type of injection


#### General Practices

> We can probably nix this section and just link to the Input Validation Cheat Sheet. I'll leave for now in case there is anything of value somebody else sees and thinks should be left in.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is fine IMO. Short introduction and link to the other CS.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to go with a general recommendation and an items list with the appropriate references.
Shorter sentences look more actionable and 1) GraphQL is well-documented and 2) other CSs already have most of what's needed to address the issue.

Example:
Validate incoming data using sufficient filters to only allow valid values for each input parameter.


Implementing this should be very simple for most data types. Whitelist the characters that are allowed for any input given to the API and throw an error if illegal characters are given. For example, a user's ID might only contain numbers, so limiting an input field for user IDs to numbers is the best approach. The allowed characters will depend on the piece of data being passed. If alphanumeric characters are allowed there is very little risk of SSRF with an HTTP call. There is also very little risk for SQL injection, but any DB queries should be parameterized anyway. Unicode characters should also be disallowed unless they are specifically required in a field. If the field must have more than alphanumeric characters or Unicode then the other protection options (sanitization and/or parameterization) will be needed.

This can be achieved by using specific GraphQL types (such as numbers or enums) or by writing custom GraphQL [validators](https://graphql.org/learn/validation/) for more complicated validations.

See the OWASP Cheat Sheet on [Input Validation](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html) for more info.

#### SQL Injection Prevention

Anytime a DB or similar query is being made, any input should be properly parameterized with prepared statements or stored procedures in order to prevent SQL/DB injection. See the [OWASP Cheat Sheet for SQL Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html) for more info.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I don't like the idea of narrowing Injections to SQL Injection.
GraphQL is widely used with NoSQL databases and LDAP queries, OS commands, XML parsers, and ORM/ODM injections can not be neglected.

While looking for public API incidents to include in the OWAS API Security Top 10, we found several OS commands.


When handling input meant to be passed to another interpreter (e.g. SQL/NoSQL, OS, LDAP), always prefer safe APIs with support for parameterized statements. If such APIs are not available, always escape/encode input data according to the target interpreter.

  • Use prepared statements for querying as a way to prevent SQL Injection.
  • Escape/Encode input data according to the target interpreter e.g. OS, LDAP.
  • Choose a well-documented and actively maintained escaping/encoding library.


#### Process Validation

When using user input, even if sanitized and/or validated it should not be used for certain purposes that would give a user control over data flow. For example, do not make an HTTP/resource request to a host that the user supplies (unless there is a business need).

### Resource Management

> I assume we don't want the "internal vs external" API talk in here?

For a GraphQL API that receives input more or less directly from an external party, it can be difficult to limit the possibilities a malicious user can use to exhaust the API's resources to cause slow downs or indefinite outages. It is easier to protect an API that is only used by other internal services. Because of this, it may be better to only expose your API internally. See the table below for which of these controls should be added to each type of GraphQL API.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely we should not say "Because of this, it may be better to only expose your API internally".
I am not sure whether I understood your thoughts about resources managements.

My suggestion

Not properly limiting the amount of resource your API can use (e.g. CPU or memory), may compromise your API responsiveness and availability, leaving it vulnerable to DoS attacks. Containerization platforms tend to make this task much easier: see how to limit memory, CPU, number of restarts, file descriptors, and processes using Docker.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doc was originally made for my company which has APIs that are internal-only and externally-facing. So I was trying to basically say if the API is not exposed externally we don't have to be as careful with preventing DoS given the low likelihood of exploitation and significant cost to add protections against DoS. I don't know if we want to add this line of thinking to a CS; it's basically recommending to accept the risk because it's low enough. Seems out of place in a CS but is valuable info to engineering teams.

There are a ton of things that can be done to prevent DoS, for sure. We could link to the DoS CS, but it seems in need of work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, now I see your point, nevertheless I still think it is risky to say something like that.

  • "Internal-only" is something hard to define and someone may lower defenses based on a wrong premise.
  • If internal-only APIs interact with external services, then those services are potential threat agents.
  • Sometimes threat agents belong to the organization.
  • Compromised systems may allow access to internal-only APIs.

I don't think that we should advice accepting even low enough risks.
This is something engineering teams should discuss and define with the business: what's the risk it is willing to accept.

Let's see what other think about this subject.

Regarding the work needed in the DoS CS, may be we can open a new issue to put it in the agenda.


#### Depth Limiting

This is limiting the depth of incoming queries so that the user cannot supply unnecessarily deep queries that could consume a lot of resources. See [this](https://www.apollographql.com/blog/securing-your-graphql-api-from-malicious-queries-16130a324a6b) and [this blog post](https://www.howtographql.com/advanced/4-security/) as well as [this Github repo](https://github.com/stems/graphql-depth-limit) (old, potentially unsupported) for more details on implementing this control. I'm not sure if there is a good/trusted open source project that does this.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would delete _ I'm not sure if there is a good/trusted open source project that does this._.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah from my quick searching I couldn't really find anything legit or trusted. We can def delete this. It seems like the code to do this is pretty simple though; would be cool to see an official OWASP project tackle this!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you feel that it is worth to have a short code snippet here we can think about it.
We try to not have longer code samples because they are hard to maintain but short snippet or pseudocode is a good idea sometimes.


#### Amount Limiting

This is limiting the quantity that can be requested for a given resource/object. See [this](https://www.apollographql.com/blog/securing-your-graphql-api-from-malicious-queries-16130a324a6b) and [this blog post](https://www.howtographql.com/advanced/4-security/) as well as [this Github repo](https://github.com/joonhocho/graphql-input-number) for more details on implementing this control. I'm not sure if there is a good/trusted open source project that does this.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about shortly summarising these articles and link to them only for further reference. Now it is impossible to use it without reading more articles that can disappear in some time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion

The amount of resources required to satisfy a request greatly depends on the user input and endpoint business logic. As long as your API accepts concurrent requests, what is generally true, then these requests compete for available resources.

  • Define and enforce maximum size of data on all incoming parameters and payloads such as maximum length for strings and maximum number of elements in arrays.
  • Add proper validation for request parameters controlling the number of resources to be returned in the response.
  • Implement pagination mechanism to limit the amount of data to be returned in a single request/response.


#### Timeouts

Adding timeouts can be a simple way to limit how much resources any single request can consume. Timeout requirements will differ by API and data fetching mechanism; there isn't one timeout value that will work across the board. It doesn't seem like GraphQL natively supports timeouts so this would require custom code (non-trivial) or adding a timeout on an HTTP server, reverse proxy, or load balancer (easy). See [this](https://www.howtographql.com/advanced/4-security/) and [this blog post](https://medium.com/workflowgen/graphql-query-timeout-and-complexity-management-fab4d7315d8d) about timeouts with GraphQL.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check if timeouts are nativley supported. If not then delete It doesn’t seem.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not aware of any native timeouts.
Such feature would be implementation dependent. No reference to timeouts was found in the popular Apollo Server documentation.


#### Query Cost Analysis

This is not easy to implement and may not always be needed. See [this blog post](https://www.apollographql.com/blog/securing-your-graphql-api-from-malicious-queries-16130a324a6b) for more details on implementing this control.

Apollo recommends: "**Before you go ahead and spend a ton of time implementing query cost analysis be certain you need it.** Try to crash or slow down your staging API with a nasty query and see how far you get — maybe your API doesn’t have these kinds of nested relationships, or maybe it can handle fetching thousands of records at a time perfectly fine and doesn’t need query cost analysis!"

#### Rate Limiting

Enforcing rate limiting on a per IP/user basis can help limit a single user's ability to spam requests to the service. Ideally this can be done with a WAF, API gateway, or web server to reduce the cost of adding rate limiting.

Or you could get somewhat complex with throttling and implement it in your code (non-trivial). See [here](https://www.howtographql.com/advanced/4-security/) for more about GraphQL-specific throttling.

### Access Control

There are three main areas for managing access/permissions with GraphQL:

- Queries (data fetching)
- Mutation (write) queries
- [Introspection](https://graphql.org/learn/introspection/) system/query

Each of these need to have permission checks for most GraphQL setups.

#### Query Access

As part of a GraphQL API there will be various data fields that can be returned. One thing to consider is if you want different levels of access around these fields. For example, you may only want certain consumers to be able to fetch certain data fields rather than allowing all consumers to be able to retrieve all available fields. This can be done by adding a check in the code to ensure that the requestor should be able to read a field they are trying to fetch. This may be best implemented with simple [role-based access control](https://auth0.com/docs/authorization/concepts/rbac) ([RBAC](https://en.wikipedia.org/wiki/Role-based_access_control)): by creating roles which have access to certain fields and then attaching the correct roles to individual consumers/users. ABAC or other access control methods could also work.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we should link to our RBAC cheatsheet https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Access_Control_Cheat_Sheet.md#role-based-access-control-rbac and if we are missing something in that CS let improve it :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GraphQL Interfaces and Unions, as well as Query Resolvers are good recommendations to tackle access control issues:

  • Interfaces and Unions allows to create more structured and "incremental" data types which can be used to return more or less object properties, according to requestor rights
  • Query Resolvers a good candidate to perform access controls maybe using some RBAC middleware.


#### Mutation Access

GraphQL supports mutation, or manipulation of data, in addition to its most common use case of data fetching. If your service implements/allows mutation then there may need to be access controls put in place to restrict which consumers, if any, can modify data through the API. Setups requiring mutation access control include APIs where only read access is intended or where only certain parties should be able to modify certain fields. This should be implemented similarly to Query access: use [RBAC](https://auth0.com/docs/authorization/concepts/rbac) and have the code only allow certain roles to perform mutation on approved data fields.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do agree with the general idea, but we need to make this more actionable.

  • Use Interfaces and Unions to create hierarchical data types.
    Then, based on requester's profile/permissions, return the most appropriate data type.
  • Use Mutation Resolvers to update data, and perform access control validation, may be passing some middleware
  • Always validate whether requester is authorized to execute the requested mutation (RBAC).
    Access Control validation may be performed passing some middleware to the mutation function.


#### Introspection
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GraphiQL is quite often found on production systems.
We should also add some recommendation to do not deploy such tools in production environments, nor make them publicly accessible on other environments (e.g. QA, staging, dev).

May be this should has it's own category e.g. "Security Misconfigurations", but it came up to my mind while reviewing the Introspection section, because it's GraphiQL first query.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't heard of GraphiQL. Great call out! I think we should add a general note about not providing utilities like this in production and specifically name GraphiQL.


Many implementations of GraphQL have Introspection enabled by default and leave it accessible to any incoming requests without requiring authentication. This is usually problematic because introspection allows the requester to learn all about supported schema and queries (see a [real-world example](https://hackerone.com/reports/291531) abusing this). Introspection might be how the API owner wants to educate consumers about how to use the API. However, the preferred way to educate consumers about a service is through a separate documentation channel such as a wiki, Git Readme, or readthedocs.

The safest and usually easiest approach is to just disable introspection system-wide. See [this page](https://lab.wallarm.com/why-and-how-to-disable-introspection-query-for-graphql-apis/) or consult your GraphQL implementation's documentation to learn how to disable introspection altogether. If your implementation does not natively support disabling introspection or if you would like to allow some consumers/roles to have this access you can build a filter in your service to only allow approved consumers to access the introspection system.

### IDOR Protection
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In OWASP API Security Top 10 2019 we decided to split IDOR back in two different categories:

Insecure Direct Object Reference isn't a very accurate name: there's nothing insecure about using object's unique identifier as long as proper access control validations are performed. Creating some identifiers indirection won't solve the real issue unless the translation mechanism performs the required access control validations.

How are these recommendations different from "Query Access" ones?

I think we should remove this section and add the IDOR CS as a reference to the Query Access section.


See the [IDOR prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html) for a comprehensive rundown of preventing IDOR.

More specific to GraphQL, it's likely that you want consumers to be able to provide the direct identifier rather than creating an abstraction layer, which can be fine. In this case you would simply add a check that the requestor is able to access the ID that they gave. For APIs where individuals make their own requests (such as traditional website with backend API) you would just be checking that the ID given is owned by the user who is authenticated (e.g. does user 123 own picture with ID 564?). For more of a service account scenario where one consumer makes requests on behalf of many users it may not make sense to add a check if a given service account should be able to access any object.

> The additional mitigation technique below probably belongs in the IDOR prevention cheat sheet but isn't there so I'll leave it here for now.

One alternative protection would be creating an abstraction of the ID that is usually mapped to the requester's session. For example, instead of the user requesting a picture via its direct ID, they would request picture 2 in their account and the backend would use that abstract ID with the user's ID to derive the actual direct ID of the picture. This prevents the user from being able to provide their own direct identifier for an object and ensures that the user can only access objects belonging to them. Another abstraction mechanism could involve using different IDs for the frontend vs the backend with some unpredictable translation that happens on the backend where the user does not have any influence.

## Other Resources
bigshebang marked this conversation as resolved.
Show resolved Hide resolved

> I went overboard with external resources, so these should probably be pared down a bunch.

- [https://leapgraph.com/graphql-api-security](https://leapgraph.com/graphql-api-security) - GraphQL security best practices
- [https://www.apollographql.com/blog/securing-your-graphql-api-from-malicious-queries-16130a324a6b](https://www.apollographql.com/blog/securing-your-graphql-api-from-malicious-queries-16130a324a6b) - Covers Depth Limiting, Amount Limiting, & Query Cost Analysis
- [https://blog.doyensec.com/2018/05/17/graphql-security-overview.html](https://blog.doyensec.com/2018/05/17/graphql-security-overview.html) - some common attacks; attacker mindset related to GraphQL
- [https://medium.com/swlh/protecting-your-graphql-api-from-security-vulnerabilities-e8afdfa6fbe4](https://medium.com/swlh/protecting-your-graphql-api-from-security-vulnerabilities-e8afdfa6fbe4) - Protecting GraphQL APIs from security threats
- [https://labs.detectify.com/2018/03/14/graphql-abuse/](https://labs.detectify.com/2018/03/14/graphql-abuse/) - bypassing permissions by smuggling parameters
- [https://nordicapis.com/security-points-to-consider-before-implementing-graphql/](https://nordicapis.com/security-points-to-consider-before-implementing-graphql/)
- [https://www.apollographql.com/docs/graphql-tools/scalars/](https://www.apollographql.com/docs/graphql-tools/scalars/)
- [https://itnext.io/custom-scalars-in-graphql-9c26f43133f3](https://itnext.io/custom-scalars-in-graphql-9c26f43133f3)
- [https://developer.github.com/v4/guides/resource-limitations/](https://developer.github.com/v4/guides/resource-limitations/) - limiting resource usage to prevent DoS (timeouts, throttling, complexity management, depth limiting, etc.)
- [https://medium.com/workflowgen/graphql-query-timeout-and-complexity-management-fab4d7315d8d](https://medium.com/workflowgen/graphql-query-timeout-and-complexity-management-fab4d7315d8d) - handling timeouts and managing query complexity (preventing DoS)
- [https://medium.com/bugbountywriteup/graphql-voyager-as-a-tool-for-security-testing-86d3c634bcd9](https://medium.com/bugbountywriteup/graphql-voyager-as-a-tool-for-security-testing-86d3c634bcd9) - attacker mindset
- [https://raz0r.name/articles/looting-graphql-endpoints-for-fun-and-profit/](https://raz0r.name/articles/looting-graphql-endpoints-for-fun-and-profit/) - attacker mindset
- [https://medium.com/planes-agency/how-to-survive-a-penetration-test-as-a-graphql-developer-2759cababf8e](https://medium.com/planes-agency/how-to-survive-a-penetration-test-as-a-graphql-developer-2759cababf8e) - developer focused security
- [Real](https://vulners.com/myhack58/MYHACK58:62201994269) [world](https://www.pentestpartners.com/security-blog/pwning-wordpress-graphql/) [attacks](https://hackerone.com/reports/419883) [against](https://vulners.com/hackerone/H1:435066) [GraphQL](https://www.jonbottarini.com/2018/01/02/abusing-internal-api-to-achieve-idor-in-new-relic/) [in the](https://about.gitlab.com/blog/2019/07/03/security-release-gitlab-12-dot-0-dot-3-released/#authorization-issues-in-graphql) past
- [Security talk about Abusing GraphQL](https://www.youtube.com/watch?v=NPDp7GHmMa0)
- [https://www.abhaybhargav.com/from-the-trenches-diy-security-perspectives-of-graphql/](https://www.abhaybhargav.com/from-the-trenches-diy-security-perspectives-of-graphql/)
- [https://cheatsheetseries.owasp.org/cheatsheets/SQL\_Injection\_Prevention\_Cheat\_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html) - OWASP's SQL Injection Prevention Cheat Sheet
- [https://cheatsheetseries.owasp.org/cheatsheets/Insecure\_Direct\_Object\_Reference\_Prevention\_Cheat\_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html) - OWASP's IDOR prevention Cheat Sheet