【go语言系列】(202410) go语言中httpServer的pprof漏洞如何避免

背景

工作中写的一个go代码被安全中心检查出来了pprof漏洞,想要避免这个问题,故做了如下实验。

解决方案1:直接去掉pprof

代码如下

左边的代码没有pprof包,右边的代码有pprof包,两边各起了两个httpServer

image.png

分别开两个shell启动进程

1
2
3
4
# go run hEqual1/main.go -a="0.0.0.0:6010" -b="0.0.0.0:6011" 
2024/10/22 06:36:47 Starting server on 0.0.0.0:6010
2024/10/22 06:36:47 Starting server on 0.0.0.0:6011

1
2
3
4
# go run hEqual0/main.go -a="0.0.0.0:6020" -b="0.0.0.0:6021" 
2024/10/22 06:37:05 Starting server on 0.0.0.0:6020
2024/10/22 06:37:05 Starting server on 0.0.0.0:6021

校验结果:
有pprof包的结果如下:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
[root@ningan chapter58-httpserver]# curl http://192.168.20.201:6010/debug/pprof/goroutine?debug=1
goroutine profile: total 4
1 @ 0x430fd1 0x467fbd 0x661411 0x661245 0x65dce6 0x66f2e8 0x66fde5 0x61dee9 0x61f802 0x6204ae 0x61cd14 0x46d821
# 0x467fbc runtime/pprof.runtime_goroutineProfileWithLabels+0x1c /usr/local/go/src/runtime/mprof.go:844
# 0x661410 runtime/pprof.writeRuntimeProfile+0xb0 /usr/local/go/src/runtime/pprof/pprof.go:734
# 0x661244 runtime/pprof.writeGoroutine+0x44 /usr/local/go/src/runtime/pprof/pprof.go:694
# 0x65dce5 runtime/pprof.(*Profile).WriteTo+0x145 /usr/local/go/src/runtime/pprof/pprof.go:329
# 0x66f2e7 net/http/pprof.handler.ServeHTTP+0x4a7 /usr/local/go/src/net/http/pprof/pprof.go:267
# 0x66fde4 net/http/pprof.Index+0xe4 /usr/local/go/src/net/http/pprof/pprof.go:384
# 0x61dee8 net/http.HandlerFunc.ServeHTTP+0x28 /usr/local/go/src/net/http/server.go:2136
# 0x61f801 net/http.(*ServeMux).ServeHTTP+0x141 /usr/local/go/src/net/http/server.go:2514
# 0x6204ad net/http.serverHandler.ServeHTTP+0x8d /usr/local/go/src/net/http/server.go:2938
# 0x61cd13 net/http.(*conn).serve+0x5f3 /usr/local/go/src/net/http/server.go:2009

1 @ 0x43bb8e 0x434597 0x468385 0x4b2da7 0x4b38fa 0x4b38e8 0x5581a5 0x562125 0x616c57 0x46d821
# 0x468384 internal/poll.runtime_pollWait+0x84 /usr/local/go/src/runtime/netpoll.go:343
# 0x4b2da6 internal/poll.(*pollDesc).wait+0x26 /usr/local/go/src/internal/poll/fd_poll_runtime.go:84
# 0x4b38f9 internal/poll.(*pollDesc).waitRead+0x279 /usr/local/go/src/internal/poll/fd_poll_runtime.go:89
# 0x4b38e7 internal/poll.(*FD).Read+0x267 /usr/local/go/src/internal/poll/fd_unix.go:164
# 0x5581a4 net.(*netFD).Read+0x24 /usr/local/go/src/net/fd_posix.go:55
# 0x562124 net.(*conn).Read+0x44 /usr/local/go/src/net/net.go:179
# 0x616c56 net/http.(*connReader).backgroundRead+0x36 /usr/local/go/src/net/http/server.go:683

1 @ 0x43bb8e 0x434597 0x468385 0x4b2da7 0x4b446c 0x4b445a 0x5592e9 0x56965e 0x568970 0x620904 0x620571 0x6774dd 0x677489 0x43b71b 0x46d821
# 0x468384 internal/poll.runtime_pollWait+0x84 /usr/local/go/src/runtime/netpoll.go:343
# 0x4b2da6 internal/poll.(*pollDesc).wait+0x26 /usr/local/go/src/internal/poll/fd_poll_runtime.go:84
# 0x4b446b internal/poll.(*pollDesc).waitRead+0x2ab /usr/local/go/src/internal/poll/fd_poll_runtime.go:89
# 0x4b4459 internal/poll.(*FD).Accept+0x299 /usr/local/go/src/internal/poll/fd_unix.go:611
# 0x5592e8 net.(*netFD).accept+0x28 /usr/local/go/src/net/fd_unix.go:172
# 0x56965d net.(*TCPListener).accept+0x1d /usr/local/go/src/net/tcpsock_posix.go:152
# 0x56896f net.(*TCPListener).Accept+0x2f /usr/local/go/src/net/tcpsock.go:315
# 0x620903 net/http.(*Server).Serve+0x363 /usr/local/go/src/net/http/server.go:3056
# 0x620570 net/http.(*Server).ListenAndServe+0x70 /usr/local/go/src/net/http/server.go:2985
# 0x6774dc net/http.ListenAndServe+0x2bc /usr/local/go/src/net/http/server.go:3239
# 0x677488 main.main+0x268 /root/go-practice/chapter58-httpserver/hEqual1/main.go:42
# 0x43b71a runtime.main+0x2ba /usr/local/go/src/runtime/proc.go:267

1 @ 0x43bb8e 0x434597 0x468385 0x4b2da7 0x4b446c 0x4b445a 0x5592e9 0x56965e 0x568970 0x620904 0x620571 0x677745 0x6776ec 0x46d821
# 0x468384 internal/poll.runtime_pollWait+0x84 /usr/local/go/src/runtime/netpoll.go:343
# 0x4b2da6 internal/poll.(*pollDesc).wait+0x26 /usr/local/go/src/internal/poll/fd_poll_runtime.go:84
# 0x4b446b internal/poll.(*pollDesc).waitRead+0x2ab /usr/local/go/src/internal/poll/fd_poll_runtime.go:89
# 0x4b4459 internal/poll.(*FD).Accept+0x299 /usr/local/go/src/internal/poll/fd_unix.go:611
# 0x5592e8 net.(*netFD).accept+0x28 /usr/local/go/src/net/fd_unix.go:172
# 0x56965d net.(*TCPListener).accept+0x1d /usr/local/go/src/net/tcpsock_posix.go:152
# 0x56896f net.(*TCPListener).Accept+0x2f /usr/local/go/src/net/tcpsock.go:315
# 0x620903 net/http.(*Server).Serve+0x363 /usr/local/go/src/net/http/server.go:3056
# 0x620570 net/http.(*Server).ListenAndServe+0x70 /usr/local/go/src/net/http/server.go:2985
# 0x677744 net/http.ListenAndServe+0x1a4 /usr/local/go/src/net/http/server.go:3239
# 0x6776eb main.main.func1+0x14b /root/go-practice/chapter58-httpserver/hEqual1/main.go:34

[root@ningan chapter58-httpserver]#
[root@ningan chapter58-httpserver]#
[root@ningan chapter58-httpserver]#
[root@ningan chapter58-httpserver]# curl http://192.168.20.201:6011/debug/pprof/goroutine?debug=1
goroutine profile: total 4
1 @ 0x430fd1 0x467fbd 0x661411 0x661245 0x65dce6 0x66f2e8 0x66fde5 0x61dee9 0x61f802 0x6204ae 0x61cd14 0x46d821
# 0x467fbc runtime/pprof.runtime_goroutineProfileWithLabels+0x1c /usr/local/go/src/runtime/mprof.go:844
# 0x661410 runtime/pprof.writeRuntimeProfile+0xb0 /usr/local/go/src/runtime/pprof/pprof.go:734
# 0x661244 runtime/pprof.writeGoroutine+0x44 /usr/local/go/src/runtime/pprof/pprof.go:694
# 0x65dce5 runtime/pprof.(*Profile).WriteTo+0x145 /usr/local/go/src/runtime/pprof/pprof.go:329
# 0x66f2e7 net/http/pprof.handler.ServeHTTP+0x4a7 /usr/local/go/src/net/http/pprof/pprof.go:267
# 0x66fde4 net/http/pprof.Index+0xe4 /usr/local/go/src/net/http/pprof/pprof.go:384
# 0x61dee8 net/http.HandlerFunc.ServeHTTP+0x28 /usr/local/go/src/net/http/server.go:2136
# 0x61f801 net/http.(*ServeMux).ServeHTTP+0x141 /usr/local/go/src/net/http/server.go:2514
# 0x6204ad net/http.serverHandler.ServeHTTP+0x8d /usr/local/go/src/net/http/server.go:2938
# 0x61cd13 net/http.(*conn).serve+0x5f3 /usr/local/go/src/net/http/server.go:2009

1 @ 0x43bb8e 0x434597 0x468385 0x4b2da7 0x4b446c 0x4b445a 0x5592e9 0x56965e 0x568970 0x620904 0x620571 0x6774dd 0x677489 0x43b71b 0x46d821
# 0x468384 internal/poll.runtime_pollWait+0x84 /usr/local/go/src/runtime/netpoll.go:343
# 0x4b2da6 internal/poll.(*pollDesc).wait+0x26 /usr/local/go/src/internal/poll/fd_poll_runtime.go:84
# 0x4b446b internal/poll.(*pollDesc).waitRead+0x2ab /usr/local/go/src/internal/poll/fd_poll_runtime.go:89
# 0x4b4459 internal/poll.(*FD).Accept+0x299 /usr/local/go/src/internal/poll/fd_unix.go:611
# 0x5592e8 net.(*netFD).accept+0x28 /usr/local/go/src/net/fd_unix.go:172
# 0x56965d net.(*TCPListener).accept+0x1d /usr/local/go/src/net/tcpsock_posix.go:152
# 0x56896f net.(*TCPListener).Accept+0x2f /usr/local/go/src/net/tcpsock.go:315
# 0x620903 net/http.(*Server).Serve+0x363 /usr/local/go/src/net/http/server.go:3056
# 0x620570 net/http.(*Server).ListenAndServe+0x70 /usr/local/go/src/net/http/server.go:2985
# 0x6774dc net/http.ListenAndServe+0x2bc /usr/local/go/src/net/http/server.go:3239
# 0x677488 main.main+0x268 /root/go-practice/chapter58-httpserver/hEqual1/main.go:42
# 0x43b71a runtime.main+0x2ba /usr/local/go/src/runtime/proc.go:267

1 @ 0x43bb8e 0x434597 0x468385 0x4b2da7 0x4b446c 0x4b445a 0x5592e9 0x56965e 0x568970 0x620904 0x620571 0x677745 0x6776ec 0x46d821
# 0x468384 internal/poll.runtime_pollWait+0x84 /usr/local/go/src/runtime/netpoll.go:343
# 0x4b2da6 internal/poll.(*pollDesc).wait+0x26 /usr/local/go/src/internal/poll/fd_poll_runtime.go:84
# 0x4b446b internal/poll.(*pollDesc).waitRead+0x2ab /usr/local/go/src/internal/poll/fd_poll_runtime.go:89
# 0x4b4459 internal/poll.(*FD).Accept+0x299 /usr/local/go/src/internal/poll/fd_unix.go:611
# 0x5592e8 net.(*netFD).accept+0x28 /usr/local/go/src/net/fd_unix.go:172
# 0x56965d net.(*TCPListener).accept+0x1d /usr/local/go/src/net/tcpsock_posix.go:152
# 0x56896f net.(*TCPListener).Accept+0x2f /usr/local/go/src/net/tcpsock.go:315
# 0x620903 net/http.(*Server).Serve+0x363 /usr/local/go/src/net/http/server.go:3056
# 0x620570 net/http.(*Server).ListenAndServe+0x70 /usr/local/go/src/net/http/server.go:2985
# 0x677744 net/http.ListenAndServe+0x1a4 /usr/local/go/src/net/http/server.go:3239
# 0x6776eb main.main.func1+0x14b /root/go-practice/chapter58-httpserver/hEqual1/main.go:34

1 @ 0x46d821

无pprof包的结果如下:

1
2
3
4
[root@ningan chapter58-httpserver]# curl http://192.168.20.201:6020/debug/pprof/goroutine?debug=1
404 page not found
[root@ningan chapter58-httpserver]# curl http://192.168.20.201:6021/debug/pprof/goroutine?debug=1
404 page not found

结果证明,只要把引用的pprof包删除,便可以解决这个问题~

解决方案2

正常服务端口改为http.NewServeMux

image.png

启动程序

1
go run perfect/main.go -a="0.0.0.0:6030" -b="127.0.0.1:6031"

最终结果如下:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
[root@ningan ~]# curl http://192.168.20.201:6030/debug/pprof/goroutine?debug=1
404 page not found
[root@ningan ~]# curl http://192.168.20.201:6031/debug/pprof/goroutine?debug=1
curl: (7) Failed to connect to 192.168.20.201 port 6031: Connection refused
[root@ningan ~]# curl http://127.0.0.1:6031/debug/pprof/goroutine?debug=1
goroutine profile: total 4
1 @ 0x433911 0x46f09d 0x678b91 0x6789c5 0x6757eb 0x68590f 0x6863fe 0x637489 0x63930d 0x63a34e 0x6360c8 0x474921
# 0x46f09c runtime/pprof.runtime_goroutineProfileWithLabels+0x1c /usr/local/go/src/runtime/mprof.go:1079
# 0x678b90 runtime/pprof.writeRuntimeProfile+0xb0 /usr/local/go/src/runtime/pprof/pprof.go:774
# 0x6789c4 runtime/pprof.writeGoroutine+0x44 /usr/local/go/src/runtime/pprof/pprof.go:734
# 0x6757ea runtime/pprof.(*Profile).WriteTo+0x14a /usr/local/go/src/runtime/pprof/pprof.go:369
# 0x68590e net/http/pprof.handler.ServeHTTP+0x52e /usr/local/go/src/net/http/pprof/pprof.go:267
# 0x6863fd net/http/pprof.Index+0xdd /usr/local/go/src/net/http/pprof/pprof.go:384
# 0x637488 net/http.HandlerFunc.ServeHTTP+0x28 /usr/local/go/src/net/http/server.go:2171
# 0x63930c net/http.(*ServeMux).ServeHTTP+0x1ac /usr/local/go/src/net/http/server.go:2688
# 0x63a34d net/http.serverHandler.ServeHTTP+0x8d /usr/local/go/src/net/http/server.go:3142
# 0x6360c7 net/http.(*conn).serve+0x5e7 /usr/local/go/src/net/http/server.go:2044

1 @ 0x43e1ce 0x436f37 0x46f465 0x4bcb27 0x4bd67a 0x4bd668 0x5657e5 0x56f745 0x6300f7 0x474921
# 0x46f464 internal/poll.runtime_pollWait+0x84 /usr/local/go/src/runtime/netpoll.go:345
# 0x4bcb26 internal/poll.(*pollDesc).wait+0x26 /usr/local/go/src/internal/poll/fd_poll_runtime.go:84
# 0x4bd679 internal/poll.(*pollDesc).waitRead+0x279 /usr/local/go/src/internal/poll/fd_poll_runtime.go:89
# 0x4bd667 internal/poll.(*FD).Read+0x267 /usr/local/go/src/internal/poll/fd_unix.go:164
# 0x5657e4 net.(*netFD).Read+0x24 /usr/local/go/src/net/fd_posix.go:55
# 0x56f744 net.(*conn).Read+0x44 /usr/local/go/src/net/net.go:185
# 0x6300f6 net/http.(*connReader).backgroundRead+0x36 /usr/local/go/src/net/http/server.go:681

1 @ 0x43e1ce 0x436f37 0x46f465 0x4bcb27 0x4be1cc 0x4be1ba 0x5668e9 0x57727e 0x5765d0 0x63a77e 0x63a411 0x68d8e7 0x68d87b 0x43dd7d 0x474921
# 0x46f464 internal/poll.runtime_pollWait+0x84 /usr/local/go/src/runtime/netpoll.go:345
# 0x4bcb26 internal/poll.(*pollDesc).wait+0x26 /usr/local/go/src/internal/poll/fd_poll_runtime.go:84
# 0x4be1cb internal/poll.(*pollDesc).waitRead+0x2ab /usr/local/go/src/internal/poll/fd_poll_runtime.go:89
# 0x4be1b9 internal/poll.(*FD).Accept+0x299 /usr/local/go/src/internal/poll/fd_unix.go:611
# 0x5668e8 net.(*netFD).accept+0x28 /usr/local/go/src/net/fd_unix.go:172
# 0x57727d net.(*TCPListener).accept+0x1d /usr/local/go/src/net/tcpsock_posix.go:159
# 0x5765cf net.(*TCPListener).Accept+0x2f /usr/local/go/src/net/tcpsock.go:327
# 0x63a77d net/http.(*Server).Serve+0x33d /usr/local/go/src/net/http/server.go:3260
# 0x63a410 net/http.(*Server).ListenAndServe+0x70 /usr/local/go/src/net/http/server.go:3189
# 0x68d8e6 net/http.ListenAndServe+0x2e6 /usr/local/go/src/net/http/server.go:3443
# 0x68d87a main.main+0x27a /root/go-practice/chapter58-httpserver/perfect/main.go:36
# 0x43dd7c runtime.main+0x29c /usr/local/go/src/runtime/proc.go:271

1 @ 0x43e1ce 0x436f37 0x46f465 0x4bcb27 0x4be1cc 0x4be1ba 0x5668e9 0x57727e 0x5765d0 0x63a77e 0x63a411 0x68daaa 0x68da55 0x474921
# 0x46f464 internal/poll.runtime_pollWait+0x84 /usr/local/go/src/runtime/netpoll.go:345
# 0x4bcb26 internal/poll.(*pollDesc).wait+0x26 /usr/local/go/src/internal/poll/fd_poll_runtime.go:84
# 0x4be1cb internal/poll.(*pollDesc).waitRead+0x2ab /usr/local/go/src/internal/poll/fd_poll_runtime.go:89
# 0x4be1b9 internal/poll.(*FD).Accept+0x299 /usr/local/go/src/internal/poll/fd_unix.go:611
# 0x5668e8 net.(*netFD).accept+0x28 /usr/local/go/src/net/fd_unix.go:172
# 0x57727d net.(*TCPListener).accept+0x1d /usr/local/go/src/net/tcpsock_posix.go:159
# 0x5765cf net.(*TCPListener).Accept+0x2f /usr/local/go/src/net/tcpsock.go:327
# 0x63a77d net/http.(*Server).Serve+0x33d /usr/local/go/src/net/http/server.go:3260
# 0x63a410 net/http.(*Server).ListenAndServe+0x70 /usr/local/go/src/net/http/server.go:3189
# 0x68daa9 net/http.ListenAndServe+0x109 /usr/local/go/src/net/http/server.go:3443
# 0x68da54 main.main.func1+0xb4 /root/go-practice/chapter58-httpserver/perfect/main.go:27

[root@ningan ~]#
[root@ningan ~]#

参考

源码参考:
go-practice/chapter58-httpserver at master · ningan123/go-practice

解决方案参考:
你的 pprof 暴露了 - Go语言中文网 - Golang中文社区

深入剖析参考:
Go 每日一库之 net/http(基础和中间件) - 大俊的博客


【go语言系列】(202410) go语言中httpServer的pprof漏洞如何避免
http://example.com/2024/10/23/go/【go语言系列】(202410) go语言中httpServer的pprof漏洞如何避免/
作者
ningan123
发布于
2024年10月23日
许可协议