zgrab2

package module
v0.1.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 22, 2024 License: Apache-2.0, ISC Imports: 29 Imported by: 66

README

ZGrab 2.0

ZGrab is a fast, modular application-layer network scanner designed for completing large Internet-wide surveys. ZGrab is built to work with ZMap (ZMap identifies L4 responsive hosts, ZGrab performs in-depth, follow-up L7 handshakes). Unlike many other network scanners, ZGrab outputs detailed transcripts of network handshakes (e.g., all messages exchanged in a TLS handshake) for offline analysis.

ZGrab 2.0 contains a new, modular ZGrab framework, which fully supersedes https://github.com/zmap/zgrab.

Building

For Go 1.17 and later you must build from source:

git clone https://github.com/zmap/zgrab2.git
cd zgrab2
make
./zgrab2

For Go 1.16 and below you can install via go get:

You will need to have a valid $GOPATH set up, for more information about $GOPATH, see https://golang.org/doc/code.html.

Once you have a working $GOPATH, run:

go get github.com/zmap/zgrab2

This will install zgrab under $GOPATH/src/github.com/zmap/zgrab2

cd $GOPATH/src/github.com/zmap/zgrab2
make

Single Module Usage

ZGrab2 supports modules. For example, to run the ssh module use

./zgrab2 ssh

To retrieve detailed command-line usage and options for a specific module, append -h to the command:

./zgrab2 [module] -h

This will display the module-specific options, as well as the application-wide options, including usage examples, available flags, and descriptions for each option.

Module specific options must be included after the module. Application specific options can be specified at any time.

Input Format

Targets are specified with input files or from stdin, in CSV format. Each input line has three fields:

IP, DOMAIN, TAG

Each line must specify IP, DOMAIN, or both. If only DOMAIN is provided, scanners perform a DNS hostname lookup to determine the IP address. If both IP and DOMAIN are provided, scanners connect to IP but use DOMAIN in protocol-specific contexts, such as the HTTP HOST header and TLS SNI extension.

If the IP field contains a CIDR block, the framework will expand it to one target for each IP address in the block.

The TAG field is optional and used with the --trigger scanner argument.

Unused fields can be blank, and trailing unused fields can be omitted entirely. For backwards compatibility, the parser allows lines with only one field to contain DOMAIN.

These are examples of valid input lines:

10.0.0.1
domain.com
10.0.0.1, domain.com
10.0.0.1, domain.com, tag
10.0.0.1, , tag
, domain.com, tag
192.168.0.0/24, , tag

Multiple Module Usage

To run a scan with multiple modules, a .ini file must be used with the multiple module. Below is an example .ini file with the corresponding zgrab2 command.

multiple.ini

[Application Options]
output-file="output.txt"
input-file="input.txt"
[http]
name="http80"
port=80
endpoint="/"
[http]
name="http8080"
port=8080
endpoint="/"
[ssh]
port=22
./zgrab2 multiple -c multiple.ini

Application Options must be the initial section name. Other section names should correspond exactly to the relevant zgrab2 module name. The default name for each module is the command name. If the same module is to be used multiple times then name must be specified and unique.

Multiple module support is particularly powerful when combined with input tags and the --trigger scanner argument. For example, this input contains targets with two different tags:

141.212.113.199, , tagA
216.239.38.21, censys.io, tagB

Invoking zgrab2 with the following multiple configuration will perform an SSH grab on the first target above and an HTTP grab on the second target:

[ssh]
trigger="tagA"
name="ssh22"
port=22

[http]
trigger="tagB"
name="http80"
port=80

Adding New Protocols

Add module to modules/ that satisfies the following interfaces: Scanner, ScanModule, ScanFlags.

The flags struct must embed zgrab2.BaseFlags. In the modules init() function the following must be included.

func init() {
    var newModule NewModule
    _, err := zgrab2.AddCommand("module", "short description", "long description of module", portNumber, &newModule)
    if err != nil {
        log.Fatal(err)
    }
}
Output schema

To add a schema for the new module, add a module under schemas, and update zgrab2_schemas/zgrab2/__init__.py to ensure that it is loaded.

See zgrab2_schemas/README.md for details.

Integration tests

To add integration tests for the new module, run integration_tests/new.sh [your_new_protocol_name]. This will add stub shell scripts in integration_tests/your_new_protocol_name; update these as needed. See integration_tests/mysql/* for an example. The only hard requirement is that the test.sh script drops its output in $ZGRAB_OUTPUT/[your-module]/*.json, so that it can be validated against the schema.

How to Run Integration Tests

To run integration tests, you must have Docker and Python 2 on host installed. Then, you can follow the following steps to run integration tests:

go get github.com/jmespath/jp && go build github.com/jmespath/jp
# or, sudo wget https://github.com/jmespath/jp/releases/download/0.2.1/jp-linux-amd64 -O /usr/local/bin/jp && sudo chmod +x /usr/local/bin/jp
pip2 install --user zschema
pip2 install --user -r requirements.txt
make integration-test

Running the integration tests will generate quite a bit of debug output. To ensure that tests completed successfully, you can check for a successful exit code after the tests complete:

echo $?
0

Refer to our Github Actions workflow for an example of how to prepare environment for integration tests.

License

ZGrab2.0 is licensed under Apache 2.0 and ISC. For more information, see the LICENSE file.

Documentation

Index

Examples

Constants

View Source
const (
	// ReadLimitExceededActionNotSet is a placeholder for the zero value, so that explicitly set values can be
	// distinguished from the empty default.
	ReadLimitExceededActionNotSet = ReadLimitExceededAction("")

	// ReadLimitExceededActionTruncate causes the connection to truncate at BytesReadLimit bytes and return a bogus
	// io.EOF error. The fact that a truncation took place is logged at debug level.
	ReadLimitExceededActionTruncate = ReadLimitExceededAction("truncate")

	// ReadLimitExceededActionError causes the Read call to return n, ErrReadLimitExceeded (in addition to truncating).
	ReadLimitExceededActionError = ReadLimitExceededAction("error")

	// ReadLimitExceededActionPanic causes the Read call to panic(ErrReadLimitExceeded).
	ReadLimitExceededActionPanic = ReadLimitExceededAction("panic")
)
View Source
const (
	SCAN_SUCCESS            = ScanStatus("success")            // The protocol in question was positively identified and the scan encountered no errors
	SCAN_CONNECTION_REFUSED = ScanStatus("connection-refused") // TCP connection was actively rejected
	SCAN_CONNECTION_TIMEOUT = ScanStatus("connection-timeout") // No response to TCP connection request
	SCAN_CONNECTION_CLOSED  = ScanStatus("connection-closed")  // The TCP connection was unexpectedly closed
	SCAN_IO_TIMEOUT         = ScanStatus("io-timeout")         // Timed out waiting on data
	SCAN_PROTOCOL_ERROR     = ScanStatus("protocol-error")     // Received data incompatible with the target protocol
	SCAN_APPLICATION_ERROR  = ScanStatus("application-error")  // The application reported an error
	SCAN_UNKNOWN_ERROR      = ScanStatus("unknown-error")      // Catch-all for unrecognized errors
)

TODO: Conform to standard string const format (names, capitalization, hyphens/underscores, etc) TODO: Enumerate further status types TODO: lump connection closed / io timeout? TODO: Add SCAN_TLS_PROTOCOL_ERROR? For purely TLS-wrapped protocols, SCAN_PROTOCOL_ERROR is fine -- but for protocols that have a non-TLS bootstrap (e.g. a STARTTLS procedure), SCAN_PROTOCOL_ERROR is misleading, since it did get far-enough into the application protocol to start TLS handshaking -- but a garbled TLS handshake is certainly not a SCAN_APPLICATION_ERROR

View Source
const (
	ErrTotalTimeout = errTotalTimeout("timeout")
)

Variables

View Source
var (
	// DefaultBytesReadLimit is the maximum number of bytes to read per connection when no explicit value is provided.
	DefaultBytesReadLimit = 256 * 1024 * 1024

	// DefaultReadLimitExceededAction is the action used when no explicit action is set.
	DefaultReadLimitExceededAction = ReadLimitExceededActionTruncate

	// DefaultSessionTimeout is the default maximum time a connection may be used when no explicit value is provided.
	DefaultSessionTimeout = 1 * time.Minute
)
View Source
var ErrInvalidArguments = errors.New("invalid arguments")

ErrInvalidArguments is thrown if the command-line arguments invalid.

View Source
var ErrInvalidResponse = errors.New("invalid response")

ErrInvalidResponse is returned when the server returns a syntactically-invalid response.

View Source
var ErrMismatchedFlags = errors.New("mismatched flag/module")

ErrMismatchedFlags is thrown if the flags for one module type are passed to an incompatible module type.

View Source
var ErrReadLimitExceeded = errors.New("read limit exceeded")

ErrReadLimitExceeded is returned / panic'd from Read if the read limit is exceeded when the ReadLimitExceededAction is error / panic.

View Source
var ErrUnexpectedResponse = errors.New("unexpected response")

ErrUnexpectedResponse is returned when the server returns a syntactically-valid but unexpected response.

View Source
var InsufficientBufferError = errors.New("not enough buffer space")

Functions

func AddCommand

func AddCommand(command string, shortDescription string, longDescription string, port int, m ScanModule) (*flags.Command, error)

AddCommand adds a module to the parser and returns a pointer to a flags.command object or an error

func AddGroup

func AddGroup(shortDescription string, longDescription string, data interface{})

AddGroup exposes the parser's AddGroup function, allowing extension of the global arguments.

func DialTimeoutConnection

func DialTimeoutConnection(proto string, target string, timeout time.Duration, bytesReadLimit int) (net.Conn, error)

DialTimeoutConnection dials the target and returns a net.Conn that uses the configured single timeout for all operations.

func DialTimeoutConnectionEx

func DialTimeoutConnectionEx(proto string, target string, dialTimeout, sessionTimeout, readTimeout, writeTimeout time.Duration, bytesReadLimit int) (net.Conn, error)

DialTimeoutConnectionEx dials the target and returns a net.Conn that uses the configured timeouts for Read/Write operations.

func EncodeGrab added in v0.1.5

func EncodeGrab(raw *Grab, includeDebug bool) ([]byte, error)

EncodeGrab serializes a Grab to JSON, handling the debug fields if necessary.

func FlagsToSet

func FlagsToSet(flags uint64, mapping map[uint64]string) (map[string]bool, []uint64)

FlagsToSet converts an integer flags variable to a set of string labels corresponding to each bit, in the format described by the wiki (see https://github.com/zmap/zgrab2/wiki/Scanner-details). The mapping maps the bit mask value (i.e. a number of the form (1 << x)) to the label for that bit. Flags not present in mapping are appended to the unknown list.

Example
output, unknowns := FlagsToSet(0x5, WidenMapKeys(map[int]string{
	0x1: "bit0",
	0x2: "bit1",
	0x8: "bit3",
}))
for k, v := range output {
	fmt.Printf("%s: %v\n", k, v)
}
for _, v := range unknowns {
	fmt.Printf("Unknown: 0x%01x", v)
}
Output:

bit0: true
Unknown: 0x4

func GetMetaFile

func GetMetaFile() *os.File

GetMetaFile returns the file to which metadata should be output

func GetTargetsCSV

func GetTargetsCSV(source io.Reader, ch chan<- ScanTarget) error

GetTargetsCSV reads targets from a CSV source, generates ScanTargets, and delivers them to the provided channel.

func GetTimeoutDialFunc

func GetTimeoutDialFunc(timeout time.Duration) func(string, string) (net.Conn, error)

GetTimeoutDialFunc returns a DialFunc that dials with the given timeout

func InputTargetsCSV

func InputTargetsCSV(ch chan<- ScanTarget) error

InputTargetsCSV is an InputTargetsFunc that calls GetTargetsCSV with the CSV file provided on the command line.

func IsTimeoutError

func IsTimeoutError(err error) bool

IsTimeoutError checks if the given error corresponds to a timeout (of any type).

func ListFlagsToSet

func ListFlagsToSet(flags uint64, labels []string) (map[string]bool, []uint64)

ListFlagsToSet converts an integer flags variable to a set of string labels corresponding to each bit, in the format described by the wiki (see https://github.com/zmap/zgrab2/wiki/Scanner-details). The ith entry of labels gives the label for the ith bit (i.e. flags & (1<<i)). Empty strings in labels are treated as unknown, as are bits beyond the end of the list. Unknown flags are appended to the unknown list.

Example
output, unknowns := ListFlagsToSet(0x5, []string{
	"bit0",
	"bit1",
	"",
	"bit3",
})
for k, v := range output {
	fmt.Printf("%s: %v\n", k, v)
}
for _, v := range unknowns {
	fmt.Printf("Unknown: 0x%01x", v)
}
Output:

bit0: true
Unknown: 0x4

func LogPanic

func LogPanic(format string, args ...interface{})

LogPanic is intended to be called from within defer -- if there was no panic, it returns without doing anything. Otherwise, it logs the stacktrace, the panic error, and the provided message before re-raising the original panic. Example:

defer zgrab2.LogPanic("Error decoding body '%x'", body)

func MapFlagsToSet

func MapFlagsToSet(flags uint64, mapping FlagMap) (map[string]bool, []uint64)

MapFlagsToSet gets the "set" (map of strings to true) of values corresponding to the bits in flags. For each bit i set in flags, the result will have result[mapping(i << i)] = true. Any bits for which the mapping returns a non-nil error are instead appended to the unknowns list.

Example (Error)
output, unknowns := MapFlagsToSet(0x1b, func(bit uint64) (string, error) {
	if bit < 0x10 {
		return fmt.Sprintf("bit0x%01x", bit), nil
	} else {
		return "", fmt.Errorf("Unrecognized flag 0x%02x", bit)
	}
})
for k, v := range output {
	fmt.Printf("%s: %v\n", k, v)
}
for _, v := range unknowns {
	fmt.Printf("Unknown: 0x%02x", v)
}
Output:

bit0x1: true
bit0x2: true
bit0x8: true
Unknown: 0x10
Example (Success)
output, unknowns := MapFlagsToSet(0xb, func(bit uint64) (string, error) {
	return fmt.Sprintf("bit0x%01x", bit), nil
})
for k, v := range output {
	fmt.Printf("%s: %v\n", k, v)
}
for _, v := range unknowns {
	fmt.Printf("Unknown: 0x%01x", v)
}
Output:

bit0x1: true
bit0x2: true
bit0x8: true

func NewFakeResolver added in v0.1.2

func NewFakeResolver(ipstr string) (*net.Resolver, error)

Fake DNS Resolver, to force a DNS lookup to return a pinned address Inspired by the golang net/dnsclient_unix_test.go code

For a given IP, create a new Resolver that wraps a fake DNS server. This resolver will always return an IP that is represented by "ipstr", for DNS queries of the same IP type. Otherwise, it will return a DNS lookup error.

func NewIniParser

func NewIniParser() *flags.IniParser

NewIniParser creates and returns a ini parser initialized with the default parser

func OutputResults added in v0.1.4

func OutputResults(w *bufio.Writer, results <-chan []byte) error

OutputResults writes results to a buffered Writer from a channel.

func ParseCSVTarget

func ParseCSVTarget(fields []string) (ipnet *net.IPNet, domain string, tag string, port string, err error)

ParseCSVTarget takes a record from a CSV-format input file and returns the specified ipnet, domain, tag and port or an error.

ZGrab2 input files have four fields:

IP, DOMAIN, TAG, PORT

Each line specifies a target to scan by its IP address, domain name or both, as well as an optional tag used to determine which scanners will be invoked.

Port number has been added to the end of the line for compatibility reasons. A CIDR block may be provided in the IP field, in which case the framework expands the record into targets for every address in the block.

Trailing empty fields may be omitted. Comment lines begin with #, and empty lines are ignored.

func PrintScanners

func PrintScanners()

PrintScanners prints all registered scanners

func Process

func Process(mon *Monitor)

Process sets up an output encoder, input reader, and starts grab workers.

func ReadAvailable

func ReadAvailable(conn net.Conn) ([]byte, error)

ReadAvaiable reads what it can without blocking for more than defaultReadTimeout per read, or defaultTotalTimeout for the whole session. Reads at most defaultMaxReadSize bytes.

func ReadAvailableWithOptions

func ReadAvailableWithOptions(conn net.Conn, bufferSize int, readTimeout time.Duration, totalTimeout time.Duration, maxReadSize int) ([]byte, error)

ReadAvailableWithOptions reads whatever can be read (up to maxReadSize) from conn without blocking for longer than readTimeout per read, or totalTimeout for the entire session. A totalTimeout of 0 means attempt to use the connection's timeout (or, failing that, 1 second). On failure, returns anything it was able to read along with the error.

func ReadUntilRegex

func ReadUntilRegex(connection net.Conn, res []byte, expr *regexp.Regexp) (int, error)

ReadUntilRegex calls connection.Read() until it returns an error, or the cumulatively-read data matches the given regexp

func RegisterScan

func RegisterScan(name string, s Scanner)

RegisterScan registers each individual scanner to be ran by the framework

func SetInputFunc

func SetInputFunc(f InputTargetsFunc)

SetInputFunc sets the target input function to the provided function.

func SetOutputFunc

func SetOutputFunc(f OutputResultsFunc)

SetOutputFunc sets the result output function to the provided function.

func TLDMatches

func TLDMatches(host1 string, host2 string) bool

TLDMatches checks for a strict TLD match

func WidenMapKeys

func WidenMapKeys(input map[int]string) map[uint64]string

WidenMapKeys copies a map with int keys into an equivalent map with uint64 keys for use in the FlagsToSet function.

func WidenMapKeys16

func WidenMapKeys16(input map[uint16]string) map[uint64]string

WidenMapKeys16 copies a map with uint8 keys into an equivalent map with uint64 keys for use in the FlagsToSet function.

func WidenMapKeys32

func WidenMapKeys32(input map[uint32]string) map[uint64]string

WidenMapKeys32 copies a map with uint8 keys into an equivalent map with uint64 keys for use in the FlagsToSet function.

func WidenMapKeys8

func WidenMapKeys8(input map[uint8]string) map[uint64]string

WidenMapKeys8 copies a map with uint8 keys into an equivalent map with uint64 keys for use in the FlagsToSet function.

Types

type BaseFlags

type BaseFlags struct {
	Port           uint          `short:"p" long:"port" description:"Specify port to grab on"`
	Name           string        `short:"n" long:"name" description:"Specify name for output json, only necessary if scanning multiple modules"`
	Timeout        time.Duration `short:"t" long:"timeout" description:"Set connection timeout (0 = no timeout)" default:"10s"`
	Trigger        string        `short:"g" long:"trigger" description:"Invoke only on targets with specified tag"`
	BytesReadLimit int           `short:"m" long:"maxbytes" description:"Maximum byte read limit per scan (0 = defaults)"`
}

BaseFlags contains the options that every flags type must embed

func (*BaseFlags) GetName

func (b *BaseFlags) GetName() string

GetName returns the name of the respective scanner

type Config

type Config struct {
	OutputFileName     string          `short:"o" long:"output-file" default:"-" description:"Output filename, use - for stdout"`
	InputFileName      string          `short:"f" long:"input-file" default:"-" description:"Input filename, use - for stdin"`
	MetaFileName       string          `short:"m" long:"metadata-file" default:"-" description:"Metadata filename, use - for stderr"`
	LogFileName        string          `short:"l" long:"log-file" default:"-" description:"Log filename, use - for stderr"`
	Senders            int             `short:"s" long:"senders" default:"1000" description:"Number of send goroutines to use"`
	Debug              bool            `long:"debug" description:"Include debug fields in the output."`
	Flush              bool            `long:"flush" description:"Flush after each line of output."`
	GOMAXPROCS         int             `long:"gomaxprocs" default:"0" description:"Set GOMAXPROCS"`
	ConnectionsPerHost int             `long:"connections-per-host" default:"1" description:"Number of times to connect to each host (results in more output)"`
	ReadLimitPerHost   int             `long:"read-limit-per-host" default:"96" description:"Maximum total kilobytes to read for a single host (default 96kb)"`
	Prometheus         string          `long:"prometheus" description:"Address to use for Prometheus server (e.g. localhost:8080). If empty, Prometheus is disabled."`
	CustomDNS          string          `long:"dns" description:"Address of a custom DNS server for lookups. Default port is 53."`
	Multiple           MultipleCommand `command:"multiple" description:"Multiple module actions"`
	// contains filtered or unexported fields
}

Config is the high level framework options that will be parsed from the command line

type Dialer

type Dialer struct {
	// Timeout is the maximum time to wait for the entire session, after which any operations on the
	// connection will fail.
	Timeout time.Duration

	// ConnectTimeout is the maximum time to wait for a connection.
	ConnectTimeout time.Duration

	// ReadTimeout is the maximum time to wait for a Read
	ReadTimeout time.Duration

	// WriteTimeout is the maximum time to wait for a Write
	WriteTimeout time.Duration

	// Dialer is an auxiliary dialer used for DialContext (the result gets wrapped in a
	// TimeoutConnection).
	Dialer *net.Dialer

	// BytesReadLimit is the maximum number of bytes that connections dialed with this dialer will
	// read before erroring.
	BytesReadLimit int

	// ReadLimitExceededAction describes how connections dialed with this dialer deal with exceeding
	// the BytesReadLimit.
	ReadLimitExceededAction ReadLimitExceededAction
}

Dialer provides Dial and DialContext methods to get connections with the given timeout.

func GetTimeoutConnectionDialer

func GetTimeoutConnectionDialer(timeout time.Duration) *Dialer

GetTimeoutConnectionDialer gets a Dialer that dials connections with the given timeout.

func NewDialer

func NewDialer(value *Dialer) *Dialer

NewDialer creates a new Dialer with default settings.

func (*Dialer) Dial

func (d *Dialer) Dial(proto string, target string) (net.Conn, error)

Dial returns a connection with the configured timeout.

func (*Dialer) DialContext

func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error)

DialContext wraps the connection returned by net.Dialer.DialContext() with a TimeoutConnection.

func (*Dialer) SetDefaults

func (d *Dialer) SetDefaults() *Dialer

SetDefaults for the Dialer.

type FakeDNSServer added in v0.1.2

type FakeDNSServer struct {
	// Any domain name will resolve to this IP.  It can be either ipv4 or ipv6
	IP net.IP
}

func (*FakeDNSServer) DialContext added in v0.1.2

func (f *FakeDNSServer) DialContext(ctx context.Context, network,
	address string) (net.Conn, error)

This merely wraps a custom net.Conn, that is only good for DNS messages

type FlagMap

type FlagMap func(uint64) (string, error)

FlagMap is a function that maps a single-bit bitmask (i.e. a number of the form (1 << x)) to a string representing that bit. If the input is not valid / recognized, it should return a non-nil error, which will cause the flag to be added to the "unknowns" list.

func GetFlagMapFromList

func GetFlagMapFromList(bits []string) FlagMap

GetFlagMapFromList returns a FlagMap function mapping the ith bit to the ith entry of bits. bits is a list of labels for the corresponding bits; any empty strings (and bits beyond the end of the list) are treated as unknown.

func GetFlagMapFromMap

func GetFlagMapFromMap(mapping map[uint64]string) FlagMap

GetFlagMapFromMap returns a FlagMap function that uses mapping to do the mapping. Values not present in the map are treated as unknown, and a non-nil error is returned in those cases.

type Grab

type Grab struct {
	IP     string                  `json:"ip,omitempty"`
	Port   uint                    `json:"port,omitempty"`
	Domain string                  `json:"domain,omitempty"`
	Data   map[string]ScanResponse `json:"data,omitempty"`
}

Grab contains all scan responses for a single host

func BuildGrabFromInputResponse added in v0.1.5

func BuildGrabFromInputResponse(t *ScanTarget, responses map[string]ScanResponse) *Grab

BuildGrabFromInputResponse constructs a Grab object for a target, given the scan responses.

type InputTargetsFunc

type InputTargetsFunc func(ch chan<- ScanTarget) error

InputTargetsFunc is a function type for target input functions.

A function of this type generates ScanTargets on the provided channel. It returns nil if there are no further inputs or error.

type ModuleSet added in v0.1.3

type ModuleSet map[string]ScanModule

ModuleSet is a container holding named scan modules. It is a wrapper around a map.

func NewModuleSet added in v0.1.3

func NewModuleSet() ModuleSet

NewModuleSet returns an empty ModuleSet.

func (ModuleSet) AddModule added in v0.1.3

func (s ModuleSet) AddModule(name string, m ScanModule)

AddModule adds m to the ModuleSet, accessible via the given name. If the name is already in the ModuleSet, it is overwritten.

func (ModuleSet) CopyInto added in v0.1.3

func (s ModuleSet) CopyInto(destination ModuleSet)

CopyInto copies the modules in s to destination. The sets will be unique, but the underlying ScanModule instances will be the same.

func (ModuleSet) RemoveModule added in v0.1.3

func (s ModuleSet) RemoveModule(name string)

RemoveModule removes the module at the specified name. If the name is not in the module set, nothing happens.

type Monitor

type Monitor struct {

	// Callback is invoked after each scan.
	Callback func(string)
	// contains filtered or unexported fields
}

Monitor is a collection of states per scans and a channel to communicate those scans to the monitor

func MakeMonitor

func MakeMonitor(statusChanSize int, wg *sync.WaitGroup) *Monitor

MakeMonitor returns a Monitor object that can be used to collect and send the status of a running scan

func (*Monitor) GetStatuses

func (m *Monitor) GetStatuses() map[string]*State

GetStatuses returns a mapping from scanner names to the current number of successes and failures for that scanner

func (*Monitor) Stop added in v0.1.4

func (m *Monitor) Stop()

Stop indicates the monitor is done and the internal channel should be closed. This function does not block, but will allow a call to Wait() on the WaitGroup passed to MakeMonitor to return.

type MultipleCommand

type MultipleCommand struct {
	ConfigFileName  string `short:"c" long:"config-file" default:"-" description:"Config filename, use - for stdin"`
	ContinueOnError bool   `long:"continue-on-error" description:"If proceeding protocols error, do not run following protocols (default: true)"`
	BreakOnSuccess  bool   `long:"break-on-success" description:"If proceeding protocols succeed, do not run following protocols (default: false)"`
}

MultipleCommand contains the command line options for running

func (*MultipleCommand) Help

func (x *MultipleCommand) Help() string

Help returns a usage string that will be output at the command line

func (*MultipleCommand) Validate

func (x *MultipleCommand) Validate(args []string) error

Validate the options sent to MultipleCommand

type OutputResultsFunc

type OutputResultsFunc func(results <-chan []byte) error

OutputResultsFunc is a function type for result output functions.

A function of this type receives results on the provided channel and outputs them somehow. It returns nil if there are no further results or error.

func OutputResultsWriterFunc added in v0.1.4

func OutputResultsWriterFunc(w io.Writer) OutputResultsFunc

OutputResultsWriterFunc returns an OutputResultsFunc that wraps an io.Writer in a buffered writer, and uses OutputResults.

type ReadLimitExceededAction

type ReadLimitExceededAction string

ReadLimitExceededAction describes how the connection reacts to an attempt to read more data than permitted.

type ScanError

type ScanError struct {
	Status ScanStatus
	Err    error
}

ScanError an error that also includes a ScanStatus.

func DetectScanError

func DetectScanError(err error) *ScanError

DetectScanError returns a ScanError that attempts to detect the status from the given error.

func NewScanError

func NewScanError(status ScanStatus, err error) *ScanError

NewScanError returns a ScanError with the given status and error.

func (*ScanError) Error

func (err *ScanError) Error() string

Error is an implementation of the builtin.error interface -- just forward the wrapped error's Error() method

func (*ScanError) Unpack

func (err *ScanError) Unpack(results interface{}) (ScanStatus, interface{}, error)

type ScanFlags

type ScanFlags interface {
	// Help optionally returns any additional help text, e.g. specifying what empty defaults
	// are interpreted as.
	Help() string

	// Validate enforces all command-line flags and positional arguments have valid values.
	Validate(args []string) error
}

ScanFlags is an interface which must be implemented by all types sent to the flag parser

func ParseCommandLine

func ParseCommandLine(flags []string) ([]string, string, ScanFlags, error)

ParseCommandLine parses the commands given on the command line and validates the framework configuration (global options) immediately after parsing

type ScanModule

type ScanModule interface {
	// NewFlags is called by the framework to pass to the argument parser. The parsed flags will be passed
	// to the scanner created by NewScanner().
	NewFlags() interface{}

	// NewScanner is called by the framework for each time an individual scan is specified in the config or on
	// the command-line. The framework will then call scanner.Init(name, flags).
	NewScanner() Scanner

	// Description returns a string suitable for use as an overview of this
	// module within usage text.
	Description() string
}

ScanModule is an interface which represents a module that the framework can manipulate

func GetModule

func GetModule(name string) ScanModule

GetModule returns the registered module that corresponds to the given name or nil otherwise

type ScanResponse

type ScanResponse struct {
	// Status is required for all responses.
	Status ScanStatus `json:"status"`

	// Protocol is the identifier if the protocol that did the scan. In the case of a complex scan, this may differ from
	// the scan name.
	Protocol string `json:"protocol"`

	Result    interface{} `json:"result,omitempty"`
	Timestamp string      `json:"timestamp,omitempty"`
	Error     *string     `json:"error,omitempty"`
}

ScanResponse is the result of a scan on a single host

func RunScanner

func RunScanner(s Scanner, mon *Monitor, target ScanTarget) (string, ScanResponse)

RunScanner runs a single scan on a target and returns the resulting data

type ScanStatus

type ScanStatus string

ScanStatus is the enum value that states how the scan ended.

func TryGetScanStatus

func TryGetScanStatus(err error) ScanStatus

TryGetScanStatus attempts to get the ScanStatus enum value corresponding to the given error. Mostly supports network errors. A nil error is interpreted as SCAN_SUCCESS. An unrecognized error is interpreted as SCAN_UNKNOWN_ERROR.

type ScanTarget

type ScanTarget struct {
	IP     net.IP
	Domain string
	Tag    string
	Port   *uint
}

ScanTarget is the host that will be scanned

func (*ScanTarget) Host

func (target *ScanTarget) Host() string

Host gets the host identifier as a string: the IP address if it is available, or the domain if not.

func (*ScanTarget) Open

func (target *ScanTarget) Open(flags *BaseFlags) (net.Conn, error)

Open connects to the ScanTarget using the configured flags, and returns a net.Conn that uses the configured timeouts for Read/Write operations.

func (*ScanTarget) OpenTLS

func (target *ScanTarget) OpenTLS(baseFlags *BaseFlags, tlsFlags *TLSFlags) (*TLSConnection, error)

OpenTLS connects to the ScanTarget using the configured flags, then performs the TLS handshake. On success error is nil, but the connection can be non-nil even if there is an error (this allows fetching the handshake log).

func (*ScanTarget) OpenUDP

func (target *ScanTarget) OpenUDP(flags *BaseFlags, udp *UDPFlags) (net.Conn, error)

OpenUDP connects to the ScanTarget using the configured flags, and returns a net.Conn that uses the configured timeouts for Read/Write operations. Note that the UDP "connection" does not have an associated timeout.

func (ScanTarget) String

func (target ScanTarget) String() string

type Scanner

type Scanner interface {
	// Init runs once for this module at library init time
	Init(flags ScanFlags) error

	// InitPerSender runs once per Goroutine. A single Goroutine will scan some non-deterministic
	// subset of the input scan targets
	InitPerSender(senderID int) error

	// Returns the name passed at init
	GetName() string

	// Returns the trigger passed at init
	GetTrigger() string

	// Protocol returns the protocol identifier for the scan.
	Protocol() string

	// Scan connects to a host. The result should be JSON-serializable
	Scan(t ScanTarget) (ScanStatus, interface{}, error)
}

Scanner is an interface that represents all functions necessary to run a scan

type State

type State struct {
	Successes uint `json:"successes"`
	Failures  uint `json:"failures"`
}

State contains the respective number of successes and failures for a given scan

type TLSConnection

type TLSConnection struct {
	tls.Conn
	// contains filtered or unexported fields
}

func (*TLSConnection) Close

func (conn *TLSConnection) Close() error

Close the underlying connection.

func (*TLSConnection) GetLog

func (z *TLSConnection) GetLog() *TLSLog

func (*TLSConnection) Handshake

func (z *TLSConnection) Handshake() error

type TLSFlags

type TLSFlags struct {
	Config *tls.Config // Config is ready to use TLS configuration

	Heartbleed bool `long:"heartbleed" description:"Check if server is vulnerable to Heartbleed"`

	SessionTicket        bool `long:"session-ticket" description:"Send support for TLS Session Tickets and output ticket if presented" json:"session"`
	ExtendedMasterSecret bool `long:"extended-master-secret" description:"Offer RFC 7627 Extended Master Secret extension" json:"extended"`
	ExtendedRandom       bool `long:"extended-random" description:"Send TLS Extended Random Extension" json:"extran"`
	NoSNI                bool `long:"no-sni" description:"Do not send domain name in TLS Handshake regardless of whether known" json:"sni"`
	SCTExt               bool `long:"sct" description:"Request Signed Certificate Timestamps during TLS Handshake" json:"sct"`

	// TODO: Do we just lump this with Verbose (and put Verbose in TLSFlags)?
	KeepClientLogs bool `long:"keep-client-logs" description:"Include the client-side logs in the TLS handshake"`

	Time string `long:"time" description:"Explicit request time to use, instead of clock. YYYYMMDDhhmmss format."`
	// TODO: directory? glob? How to map server name -> certificate?
	Certificates string `long:"certificates" description:"Set of certificates to present to the server"`
	// TODO: re-evaluate this, or at least specify the file format
	CertificateMap string `long:"certificate-map" description:"A file mapping server names to certificates"`
	// TODO: directory? glob?
	RootCAs string `long:"root-cas" description:"Set of certificates to use when verifying server certificates"`
	// TODO: format?
	NextProtos              string `long:"next-protos" description:"A list of supported application-level protocols"`
	ServerName              string `long:"server-name" description:"Server name used for certificate verification and (optionally) SNI"`
	VerifyServerCertificate bool   `` /* 168-byte string literal not displayed */
	// TODO: format? mapping? zgrab1 had flags like ChromeOnly, FirefoxOnly, etc...
	CipherSuite      string `long:"cipher-suite" description:"A comma-delimited list of hex cipher suites to advertise."`
	MinVersion       int    `long:"min-version" description:"The minimum SSL/TLS version that is acceptable. 0 means that SSLv3 is the minimum."`
	MaxVersion       int    `long:"max-version" description:"The maximum SSL/TLS version that is acceptable. 0 means use the highest supported value."`
	CurvePreferences string `long:"curve-preferences" description:"A list of elliptic curves used in an ECDHE handshake, in order of preference."`
	NoECDHE          bool   `long:"no-ecdhe" description:"Do not allow ECDHE handshakes"`
	// TODO: format?
	SignatureAlgorithms string `long:"signature-algorithms" description:"Signature and hash algorithms that are acceptable"`
	HeartbeatEnabled    bool   `long:"heartbeat-enabled" description:"If set, include the heartbeat extension"`
	DSAEnabled          bool   `long:"dsa-enabled" description:"Accept server DSA keys"`
	// TODO: format?
	ClientRandom string `long:"client-random" description:"Set an explicit Client Random (base64 encoded)"`
	// TODO: format?
	ClientHello string `long:"client-hello" description:"Set an explicit ClientHello (base64 encoded)"`
}

Common flags for TLS configuration -- include this in your module's ScanFlags implementation to use the common TLS code Adapted from modules/ssh.go

func (*TLSFlags) Connect

func (t *TLSFlags) Connect(target *ScanTarget, flags *BaseFlags) (*TLSConnection, error)

Connect opens the TCP connection to the target using the given configuration, and then returns the configured wrapped TLS connection. The caller must still call Handshake().

func (*TLSFlags) GetTLSConfig

func (t *TLSFlags) GetTLSConfig() (*tls.Config, error)

func (*TLSFlags) GetTLSConfigForTarget

func (t *TLSFlags) GetTLSConfigForTarget(target *ScanTarget) (*tls.Config, error)

func (*TLSFlags) GetTLSConnection

func (t *TLSFlags) GetTLSConnection(conn net.Conn) (*TLSConnection, error)

func (*TLSFlags) GetTLSConnectionForTarget

func (t *TLSFlags) GetTLSConnectionForTarget(conn net.Conn, target *ScanTarget) (*TLSConnection, error)

func (*TLSFlags) GetWrappedConnection added in v0.1.7

func (t *TLSFlags) GetWrappedConnection(conn net.Conn, cfg *tls.Config) *TLSConnection

type TLSLog

type TLSLog struct {
	// TODO include TLSFlags?
	HandshakeLog *tls.ServerHandshake `json:"handshake_log"`
	// This will be nil if heartbleed is not checked because of client configuration flags
	HeartbleedLog *tls.Heartbleed `json:"heartbleed_log,omitempty"`
}

type TimeoutConnection

type TimeoutConnection struct {
	net.Conn

	Timeout                 time.Duration
	ReadTimeout             time.Duration
	WriteTimeout            time.Duration
	BytesRead               int
	BytesWritten            int
	BytesReadLimit          int
	ReadLimitExceededAction ReadLimitExceededAction
	Cancel                  context.CancelFunc
	// contains filtered or unexported fields
}

TimeoutConnection wraps an existing net.Conn connection, overriding the Read/Write methods to use the configured timeouts TODO: Refactor this into TimeoutConnection, BoundedReader, LoggedReader, etc

func NewTimeoutConnection

func NewTimeoutConnection(ctx context.Context, conn net.Conn, timeout, readTimeout, writeTimeout time.Duration, bytesReadLimit int) *TimeoutConnection

NewTimeoutConnection returns a new TimeoutConnection with the appropriate defaults.

func (*TimeoutConnection) Close

func (c *TimeoutConnection) Close() error

Close the underlying connection.

func (*TimeoutConnection) Read

func (c *TimeoutConnection) Read(b []byte) (n int, err error)

TimeoutConnection.Read calls Read() on the underlying connection, using any configured deadlines

func (*TimeoutConnection) SetDeadline

func (c *TimeoutConnection) SetDeadline(deadline time.Time) error

SetDeadline sets a read / write deadline that will override the deadline for a single read/write. Use deadline = 0 to clear the deadline.

func (*TimeoutConnection) SetDefaults

func (c *TimeoutConnection) SetDefaults() *TimeoutConnection

SetDefaults on the connection.

func (*TimeoutConnection) SetReadDeadline

func (c *TimeoutConnection) SetReadDeadline(deadline time.Time) error

SetReadDeadline sets an explicit ReadDeadline that will override the timeout for one read. Use deadline = 0 to clear the deadline.

func (*TimeoutConnection) SetWriteDeadline

func (c *TimeoutConnection) SetWriteDeadline(deadline time.Time) error

SetWriteDeadline sets an explicit WriteDeadline that will override the WriteDeadline for one write. Use deadline = 0 to clear the deadline.

func (*TimeoutConnection) Write

func (c *TimeoutConnection) Write(b []byte) (n int, err error)

TimeoutConnection.Write calls Write() on the underlying connection, using any configured deadlines.

type UDPFlags

type UDPFlags struct {
	LocalPort    uint   `long:"local-port" description:"Set an explicit local port for UDP traffic"`
	LocalAddress string `long:"local-addr" description:"Set an explicit local address for UDP traffic"`
}

UDPFlags contains the common options used for all UDP scans

Directories

Path Synopsis
Package bin contains functions useful for creating a binary version of ZGrab2.
Package bin contains functions useful for creating a binary version of ZGrab2.
cmd
lib
http
Package http provides HTTP client and server implementations.
Package http provides HTTP client and server implementations.
http/cookiejar
Package cookiejar implements an in-memory RFC 6265-compliant http.CookieJar.
Package cookiejar implements an in-memory RFC 6265-compliant http.CookieJar.
http/httptest
Package httptest provides utilities for HTTP testing.
Package httptest provides utilities for HTTP testing.
http/httptrace
Package httptrace provides mechanisms to trace the events within HTTP client requests.
Package httptrace provides mechanisms to trace the events within HTTP client requests.
mysql
Package mysql is a very basic MySQL connection library.
Package mysql is a very basic MySQL connection library.
output
Package output contains utilities for processing results from zgrab2 scanners for eventual output and consumption by ztag.
Package output contains utilities for processing results from zgrab2 scanners for eventual output and consumption by ztag.
ssh/agent
Package agent implements the ssh-agent protocol, and provides both a client and a server.
Package agent implements the ssh-agent protocol, and provides both a client and a server.
ssh/terminal
Package terminal provides support functions for dealing with terminals, as commonly found on UNIX systems.
Package terminal provides support functions for dealing with terminals, as commonly found on UNIX systems.
ssh/test
This package contains integration tests for the github.com/zmap/zgrab2/lib/ssh.
This package contains integration tests for the github.com/zmap/zgrab2/lib/ssh.
bacnet
Package bacnet provides a zgrab2 module that scans for bacnet.
Package bacnet provides a zgrab2 module that scans for bacnet.
dnp3
Package dnp3 provides a zgrab2 module that scans for dnp3.
Package dnp3 provides a zgrab2 module that scans for dnp3.
fox
Package fox provides a zgrab2 module that scans for fox.
Package fox provides a zgrab2 module that scans for fox.
ftp
Package ftp contains the zgrab2 Module implementation for FTP(S).
Package ftp contains the zgrab2 Module implementation for FTP(S).
http
Package http contains the zgrab2 Module implementation for HTTP(S).
Package http contains the zgrab2 Module implementation for HTTP(S).
imap
Package imap provides a zgrab2 module that scans for IMAP mail servers.
Package imap provides a zgrab2 module that scans for IMAP mail servers.
ipp
Package ipp provides a zgrab2 module that scans for ipp.
Package ipp provides a zgrab2 module that scans for ipp.
jarm
Ref: https://github.com/salesforce/jarm https://engineering.salesforce.com/easily-identify-malicious-servers-on-the-internet-with-jarm-e095edac525a?gi=4dd05e2277e4
Ref: https://github.com/salesforce/jarm https://engineering.salesforce.com/easily-identify-malicious-servers-on-the-internet-with-jarm-e095edac525a?gi=4dd05e2277e4
modbus
Package modbus provides a zgrab2 module that scans for modbus.
Package modbus provides a zgrab2 module that scans for modbus.
mssql
Package mssql provides the zgrab2 scanner module for the MSSQL protocol.
Package mssql provides the zgrab2 scanner module for the MSSQL protocol.
mysql
Package mysql provides the mysql implementation of the zgrab2.Module.
Package mysql provides the mysql implementation of the zgrab2.Module.
ntp
Package ntp provides a zgrab2 module that probes for the NTP service.
Package ntp provides a zgrab2 module that probes for the NTP service.
oracle
Package oracle provides the zgrab2 scanner module for Oracle's TNS protocol.
Package oracle provides the zgrab2 scanner module for Oracle's TNS protocol.
pop3
Package pop3 provides a zgrab2 module that scans for POP3 mail servers.
Package pop3 provides a zgrab2 module that scans for POP3 mail servers.
postgres
Package postgres contains the postgres zgrab2 Module implementation.
Package postgres contains the postgres zgrab2 Module implementation.
redis
Package redis provides a zgrab2 Module that probes for redis services.
Package redis provides a zgrab2 Module that probes for redis services.
siemens
Package siemens provides a zgrab2 module that scans for Siemens S7.
Package siemens provides a zgrab2 module that scans for Siemens S7.
smb
Package smb provides a zgrab2 module that scans for smb.
Package smb provides a zgrab2 module that scans for smb.
smtp
Package smtp provides a zgrab2 module that scans for SMTP mail servers.
Package smtp provides a zgrab2 module that scans for SMTP mail servers.
telnet
Package telnet provides a zgrab2 module that scans for telnet daemons.
Package telnet provides a zgrab2 module that scans for telnet daemons.
tools

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL