Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding initial support for tls version enum #69

Merged
merged 7 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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

Check failure

Code scanning / CodeQL

Insecure TLS configuration

Use of an insecure cipher suite: TLS_RSA_WITH_RC4_128_SHA. Use of an insecure cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256. Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_RC4_128_SHA. Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_RC4_128_SHA. Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256.
}
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

Check failure

Code scanning / CodeQL

Insecure TLS configuration

Use of an insecure cipher suite: TLS_RSA_WITH_RC4_128_SHA. Use of an insecure cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256. Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_RC4_128_SHA. Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_RC4_128_SHA. Use of an insecure cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256. Use of an insecure cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256.
}

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