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

cipher enum bug fixes and improvements #168

Merged
merged 3 commits into from
Jan 25, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/projectdiscovery/goflags v0.1.6
github.com/projectdiscovery/gologger v1.1.7
github.com/projectdiscovery/mapcidr v1.0.3
github.com/projectdiscovery/stringsutil v0.0.2
tarunKoyalwar marked this conversation as resolved.
Show resolved Hide resolved
github.com/projectdiscovery/utils v0.0.4-0.20230102120019-c7a04e2045be
github.com/rs/xid v1.4.0
github.com/stretchr/testify v1.8.1
Expand Down Expand Up @@ -67,7 +68,6 @@ require (
github.com/projectdiscovery/retryabledns v1.0.20 // indirect
github.com/projectdiscovery/retryablehttp-go v1.0.8 // indirect
github.com/projectdiscovery/sliceutil v0.0.1 // indirect
github.com/projectdiscovery/stringsutil v0.0.2 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions internal/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ func New(options *clients.Options) (*Runner, error) {
if options.OpenSSLBinary != "" {
openssl.UseOpenSSLBinary(options.OpenSSLBinary)
}
if options.TlsCiphersEnum {
// cipher enumeration requires tls versions
options.TlsVersionsEnum = true
}
showBanner()

if options.Version {
Expand Down
10 changes: 8 additions & 2 deletions pkg/output/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package output

import (
"bytes"
"fmt"
"os"
"regexp"
"strings"
Expand Down Expand Up @@ -147,7 +148,7 @@ func (w *StandardWriter) formatStandard(output *clients.Response) ([]byte, error
}
}

if !w.options.SAN && !w.options.CN {
if !w.options.SAN && !w.options.CN && !w.options.TlsCiphersEnum {
builder.WriteString(outputPrefix)
}
if !output.ProbeStatus {
Expand Down Expand Up @@ -235,7 +236,12 @@ func (w *StandardWriter) formatStandard(output *clients.Response) ([]byte, error
builder.WriteString("]")
}

if w.options.TlsVersionsEnum {
if w.options.TlsCiphersEnum {
for _, v := range output.TlsCiphers {
builder.WriteString(outputPrefix)
builder.WriteString(fmt.Sprintf(" [%v] [%v]\n", w.aurora.BrightBlue(v.Version), w.aurora.BrightGreen(strings.Join(v.Ciphers, ","))))
}
} else if w.options.TlsVersionsEnum {
builder.WriteString(" [")
builder.WriteString(w.aurora.Magenta(strings.Join(output.VersionEnum, ",")).String())
builder.WriteString("]")
Expand Down
3 changes: 3 additions & 0 deletions pkg/tlsx/auto/util.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package auto

import (
"github.com/projectdiscovery/tlsx/pkg/tlsx/openssl"
"github.com/projectdiscovery/tlsx/pkg/tlsx/tls"
"github.com/projectdiscovery/tlsx/pkg/tlsx/ztls"
sliceutil "github.com/projectdiscovery/utils/slice"
Expand All @@ -13,7 +14,9 @@ var (

func init() {
allCiphersNames = append(tls.AllCiphersNames, ztls.AllCiphersNames...)
allCiphersNames = append(allCiphersNames, openssl.AllCiphersNames...)
supportedTlsVersions = append(tls.SupportedTlsVersions, ztls.SupportedTlsVersions...)
supportedTlsVersions = append(supportedTlsVersions, openssl.SupportedTLSVersions...)
allCiphersNames = sliceutil.Dedupe(allCiphersNames)
supportedTlsVersions = sliceutil.Dedupe(supportedTlsVersions)
}
9 changes: 9 additions & 0 deletions pkg/tlsx/clients/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,10 +387,19 @@ func PemEncode(cert []byte) string {
return buf.String()
}

type EnumMode uint

const (
None EnumMode = iota
Version
Cipher
)

type ConnectOptions struct {
SNI string
VersionTLS string
Ciphers []string
EnumMode EnumMode // Enumeration Mode (version or ciphers)
}

// ParseASN1DNSequenceWithZpkixOrDefault return the parsed value of ASN1DNSequence or a default string value
Expand Down
24 changes: 21 additions & 3 deletions pkg/tlsx/openssl/openssl.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/projectdiscovery/tlsx/pkg/tlsx/clients"
errorutils "github.com/projectdiscovery/utils/errors"
iputil "github.com/projectdiscovery/utils/ip"
stringsutil "github.com/projectdiscovery/utils/strings"
tarunKoyalwar marked this conversation as resolved.
Show resolved Hide resolved
)

// Client is a TLS grabbing client using crypto/tls
Expand Down Expand Up @@ -44,13 +45,30 @@ func (c *Client) ConnectWithOptions(hostname, ip, port string, options clients.C
return nil, errorutils.NewWithTag("openssl", "client requires valid address got port=%v,hostname=%v,ip=%v", port, hostname, ip)
}

// In enum mode return if given options are not supported
if options.EnumMode == clients.Version && (options.VersionTLS == "" || !stringsutil.EqualFoldAny(options.VersionTLS, SupportedTLSVersions...)) {
// version not supported
return nil, errorutils.NewWithTag("openssl", "tlsversion `%v` not supported in openssl", options.VersionTLS)
}
if options.EnumMode == clients.Cipher {
if len(options.Ciphers) == 0 {
return nil, errorutils.NewWithTag("openssl", "missing cipher value in cipher enum mode")
}
if _, err := toOpenSSLCiphers(options.Ciphers...); err != nil {
return nil, errorutils.NewWithErr(err).WithTag("openssl")
}
}

// Note: CLI options are omitted if given value is empty
opensslOptions := &Options{
Address: address,
ServerName: options.SNI,
Protocol: getProtocol(options.VersionTLS),
CAFile: c.options.CACertificate,
Cipher: validateCiphers(options.Ciphers...),
}

if ciphers, _ := toOpenSSLCiphers(options.Ciphers...); len(ciphers) > 0 {
opensslOptions.Cipher = ciphers
}

if opensslOptions.ServerName == "" {
Expand Down Expand Up @@ -120,12 +138,12 @@ func (c *Client) ConnectWithOptions(hostname, ip, port string, options clients.C

// SupportedTLSVersions is meaningless here but necessary due to the interface system implemented
func (c *Client) SupportedTLSVersions() ([]string, error) {
return supportedTLSVersions(), nil
return SupportedTLSVersions, nil
}

// SupportedTLSVersions is meaningless here but necessary due to the interface system implemented
func (c *Client) SupportedTLSCiphers() ([]string, error) {
return fetchCiphers(), nil
return AllCiphersNames, nil
}

// Openssl s_client does not dump certificate chain unless specified
Expand Down
32 changes: 15 additions & 17 deletions pkg/tlsx/openssl/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ import (
"strings"
)

// SupportedTLSVersion of OpenSSL Mode
var SupportedTLSVersions = []string{
"tls10",
"tls11",
"tls12",
// "tls13",
}

type Protocols int

const (
Expand Down Expand Up @@ -36,16 +44,6 @@ func (p *Protocols) String() string {
}
}

// supported tls version
func supportedTLSVersions() []string {
return []string{
"tls10",
"tls11",
"tls12",
// "tls13",
}
}

func getProtocol(versionTLS string) Protocols {
var tlsversion Protocols
switch versionTLS {
Expand All @@ -55,15 +53,15 @@ func getProtocol(versionTLS string) Protocols {
tlsversion = TLSv1_1
case "tls12":
tlsversion = TLSv1_2
// case "tls13":
// tlsversion = TLSv1_3
case "dtls10":
tlsversion = DTLSv1
case "dtls12":
tlsversion = DTLSv1_2
// case "tls13":
// tlsversion = TLSv1_3
// case "dtls10":
// tlsversion = DTLSv1
// case "dtls12":
// tlsversion = DTLSv1_2
}
if versionTLS == "" {
// if no tls version is used use tls13
// if no tls version is used use tls12
// to avoid possible chances of handshake failures
return TLSv1_2
}
Expand Down
25 changes: 10 additions & 15 deletions pkg/tlsx/openssl/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,23 @@ import (
errorutil "github.com/projectdiscovery/utils/errors"
)

// AllCiphers
var AllCiphers map[string]struct{} = map[string]struct{}{}
// AllCipherNames contains all ciphers supported by openssl
var AllCiphersNames []string = []string{}

// returns array of openssl Ciphers
func fetchCiphers() []string {
arr := []string{}
for k := range AllCiphers {
arr = append(arr, k)
}
return arr
}
// cipherMap
var cipherMap map[string]struct{} = map[string]struct{}{}

// validate given ciphers and
func validateCiphers(cipher ...string) []string {
func toOpenSSLCiphers(cipher ...string) ([]string, error) {
arr := []string{}
for _, v := range cipher {
if _, ok := AllCiphers[v]; ok {
if _, ok := cipherMap[v]; ok {
arr = append(arr, v)
} else {
gologger.Debug().Label("openssl").Msgf("does not support %v cipher. skipping..", v)
return arr, errorutil.NewWithTag("openssl", "cipher suite %v not supported", v)
}
}
return arr
return arr, nil
}

func parseSessionValue(line string) string {
Expand Down Expand Up @@ -59,6 +53,7 @@ func init() {
gologger.Debug().Label("openssl").Msg(err.Error())
}
for _, v := range ciphers {
AllCiphers[v] = struct{}{}
cipherMap[v] = struct{}{}
AllCiphersNames = append(AllCiphersNames, v)
}
}
18 changes: 18 additions & 0 deletions pkg/tlsx/tls/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/projectdiscovery/fastdialer/fastdialer"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/stringsutil"
"github.com/projectdiscovery/tlsx/pkg/tlsx/clients"
errorutil "github.com/projectdiscovery/utils/errors"
iputil "github.com/projectdiscovery/utils/ip"
Expand Down Expand Up @@ -107,6 +108,23 @@ func (c *Client) ConnectWithOptions(hostname, ip, port string, options clients.C
return nil, errorutil.NewWithTag("ctls", "client requires valid address got port=%v,hostname=%v,ip=%v", port, hostname, ip)
}

// In enum mode return if given options are not supported
if options.EnumMode == clients.Version && (options.VersionTLS == "" || !stringsutil.EqualFoldAny(options.VersionTLS, SupportedTlsVersions...)) {
// version not supported
return nil, errorutil.NewWithTag("ctls", "tlsversion `%v` not supported in ctls", options.VersionTLS)
}
if options.EnumMode == clients.Cipher {
if options.VersionTLS == "tls13" {
return nil, errorutil.NewWithTag("ctls", "cipher enum not supported in ctls with tls1.3")
}
if len(options.Ciphers) == 0 {
return nil, errorutil.NewWithTag("ctls", "missing cipher value in cipher enum mode")
}
if _, err := toTLSCiphers(options.Ciphers); err != nil {
return nil, errorutil.NewWithErr(err).WithTag("ctls")
}
}

ctx := context.Background()
if c.options.Timeout != 0 {
var cancel context.CancelFunc
Expand Down
5 changes: 3 additions & 2 deletions pkg/tlsx/tls/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ package tls

import (
"crypto/tls"
"fmt"

errorutil "github.com/projectdiscovery/utils/errors"
)

var (
Expand All @@ -26,7 +27,7 @@ func toTLSCiphers(items []string) ([]uint16, error) {
for _, item := range items {
cipher, ok := tlsCiphers[item]
if !ok {
return nil, fmt.Errorf("unsupported cipher suite: %s", item)
return nil, errorutil.NewWithTag("ctls", "cipher suite %v not supported", item)
}
convertedCiphers = append(convertedCiphers, cipher)
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/tlsx/tlsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ func (s *Service) ConnectWithOptions(host, ip, port string, options clients.Conn
}

if s.options.TlsVersionsEnum {
options.EnumMode = clients.Version
supportedTlsVersions := []string{resp.Version}
enumeratedTlsVersions, _ := s.enumTlsVersions(host, ip, port, options)
supportedTlsVersions = append(supportedTlsVersions, enumeratedTlsVersions...)
Expand All @@ -102,6 +103,7 @@ func (s *Service) ConnectWithOptions(host, ip, port string, options clients.Conn

var supportedTlsCiphers []clients.TlsCiphers
if s.options.TlsCiphersEnum {
options.EnumMode = clients.Cipher
for _, supportedTlsVersion := range resp.VersionEnum {
options.VersionTLS = supportedTlsVersion
enumeratedTlsVersions, _ := s.enumTlsCiphers(host, ip, port, options)
Expand Down
5 changes: 2 additions & 3 deletions pkg/tlsx/ztls/utils.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package ztls

import (
"fmt"

errorutil "github.com/projectdiscovery/utils/errors"
"github.com/zmap/zcrypto/tls"
)

Expand All @@ -27,7 +26,7 @@ func toZTLSCiphers(items []string) ([]uint16, error) {
for _, item := range items {
zcipher, ok := ztlsCiphers[item]
if !ok {
return nil, fmt.Errorf("unsupported cipher suite: %s", item)
return nil, errorutil.NewWithTag("ztls", "cipher suite %v not supported", item)
}
convertedCiphers = append(convertedCiphers, zcipher)
}
Expand Down
15 changes: 15 additions & 0 deletions pkg/tlsx/ztls/ztls.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/projectdiscovery/fastdialer/fastdialer"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/stringsutil"
"github.com/projectdiscovery/tlsx/pkg/tlsx/clients"
"github.com/projectdiscovery/tlsx/pkg/tlsx/ztls/ja3"
errorutil "github.com/projectdiscovery/utils/errors"
Expand Down Expand Up @@ -116,6 +117,20 @@ func (c *Client) ConnectWithOptions(hostname, ip, port string, options clients.C
return nil, errorutil.NewWithTag("ztls", "client requires valid address got port=%v,hostname=%v,ip=%v", port, hostname, ip)
}

// In enum mode return if given options are not supported
if options.EnumMode == clients.Version && (options.VersionTLS == "" || !stringsutil.EqualFoldAny(options.VersionTLS, SupportedTlsVersions...)) {
// version not supported
return nil, errorutil.NewWithTag("ztls", "tlsversion `%v` not supported in ctls", options.VersionTLS)
}
if options.EnumMode == clients.Cipher {
if len(options.Ciphers) == 0 {
return nil, errorutil.NewWithTag("ztls", "missing cipher value in cipher enum mode")
}
if _, err := toZTLSCiphers(options.Ciphers); err != nil {
return nil, errorutil.NewWithErr(err).WithTag("ztls")
}
}

if c.options.ScanAllIPs || len(c.options.IPVersion) > 0 {
address = net.JoinHostPort(ip, port)
}
Expand Down