new: api.rest is now on HTTPS (closes #5)

This commit is contained in:
evilsocket 2018-01-08 07:37:29 +01:00
parent be570432ef
commit 47e814c9a9
4 changed files with 143 additions and 12 deletions

View file

@ -2,7 +2,10 @@ package core
import (
"fmt"
"os"
"os/exec"
"os/user"
"path/filepath"
"strings"
)
@ -20,3 +23,26 @@ func Exec(executable string, args []string) (string, error) {
return strings.Trim(string(raw), "\r\n\t "), nil
}
}
func Exists(path string) bool {
if _, err := os.Stat(path); os.IsNotExist(err) {
return false
}
return true
}
func ExpandPath(path string) (string, error) {
// Check if path is empty
if path != "" {
if strings.HasPrefix(path, "~") {
usr, err := user.Current()
if err != nil {
return "", err
}
// Replace only the first occurence of ~
path = strings.Replace(path, "~", usr.HomeDir, 1)
}
return filepath.Abs(path)
}
return "", nil
}

10
main.go
View file

@ -30,11 +30,11 @@ func main() {
sess.Register(session_modules.NewRestAPI(sess))
if err = sess.Start(); err != nil {
sess.Events.Log(session.FATAL, "%s", err)
panic(err)
}
if err = sess.Run("events.stream on"); err != nil {
sess.Events.Log(session.FATAL, "%s", err)
panic(err)
}
defer sess.Close()
@ -43,21 +43,21 @@ func main() {
for _, cmd := range strings.Split(*sess.Options.Commands, ";") {
cmd = strings.Trim(cmd, "\r\n\t ")
if err = sess.Run(cmd); err != nil {
sess.Events.Log(session.FATAL, "%s", err)
panic(err)
}
}
}
if *sess.Options.Caplet != "" {
if err = sess.RunCaplet(*sess.Options.Caplet); err != nil {
sess.Events.Log(session.FATAL, "%s", err)
panic(err)
}
}
for sess.Active {
line, err := sess.ReadLine()
if err != nil {
sess.Events.Log(session.FATAL, "%s", err)
panic(err)
}
if line == "" || line[0] == '#' {

View file

@ -8,7 +8,9 @@ import (
"strconv"
"strings"
"github.com/evilsocket/bettercap-ng/core"
"github.com/evilsocket/bettercap-ng/session"
"github.com/evilsocket/bettercap-ng/tls"
)
type RestAPI struct {
@ -16,6 +18,8 @@ type RestAPI struct {
server *http.Server
username string
password string
certFile string
keyFile string
}
func NewRestAPI(s *session.Session) *RestAPI {
@ -32,7 +36,7 @@ func NewRestAPI(s *session.Session) *RestAPI {
"Address to bind the API REST server to."))
api.AddParam(session.NewIntParameter("api.rest.port",
"8081",
"8083",
"Port to bind the API REST server to."))
api.AddParam(session.NewStringParameter("api.rest.username",
@ -40,6 +44,16 @@ func NewRestAPI(s *session.Session) *RestAPI {
"",
"API authentication username."))
api.AddParam(session.NewStringParameter("api.rest.certificate",
"~/.bettercap-ng.certificate.pem",
"",
"API TLS certificate."))
api.AddParam(session.NewStringParameter("api.rest.key",
"~/.bettercap-ng.key.pem",
"",
"API TLS key"))
api.AddParam(session.NewStringParameter("api.rest.password",
"",
"",
@ -229,6 +243,24 @@ func (api *RestAPI) Start() error {
port = v.(int)
}
if err, v := api.Param("api.rest.certificate").Get(api.Session); err != nil {
return err
} else {
api.certFile = v.(string)
if api.certFile, err = core.ExpandPath(api.certFile); err != nil {
return err
}
}
if err, v := api.Param("api.rest.key").Get(api.Session); err != nil {
return err
} else {
api.keyFile = v.(string)
if api.keyFile, err = core.ExpandPath(api.keyFile); err != nil {
return err
}
}
if err, v := api.Param("api.rest.username").Get(api.Session); err != nil {
return err
} else {
@ -247,16 +279,25 @@ func (api *RestAPI) Start() error {
}
}
if core.Exists(api.certFile) == false || core.Exists(api.keyFile) == false {
api.Session.Events.Log(session.INFO, "Generating RSA key to %s", api.keyFile)
api.Session.Events.Log(session.INFO, "Generating TLS certificate to %s", api.certFile)
if err := tls.Generate(api.certFile, api.keyFile); err != nil {
return err
}
} else {
api.Session.Events.Log(session.INFO, "Loading RSA key from %s", api.keyFile)
api.Session.Events.Log(session.INFO, "Loading TLS certificate from %s", api.certFile)
}
if api.Running() == false {
api.SetRunning(true)
api.server.Addr = fmt.Sprintf("%s:%d", address, port)
go func() {
api.Session.Events.Log(session.INFO, "API server starting on http://%s", api.server.Addr)
err := api.server.ListenAndServe()
if err != nil {
api.Session.Events.Log(session.ERROR, "%s", err)
api.Session.Events.Log(session.INFO, "API server starting on https://%s", api.server.Addr)
err := api.server.ListenAndServeTLS(api.certFile, api.keyFile)
if err != nil && err != http.ErrServerClosed {
panic(err)
}
}()

64
tls/cert.go Normal file
View file

@ -0,0 +1,64 @@
package tls
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"os"
"time"
)
func Generate(certPath string, keyPath string) error {
keyfile, err := os.Create(keyPath)
if err != nil {
return err
}
defer keyfile.Close()
certfile, err := os.Create(certPath)
if err != nil {
return err
}
defer certfile.Close()
priv, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return err
}
notBefore := time.Now()
notAfter := notBefore.Add(time.Duration(24*365) * time.Hour)
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return err
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
CommonName: "bettercap-ng",
Organization: []string{"bettercap-ng"},
OrganizationalUnit: []string{"RSA key generation module"},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
cert_raw, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
return err
}
if err := pem.Encode(keyfile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
return err
}
return pem.Encode(certfile, &pem.Block{Type: "CERTIFICATE", Bytes: cert_raw})
}