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

Added JARM fingerprinting module #282

Merged
merged 4 commits into from
Jun 7, 2021
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
7 changes: 7 additions & 0 deletions modules/jarm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package modules

import "github.com/zmap/zgrab2/modules/jarm"

func init() {
jarm.RegisterModule()
}
153 changes: 153 additions & 0 deletions modules/jarm/scanner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Ref: https://github.com/salesforce/jarm
// https://engineering.salesforce.com/easily-identify-malicious-servers-on-the-internet-with-jarm-e095edac525a?gi=4dd05e2277e4
package jarm

import (
_ "fmt"
jarm "github.com/RumbleDiscovery/jarm-go"
"github.com/zmap/zgrab2"
"io"
"log"
"net"
"strings"
"time"
)

// Flags give the command-line flags for the banner module.
type Flags struct {
zgrab2.BaseFlags
MaxTries int `long:"max-tries" default:"1" description:"Number of tries for timeouts and connection errors before giving up."`
}

// Module is the implementation of the zgrab2.Module interface.
type Module struct {
}

// Scanner is the implementation of the zgrab2.Scanner interface.
type Scanner struct {
config *Flags
}

type Results struct {
Fingerprint string `json:"fingerprint"`
error string `json:"error,omitempty"`
}

// RegisterModule is called by modules/banner.go to register the scanner.
func RegisterModule() {
var module Module
_, err := zgrab2.AddCommand("jarm", "jarm", module.Description(), 443, &module)
if err != nil {
log.Fatal(err)
}
}

// NewFlags returns a new default flags object.
func (m *Module) NewFlags() interface{} {
return new(Flags)
}

// Description returns an overview of this module.
func (module *Module) Description() string {
return "Send TLS requiests and generate a JARM fingerprint"
}

// GetName returns the Scanner name defined in the Flags.
func (scanner *Scanner) GetName() string {
return scanner.config.Name
}

// GetPort returns the port being scanned.
func (scanner *Scanner) GetPort() uint {
return scanner.config.Port
}

// GetTrigger returns the Trigger defined in the Flags.
func (scanner *Scanner) GetTrigger() string {
return scanner.config.Trigger
}

// Protocol returns the protocol identifier of the scan.
func (scanner *Scanner) Protocol() string {
return "jarm"
}

// InitPerSender initializes the scanner for a given sender.
func (scanner *Scanner) InitPerSender(senderID int) error {
return nil
}

// NewScanner returns a new Scanner object.
func (m *Module) NewScanner() zgrab2.Scanner {
return new(Scanner)
}

// Validate validates the flags and returns nil on success.
func (f *Flags) Validate(args []string) error {
return nil
}

// Help returns the module's help string.
func (f *Flags) Help() string {
return ""
}

// Init initializes the Scanner with the command-line flags.
func (scanner *Scanner) Init(flags zgrab2.ScanFlags) error {
f, _ := flags.(*Flags)
scanner.config = f
return nil
}

func (scanner *Scanner) Scan(target zgrab2.ScanTarget) (zgrab2.ScanStatus, interface{}, error) {
// Stores raw hashes returned from parsing each protocols Hello message
rawhashes := []string{}

// Stores final module results
r := Results{}

// Loop through each Probe type
for _, probe := range jarm.GetProbes(target.Host(), int(scanner.GetPort())) {
data := jarm.BuildProbe(probe)

var (
conn net.Conn
err error
ret []byte
)
conn, err = target.Open(&scanner.config.BaseFlags)
if err != nil {
return zgrab2.TryGetScanStatus(err), nil, err
}

_, err = conn.Write([]byte(data))
if err != nil {
rawhashes = append(rawhashes, "")
conn.Close()
continue
}

// ret, err = zgrab2.ReadAvailable(conn)
ret, err = zgrab2.ReadAvailableWithOptions(conn, 1484, 500*time.Millisecond, 0, 1484)
if err != io.EOF && err != nil {
rawhashes = append(rawhashes, "")
conn.Close()
continue
}

ans, err := jarm.ParseServerHello(ret, probe)
silascutler marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
rawhashes = append(rawhashes, "")
conn.Close()
continue
}

rawhashes = append(rawhashes, string(ans))
conn.Close()

}

fprint := jarm.RawHashToFuzzyHash(strings.Join(rawhashes, ","))
r.Fingerprint = string(fprint)
return zgrab2.SCAN_SUCCESS, &r, nil
}