visit
Working with the latest tech is fun. It’s fresh and exciting. As developers we
feel invigorated by being on the bleeding edge. Consider us thrill
seekers.
Thrills, however, shouldn’t come from 2am alerts resulting in the binge triaging of production security bugs found in that latest tech stack. Perhaps
it’s the reason you’re here. Perhaps you believe, like we do, that bugs
are best squashed before deploying to prod.
StackHawk was built to help developers ship secure applications. Existing
security testing tools do not work well with modern development
paradigms. We’ve built functionality to ensure that modern developers
can run security tests simply, including CI integrations, scanning REST
API backed applications, and more.
As we work to cover the modern application stack, we were well aware of
the black hole for GraphQL security testing.We just released GraphQL
scanning support to ensure that you can ship secure GraphQL APIs.
But before we jump into the specifics of the solution and follow up with a
demo, let’s do a quick overview of the GraphQL specification. This is a
unique space with an interesting set of challenges.
If you’re already well versed in GraphQL and the potential challenges
posed by its current state of scan-ability, please feel free to skip
ahead to How it Works for a demo and walkthrough.
If you enjoy a little flavor and some additional back story then I welcome you to join me on a brief detour.
Now unless your tech stack has been in a quarantine with the rest of us,
you’ve probably seen GraphQL implementations in the wild. If your
business is inline with, or already one of the 3,026 star adopters reported in the, then you’re probably already building and deploying a in production today.
Again, being at the forefront of change is always an exciting adventure, but have you taken time to ask yourself…
How secure is my GraphQL API?
If we take a look at some of the numbers, such as the report for Drupal customers or this survey on the , we get a sense of how this new specification continues gaining traction.
A rising popularity of any new technology typically results in a rise in
broken implementations. Considering most of these apps are likely to
lack proper testing we suddenly have some serious concerns.
While our craft remains the same despite new paradigms, the way in which we express ourselves through our systems will naturally have to be
adjusted. This change presents a potential breeding ground for unchecked vulnerabilities on new and existing web apps.
At StackHawk, we believe it is important to simplify and automate security testing for your applications.
Indeed. The specification on the surface defines an outline for representing and interfacing with your data… as a graph and stuff.
At its core GraphQL works on the principle that data is interconnected and can be effectively represented as vertices on a graph. Most of us will be aware that this means two or more pairs of connected vertices, having one or more edges which may or may not come together to form forests,
trees and leaves in a directed, acyclical or cyclical fashion, etc, ad infinitum… recursively, and on and on.
This is all just to say that the designers of GraphQL have brilliantly
outlined the capacity for engineers to represent data in pretty much any complex structure desired (or maybe not desired). Anything goes as long as the implementation is within the confines of the specification and
meets a few key criteria.
It’s the Wild West of the web! In fact, if you live in a quiet part of the
city on dark summer evenings and draw the blinds, turn down the lights,
and listen very carefully, you may just catch the sound of the faint grumblings emitted by backend engineers all over as they beg for mercy from the agony of rearchitecting their RESTful service into the promised land The Graph.
Now, this is dangerously close to falling into some wretched and poorly
written essay about graph theory and the GraphQL API, but that would never be nearly as informative as what’s already available at so let’s fast forward to what this all means for the security bottom-line.
One key feature of GraphQL that we at StackHawk, and your potential
attacker no doubt, will employ in our endeavors to discover and audit
routes is one of introspection.
An introspection query allows a client to request a fully inclusive description of the API in a single query, which can contain all the
definitions of types, fields, custom types, primitives, directives,
subscriptions and other operations which we can query.
HawkScan gathers this introspection data and quickly begins to determine
available routes throughout the app. It then proceeds to generate
queries which include fields and dependencies, expected input values,
and available parameters to use as variable arguments. We provide the
required input types, unwrapped custom types, scalars, enums, lists and
so on and insert test values wherever possible.
Along with this automatic discovery and generation of both query and mutation requests, we further provide the ability to tune the scanner with
options such as making GET vs POST requests, setting recursion depth on
introspection, and setting control over the method of how queries are generated. The latter being configurable for either batch form compost of all fields and types, or individual requests with each field and required type sent one-by-one.
is SQL Injection whether the route exists in a REST endpoint, an input form with sanitization missing, or a field query that takes an input
parameter in GraphQL. Remote code injections are possible here, as they have been from the beginning of web applications, and they aren’t going away any time soon.
Security through obscurity is not a viable practice. If you have GraphQL running in your ecosystem, we’ll help you ensure that you ship secure
applications.
Let’s see it in action!
Adding security testing to your GraphQL application is easy with StackHawk. Below are details of how to test it with our sample . This will also serve as an example of how you can set up StackHawk to scan your own app.
We begin by pulling down StackHawk’s vulnerable GraphQL project from Github.
git clone https://github.com/stackhawk/vuln-graphql-api.git
Choose a listening port for the app and build the project with docker-compose:
SERVER_PORT=3000
docker-compose up
Once done, you’ll have a vulnerable GraphQL instance to attack. Now, let’s run theHawkScan, StackHawk’s security scanner.
Log in to your (or sign up if you don’t have an account) and create a new application.
Make sure to provide the //localhost and the selected port that reflects your setup:
If you’ve run through StackHawk’s initial setup during account creation, you should already have a hawk.rc file saved in an accessible location. This contains the
HAWK_API_KEY
that links to your account. If this is missing, simply generate a new key in the Account UI and populate that file.After creating the new application, download the generated stackhawk.yml base file and place it in the source’s path. Then, go ahead and edit with your favorite editor (I’m not biased but ).
Inside we’ll add two new lines under the app portion of the yaml:
app:
graphQL: true
graphQLConf: # Optional
schemaPath: /graphql
With that, we’re ready to scan. Initiate the scan with the following:
source ~/.hawk/hawk.rc
docker run -e API_KEY=${HAWK_API_KEY} --rm -v $(pwd):/hawk:rw -it stackhawk/hawkscan:latest
HawkScan updates the status and progress on the terminal while it runs. GraphQL focused scans will typically find a lot more routes, so expect some longer runtimes.
Upon completion you’ll see the output of all discovered routes and alerts.
We can see in the output of our scan that we’ve found two high severity
bugs in this vulnerable GraphQL app. One for SQL Injection and another for Remote Code Execution.
These are two nasty bugs that you hopefully will never see in your app. If
you have StackHawk running tests on every PR, then you know these bugs
will never see the light of prod.
Back in the UI, our results are now available under the Applications view:
Browse the findings and we can now grab the original request query and response and proceed to take action, accordingly.
Let’s have a quick look at the Remote OS Command Injection alert.
We find our GraphQL query present in the Request view:
{"query":"mutation
superSecretPrivateMutation($command:String ) {
superSecretPrivateMutation(command:$command) { stdout stderr }
}","variables":{"command":"KaaaKaww!&cat /etc/passwd&"}}
And the response in the Response view:
{"data":{"superSecretPrivateMutation":{"stdout":"
root:x:0:0
:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:/sbin/n
root:x:0:0
:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nadm:x:3:4:adm:/var/adm:/sbin/nologin\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\nsync:x:5:0:sync:/sbin:/bin/sync\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8:12:mail:/var/spool/mail:/sbin/nologin\noperator:x:11:0:operator:/root:/sbin/nologin\ngames:x:12:100:games:/usr/games:/sbin/nologin\nftp:x:14:50:FTP
User:/var/ftp:/sbin/nologin\nnobody:x:65534:65534:Kernel Overflow
User:/:/sbin/nologin\ndbus:x:81:81:System message
bus:/:/sbin/nologin\nsystemd-coredump:x:999:997:systemd Core
Dumper:/:/sbin/nologin\nsystemd-resolve:x:193:193:systemd
Resolver:/:/sbin/nologin\napp:x:1000:1000::/home/app:/bin/bash\n","stderr":"/bin/sh:
KaaaKaww!: command not found\n"}}}
This would be a frightening sight, indeed, if this had been a production bug!
That concludes this week’s HawkTastic adventure, folks. And remember, make sure to always run StackHawk to help keep your web services fortified, healthy, happy, and most importantly, free of security bugs. Until next time, be sure to scan early and scan often!
KAAKAWW!
Previously published at