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 1 commit
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
56 changes: 40 additions & 16 deletions cheatsheets_draft/GraphQL_Cheat_Sheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Below are some quick high-level ideas to keep in mind when building a secure API

- Strict input validation is highly recommended and easy
bigshebang marked this conversation as resolved.
Show resolved Hide resolved
- Expensive queries can easily lead to Denial of Service (DoS); there are several defenses ranging from simple to complex
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- Expensive queries can easily lead to Denial of Service (DoS); there are several defenses ranging from simple to complex
- Use simple and straight forward queries. Expensive queries will lead to Denial of Service attacks.

- It is very important to implement proper access control (authorization) but it can be tricky
- It is very important to implement proper access control (authorization), but this can be tricky
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- It is very important to implement proper access control (authorization), but this can be tricky
- Ensure proper access control checks are there.

- Some default configurations (Introspection, GraphiQL, excessive errors) should be disabled/changed before releasing an API to production
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- Some default configurations (Introspection, GraphiQL, excessive errors) should be disabled/changed before releasing an API to production
- Disable default configurations (_e.g._ Introspection, GraphiQL, excessive errors, etc.).


## Common Attacks
Expand Down Expand Up @@ -112,10 +112,10 @@ Adding timeouts can be a simple way to limit how many resources any single reque

At the application level, timeouts can be added for queries and resolver functions. This option is usually more effective since the query/resolution can be stopped once the timeout is reached. GraphQL does not natively support query timeouts so custom code is required. See [this blog post](https://medium.com/workflowgen/graphql-query-timeout-and-complexity-management-fab4d7315d8d) for more about using timeouts with GraphQL or the two examples below.

> I grabbed the JavaScript snippet from the medium blog post I linked above and the java snippet from [this SO answer](https://stackoverflow.com/a/53277955/1200388). I haven't tested the code to verify it works. Is that something we should do?

***JavaScript Timeout Example***

Code snippet from [this SO answer](https://stackoverflow.com/a/53277955/1200388):

```javascript
request.incrementResolverCount = function () {
var runTime = Date.now() - startTime;
Expand Down Expand Up @@ -173,17 +173,7 @@ To increase efficiency of a GraphQL API and reduce its resource consumption, [th

#### OS/Container Resource Management
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
#### OS/Container Resource Management
#### System Resource Management


> Planning to leave this section in until it's replaced by a better section in the "Availability" section of the [Web Security CS](https://cheatsheetseries.owasp.org/cheatsheets/Web_Service_Security_Cheat_Sheet.html#availability).

> Also we are lacking advice for OS resource limitation on Windows. I have no idea how to do that but come across some [freeware](https://superuser.com/questions/214566/are-there-solutions-that-can-limit-the-cpu-usage-of-a-process) and [open-source](https://github.com/lowleveldesign/process-governor) options. Also found some [MS](https://docs.microsoft.com/en-us/windows/win32/procthread/processor-groups) [documentation](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/ff384148(v=ws.10)) and [pages](https://blogs.iis.net/thomad/put-the-brakes-on-your-application-pools-cpu-rate-limits-in-windows-7) that maybe cover this.

Not properly limiting the amount of resources your API can use (e.g. CPU or memory), may compromise your API responsiveness and availability, leaving it vulnerable to DoS attacks. Some limiting can be done at the operating system level with a combination of [Control Groups(cgroups)](https://en.wikipedia.org/wiki/Cgroups), [User Limits (ulimits)](https://linuxhint.com/linux_ulimit_command/), and [Linux Containers (LXC)](https://linuxcontainers.org/lxc/security/). However, containerization platforms tend to make this task much easier. See the resource limiting section in the [Docker Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-7-limit-resources-memory-cpu-file-descriptors-processes-restarts) for how to prevent DoS when using containers.

#### Batching Attack

[GraphQL batching attack](https://lab.wallarm.com/graphql-batching-attack/)?

> This is an interesting attack that we should add. It seems like Amount Limiting will prevent it but I am not sure if that is the case. Needs some investigation. This may also belong in a different section since it's not DoS, it's brute force.
Not properly limiting the amount of resources your API can use (e.g. CPU or memory), may compromise your API responsiveness and availability, leaving it vulnerable to DoS attacks. Some limiting can be done at the operating system level with a combination of [Control Groups(cgroups)](https://en.wikipedia.org/wiki/Cgroups), [User Limits (ulimits)](https://linuxhint.com/linux_ulimit_command/), and [Linux Containers (LXC)](https://linuxcontainers.org/lxc/security/) when using Linux. There are also some options that [may work](https://docs.microsoft.com/en-us/windows/win32/procthread/processor-groups) on [Windows](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/ff384148(v=ws.10)), both [native](https://blogs.iis.net/thomad/put-the-brakes-on-your-application-pools-cpu-rate-limits-in-windows-7) and [third](https://superuser.com/questions/214566/are-there-solutions-that-can-limit-the-cpu-usage-of-a-process) [party](https://github.com/lowleveldesign/process-governor). However, containerization platforms tend to make this task much easier. See the resource limiting section in the [Docker Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-7-limit-resources-memory-cpu-file-descriptors-processes-restarts) for how to prevent DoS when using containers.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd recommend breaking this down. Too big. If I am a Win user I don't want to read everything.
The Windows links is for win7 and 2008 R2. That's not a good recommendation. If there isn't anything else, don't set them.

I'd split these into 3 steps/sections/paragraphs

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 I hastily grabbed the first windows resources I could find, but yeah those OSes are deprecated now so I'll remove.

I'll also break this paragraph out to be more digestible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I just removed the Windows section completely. Most of the links are old and I have never had any experience with them. We can add Windows recommendations at another time.


### Access Control

Expand All @@ -201,8 +191,6 @@ To ensure that a GraphQL API has proper access control, do the following:

It's commonplace for GraphQL requests to include one or more direct IDs of objects in order to fetch or modify them. For example, a request for a certain picture may include the ID that is actually the primary key in the database for that picture. As with any request, the server must verify that the caller has access to the object they are requesting. But sometimes developers make the mistake of assuming that possession of the object's ID means the caller should have access. Failure to verify the requester's access in this case is called [Broken Object Level Authentication](https://github.com/OWASP/API-Security/blob/master/2019/en/src/0xa1-broken-object-level-authorization.md), also known as [IDOR](https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html).

> New section from nikitastupin. Not something I can personally verify with my limited GraphQL experience, so would be great if someone else can check this out.

It's possible for a GraphQL API to support access to objects using their ID even if that is not intended. Sometimes there are `node` or `nodes` or both fields in a query object, and these can be used to access objects directly by `ID`. You can check whether your schema has these fields by running this on the command line (assuming that `schema.json` contains your GraphQL schema): `cat schema.json | jq ".data.__schema.types[] | select(.name==\"Query\") | .fields[] | .name" | grep node`. Removing these fields from the schema should disable the functionality, but you should always apply proper authorization checks to verify the caller has access to the object they are requesting.

#### Query Access (Data Fetching)
Expand Down Expand Up @@ -232,6 +220,42 @@ app.use('/graphql', graphqlHTTP({
}));
```

### Batching Attacks
bigshebang marked this conversation as resolved.
Show resolved Hide resolved
bigshebang marked this conversation as resolved.
Show resolved Hide resolved

Because GraphQL supports batching requests for multiple different objects of the same type in a single network call it allows what is called a [batching attack](https://lab.wallarm.com/graphql-batching-attack/). This is a form of brute force attack, specific to GraphQL, that usually allows for faster and less detectable exploits. Here is an example query of a single batched GraphQL call requesting multiple different objects of type `droid`:

```javascript
query {
droid(id: "2000") {
name
}
second:droid(id: "2001") {
name
}
third:droid(id: "2002") {
name
}
}
```
bigshebang marked this conversation as resolved.
Show resolved Hide resolved

In this case it could be used to enumerate every possible `droid` object that is stored on the server in very few network requests as opposed to a standard REST API where the requester would need to submit a different network request for every different `droid` ID they want to request. This type of attack can lead to the following issues:

- Enumerating every instance of an object on the server, such as users, emails, and user IDs.
- Brute forcing passwords, 2 factor authentication codes (OTPs), session tokens, or other sensitive values.
- WAFs, RASPs, IDS/IPS, SIEMs, or other security tooling will likely not detect these attacks since they only appear to be one single request rather than an a massive amount of network traffic.
- This attack will likely bypass existing rate limits in tools like Nginx or other proxies/gateways since they rely on looking at the raw number of requests.
bigshebang marked this conversation as resolved.
Show resolved Hide resolved

#### Mitigating Batching Attacks

In order to mitigate this type of attack you should put limits on incoming requests at the code level so that they can be applied per request. There are 2 main options:
bigshebang marked this conversation as resolved.
Show resolved Hide resolved

- Prevent batching for sensitive objects
- Add object request rate limiting in code
bigshebang marked this conversation as resolved.
Show resolved Hide resolved

One option is to prevent batching for sensitive objects that you don't want to be brute forced, such as usernames, emails, passwords, OTPs, session tokens, etc. This way an attacker is forced to attack the API like a REST API and make a different network call per object instance. This is not supported natively so it will require a custom solution. However once this control is put in place other standard controls will function normally to help prevent any brute forcing.

Another option is to create a code-level rate limit on how many objects that callers can request. This means the backend would track how many different object instances the caller has requested, so that they will be blocked after requesting too many objects even if they batch the object requests in a single network call. This replicates a network-level rate limit that a WAF or other tool would do.
bigshebang marked this conversation as resolved.
Show resolved Hide resolved

bigshebang marked this conversation as resolved.
Show resolved Hide resolved
### Secure Configurations

By default, most GraphQL implementations have some insecure default configurations which should be changed:
Expand Down