diff --git a/config.json b/config.json index ec6a41d0..44c07c0b 100644 --- a/config.json +++ b/config.json @@ -1,9 +1,9 @@ { "admin_server" : { "listen_url" : "127.0.0.1:3333", - "use_tls" : false, - "cert_path" : "example.crt", - "key_path" : "example.key" + "use_tls" : true, + "cert_path" : "gophish_admin.crt", + "key_path" : "gophish_admin.key" }, "phish_server" : { "listen_url" : "0.0.0.0:80", diff --git a/gophish.go b/gophish.go index 783984b6..30b1305d 100644 --- a/gophish.go +++ b/gophish.go @@ -37,6 +37,7 @@ import ( "github.com/gophish/gophish/config" "github.com/gophish/gophish/controllers" "github.com/gophish/gophish/models" + "github.com/gophish/gophish/util" "github.com/gorilla/handlers" ) @@ -56,6 +57,10 @@ func main() { adminHandler := gziphandler.GzipHandler(controllers.CreateAdminRouter()) auth.Store.Options.Secure = config.Conf.AdminConf.UseTLS if config.Conf.AdminConf.UseTLS { // use TLS for Admin web server if available + err := util.CheckAndCreateSSL(config.Conf.AdminConf.CertPath, config.Conf.AdminConf.KeyPath) + if err != nil { + Logger.Fatal(err) + } Logger.Printf("Starting admin server at https://%s\n", config.Conf.AdminConf.ListenURL) Logger.Fatal(http.ListenAndServeTLS(config.Conf.AdminConf.ListenURL, config.Conf.AdminConf.CertPath, config.Conf.AdminConf.KeyPath, handlers.CombinedLoggingHandler(os.Stdout, adminHandler))) diff --git a/util/util.go b/util/util.go index 7343246c..269fa747 100644 --- a/util/util.go +++ b/util/util.go @@ -1,17 +1,31 @@ package util import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" "encoding/csv" + "encoding/pem" + "errors" "fmt" "io" "io/ioutil" + "log" + "math/big" "net/http" "net/mail" + "os" + "time" "github.com/gophish/gophish/models" "github.com/jordan-wright/email" ) +// Logger is used to send logging messages to stdout. +var Logger = log.New(os.Stdout, " ", log.Ldate|log.Ltime|log.Lshortfile) + // ParseMail takes in an HTTP Request and returns an Email object // TODO: This function will likely be changed to take in a []byte func ParseMail(r *http.Request) (email.Email, error) { @@ -96,3 +110,70 @@ func ParseCSV(r *http.Request) ([]models.Target, error) { } return ts, nil } + +// CheckAndCreateSSL is a helper to setup self-signed certificates for the administrative interface. +func CheckAndCreateSSL(cp string, kp string) error { + // Check whether there is an existing SSL certificate and/or key, and if so, abort execution of this function + if _, err := os.Stat(cp); !os.IsNotExist(err) { + return nil + } + if _, err := os.Stat(kp); !os.IsNotExist(err) { + return nil + } + + Logger.Printf("Creating new self-signed certificates for administration interface...\n") + + priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + + notBefore := time.Now() + // Generate a certificate that lasts for 10 years + notAfter := notBefore.Add(10 * 365 * 24 * time.Hour) + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + + if err != nil { + return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to generate a random serial number: %s", err)) + } + + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{"Gophish"}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv) + if err != nil { + return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to create certificate: %s", err)) + } + + certOut, err := os.Create(cp) + if err != nil { + return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to open %s for writing: %s", cp, err)) + } + pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + certOut.Close() + + keyOut, err := os.OpenFile(kp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + return errors.New(fmt.Sprintf("TLS Certificate Generation: Failed to open %s for writing", kp)) + } + + b, err := x509.MarshalECPrivateKey(priv) + if err != nil { + return errors.New(fmt.Sprintf("TLS Certificate Generation: Unable to marshal ECDSA private key: %v", err)) + } + + pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}) + keyOut.Close() + + Logger.Println("TLS Certificate Generation complete") + return nil +}