Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Parse technology stack from crawl headers, grab SSH/HTTP/WinRM banners, merge smart port bundles with FleetPorts, and suggest deploy-kit lane plus SSM for EC2 metadata targets.
114 lines
2.3 KiB
Go
114 lines
2.3 KiB
Go
package recon
|
|
|
|
import (
|
|
"net"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
PortProfileWeb = "web"
|
|
PortProfileWindows = "windows"
|
|
PortProfileLinux = "linux"
|
|
PortProfileCloudMetadata = "cloud_metadata"
|
|
)
|
|
|
|
var portProfilePorts = map[string][]int{
|
|
PortProfileWeb: {80, 443, 6262},
|
|
PortProfileWindows: {445, 5985, 3389},
|
|
PortProfileLinux: {22},
|
|
}
|
|
|
|
var dialPortFn func(host string, port int, timeout time.Duration) bool
|
|
|
|
func ScanPorts(host string, ports []int) []PortResult {
|
|
if len(ports) == 0 {
|
|
ports = FleetPorts
|
|
}
|
|
out := make([]PortResult, 0, len(ports))
|
|
for _, port := range ports {
|
|
out = append(out, PortResult{Port: port, Open: dialPort(host, port, DefaultPortDialTimeout)})
|
|
}
|
|
return out
|
|
}
|
|
|
|
func dialPort(host string, port int, timeout time.Duration) bool {
|
|
if dialPortFn != nil {
|
|
return dialPortFn(host, port, timeout)
|
|
}
|
|
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, strconv.Itoa(port)), timeout)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
_ = conn.Close()
|
|
return true
|
|
}
|
|
|
|
func ResolveScanPortsFromRequest(req ScanRequest) ([]int, []string) {
|
|
return ResolveScanPorts(req.Profiles)
|
|
}
|
|
|
|
func ResolveScanPorts(profiles []string) ([]int, []string) {
|
|
seen := map[int]bool{}
|
|
var ports []int
|
|
for _, p := range FleetPorts {
|
|
if !seen[p] {
|
|
seen[p] = true
|
|
ports = append(ports, p)
|
|
}
|
|
}
|
|
var used []string
|
|
for _, raw := range profiles {
|
|
name := strings.ToLower(strings.TrimSpace(raw))
|
|
if name == "" {
|
|
continue
|
|
}
|
|
if name == PortProfileCloudMetadata {
|
|
if !containsPortProfile(used, name) {
|
|
used = append(used, name)
|
|
}
|
|
continue
|
|
}
|
|
bundle, ok := portProfilePorts[name]
|
|
if !ok {
|
|
continue
|
|
}
|
|
if !containsPortProfile(used, name) {
|
|
used = append(used, name)
|
|
}
|
|
for _, p := range bundle {
|
|
if !seen[p] {
|
|
seen[p] = true
|
|
ports = append(ports, p)
|
|
}
|
|
}
|
|
}
|
|
sort.Ints(ports)
|
|
return ports, used
|
|
}
|
|
|
|
func containsPortProfile(list []string, want string) bool {
|
|
for _, s := range list {
|
|
if s == want {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func TargetLooksEC2(host string) bool {
|
|
host = strings.ToLower(strings.TrimSpace(host))
|
|
if host == "" {
|
|
return false
|
|
}
|
|
if host == "169.254.169.254" {
|
|
return true
|
|
}
|
|
return strings.Contains(host, ".compute.amazonaws.com") ||
|
|
strings.Contains(host, ".compute.internal") ||
|
|
strings.HasPrefix(host, "ip-10-") ||
|
|
strings.HasPrefix(host, "ec2-")
|
|
}
|