How to protect popular query language GraphQL APIs from exploits
Many companies, including GitHub, Credit Karma, Intuit and PayPal use GraphQL, which is a query language for application programming interfaces (APIs) and a runtime for fulfilling queries with existing data
A recent Gartner report shared that by 2025, more than 50% of enterprises will use GraphQL in production, up from less than 10% in 2021. Originally developed by Facebook, GraphQL is being used to build application programming interfaces (APIs) as an alternative to the better known REST and SOAP.
The open source language has gained popularity since its inception in 2012 because of what its native flexibility offers to those building and calling the API. GraphQL servers and clients work together so that clients specify queries and servers validate data with GraphQL implementations working across various languages.
So let's cover the API security issues related to GraphQL APIs, and the best practices to protect GraphQL APIs, including threats covered in the Open Web Application Security Project OWASP API Security Top 10.
GraphQL allows making multiple resource requests in a single query call, which saves time and bandwidth by reducing the number of network round trips to the server. It also helps to save waterfall network requests, where IT needs to resolve dependent resources on previous requests.
This simplifies pulling large data resources into a framework allowing for pages like Facebook that have your profile, your friends' data, online ads, and maps.
Potential security issues may arise, as GraphQL APIs can be incorrectly coded, resulting in data compromise, access control issues, and other high-risk vulnerabilities. Tackling some items in the GraphQL cheat sheet that the Open Web Application Security Project (OWASP) publishes, we can see what's needed at a minimum to secure GraphQL APIs.
Injection can include OS command injection, SQL style injection, and file inclusion type injections. This means that input validation is extremely important. Trusting client supplied data, without validation of some type, can result in any of these injection styles.
The biggest injection takeaway from the OWASP GraphQL cheat sheet is to permit only certain input via a whitelist while gracefully rejecting poor input without excessive detail.
Almost all denial-of-service attacks are based on resource consumption. If the server is tied up answering a billion requests a second, the server becomes slow and will crash, causing more resource consumption on the backup or load balancing devices.
Fortunately it is possible to stop denial-of-service attacks, including recursion attacks as well as standard resource consumption attacks with simple depth and request limits. Similarly adding pagination means the server doesn't tie up memory with huge data fetches but only fetches one page at a time.
Many other techniques such as time outs are simple to implement as well as moving to a content delivery network (CDN) front end provider.
The simple rule for authorisation is to validate that the end user is permitted to view/modify/create/delete, whatever they are touching, and they need to be validated on every request. This prevents Insecure direct object references (IDOR) attacks as well as mutation attacks.
For batching attacks it is possible to figure out a few queries that work and throw them into one big query to have the server fetch the data in batches. This would allow for things like pulling data for all the records of a certain type. Batching allows for mass data exfiltration utilising the victim API to do the heavy lifting.
My key suggestion is to make sure introspection isn't enabled and to make sure the GraphQL playground is disabled or at a minimum, not public. When testing APIs or simply just looking at API requests and responses, think what could be done to exploit the API. If an error message arises, read it. Does it help, do you have excessive errors enabled still?
Looking at the OWASP GraphQL Cheat Sheet and comparing a GraphQL environment to the suggestions there will certainly advise some great first steps. Where to go next is up to an individual's own risk tolerance and security journey.
Comprehensive API protection requires a prevention-first approach that combines complete API visibility, runtime risk assessment, and remediation with native, inline attack prevention. I have put together best practices that will help you to minimise potential security events associated with your GraphQL APIs:
Step 1: API discovery and inventory tracking: We cannot protect what we can't see. Integration with any element of API management infrastructure using either an inline or out-of-band data collection ensures all APIs, including GraphQL APIs are found, tracked, categorised and assigned a respective owner.
Step 2: API risk assessment and remediation: Acting as a final security check, using predefined or custom risk assessment rules helps uncover and remediate APIs with weak authentication, exposing sensitive data, using verbose error messages, or out of conformance with published specifications.
Step 3: Native, inline protection from attacks and vulnerability exploits: Even a perfectly coded API can be attacked, strengthening the need to actively analyse and prevent attacks in real-time, using predefined, customisable policies with response options that include log, block, rate limit, geo-fence, header injection, or deception configured per app or API.
When it comes to protecting GraphQL APIs from attack, an API protection solution must include comprehensive and native protection against all the threats listed in the OWASP API Security Top 10.
Pitfalls to avoid
# Avoid signature-based tools like WAFs that attackers can easily bypass.
# Stay away from solely DevOps-focused tools and lack a balanced approach to preventing threats while code is being fixed.
# Avoid using a vendor's own test suite to validate this functionality. Create a battery of tests based on your APIs and the threats that can target them.
# Avoid API security tools that cannot natively mitigate threats and rely solely on third-party tools such as WAFs. Such tools cause a time delay between detection and response and higher than average false positives, which leave APIs vulnerable to compromise.
To select a unified API protection (UAP) solution, seek one that addresses all phases of the API security lifecycle to protect GraphQL APIs from attackers and eliminate unknown and unmitigated API security risks that can lead to data loss, fraud, and business disruption.
A comprehensive UAP should create a complete runtime inventory of all managed and unmanaged APIs, known and previously unknown. Discovered APIs risks must be flagged for remediation while sophisticated threats are detected and mitigated in real time.
The result will be complete protection from API threats that cause data loss, theft, fraud and business disruption.