From 73492d6b5544b494d83f974dc25b2a5d53a62e3d Mon Sep 17 00:00:00 2001 From: j3ssie Date: Tue, 6 Feb 2024 14:34:51 +0700 Subject: [PATCH 1/6] Adding the scan for Graphql Introspection Query Enabled --- .../graphql-introspection-enabled.bcheck | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 other/GraphQL/graphql-introspection-enabled.bcheck diff --git a/other/GraphQL/graphql-introspection-enabled.bcheck b/other/GraphQL/graphql-introspection-enabled.bcheck new file mode 100644 index 0000000..a057a8c --- /dev/null +++ b/other/GraphQL/graphql-introspection-enabled.bcheck @@ -0,0 +1,42 @@ +metadata: + language: v1-beta + name: "Graphql Introspection Query Enabled" + description: "Refers to the condition where the GraphQL server allows introspection queries, potentially exposing sensitive schema information" + author: "j3ssie" + tags: "exposure", "graphql", "introspection" + +define: + introQuery = "{\"query\":\"\n query IntrospectionQuery {\n __schema {\n \n queryType { name }\n mutationType { name }\n subscriptionType { name }\n types {\n ...FullType\n }\n directives {\n name\n description\n \n locations\n args {\n ...InputValue\n }\n }\n }\n }\n\n fragment FullType on __Type {\n kind\n name\n description\n \n fields(includeDeprecated: true) {\n name\n description\n args {\n ...InputValue\n }\n type {\n ...TypeRef\n }\n isDeprecated\n deprecationReason\n }\n inputFields {\n ...InputValue\n }\n interfaces {\n ...TypeRef\n }\n enumValues(includeDeprecated: true) {\n name\n description\n isDeprecated\n deprecationReason\n }\n possibleTypes {\n ...TypeRef\n }\n }\n\n fragment InputValue on __InputValue {\n name\n description\n type { ...TypeRef }\n defaultValue\n \n \n }\n\n fragment TypeRef on __Type {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n }\n }\n }\n }\n }\n }\n }\n }\n \"}" + +run for each: + potential_path = + "/", + "/api", + "/api/graphql", + "/console", + "/graph", + "/graphiql", + "/graphql", + "/graphql/console/", + "/v1/explorer", + "/v1/graphiql" + +given request then + send request called check: + method: "POST" + path: `{potential_path}` + replacing headers: + "Content-Type": "application/json" + body: `{introQuery}` + + if {latest.response.status_code} is "200" and + {latest.response.headers} matches "application/json" then + if {latest.response.body} matches "__schema" and + {latest.response.body} matches "defaultValue" and + {latest.response.body} matches "queryType" then + report issue: + severity: low + confidence: firm + detail: `Graphql Introspection Query Enabled` + end if + end if From f00e6c0d163a9633249feab41beb03782832154e Mon Sep 17 00:00:00 2001 From: j3ssie Date: Tue, 6 Feb 2024 14:40:58 +0700 Subject: [PATCH 2/6] Adding the scan for SVN Configuration File Exposed --- other/files/svn-exposed.bcheck | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 other/files/svn-exposed.bcheck diff --git a/other/files/svn-exposed.bcheck b/other/files/svn-exposed.bcheck new file mode 100644 index 0000000..3c65882 --- /dev/null +++ b/other/files/svn-exposed.bcheck @@ -0,0 +1,32 @@ +metadata: + language: v1-beta + name: "SVN Configuration File Exposed" + description: "Tests for exposed svn config in current path and at the root directory of site" + author: "j3ssie" + tags: "exposure", "svn", "config", "file" + +run for each: + potential_path = ".svn/entries", ".svn/text", ".svn/all-wcprops", "CVS/Entries" + +given request then + # replace the potential path with the last path + send request called check: + method: "GET" + replacing path: `{regex_replace({regex_replace({base.request.url}, "^.*?\/.*?\/.*?\/", "/")}, "([^/]+)$", "")}{potential_path}` + + # replace the potential path with entire URI + send request called check1: + method: "GET" + replacing path: `{regex_replace({base.request.url}, "^.*", "")}/{potential_path}` + + if {latest.response.status_code} is "200" then + if ("END" in {latest.response.body} and + "svn:" in {latest.response.body}) or + ("dir" in {latest.response.body} and + " Date: Tue, 6 Feb 2024 14:44:32 +0700 Subject: [PATCH 3/6] Adding the scan for .DS_Store Configuration Check --- other/files/ds-store-exposed.bcheck | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 other/files/ds-store-exposed.bcheck diff --git a/other/files/ds-store-exposed.bcheck b/other/files/ds-store-exposed.bcheck new file mode 100644 index 0000000..f0bea4b --- /dev/null +++ b/other/files/ds-store-exposed.bcheck @@ -0,0 +1,32 @@ +metadata: + language: v1-beta + name: ".DS_Store Configuration Check" + description: "Tests for exposed svn config in current path and at the root directory of site" + author: "j3ssie" + tags: "exposure", "ds_store", "config", "file" + +run for each: + potential_path = ".DS_Store" + +given request then + # replace the potential path with the last path + send request called check: + method: "GET" + replacing path: `{regex_replace({regex_replace({base.request.url}, "^.*?\/.*?\/.*?\/", "/")}, "([^/]+)$", "")}{potential_path}` + + # replace the potential path with entire URI + send request called check1: + method: "GET" + replacing path: `{regex_replace({base.request.url}, "^.*", "")}/{potential_path}` + + if {latest.response.status_code} is "200" and + "Bud1" in {latest.response.body} and + "DSDB" in {latest.response.body} then + if {latest.response.headers} matches "Accept-Ranges: bytes" or + {latest.response.headers} matches "octet-stream" then + report issue: + severity: low + confidence: certain + detail: `.DS_Store configuration found at {potential_path}.` + end if + end if From 2eb260a1d81340ae8b5acbe149a05eda10b635d9 Mon Sep 17 00:00:00 2001 From: j3ssie Date: Thu, 8 Feb 2024 01:08:18 +0700 Subject: [PATCH 4/6] Update the language to v2-beta and implement some checks to prevent duplicate requests --- other/files/ds-store-exposed.bcheck | 14 +++++++++----- other/files/svn-exposed.bcheck | 16 ++++++++++------ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/other/files/ds-store-exposed.bcheck b/other/files/ds-store-exposed.bcheck index f0bea4b..d5083a5 100644 --- a/other/files/ds-store-exposed.bcheck +++ b/other/files/ds-store-exposed.bcheck @@ -1,5 +1,5 @@ metadata: - language: v1-beta + language: v2-beta name: ".DS_Store Configuration Check" description: "Tests for exposed svn config in current path and at the root directory of site" author: "j3ssie" @@ -8,11 +8,15 @@ metadata: run for each: potential_path = ".DS_Store" -given request then +given path then # replace the potential path with the last path - send request called check: - method: "GET" - replacing path: `{regex_replace({regex_replace({base.request.url}, "^.*?\/.*?\/.*?\/", "/")}, "([^/]+)$", "")}{potential_path}` + # like if the path is `/v1/settings/public`. it will be convert to `/v1/settings/{potential_path}` + if not({base.request.url.path} is "/") then + send request called check: + method: "GET" + replacing path: `{regex_replace({regex_replace({base.request.url}, "^.*?\/.*?\/.*?\/", "/")}, "([^/]+)$", "")}{potential_path}` + + end if # replace the potential path with entire URI send request called check1: diff --git a/other/files/svn-exposed.bcheck b/other/files/svn-exposed.bcheck index 3c65882..caddbe8 100644 --- a/other/files/svn-exposed.bcheck +++ b/other/files/svn-exposed.bcheck @@ -1,19 +1,23 @@ metadata: - language: v1-beta + language: v2-beta name: "SVN Configuration File Exposed" description: "Tests for exposed svn config in current path and at the root directory of site" author: "j3ssie" tags: "exposure", "svn", "config", "file" run for each: - potential_path = ".svn/entries", ".svn/text", ".svn/all-wcprops", "CVS/Entries" + potential_path = ".svn/entries", ".svn/text", ".svn/all-wcprops" -given request then +given path then # replace the potential path with the last path - send request called check: - method: "GET" - replacing path: `{regex_replace({regex_replace({base.request.url}, "^.*?\/.*?\/.*?\/", "/")}, "([^/]+)$", "")}{potential_path}` + # like if the path is `/v1/settings/public`. it will be convert to `/v1/settings/{potential_path}` + if not({base.request.url.path} is "/") then + send request called check: + method: "GET" + replacing path: `{regex_replace({regex_replace({base.request.url}, "^.*?\/.*?\/.*?\/", "/")}, "([^/]+)$", "")}{potential_path}` + end if + # replace the potential path with entire URI send request called check1: method: "GET" From a4645c78c2326637a6f1cd0dfc270be767acded8 Mon Sep 17 00:00:00 2001 From: Hannah-PortSwigger <58562826+Hannah-PortSwigger@users.noreply.github.com> Date: Thu, 8 Feb 2024 13:19:28 +0000 Subject: [PATCH 5/6] Change graphql-introspection-enabled.bcheck to per host --- other/GraphQL/graphql-introspection-enabled.bcheck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/GraphQL/graphql-introspection-enabled.bcheck b/other/GraphQL/graphql-introspection-enabled.bcheck index a057a8c..26459a9 100644 --- a/other/GraphQL/graphql-introspection-enabled.bcheck +++ b/other/GraphQL/graphql-introspection-enabled.bcheck @@ -21,7 +21,7 @@ run for each: "/v1/explorer", "/v1/graphiql" -given request then +given host then send request called check: method: "POST" path: `{potential_path}` From 21097fca5b2f8e5357ebd213f47525462e3e649f Mon Sep 17 00:00:00 2001 From: Hannah-PortSwigger <58562826+Hannah-PortSwigger@users.noreply.github.com> Date: Thu, 8 Feb 2024 13:38:25 +0000 Subject: [PATCH 6/6] Update svn-exposed.bcheck --- other/files/svn-exposed.bcheck | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/other/files/svn-exposed.bcheck b/other/files/svn-exposed.bcheck index caddbe8..ac2ba98 100644 --- a/other/files/svn-exposed.bcheck +++ b/other/files/svn-exposed.bcheck @@ -9,19 +9,18 @@ run for each: potential_path = ".svn/entries", ".svn/text", ".svn/all-wcprops" given path then - # replace the potential path with the last path - # like if the path is `/v1/settings/public`. it will be convert to `/v1/settings/{potential_path}` - if not({base.request.url.path} is "/") then + if {base.request.url.path} is "/" then + # replace the potential path with entire URI send request called check: + method: "GET" + replacing path: `{regex_replace({base.request.url}, "^.*", "")}/{potential_path}` + else then + # replace the potential path with the last path + # like if the path is `/v1/settings/public`. it will be convert to `/v1/settings/{potential_path}` + send request called check1: method: "GET" replacing path: `{regex_replace({regex_replace({base.request.url}, "^.*?\/.*?\/.*?\/", "/")}, "([^/]+)$", "")}{potential_path}` - end if - - # replace the potential path with entire URI - send request called check1: - method: "GET" - replacing path: `{regex_replace({base.request.url}, "^.*", "")}/{potential_path}` if {latest.response.status_code} is "200" then if ("END" in {latest.response.body} and