Skip to content

debugging-interface-publicly-exposed

Ensure debug interface is not exposed

Certain frameworks may allow debugging interfaces to be exposed over the web. Debugging interfaces should never be publicly exposed as they often allow for remote code execution or leak sensitive data.

In the Go standard library, importing the "net/http/pprof" package automatically exposes profiling tools on the default HTTP server under the /debug/pprof path. Sometimes this debug package is left in production code, in which case it should be removed. If you do want to include the "net/http/pprof" package however, override the http.DefaultServeMux configuration to instead expose those paths on a different HTTP port (such as port 6060) and not expose it to the public.

Examples

Insecure Example

package main

import (
    "fmt"
    "log"
    "net/http"

    // The mere fact of importing the package adds routes to http.DefaultServeMux
    _ "net/http/pprof"
)

func main() {
    // Some simple Hello World
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello World!")
    })

    // If publicly exposed, this exposes powerful profiling / debugging interface
    // This would allow an attacker to dump the Web server's memory or cause Denial Of Service
    log.Fatal(http.ListenAndServe(":80", nil))
}

Secure Example

package main

import (
    "fmt"
    "log"
    "net/http"

    // The mere fact of importing the package adds routes to http.DefaultServeMux
    _ "net/http/pprof"
)

func main() {
    // Reset default routes (removing access to profiling)
    http.DefaultServeMux = http.NewServeMux()

    // Recreating routes to profiling manually
    pprofServeMux := http.NewServeMux()
    pprofServeMux.HandleFunc("/debug/pprof/", pprof.Index)
    pprofServeMux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
    pprofServeMux.HandleFunc("/debug/pprof/profile", pprof.Profile)
    pprofServeMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
    go func() {
        log.Fatal(&http.Server{
            // Only use routes for the profiling interface
            Handler: pprofServeMux,
            // Exposing them on loopback on a specific port for debbuging access
            Addr:    "localhost:6060",
        }.ListenAndServe())
    }()

    // Some simple Hello World
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello World!")
    })
    // This will only expose the Hello World endpoint
    log.Fatal(http.ListenAndServe(":80", nil))
}