Files

317 lines
9.1 KiB
Go

package certs
// Copied from Silver C2: https://github.com/BishopFox/sliver/blob/master/server/certs/https.go
import (
"bytes"
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/binary"
"encoding/pem"
"fmt"
"math/big"
"net"
"strings"
"time"
"Havoc/pkg/logger"
insecureRand "math/rand"
)
const (
// HTTPSCA - Directory containing operator certificates
HTTPSCA = "https"
// RSAKeySize - Default size of RSA keys in bits
RSAKeySize = 2048 // This is plenty 4096 is overkill
// Certs are valid for ~3 Years, minus up to 1 year from Now()
validFor = 3 * (365 * 24 * time.Hour)
// ECCKey - Namespace for ECC keys
ECCKey = "ecc"
// RSAKey - Namespace for RSA keys
RSAKey = "rsa"
)
var (
// State -> Localities -> Street Addresses
states = map[string]map[string][]string{
"": {
"": {""},
},
"Arizona": {
"Phoenix": {""},
"Mesa": {""},
"Scottsdale": {""},
"Chandler": {""},
},
"California": {
"San Francisco": {"", "Golden Gate Bridge"},
"Oakland": {""},
"Berkeley": {""},
"Palo Alto": {""},
"Los Angeles": {""},
"San Diego": {""},
"San Jose": {""},
},
"Colorado": {
"Denver": {""},
"Boulder": {""},
"Aurora": {""},
"Fort Collins": {""},
},
"Connecticut": {
"New Haven": {""},
"Bridgeport": {""},
"Stamford": {""},
"Norwalk": {""},
},
"Washington": {
"Seattle": {""},
"Tacoma": {""},
"Olympia": {""},
"Spokane": {""},
},
"Florida": {
"Miami": {""},
"Orlando": {""},
"Tampa": {""},
"Jacksonville": {""},
},
"Illinois": {
"Chicago": {""},
"Aurora": {""},
"Naperville": {""},
"Peoria": {""},
},
}
orgNames = []string{
"",
"ACME",
"Partners",
"Tech",
"Cloud",
"Synergy",
"Test",
"Debug",
}
orgSuffixes = []string{
"",
"co",
"llc",
"inc",
"corp",
"ltd",
}
)
func randomState() string {
keys := make([]string, 0, len(states))
for k := range states {
keys = append(keys, k)
}
return keys[insecureRand.Intn(len(keys))]
}
func randomLocality(state string) string {
locales := states[state]
keys := make([]string, 0, len(locales))
for k := range locales {
keys = append(keys, k)
}
return keys[insecureRand.Intn(len(keys))]
}
func randomStreetAddress(state string, locality string) string {
addresses := states[state][locality]
return addresses[insecureRand.Intn(len(addresses))]
}
func randomProvinceLocalityStreetAddress() ([]string, []string, []string) {
state := randomState()
locality := randomLocality(state)
streetAddress := randomStreetAddress(state, locality)
return []string{state}, []string{locality}, []string{streetAddress}
}
func randomPostalCode() []string {
switch insecureRand.Intn(1) {
case 0:
return []string{fmt.Sprintf("%d", insecureRand.Intn(8000)+1000)}
default:
return []string{}
}
}
func randomSubject(commonName string) *pkix.Name {
province, locale, street := randomProvinceLocalityStreetAddress()
return &pkix.Name{
Organization: randomOrganization(),
Country: []string{"US"},
Province: province,
Locality: locale,
StreetAddress: street,
PostalCode: randomPostalCode(),
CommonName: commonName,
}
}
func randomOrganization() []string {
name := orgNames[insecureRand.Intn(len(orgNames))]
suffix := orgSuffixes[insecureRand.Intn(len(orgSuffixes))]
switch insecureRand.Intn(4) {
case 0:
return []string{strings.TrimSpace(strings.ToLower(name + " " + suffix))}
case 1:
return []string{strings.TrimSpace(strings.ToUpper(name + " " + suffix))}
case 2:
return []string{strings.TrimSpace(strings.Title(fmt.Sprintf("%s %s", name, suffix)))}
default:
return []string{}
}
}
func publicKey(priv interface{}) interface{} {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &k.PublicKey
case *ecdsa.PrivateKey:
return &k.PublicKey
default:
return nil
}
}
func randomInt(max int) int {
buf := make([]byte, 4)
rand.Read(buf)
i := binary.LittleEndian.Uint32(buf)
return int(i) % max
}
func pemBlockForKey(priv interface{}) *pem.Block {
switch key := priv.(type) {
case *rsa.PrivateKey:
data := x509.MarshalPKCS1PrivateKey(key)
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: data}
case *ecdsa.PrivateKey:
data, err := x509.MarshalECPrivateKey(key)
if err != nil {
logger.Fatal(fmt.Sprintf("Unable to marshal ECDSA private key: %v", err))
}
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: data}
default:
return nil
}
}
func generateCertificate(caType string, subject pkix.Name, isCA bool, isClient bool, privateKey interface{}) ([]byte, []byte) {
// Valid times, subtract random days from .Now()
notBefore := time.Now()
days := randomInt(365) * -1 // Within -1 year
notBefore = notBefore.AddDate(0, 0, days)
notAfter := notBefore.Add(validFor)
logger.Debug(fmt.Sprintf("Valid from %v to %v", notBefore, notAfter))
// Serial number
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit)
logger.Debug(fmt.Sprintf("Serial Number: %d", serialNumber))
var keyUsage = x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature
var extKeyUsage []x509.ExtKeyUsage
if isCA {
logger.Debug("Authority certificate")
keyUsage = x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature
extKeyUsage = []x509.ExtKeyUsage{
x509.ExtKeyUsageServerAuth,
x509.ExtKeyUsageClientAuth,
}
} else if isClient {
logger.Debug("Client authentication certificate")
extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
} else {
logger.Debug("Server authentication certificate")
extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}
}
logger.Debug(fmt.Sprintf("ExtKeyUsage = %v", extKeyUsage))
// Certificate template
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: subject,
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: keyUsage,
ExtKeyUsage: extKeyUsage,
BasicConstraintsValid: isCA,
}
if !isClient {
// Host or IP address
if ip := net.ParseIP(subject.CommonName); ip != nil {
logger.Debug(fmt.Sprintf("Certificate authenticates IP address: %v", ip))
template.IPAddresses = append(template.IPAddresses, ip)
} else {
logger.Debug(fmt.Sprintf("Certificate authenticates host: %v", subject.CommonName))
template.DNSNames = append(template.DNSNames, subject.CommonName)
}
} else {
logger.Debug(fmt.Sprintf("Client certificate authenticates CN: %v", subject.CommonName))
}
// Sign certificate or self-sign if CA
var certErr error
var derBytes []byte
if isCA {
logger.Debug("Certificate is an AUTHORITY")
template.IsCA = true
template.KeyUsage |= x509.KeyUsageCertSign
derBytes, certErr = x509.CreateCertificate(rand.Reader, &template, &template, publicKey(privateKey), privateKey)
}
if certErr != nil {
// We maybe don't want this to be fatal, but it should basically never happen afaik
logger.Fatal(fmt.Sprintf("Failed to create certificate: %s", certErr))
}
// Encode certificate and key
certOut := bytes.NewBuffer([]byte{})
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
keyOut := bytes.NewBuffer([]byte{})
pem.Encode(keyOut, pemBlockForKey(privateKey))
return certOut.Bytes(), keyOut.Bytes()
}
// HTTPSGenerateRSACertificate - Generate a server certificate signed with a given CA
func HTTPSGenerateRSACertificate(host string) ([]byte, []byte, error) {
logger.Debug(fmt.Sprintf("Generating TLS certificate (RSA) for '%s' ...", host))
var privateKey interface{}
var err error
// Generate private key
privateKey, err = rsa.GenerateKey(rand.Reader, RSAKeySize)
if err != nil {
logger.Debug("Failed to generate private key %s", err)
return nil, nil, err
}
subject := randomSubject(host)
cert, key := generateCertificate(HTTPSCA, (*subject), true, false, privateKey)
// err = saveCertificate(HTTPSCA, RSAKey, host, cert, key)
return cert, key, err
}