Skip to content

Commit

Permalink
Adding openssl prototype via cgo bindings (#64)
Browse files Browse the repository at this point in the history
* Adding openssl prototype via cgo bindings

* making openssl optional

* using zcrypto

* removing unused fields

* attempting to fix go.sum hashes

* moving code around + fixing connect issues

* Added openssl support to auto mode + misc

* Added SNI support to openssl + misc fixes to auto

* Fixed errrors in logic + remove dead code

* Accept any version of SSL

* adding linux snippet + updating readme

* listing openssl only if supported

* fixing go.mod

Co-authored-by: Ice3man <[email protected]>
  • Loading branch information
Mzack9999 and Ice3man543 authored Aug 4, 2022
1 parent 01500b0 commit 3093b49
Show file tree
Hide file tree
Showing 15 changed files with 345 additions and 59 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,30 @@ $ tlsx -u example.com -ci TLS_AES_256_GCM_SHA384 -cipher
$ tlsx -u example.com -ci cipher_list.txt -cipher
```

### OpenSSL
`tlsx` can be built with support for `OpenSSL` for osx and linux systems. The library must be installed with the following commands:

- OSx: `brew install openssl`
- Linux: `apt install openssl`

On some linux systems the default configuration is restrictive, and in order to allow more tls coverage the enclosed `assets/openssl.include` should be copied onto the system and the following snippet added to `/etc/ssl/openssl.cnf`:

```
.include /path/to/openssl.include
```

Finally the binary must be built with the `openssl` tag:

```console
go build -tags openssl .
```

At this point the engine can be used with:

```console
tlsx -sm openssl -json
```

## Acknowledgements

This program optionally uses the [zcrypto](https://github.com/zmap/zcrypto) library from the zmap team.
Expand Down
13 changes: 13 additions & 0 deletions assets/openssl.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
openssl_conf = default_conf

[ default_conf ]

ssl_conf = ssl_sect

[ssl_sect]

system_default = system_default_sect

[system_default_sect]
MinProtocol = TLSv1
CipherString = DEFAULT:@SECLEVEL=1
16 changes: 13 additions & 3 deletions cmd/tlsx/main.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package main

import (
"strings"

"github.com/pkg/errors"
"github.com/projectdiscovery/goflags"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/tlsx/internal/runner"
"github.com/projectdiscovery/tlsx/pkg/tlsx/clients"
"github.com/projectdiscovery/tlsx/pkg/tlsx/openssl"
)

var (
Expand All @@ -14,6 +17,7 @@ var (
)

func main() {

if err := process(); err != nil {
gologger.Fatal().Msgf("Could not process: %s", err)
}
Expand Down Expand Up @@ -44,16 +48,22 @@ func readFlags() error {
flagSet.SetDescription(`TLSX is a tls data gathering and analysis toolkit.`)

flagSet.CreateGroup("input", "Input",
flagSet.StringSliceVarP(&options.Inputs, "host", "u", []string{}, "target host to scan (-u INPUT1,INPUT2)", goflags.CommaSeparatedStringSliceOptions),
flagSet.StringSliceVarP(&options.Inputs, "host", "u", nil, "target host to scan (-u INPUT1,INPUT2)", goflags.CommaSeparatedStringSliceOptions),
flagSet.StringVarP(&options.InputList, "list", "l", "", "target list to scan (-l INPUT_FILE)"),
flagSet.StringSliceVarP(&options.Ports, "port", "p", nil, "target port to connect (default 443)", goflags.FileCommaSeparatedStringSliceOptions),
)

availableScanModes := []string{"ctls", "ztls"}
if openssl.Enabled {
availableScanModes = append(availableScanModes, "openssl")
}
availableScanModes = append(availableScanModes, "auto")

flagSet.CreateGroup("scan-mode", "Scan-Mode",
flagSet.StringVarP(&options.ScanMode, "scan-mode", "sm", "", "tls connection mode to use (ctls, ztls, auto) (default ctls)"),
flagSet.StringVarP(&options.ScanMode, "scan-mode", "sm", "", "tls connection mode to use ("+strings.Join(availableScanModes, ", ")+") (default ctls)"),
flagSet.BoolVarP(&options.CertsOnly, "pre-handshake", "ps", false, "enable pre-handshake tls connection (early termination) using ztls"),
flagSet.BoolVarP(&options.ScanAllIPs, "scan-all-ips", "sa", false, "scan all ips for a host (default false)"),
flagSet.StringSliceVarP(&options.IPVersion, "ip-version", "iv", []string{}, "ip version to use (4, 6) (default 4)", goflags.NormalizedStringSliceOptions),
flagSet.StringSliceVarP(&options.IPVersion, "ip-version", "iv", nil, "ip version to use (4, 6) (default 4)", goflags.NormalizedStringSliceOptions),
)

flagSet.CreateGroup("probes", "Probes",
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/projectdiscovery/sliceutil v0.0.0-20220617151003-15892688e1d6
github.com/projectdiscovery/stringsutil v0.0.0-20220612082425-0037ce9f89f3
github.com/rs/xid v1.4.0
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a
github.com/zmap/zcrypto v0.0.0-20220605182715-4dfcec6e9a8c
go.uber.org/multierr v1.8.0
)
Expand Down Expand Up @@ -53,12 +54,13 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/projectdiscovery/blackrock v0.0.0-20210903102120-5a9d2412d21d // indirect
github.com/projectdiscovery/cryptoutil v0.0.0-20210805184155-b5d2512f9345 // indirect
github.com/projectdiscovery/hmap v0.0.2-0.20220308104318-929a45d8e775 // indirect
github.com/projectdiscovery/hmap v0.0.2 // indirect
github.com/projectdiscovery/networkpolicy v0.0.1 // indirect
github.com/projectdiscovery/retryabledns v1.0.13 // indirect
github.com/projectdiscovery/retryablehttp-go v1.0.2 // indirect
github.com/rogpeppe/go-internal v1.8.0 // indirect
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 // indirect
github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236 // indirect
Expand Down
7 changes: 6 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ github.com/projectdiscovery/gologger v1.1.4 h1:qWxGUq7ukHWT849uGPkagPKF3yBPYAsTt
github.com/projectdiscovery/gologger v1.1.4/go.mod h1:Bhb6Bdx2PV1nMaFLoXNBmHIU85iROS9y1tBuv7T5pMY=
github.com/projectdiscovery/hmap v0.0.1/go.mod h1:VDEfgzkKQdq7iGTKz8Ooul0NuYHQ8qiDs6r8bPD1Sb0=
github.com/projectdiscovery/hmap v0.0.2-0.20210917080408-0fd7bd286bfa/go.mod h1:lV5f/PNPmCCjCN/dR317/chN9s7VG5h/xcbFfXOz8Fo=
github.com/projectdiscovery/hmap v0.0.2-0.20220308104318-929a45d8e775 h1:6E9T0I+6TfQYaYxEwiNKIIhXasz/tl1pLbt8gIEVXqw=
github.com/projectdiscovery/hmap v0.0.2-0.20220308104318-929a45d8e775/go.mod h1:RWJgRqpBPJW1R9CzcEH3zmiqPFEOfcbn6lLvHD9xrKE=
github.com/projectdiscovery/hmap v0.0.2 h1:fe3k0b6tj95mn9a1phD3JXvAAOmmWAh/Upg1Bf0Tfos=
github.com/projectdiscovery/hmap v0.0.2/go.mod h1:YU3TeNTDmLW2dtb4LvuEtDsPTsQ06XMnmOeD3KOuU6c=
github.com/projectdiscovery/ipranger v0.0.2/go.mod h1:kcAIk/lo5rW+IzUrFkeYyXnFJ+dKwYooEOHGVPP/RWE=
github.com/projectdiscovery/iputil v0.0.0-20210414194613-4b4d2517acf0/go.mod h1:PQAqn5h5NXsQTF4ZA00ZTYLRzGCjOtcCq8llAqrsd1A=
github.com/projectdiscovery/iputil v0.0.0-20210804143329-3a30fcde43f3/go.mod h1:blmYJkS8lSrrx3QcmcgS2tZIxlojeVmoGeA9twslCBU=
Expand Down Expand Up @@ -317,6 +318,10 @@ github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek=
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
Expand Down
1 change: 1 addition & 0 deletions internal/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ func (r *Runner) Execute() error {
if r.options.ScanMode == "auto" {
gologger.Info().Msgf("Connections made using crypto/tls: %d", stats.LoadCryptoTLSConnections())
gologger.Info().Msgf("Connections made using zcrypto/tls: %d", stats.LoadZcryptoTLSConnections())
gologger.Info().Msgf("Connections made using openssl: %d", stats.LoadOpensslTLSConnections())
}
return nil
}
Expand Down
13 changes: 13 additions & 0 deletions pkg/output/stats/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ var (
// zCryptoTLSConnections contains number of connections made with
// zcrypto/tls
zcryptoTLSConnections uint64
// opensslTLSConnections contains number of connections made with
// openssl
opensslTLSConnections uint64
)

// IncrementCryptoTLSConnections increments crypto/tls connections
Expand All @@ -21,6 +24,11 @@ func IncrementZcryptoTLSConnections() {
atomic.AddUint64(&zcryptoTLSConnections, 1)
}

// IncrementOpensslTLSConnections increments openssl connections
func IncrementOpensslTLSConnections() {
atomic.AddUint64(&opensslTLSConnections, 1)
}

// LoadCryptoTLSConnections returns crypto/tls connections
func LoadCryptoTLSConnections() uint64 {
return atomic.LoadUint64(&cryptoTLSConnections)
Expand All @@ -30,3 +38,8 @@ func LoadCryptoTLSConnections() uint64 {
func LoadZcryptoTLSConnections() uint64 {
return atomic.LoadUint64(&zcryptoTLSConnections)
}

// LoadOpensslTLSConnections returns openssl connections
func LoadOpensslTLSConnections() uint64 {
return atomic.LoadUint64(&opensslTLSConnections)
}
37 changes: 17 additions & 20 deletions pkg/tlsx/auto/auto.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
package auto

import (
"strings"

"github.com/pkg/errors"
"github.com/projectdiscovery/tlsx/pkg/output/stats"
"github.com/projectdiscovery/tlsx/pkg/tlsx/clients"
"github.com/projectdiscovery/tlsx/pkg/tlsx/openssl"
"github.com/projectdiscovery/tlsx/pkg/tlsx/tls"
"github.com/projectdiscovery/tlsx/pkg/tlsx/ztls"
)

// Client is a TLS grabbing client using auto fallback
type Client struct {
tlsClient *tls.Client
ztlsClient *ztls.Client
tlsClient *tls.Client
ztlsClient *ztls.Client
opensslClient *openssl.Client
}

// New creates a new grabbing client using auto fallback
Expand All @@ -28,17 +28,26 @@ func New(options *clients.Options) (*Client, error) {
if err != nil {
return nil, errors.Wrap(err, "could not create ztls client")
}
return &Client{tlsClient: tlsClient, ztlsClient: ztlsClient}, nil
opensslClient, err := openssl.New(options)
if err != nil && err != openssl.ErrNotSupported {
return nil, errors.Wrap(err, "could not create ztls client")
}
return &Client{tlsClient: tlsClient, ztlsClient: ztlsClient, opensslClient: opensslClient}, nil
}

// Connect connects to a host and grabs the response data
func (c *Client) ConnectWithOptions(hostname, ip, port string, options clients.ConnectOptions) (*clients.Response, error) {
response, err := c.tlsClient.ConnectWithOptions(hostname, ip, port, options)
isInvalidResponse := c.isResponseInvalid(response)
if err != nil || isInvalidResponse {
if err != nil {
ztlsResponse, ztlsErr := c.ztlsClient.ConnectWithOptions(hostname, ip, port, options)
if ztlsErr != nil {
return nil, ztlsErr
opensslResponse, opensslError := c.opensslClient.ConnectWithOptions(hostname, ip, port, options)
if opensslError != nil {
return nil, opensslError
}
opensslResponse.TLSConnection = "openssl"
stats.IncrementOpensslTLSConnections()
return opensslResponse, nil
}
ztlsResponse.TLSConnection = "ztls"
stats.IncrementZcryptoTLSConnections()
Expand All @@ -48,15 +57,3 @@ func (c *Client) ConnectWithOptions(hostname, ip, port string, options clients.C
stats.IncrementCryptoTLSConnections()
return response, nil
}

// isResponseInvalid handles invalid response
func (c *Client) isResponseInvalid(resp *clients.Response) bool {
if resp == nil {
return true
}
// case for invalid google resolving response
if strings.EqualFold(resp.CertificateResponse.IssuerCN, "invalid2.invalid") {
return true
}
return false
}
26 changes: 26 additions & 0 deletions pkg/tlsx/clients/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/projectdiscovery/fastdialer/fastdialer"
"github.com/projectdiscovery/goflags"
"github.com/projectdiscovery/stringsutil"
zasn1 "github.com/zmap/zcrypto/encoding/asn1"
zpkix "github.com/zmap/zcrypto/x509/pkix"
)

// Implementation is an interface implemented by TLSX client
Expand Down Expand Up @@ -289,3 +291,27 @@ func PemEncode(cert []byte) string {
type ConnectOptions struct {
SNI string
}

// ParseASN1DNSequenceWithZpkixOrDefault return the parsed value of ASN1DNSequence or a default string value
func ParseASN1DNSequenceWithZpkixOrDefault(data []byte, defaultValue string) string {
if value := ParseASN1DNSequenceWithZpkix(data); value != "" {
return value
}
return defaultValue
}

// ParseASN1DNSequenceWithZpkix tries to parse raw ASN1 of a TLS DN with zpkix and
// zasn1 library which includes additional information not parsed by go standard
// library which may be useful.
//
// If the parsing fails, a blank string is returned and the standard library data is used.
func ParseASN1DNSequenceWithZpkix(data []byte) string {
var rdnSequence zpkix.RDNSequence
var name zpkix.Name
if _, err := zasn1.Unmarshal(data, &rdnSequence); err != nil {
return ""
}
name.FillFromRDNSequence(&rdnSequence)
dnParsedString := name.String()
return dnParsedString
}
5 changes: 5 additions & 0 deletions pkg/tlsx/openssl/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package openssl

import "github.com/pkg/errors"

var ErrNotSupported = errors.New("openssl not supported")
24 changes: 24 additions & 0 deletions pkg/tlsx/openssl/no_openssl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//go:build !openssl

// Package openssl implements a tls grabbing implementation using openssl
package openssl

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

// Enabled reports if the tool was compiled with openssl support
const Enabled = false

// Client is a TLS grabbing client using crypto/tls
type Client struct{}

// New creates a new grabbing client using crypto/tls
func New(options *clients.Options) (*Client, error) {
return nil, ErrNotSupported
}

// Connect connects to a host and grabs the response data
func (c *Client) ConnectWithOptions(hostname, ip, port string, options clients.ConnectOptions) (*clients.Response, error) {
return nil, ErrNotSupported
}
Loading

0 comments on commit 3093b49

Please sign in to comment.