Identifying SQL Injections in a GraphQL API

sql-master-hero

Overview

Many vulnerabilities in modern web applications occur due to the improper handling of user-supplied input. Command injection, cross-site scripting, XML External Entity (XXE) injections, and SQL injections all emerge from the downstream effects of unsanitized user input. SQL injection has held a high-ranking spot on the OWASP top 10 list since its inception. Despite the seemingly straightforward fix of parameterizing queries and sanitizing search terms, SQL injections continue to occur at a high frequency. As we will explore, even newer technologies like GraphQL are susceptible to classic SQL injection attacks. This blog post describes a SQL injection in a GraphQL API that utilizes Postgres as a back-end database.

Discovering The Vulnerability

Praetorian was engaged to perform a security assessment on an internal web application. The web app allowed employees to create and use processes that operated on financial data. These processes were stored in the application’s backend and were accessed using a GraphQL API. After proxying the traffic through Burpsuite, Praetorian’s security engineers observed that a specific series of functions were called when an authenticated user created a new process. One of these functions retrieved data based on a search term. This search term was generated on the client side based on how an authenticated user interacted with the application. The function call could be intercepted and the search term altered with Burpsuite’s interceptor. Knowing that the application relied on an SQL database made the function a prime target to test for potential SQL injections.

Praetorian was able to intercept the request and replace the search term with an SQL payload (“’ OR 1=1–”). This produced a SQL error, confirming that SQL injections were possible.

Figure 1: Generating an SQL Error

Praetorian identified the SQL injection attack vector with a time-based SQL injection. Information within the database could be extracted by executing a list of targeted true or false SQL queries and analyzing response times. With the help of specially constructed queries, true statements about the data in the database would have a delayed response time while false state returned instantaneously. The following SQL query was used to confirm if the SQL database could execute commands with superuser privileges as it generated a valid list after delaying its response for 25 seconds as per pg_sleep(25):

SQLi Used Below: ‘;SELECT case when (SELECT current_setting(‘is_superuser’))=’on’ then
pg_sleep(25) end;– –

Although false statements returned instantaneously, a delay was used to determine if a statement evaluated a True in subsequent queries. Figure 3 below displays the command returning without any delay, indicating that the command execution that occurs as a result of the SQLi does not occur on behalf of a super user.

Figure 2: Timed response for Admin

Using time-based SQL injection attacks Praetorian was successfully able to enumerate tables and column names stored in the Postgres database. Being able to successfully call the SELECT function on a specified table means that an attacker could enumerate sensitive data within the database. As per the screenshot below Praetorian was able to successfully confirm the existence of a table it had created, called cmd_exec through a blind SQL injection.

Figure 3: Checking for the existence of a table with a valid response.

The INSERT, UPDATE, and DELETE commands were also successfully called on the cmd_exec table indicating that an attacker could directly compromise the integrity and availability of critical data. Attackers could potentially obtain Remote Code Execution through known vulnerabilities like CVE-2019–9193 as well.

Conclusion

SQL injection is still a leading cause of security vulnerability, despite being well-understood. New frameworks, tools, and query languages, such as GraphQL, introduce new opportunities for injections to occur. However, the solution generally remains the same. There are two complementary and successful methods of mitigating SQL Injection attacks:

  • Parameterized queries using bound, typed parameters
  • Careful use of parameterized stored procedures

Parameterized queries are the easiest to adopt, and work in similar ways among most web technologies in use today, including Java, .NET, Perl, and PHP.

icon-praetorian-

See Praetorian in Action

Request a 30-day free trial of our Managed Continuous Threat Exposure Management solution.

About the Authors

Catch the Latest

Catch our latest exploits, news, articles, and events.

Ready to Discuss Your Next Continuous Threat Exposure Management Initiative?

Praetorian’s Offense Security Experts are Ready to Answer Your Questions

0 Shares
Copy link