nuclei/pkg/fuzz/dataformat/graphql_test.go

112 lines
3.2 KiB
Go

package dataformat
import (
"strings"
"testing"
"github.com/stretchr/testify/require"
)
const (
graphqlQueryWithInlineArgs = `{
"query": "\n query {\n jobs(jobType: \"front-end\") {\n id\n name\n type\n description\n }\n }\n "
}`
graphqlQueryWithVariables = `{
"query": "mutation ImportPaste ($host: String!, $port: Int!, $path: String!, $scheme: String!) {\n importPaste(host: $host, port: $port, path: $path, scheme: $scheme) {\n result\n }\n }",
"variables": {
"host": "example.com",
"port": 80,
"path": "/robots.txt",
"scheme": "http"
}
}`
)
func Test_GraphQL_IsGraphQL(t *testing.T) {
graphql := NewGraphql()
require.True(
t,
graphql.IsType(graphqlQueryWithInlineArgs),
"expected query to be detected as graphql",
)
require.False(
t,
graphql.IsType("not a graphql query"),
"expected query to not be detected as graphql",
)
require.False(
t,
graphql.IsType(`{"query": "not a graphql query"}`),
"expected query to not be detected as graphql",
)
}
func Test_GraphQL_DecodeEncode_InlineArgs(t *testing.T) {
decodeQueryGetKV := func(query string) (KV, map[string]interface{}, *Graphql) {
graphql := NewGraphql()
decoded, err := graphql.Decode(query)
require.Nil(t, err, "could not decode graphql query")
keyValues := make(map[string]interface{})
decoded.Iterate(func(key string, value interface{}) bool {
if strings.HasPrefix(key, "#_") {
return true
}
keyValues[key] = value
return true
})
return decoded, keyValues, graphql
}
// Test decoding and encoding
t.Run("inline args with variables", func(t *testing.T) {
decoded, keyValues, graphql := decodeQueryGetKV(graphqlQueryWithVariables)
require.Equal(t, map[string]interface{}{
"host": "example.com",
"port": float64(80),
"path": "/robots.txt",
"scheme": "http",
}, keyValues)
decoded.Set("path", "/robots.txt; cat /etc/passwd")
// Test encoding
encoded, err := graphql.Encode(decoded)
require.Nil(t, err, "could not encode graphql query")
_, newKeyValues, _ := decodeQueryGetKV(encoded)
require.Equal(t, "/robots.txt; cat /etc/passwd", newKeyValues["path"])
// Try to write non-string paths as well
t.Run("non-string paths", func(t *testing.T) {
decoded.Set("port", "80; cat /etc/passwd")
encoded, err = graphql.Encode(decoded)
require.Nil(t, err, "could not encode graphql query")
_, newKeyValues, _ = decodeQueryGetKV(encoded)
require.Equal(t, "80; cat /etc/passwd", newKeyValues["port"])
})
})
t.Run("inline args", func(t *testing.T) {
decoded, keyValues, graphql := decodeQueryGetKV(graphqlQueryWithInlineArgs)
require.Equal(t, map[string]interface{}{
"jobType": "front-end",
}, keyValues)
decoded.Set("jobType", "canary")
// Test encoding
encoded, err := graphql.Encode(decoded)
require.Nil(t, err, "could not encode graphql query")
_, newKeyValues, _ := decodeQueryGetKV(encoded)
require.Equal(t, map[string]interface{}{
"jobType": "canary",
}, newKeyValues)
})
}