Technical information leak - API - Go

Technical information leak - API - Go

Need

Protection of sensitive technical information in the API

Context

  • Usage of Go 1.16 for building high-performance and efficient applications
  • Usage of Gin for building web applications in Go
  • Usage of graphql-go/graphql for implementing GraphQL in a Go application
  • Usage of github.com/graphql-go/handler for handling GraphQL requests in Go

Description

Non compliant code

        package main

import (
	"github.com/gin-gonic/gin"
	"github.com/graphql-go/graphql"
	"github.com/graphql-go/handler"
)

func main() {
	// define schema, with our rootQuery and rootMutation
	schema, _ := graphql.NewSchema(graphql.SchemaConfig{
		Query:    rootQuery,
		Mutation: rootMutation,
	})

	h := handler.New(&handler.Config{
		Schema:   &schema,
		Pretty:   true,
		GraphiQL: true,
	})

	r := gin.Default()
	r.POST("/graphql", gin.WrapH(h))
	r.GET("/", gin.WrapH(h))
	r.Run() // listen and serve on 0.0.0.0:8080
}
        
        

This Go application uses the Gin framework and GraphQL. The /graphql endpoint is exposed for both POST and GET requests.

The GraphQL handler is configured with the application's schema and GraphiQL is enabled. GraphiQL is an in-browser tool for writing, validating, and testing GraphQL queries.

The vulnerability here is that the entire GraphQL schema (including queries and mutations) is exposed via the /graphql endpoint. This means that an attacker can send a GET request to the /graphql endpoint and get back the entire schema. This is a technical information leak vulnerability because it gives away too much information about the backend structure and might help an attacker to craft more targeted attacks.

This vulnerability can be exploited by sending a simple GET request to the /graphql endpoint. The response will contain the entire GraphQL schema structure.

In a production environment, it is recommended to disable the GraphiQL tool and limit the exposure of your GraphQL API schema.

Steps

  • Disable GraphiQL in production environment
  • Remove unnecessary routes or endpoints
  • Implement proper access control and authentication mechanisms
  • Restrict access to the GraphQL schema documentation

Compliant code

        package main

import (
	"github.com/gin-gonic/gin"
	"github.com/graphql-go/graphql"
	"github.com/graphql-go/handler"
	"os"
)

func main() {
	// define schema, with our rootQuery and rootMutation
	schema, _ := graphql.NewSchema(graphql.SchemaConfig{
		Query:    rootQuery,
		Mutation: rootMutation,
	})

	h := handler.New(&handler.Config{
		Schema:   &schema,
		Pretty:   true,
		GraphiQL: false, // Disable GraphiQL
	})

	r := gin.Default()
	r.POST("/graphql", gin.WrapH(h)) // Only allow POST requests to /graphql
	if os.Getenv("ENV") == "development" { // Only enable GraphiQL in development environment
		r.GET("/graphql", gin.WrapH(h))
	}
	r.Run() // listen and serve on 0.0.0.0:8080
}
        
        

The above code fixes the vulnerability by disabling GraphiQL in production environments and only allowing POST requests to the /graphql endpoint.

The GraphiQL interface is a great tool for development and testing, but it can expose sensitive information about your API's schema and data structure in a production environment. Therefore, it's best to disable it in production. This is achieved by setting GraphiQL: false in the handler configuration.

The code also restricts the HTTP methods that can be used to interact with the /graphql endpoint. By only allowing POST requests, we can prevent attackers from using GET requests to retrieve the API schema.

Finally, the code checks the environment variable "ENV" to determine whether the application is running in a development environment. If it is, the GraphiQL interface is enabled. This allows developers to continue using the tool while ensuring it's disabled in production.

Remember, these changes alone may not fully secure your application. You should also implement proper access control and authentication mechanisms to further protect your API.

References