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))
}