77 "log"
88 "net"
99 "net/http"
10+ "os"
1011 "sync"
1112 "time"
1213
@@ -18,16 +19,30 @@ import (
1819type Config struct {
1920 LogOut io.Writer
2021
21- Hostname string
22+ // Hostname can be set IP address or domain name,
23+ // If enable AutoCert, must set domain name.
24+ Hostname string
25+
26+ // PayloadDir contains Java class files.
2227 PayloadDir string
2328
29+ // about servers network and address.
2430 HTTPNetwork string
2531 HTTPAddress string
2632 LDAPNetwork string
2733 LDAPAddress string
2834
35+ // AutoCert is used to ACME client to sign
36+ // certificate automatically, don't need to
37+ // set EnableTLS true again.
38+ AutoCert bool
39+
40+ // EnableTLS is used to enable ldaps and
41+ // https server, must set TLS certificate.
2942 EnableTLS bool
30- TLSCert tls.Certificate
43+
44+ // TLSCert is used to for ldaps and https.
45+ TLSCert tls.Certificate
3146}
3247
3348// Server is used to create an exploit server that contain
@@ -37,6 +52,8 @@ type Server struct {
3752 logger * log.Logger
3853 enableTLS bool
3954
55+ secret string
56+
4057 httpListener net.Listener
4158 httpHandler * httpHandler
4259 httpServer * http.Server
@@ -51,18 +68,46 @@ type Server struct {
5168
5269// New is used to create a new log4shell server.
5370func New (cfg * Config ) (* Server , error ) {
71+ // check configuration
72+ if cfg .LogOut == nil {
73+ panic ("log4shell: Config.LogOut can not be nil" )
74+ }
75+ if cfg .Hostname == "" {
76+ return nil , errors .New ("empty host name" )
77+ }
78+ fi , err := os .Stat (cfg .PayloadDir )
79+ if err != nil {
80+ return nil , errors .WithStack (err )
81+ }
82+ if ! fi .IsDir () {
83+ return nil , errors .Errorf ("\" %s\" is not a directory" , cfg .PayloadDir )
84+ }
85+
86+ // set logger
5487 logger := log .New (cfg .LogOut , "" , log .LstdFlags )
5588 ldapserver .Logger = logger
5689
5790 // initial tls config
5891 var tlsConfig * tls.Config
59- if cfg .EnableTLS {
92+ enableTLS := cfg .EnableTLS
93+ if cfg .AutoCert {
94+ // hostname must be a domain name
95+ cert , err := autoSignCert (cfg .Hostname )
96+ if err != nil {
97+ return nil , err
98+ }
99+ tlsConfig = & tls.Config {
100+ Certificates : []tls.Certificate {* cert },
101+ }
102+ enableTLS = true
103+ } else if enableTLS {
60104 tlsConfig = & tls.Config {
61105 Certificates : []tls.Certificate {cfg .TLSCert },
62106 }
63107 }
64108
65- // for generate random http handler
109+ // generate random string and add it to the http handler
110+ // for prevent some http spider or exploit server scanner
66111 secret := randString (8 )
67112
68113 // initialize http server
@@ -90,7 +135,7 @@ func New(cfg *Config) (*Server, error) {
90135 return nil , errors .Wrap (err , "failed to create ldap listener" )
91136 }
92137 var scheme string
93- if cfg . EnableTLS {
138+ if enableTLS {
94139 scheme = "https"
95140 } else {
96141 scheme = "http"
@@ -117,7 +162,8 @@ func New(cfg *Config) (*Server, error) {
117162 // create log4shell server
118163 server := Server {
119164 logger : logger ,
120- enableTLS : cfg .EnableTLS ,
165+ enableTLS : enableTLS ,
166+ secret : secret ,
121167 httpListener : httpListener ,
122168 httpHandler : & httpHandler ,
123169 httpServer : & httpServer ,
@@ -134,6 +180,7 @@ func (srv *Server) Start() error {
134180 defer srv .mu .Unlock ()
135181
136182 errCh := make (chan error , 2 )
183+
137184 // start http server
138185 srv .wg .Add (1 )
139186 go func () {
@@ -182,18 +229,23 @@ func (srv *Server) Stop() error {
182229 srv .mu .Lock ()
183230 defer srv .mu .Unlock ()
184231
232+ // close ldap server
233+ srv .ldapServer .Stop ()
234+ srv .logger .Println ("[info]" , "ldap server is stopped" )
235+
185236 // close http server
186237 err := srv .httpServer .Close ()
187238 if err != nil {
188239 return errors .Wrap (err , "failed to close http server" )
189240 }
190241 srv .logger .Println ("[info]" , "http server is stopped" )
191242
192- // close ldap server
193- srv .ldapServer .Stop ()
194- srv .logger .Println ("[info]" , "ldap server is stopped" )
195-
196243 srv .wg .Wait ()
197244 srv .logger .Println ("[info]" , "log4shell server is stopped" )
198245 return nil
199246}
247+
248+ // Secret is used to get the generated secret about url.
249+ func (srv * Server ) Secret () string {
250+ return srv .secret
251+ }
0 commit comments