Featured image of post Prometheus golang pprof信息泄露漏洞

Prometheus golang pprof信息泄露漏洞

问题起源

我们的基础设施监控的使用到了prometheus,客户漏洞扫描扫到了Go pprof调试信息泄漏漏洞,按理来说环境是全内网隔离的,不存在什么风险,并且这个漏洞连CVE/CNVD/CNNVD的编号都没有,是安全厂商自己定义的一个编号,其实我是不想处理的,但是没办法,要求处理掉。

复现方式

访问http://ip:port/debug/pprof/ 能够看到golang的调试页面。

处理

这个问题如果你偷懒可以直接使用iptables规则去限制,我说的是彻底解决,那么这个问题分成两个部分:Prometheus Server和exporter

Prometheus Server

我们可以在cmd/prometheus/main.go中找到:

1
2
3
4
5
import (
    ...
    // _ "net/http/pprof" // Comment this line to disable pprof endpoint.
    ...
)

把这个注释掉或者删掉,然后在web/web.go中可以找到如下函数:

1
2
3
4
5
6
func New(logger log.Logger, o *Options) *Handler {
    ...
    // router.Get("/debug/*subpath", serveDebug)
    // router.Post("/debug/*subpath", serveDebug)
    ...
}

把这个路由注释掉,再把具体实现也注释掉:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// func serveDebug(w http.ResponseWriter, req *http.Request) {
// 	ctx := req.Context()
// 	subpath := route.Param(ctx, "subpath")

// 	if subpath == "/pprof" {
// 		http.Redirect(w, req, req.URL.Path+"/", http.StatusMovedPermanently)
// 		return
// 	}

// 	if !strings.HasPrefix(subpath, "/pprof/") {
// 		http.NotFound(w, req)
// 		return
// 	}
// 	subpath = strings.TrimPrefix(subpath, "/pprof/")

// 	switch subpath {
// 	case "cmdline":
// 		pprof.Cmdline(w, req)
// 	case "profile":
// 		pprof.Profile(w, req)
// 	case "symbol":
// 		pprof.Symbol(w, req)
// 	case "trace":
// 		pprof.Trace(w, req)
// 	default:
// 		req.URL.Path = "/debug/pprof/" + subpath
// 		pprof.Index(w, req)
// 	}
// }

再次编译以后访问就是404了。

exporter(以node_exporter为例)

在exporter程序的主入口,也就是packege main中,找到importnet/http/pprof的空白导入去掉:

1
2
3
4
5
import (
    ...
    // _ "net/http/pprof"
    ...
)

再次编译以后访问就只会跳转到metrics路径了。