2017-10-04 15:20:17 +00:00
|
|
|
package modules
|
2017-08-01 23:13:28 +00:00
|
|
|
|
|
|
|
import (
|
2017-10-14 23:54:37 +00:00
|
|
|
"net"
|
|
|
|
"strconv"
|
2017-10-19 17:37:56 +00:00
|
|
|
"strings"
|
2017-10-14 23:54:37 +00:00
|
|
|
"time"
|
|
|
|
|
2017-08-01 23:13:28 +00:00
|
|
|
log "github.com/sirupsen/logrus"
|
2017-08-16 16:09:20 +00:00
|
|
|
"github.com/zmap/zgrab2"
|
2017-10-14 23:54:37 +00:00
|
|
|
"github.com/zmap/zgrab2/lib/ssh"
|
2017-08-01 23:13:28 +00:00
|
|
|
)
|
|
|
|
|
2017-09-26 18:02:27 +00:00
|
|
|
type SSHFlags struct {
|
|
|
|
zgrab2.BaseFlags
|
2017-08-30 19:39:25 +00:00
|
|
|
ClientID string `long:"client" description:"Specify the client ID string to use" default:"SSH-2.0-Go"`
|
2017-08-01 23:13:28 +00:00
|
|
|
KexAlgorithms string `long:"kex-algorithms" description:"Set SSH Key Exchange Algorithms"`
|
|
|
|
HostKeyAlgorithms string `long:"host-key-algorithms" description:"Set SSH Host Key Algorithms"`
|
2017-10-14 23:54:37 +00:00
|
|
|
Ciphers string `long:"ciphers" description:"A comma-separated list of which ciphers to offer."`
|
|
|
|
CollectUserAuth bool `long:"userauth" description:"Use the 'none' authentication request to see what userauth methods are allowed"`
|
|
|
|
GexMinBits uint `long:"gex-min-bits" description:"The minimum number of bits for the DH GEX prime." default:"1024"`
|
|
|
|
GexMaxBits uint `long:"gex-max-bits" description:"The maximum number of bits for the DH GEX prime." default:"8192"`
|
|
|
|
GexPreferredBits uint `long:"gex-preferred-bits" description:"The preferred number of bits for the DH GEX prime." default:"2048"`
|
2017-10-19 17:37:56 +00:00
|
|
|
Verbose bool `long:"verbose" description:"Output additional information, including SSH client properties from the SSH handshake."`
|
2017-08-01 23:13:28 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 18:02:27 +00:00
|
|
|
type SSHModule struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
type SSHScanner struct {
|
2017-09-29 22:59:37 +00:00
|
|
|
config *SSHFlags
|
2017-09-26 18:02:27 +00:00
|
|
|
}
|
|
|
|
|
2017-08-01 23:13:28 +00:00
|
|
|
func init() {
|
2017-08-10 19:10:34 +00:00
|
|
|
var sshModule SSHModule
|
2017-10-19 17:37:56 +00:00
|
|
|
cmd, err := zgrab2.AddCommand("ssh", "SSH Banner Grab", "Grab a banner over SSH", 22, &sshModule)
|
2017-08-01 23:13:28 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2017-10-19 17:37:56 +00:00
|
|
|
s := ssh.MakeSSHConfig() //dummy variable to get default for host key, kex algorithm, ciphers
|
|
|
|
cmd.FindOptionByLongName("host-key-algorithms").Default = []string{strings.Join(s.HostKeyAlgorithms, ",")}
|
|
|
|
cmd.FindOptionByLongName("kex-algorithms").Default = []string{strings.Join(s.KeyExchanges, ",")}
|
|
|
|
cmd.FindOptionByLongName("ciphers").Default = []string{strings.Join(s.Ciphers, ",")}
|
2017-08-01 23:13:28 +00:00
|
|
|
}
|
|
|
|
|
2017-09-29 22:59:37 +00:00
|
|
|
func (m *SSHModule) NewFlags() interface{} {
|
2017-09-26 18:02:27 +00:00
|
|
|
return new(SSHFlags)
|
2017-08-25 16:04:16 +00:00
|
|
|
}
|
|
|
|
|
2017-09-29 22:59:37 +00:00
|
|
|
func (m *SSHModule) NewScanner() zgrab2.Scanner {
|
2017-09-26 18:02:27 +00:00
|
|
|
return new(SSHScanner)
|
2017-08-07 21:51:15 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 18:02:27 +00:00
|
|
|
func (f *SSHFlags) Validate(args []string) error {
|
2017-08-01 23:13:28 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-09-26 18:02:27 +00:00
|
|
|
func (f *SSHFlags) Help() string {
|
|
|
|
return ""
|
2017-08-29 01:23:16 +00:00
|
|
|
}
|
|
|
|
|
2017-09-29 22:59:37 +00:00
|
|
|
func (s *SSHScanner) Init(flags zgrab2.ScanFlags) error {
|
|
|
|
f, _ := flags.(*SSHFlags)
|
|
|
|
s.config = f
|
2017-09-26 18:02:27 +00:00
|
|
|
return nil
|
|
|
|
}
|
2017-08-29 01:23:16 +00:00
|
|
|
|
2017-09-26 18:02:27 +00:00
|
|
|
func (s *SSHScanner) InitPerSender(senderID int) error {
|
|
|
|
return nil
|
|
|
|
}
|
2017-08-29 01:23:16 +00:00
|
|
|
|
2017-09-26 18:02:27 +00:00
|
|
|
func (s *SSHScanner) GetName() string {
|
2017-10-04 02:47:58 +00:00
|
|
|
return s.config.Name
|
2017-09-26 18:02:27 +00:00
|
|
|
}
|
2017-10-14 23:54:37 +00:00
|
|
|
|
2017-12-15 14:25:17 +00:00
|
|
|
func (s *SSHScanner) Scan(t zgrab2.ScanTarget) (zgrab2.ScanStatus, interface{}, error) {
|
2017-10-14 23:54:37 +00:00
|
|
|
data := new(ssh.HandshakeLog)
|
|
|
|
|
|
|
|
port := strconv.FormatUint(uint64(s.config.Port), 10)
|
|
|
|
rhost := net.JoinHostPort(t.IP.String(), port)
|
|
|
|
|
2017-10-26 18:36:02 +00:00
|
|
|
sshConfig := ssh.MakeSSHConfig()
|
|
|
|
sshConfig.Timeout = time.Duration(s.config.Timeout) * time.Second
|
|
|
|
sshConfig.ConnLog = data
|
|
|
|
sshConfig.ClientVersion = s.config.ClientID
|
|
|
|
if err := sshConfig.SetHostKeyAlgorithms(s.config.HostKeyAlgorithms); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := sshConfig.SetKexAlgorithms(s.config.KexAlgorithms); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := sshConfig.SetCiphers(s.config.Ciphers); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
sshConfig.Verbose = s.config.Verbose
|
|
|
|
sshConfig.DontAuthenticate = s.config.CollectUserAuth
|
|
|
|
sshConfig.GexMinBits = s.config.GexMinBits
|
|
|
|
sshConfig.GexMaxBits = s.config.GexMaxBits
|
|
|
|
sshConfig.GexPreferredBits = s.config.GexPreferredBits
|
|
|
|
_, err := ssh.Dial("tcp", rhost, sshConfig)
|
2017-12-15 14:25:17 +00:00
|
|
|
// TODO FIXME: Distinguish error types
|
|
|
|
status := zgrab2.TryGetScanStatus(err)
|
|
|
|
return status, data, err
|
2017-08-01 23:13:28 +00:00
|
|
|
}
|
2018-03-12 17:36:11 +00:00
|
|
|
|
|
|
|
// Protocol returns the protocol identifer for the scanner.
|
|
|
|
func (s *SSHScanner) Protocol() string {
|
|
|
|
return "ssh"
|
|
|
|
}
|