Skip to content

Commit

Permalink
Adding initial support for tls version enum (#69)
Browse files Browse the repository at this point in the history
* Adding initial support for tls version enum

* Adding support for ciphers enum

* updating openssl to respect interface

* fixing various lint issues

* adding tls/cipher enum to auto mode

* renaming json fields
  • Loading branch information
Mzack9999 authored Aug 10, 2022
1 parent 3093b49 commit 8d911b3
Show file tree
Hide file tree
Showing 12 changed files with 226 additions and 31 deletions.
2 changes: 2 additions & 0 deletions cmd/tlsx/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ func readFlags() error {
flagSet.BoolVar(&options.Ja3, "ja3", false, "display ja3 fingerprint hash (using ztls)"),
flagSet.BoolVarP(&options.WildcardCertCheck, "wildcard-cert", "wc", false, "display host with wildcard ssl certificate"),
flagSet.BoolVarP(&options.ProbeStatus, "probe-status", "tps", false, "display tls probe status"),
flagSet.BoolVarP(&options.TlsVersionsEnum, "version-enum", "ve", false, "enumerate and display supported tls versions"),
flagSet.BoolVarP(&options.TlsCiphersEnum, "cipher-enum", "ce", false, "enumerate and display supported cipher"),
)

flagSet.CreateGroup("misconfigurations", "Misconfigurations",
Expand Down
6 changes: 6 additions & 0 deletions pkg/output/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ func (w *StandardWriter) formatStandard(output *clients.Response) ([]byte, error
builder.WriteString("]")
}

if w.options.TlsVersionsEnum {
builder.WriteString(" [")
builder.WriteString(w.aurora.Magenta(strings.Join(output.VersionEnum, ",")).String())
builder.WriteString("]")
}

outputdata := builder.Bytes()
return outputdata, nil
}
Expand Down
12 changes: 11 additions & 1 deletion pkg/tlsx/auto/auto.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func New(options *clients.Options) (*Client, error) {
}
opensslClient, err := openssl.New(options)
if err != nil && err != openssl.ErrNotSupported {
return nil, errors.Wrap(err, "could not create ztls client")
return nil, errors.Wrap(err, "could not create openssl client")
}
return &Client{tlsClient: tlsClient, ztlsClient: ztlsClient, opensslClient: opensslClient}, nil
}
Expand All @@ -57,3 +57,13 @@ func (c *Client) ConnectWithOptions(hostname, ip, port string, options clients.C
stats.IncrementCryptoTLSConnections()
return response, nil
}

// SupportedTLSVersions returns the list of supported tls versions by all engines
func (c *Client) SupportedTLSVersions() ([]string, error) {
return supportedTlsVersions, nil
}

// SupportedTLSCiphers returns the list of supported ciphers by all engines
func (c *Client) SupportedTLSCiphers() ([]string, error) {
return allCiphersNames, nil
}
19 changes: 19 additions & 0 deletions pkg/tlsx/auto/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package auto

import (
"github.com/projectdiscovery/sliceutil"
"github.com/projectdiscovery/tlsx/pkg/tlsx/tls"
"github.com/projectdiscovery/tlsx/pkg/tlsx/ztls"
)

var (
allCiphersNames []string
supportedTlsVersions []string
)

func init() {
allCiphersNames = append(tls.AllCiphersNames, ztls.AllCiphersNames...)
supportedTlsVersions = append(tls.SupportedTlsVersions, ztls.SupportedTlsVersions...)
allCiphersNames = sliceutil.Dedupe(allCiphersNames)
supportedTlsVersions = sliceutil.Dedupe(supportedTlsVersions)
}
27 changes: 22 additions & 5 deletions pkg/tlsx/clients/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import (
type Implementation interface {
// Connect connects to a host and grabs the response data
ConnectWithOptions(hostname, ip, port string, options ConnectOptions) (*Response, error)
// SupportedTLSVersions returns the list of supported tls versions
SupportedTLSVersions() ([]string, error)
// SupportedTLSCiphers returns the list of supported tls ciphers
SupportedTLSCiphers() ([]string, error)
}

// Options contains configuration options for tlsx client
Expand Down Expand Up @@ -109,6 +113,10 @@ type Options struct {
IPVersion goflags.StringSlice
// WildcardCertCheck enables wildcard certificate check
WildcardCertCheck bool
// TlsVersionsEnum enumerates supported tls versions
TlsVersionsEnum bool
// TlsCiphersEnum enumerates supported ciphers per TLS protocol
TlsCiphersEnum bool

// Fastdialer is a fastdialer dialer instance
Fastdialer *fastdialer.Dialer
Expand Down Expand Up @@ -139,10 +147,17 @@ type Response struct {
// when ran using scan-mode auto.
TLSConnection string `json:"tls_connection,omitempty"`
// Chain is the chain of certificates
Chain []*CertificateResponse `json:"chain,omitempty"`
JarmHash string `json:"jarm_hash,omitempty"`
Ja3Hash string `json:"ja3_hash,omitempty"`
ServerName string `json:"sni,omitempty"`
Chain []*CertificateResponse `json:"chain,omitempty"`
JarmHash string `json:"jarm_hash,omitempty"`
Ja3Hash string `json:"ja3_hash,omitempty"`
ServerName string `json:"sni,omitempty"`
VersionEnum []string `json:"version_enum,omitempty"`
TlsCiphers []TlsCiphers `json:"cipher_enum,omitempty"`
}

type TlsCiphers struct {
Version string `json:"version,omitempty"`
Ciphers []string `json:"ciphers,omitempty"`
}

// CertificateResponse is the response for a certificate
Expand Down Expand Up @@ -289,7 +304,9 @@ func PemEncode(cert []byte) string {
}

type ConnectOptions struct {
SNI string
SNI string
VersionTLS string
Ciphers []string
}

// ParseASN1DNSequenceWithZpkixOrDefault return the parsed value of ASN1DNSequence or a default string value
Expand Down
11 changes: 11 additions & 0 deletions pkg/tlsx/openssl/no_openssl.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package openssl

import (
"github.com/pkg/errors"
"github.com/projectdiscovery/tlsx/pkg/tlsx/clients"
)

Expand All @@ -22,3 +23,13 @@ func New(options *clients.Options) (*Client, error) {
func (c *Client) ConnectWithOptions(hostname, ip, port string, options clients.ConnectOptions) (*clients.Response, error) {
return nil, ErrNotSupported
}

// SupportedTLSVersions is meaningless here but necessary due to the interface system implemented
func (c *Client) SupportedTLSVersions() ([]string, error) {
return nil, errors.New("not implemented in auto mode")
}

// SupportedTLSVersions is meaningless here but necessary due to the interface system implemented
func (c *Client) SupportedTLSCiphers() ([]string, error) {
return nil, errors.New("not implemented in auto mode")
}
10 changes: 10 additions & 0 deletions pkg/tlsx/openssl/openssl.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,13 @@ func (c *Client) convertOpenSSLToX509Certificate(opensslCert *openssl.Certificat

return x509Certificate, nil
}

// SupportedTLSVersions is meaningless here but necessary due to the interface system implemented
func (c *Client) SupportedTLSVersions() ([]string, error) {
return nil, errors.New("not implemented in openssl mode")
}

// SupportedTLSVersions is meaningless here but necessary due to the interface system implemented
func (c *Client) SupportedTLSCiphers() ([]string, error) {
return nil, errors.New("not implemented in openssl mode")
}
33 changes: 30 additions & 3 deletions pkg/tlsx/tls/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"net"
"os"
"time"

"github.com/pkg/errors"
Expand Down Expand Up @@ -55,7 +55,7 @@ func New(options *clients.Options) (*Client, error) {
}

if options.AllCiphers {
c.tlsConfig.CipherSuites = allCiphers
c.tlsConfig.CipherSuites = AllCiphers
}
if len(options.Ciphers) > 0 {
if customCiphers, err := toTLSCiphers(options.Ciphers); err != nil {
Expand All @@ -65,7 +65,7 @@ func New(options *clients.Options) (*Client, error) {
}
}
if options.CACertificate != "" {
caCert, err := ioutil.ReadFile(options.CACertificate)
caCert, err := os.ReadFile(options.CACertificate)
if err != nil {
return nil, errors.Wrap(err, "could not read ca certificate")
}
Expand Down Expand Up @@ -136,6 +136,23 @@ func (c *Client) ConnectWithOptions(hostname, ip, port string, options clients.C
config = c
}

if options.VersionTLS != "" {
version, ok := versionStringToTLSVersion[options.VersionTLS]
if !ok {
return nil, fmt.Errorf("invalid tls version specified: %s", options.VersionTLS)
}
config.MinVersion = version
config.MaxVersion = version
}

if len(options.Ciphers) > 0 {
customCiphers, err := toTLSCiphers(options.Ciphers)
if err != nil {
return nil, errors.Wrap(err, "could not get tls ciphers")
}
c.tlsConfig.CipherSuites = customCiphers
}

conn := tls.Client(rawConn, config)
if err := conn.HandshakeContext(ctx); err != nil {
rawConn.Close()
Expand Down Expand Up @@ -201,3 +218,13 @@ func (c *Client) convertCertificateToResponse(hostname string, cert *x509.Certif
}
return response
}

// SupportedTLSVersions returns the list of standard tls library supported tls versions
func (c *Client) SupportedTLSVersions() ([]string, error) {
return SupportedTlsVersions, nil
}

// SupportedTLSCiphers returns the list of standard tls library supported ciphers
func (c *Client) SupportedTLSCiphers() ([]string, error) {
return AllCiphersNames, nil
}
14 changes: 11 additions & 3 deletions pkg/tlsx/tls/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@ import (
"fmt"
)

var allCiphers []uint16
var (
AllCiphers []uint16
AllCiphersNames []string
SupportedTlsVersions []string
)

func init() {
for _, cipher := range tlsCiphers {
allCiphers = append(allCiphers, cipher)
for name, cipher := range tlsCiphers {
AllCiphersNames = append(AllCiphersNames, name)
AllCiphers = append(AllCiphers, cipher)
}
for name := range versionStringToTLSVersion {
SupportedTlsVersions = append(SupportedTlsVersions, name)
}
}

Expand Down
50 changes: 50 additions & 0 deletions pkg/tlsx/tlsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

"github.com/pkg/errors"
"github.com/projectdiscovery/sliceutil"
"github.com/projectdiscovery/tlsx/pkg/tlsx/auto"
"github.com/projectdiscovery/tlsx/pkg/tlsx/clients"
"github.com/projectdiscovery/tlsx/pkg/tlsx/jarm"
Expand Down Expand Up @@ -80,5 +81,54 @@ func (s *Service) ConnectWithOptions(host, ip, port string, options clients.Conn
}
resp.JarmHash = jarmhash
}

if s.options.TlsVersionsEnum {
supportedTlsVersions := []string{resp.Version}
enumeratedTlsVersions, _ := s.enumTlsVersions(host, ip, port, options)
supportedTlsVersions = append(supportedTlsVersions, enumeratedTlsVersions...)
resp.VersionEnum = sliceutil.Dedupe(supportedTlsVersions)
}

var supportedTlsCiphers []clients.TlsCiphers
if s.options.TlsCiphersEnum {
for _, supportedTlsVersion := range resp.VersionEnum {
options.VersionTLS = supportedTlsVersion
enumeratedTlsVersions, _ := s.enumTlsCiphers(host, ip, port, options)
enumeratedTlsVersions = sliceutil.Dedupe(enumeratedTlsVersions)
supportedTlsCiphers = append(supportedTlsCiphers, clients.TlsCiphers{Version: supportedTlsVersion, Ciphers: enumeratedTlsVersions})
}
resp.TlsCiphers = supportedTlsCiphers
}

return resp, nil
}

func (s *Service) enumTlsVersions(host, ip, port string, options clients.ConnectOptions) ([]string, error) {
var enumeratedTlsVersions []string
clientSupportedTlsVersions, err := s.client.SupportedTLSVersions()
if err != nil {
return nil, err
}
for _, tlsVersion := range clientSupportedTlsVersions {
options.VersionTLS = tlsVersion
if resp, err := s.client.ConnectWithOptions(host, ip, port, options); err == nil && resp != nil && resp.Version == tlsVersion {
enumeratedTlsVersions = append(enumeratedTlsVersions, tlsVersion)
}
}
return enumeratedTlsVersions, nil
}

func (s *Service) enumTlsCiphers(host, ip, port string, options clients.ConnectOptions) ([]string, error) {
var enumeratedTlsCiphers []string
clientSupportedCiphers, err := s.client.SupportedTLSCiphers()
if err != nil {
return nil, err
}
for _, cipher := range clientSupportedCiphers {
options.Ciphers = []string{cipher}
if resp, err := s.client.ConnectWithOptions(host, ip, port, options); err == nil && resp != nil {
enumeratedTlsCiphers = append(enumeratedTlsCiphers, cipher)
}
}
return enumeratedTlsCiphers, nil
}
14 changes: 11 additions & 3 deletions pkg/tlsx/ztls/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@ import (
"github.com/zmap/zcrypto/tls"
)

var allCiphers []uint16
var (
AllCiphers []uint16
AllCiphersNames []string
SupportedTlsVersions []string
)

func init() {
for _, cipher := range ztlsCiphers {
allCiphers = append(allCiphers, cipher)
for name, cipher := range ztlsCiphers {
AllCiphersNames = append(AllCiphersNames, name)
AllCiphers = append(AllCiphers, cipher)
}
for name := range versionStringToTLSVersion {
SupportedTlsVersions = append(SupportedTlsVersions, name)
}
}

Expand Down
Loading

0 comments on commit 8d911b3

Please sign in to comment.