This is my RegreSSHion ip scanner written in GO. It can find single ip’s, cidr’s, ip’s from a file, and checks for different ports. This will be more effective than any Python written scanner simply because you can do concurrent scans against very long lists of ip’s, and hence, it’s much Quicker. I’ve already seen a couple of long lists out there in the wild, late last night, and one was over 5million ip’s. It was enumerated with a python script, but I still prefer GO.
( read on RegreSSHion bug check, and RegreSShion exploit POC )
A recent ISACA study revealed a startling truth: in a typical large enterprise, the number of authorized SSH keys can be 5 to 50 times the number of employees. This translates to a massive, often unmanaged, attack surface that keeps CTOs and CISOs awake at night.
Think about it: each forgotten key, each over-privileged access point, is a potential entry point for attackers. This is where RegreSSHion IP Scanner emerges as a critical line of defense. This powerful tool goes beyond simple vulnerability scanning.
It actively hunts for weaknesses within your SSH infrastructure, identifying misconfigured servers, outdated software versions (especially those vulnerable to exploits like CVE-2024-6387), and potential backdoors that attackers could exploit.
This RegreSSHion ip scanner is a command-line tool that simplifies the process of identifying potentially vulnerable servers. Here’s how it works:
- User-Friendly Output: The scanner provides clear and concise output, categorizing servers as vulnerable, not vulnerable, or unknown, along with detailed information about the detected OpenSSH version.
- Customizable Options: The tool offers flexibility with options to specify the port number, connection timeout, and the level of concurrency for faster scanning.
- Open-Source and Free: We believe in empowering the community. Our scanner is completely free to use and open-source, allowing for transparency and contributions.
Who Should Use RegreSSHion IP Scanner ?
This RegreSSHion ip scanner is an essential tool for:
- System Administrators: Identify and patch vulnerable OpenSSH servers within your network.
- Security Professionals: Proactively assess and mitigate potential risks associated with CVE-2024-6387.
- Ethical Hackers: Test and improve the security posture of systems with the RegreSSHion ip scanner during penetration testing engagements.
Get Started Now!
Don’t wait for an attack to happen. Download our RegreSSHion ip scanner (OpenSSH Vulnerability) today and take a proactive step towards securing your systems against CVE-2024-6387.
[]
Stay tuned for future updates and enhancements to our security toolkit!
Go Code below:
package main
import (
"bufio"
"fmt"
"net"
"os"
"strconv"
"strings"
"sync"
"time"
"github.com/spf13/pflag"
"golang.org/x/sync/semaphore"
)
// Version of the script
const VERSION = "0.5"
// Colors for terminal output
const (
BLUE = "\033[94m"
GREEN = "\033[92m"
RED = "\033[91m"
ORANGE = "\033[33m"
ENDC = "\033[0m"
)
// Result represents the result of a scan for a single IP address
type Result struct {
IP string
Port int
Status string
Message string
}
// Global variables for tracking progress
var (
progressMutex sync.Mutex
progressCount int
totalHosts int
)
// getSSHSock establishes a TCP connection to the given IP address and port
func getSSHSock(ip string, port int, timeout time.Duration) (net.Conn, error) {
// Create a TCP address
address := fmt.Sprintf("%s:%d", ip, port)
// Dial the TCP address with the specified timeout
return net.DialTimeout("tcp", address, timeout)
}
// getSSHBanner attempts to retrieve the SSH banner from a connected TCP connection
func getSSHBanner(conn net.Conn) (string, error) {
// Set a read deadline for the connection
conn.SetReadDeadline(time.Now().Add(time.Second))
// Create a buffer to read data from the connection
buffer := make([]byte, 1024)
// Read data from the connection
n, err := conn.Read(buffer)
if err != nil {
return "", err
}
// Convert the read data to a string and trim any whitespace
return strings.TrimSpace(string(buffer[:n])), nil
}
// checkVulnerability checks if a given IP address and port is vulnerable to CVE-2024-6387
func checkVulnerability(ip string, port int, timeout time.Duration, results chan<- Result) {
// Increment the progress counter
incrementProgressCounter()
// Attempt to establish a TCP connection to the target
conn, err := getSSHSock(ip, port, timeout)
// Handle connection errors
if err != nil {
// If the connection failed, send a "closed" result
results <- Result{IP: ip, Port: port, Status: "closed", Message: "Port closed"}
return
}
// Ensure the connection is closed after the function returns
defer conn.Close()
// Attempt to retrieve the SSH banner
banner, err := getSSHBanner(conn)
// Handle banner retrieval errors
if err != nil {
// If banner retrieval failed, send a "failed" result
results <- Result{IP: ip, Port: port, Status: "failed", Message: fmt.Sprintf("Failed to retrieve SSH banner: %s", err)}
return
}
// Check if the banner indicates an SSH server
if !strings.Contains(banner, "SSH-2.0") {
// If not an SSH server, send a "failed" result
results <- Result{IP: ip, Port: port, Status: "failed", Message: fmt.Sprintf("Failed to retrieve SSH banner: %s", banner)}
return
}
// Check if the banner indicates an OpenSSH server
if !strings.Contains(banner, "SSH-2.0-OpenSSH") {
// If not OpenSSH, send an "unknown" result
results <- Result{IP: ip, Port: port, Status: "unknown", Message: fmt.Sprintf("(banner: %s)", banner)}
return
}
// Define vulnerable OpenSSH versions
vulnerableVersions := []string{
"SSH-2.0-OpenSSH_1",
"SSH-2.0-OpenSSH_2",
"SSH-2.0-OpenSSH_3",
"SSH-2.0-OpenSSH_4.0",
"SSH-2.0-OpenSSH_4.1",
"SSH-2.0-OpenSSH_4.2",
"SSH-2.0-OpenSSH_4.3",
"SSH-2.0-OpenSSH_4.4",
"SSH-2.0-OpenSSH_8.5",
"SSH-2.0-OpenSSH_8.6",
"SSH-2.0-OpenSSH_8.7",
"SSH-2.0-OpenSSH_8.8",
"SSH-2.0-OpenSSH_8.9",
"SSH-2.0-OpenSSH_9.0",
"SSH-2.0-OpenSSH_9.1",
"SSH-2.0-OpenSSH_9.2",
"SSH-2.0-OpenSSH_9.3",
"SSH-2.0-OpenSSH_9.4",
"SSH-2.0-OpenSSH_9.5",
"SSH-2.0-OpenSSH_9.6",
"SSH-2.0-OpenSSH_9.7",
}
// Define excluded OpenSSH versions (not vulnerable)
excludedVersions := []string{
"SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.10",
"SSH-2.0-OpenSSH_9.3p1 Ubuntu-3ubuntu3.6",
"SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.3",
"SSH-2.0-OpenSSH_9.3p1 Ubuntu-1ubuntu3.6",
"SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3",
"SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u3",
}
// Check if the banner matches any vulnerable version and is not in the excluded versions
isVulnerable := false
for _, version := range vulnerableVersions {
if strings.Contains(banner, version) {
isVulnerable = true
for _, excluded := range excludedVersions {
if strings.Contains(banner, excluded) {
isVulnerable = false
break
}
}
if isVulnerable {
break
}
}
}
// Determine the vulnerability status and send the result
if isVulnerable {
results <- Result{IP: ip, Port: port, Status: "vulnerable", Message: fmt.Sprintf("(running %s)", banner)}
} else {
results <- Result{IP: ip, Port: port, Status: "not_vulnerable", Message: fmt.Sprintf("(running %s)", banner)}
}
}
// incrementProgressCounter increments the global progress counter
func incrementProgressCounter() {
progressMutex.Lock()
defer progressMutex.Unlock()
progressCount++
fmt.Printf("\rProgress: %d/%d hosts scanned", progressCount, totalHosts)
}
// displayBanner displays the script's banner
func displayBanner() {
fmt.Printf("OpenSSH Scanner v%s\n\n", VERSION)
}
// processIPList processes a list of IP addresses from a given file
func processIPList(filePath string) ([]string, error) {
// Open the file for reading
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()
// Create a scanner to read the file line by line
scanner := bufio.NewScanner(file)
var ips []string
// Iterate over each line in the file
for scanner.Scan() {
// Trim any leading/trailing whitespace from the line and append it to the ips slice
ips = append(ips, strings.TrimSpace(scanner.Text()))
}
// Check for any errors during scanning
if err := scanner.Err(); err != nil {
return nil, err
}
// Return the slice of IP addresses
return ips, nil
}
func main() {
// Define command line flags
targets := pflag.StringSliceP("target", "t", []string{}, "IP addresses, CIDR ranges, or files with IP addresses")
port := pflag.IntP("port", "p", 22, "Port to scan")
timeout := pflag.DurationP("timeout", "T", time.Second, "Connection timeout")
concurrency := pflag.IntP("concurrency", "c", 100, "Number of concurrent scans")
pflag.Parse()
// Display the banner
displayBanner()
// Collect IP addresses from arguments and files
var ips []string
for _, target := range *targets {
// Check if the target is a file
if fileContent, err := processIPList(target); err == nil {
// If it's a file, append its content to the ips slice
ips = append(ips, fileContent...)
} else {
// Otherwise, assume it's an IP address or CIDR range and append it directly
ips = append(ips, target)
}
}
// Initialize totalHosts for progress tracking
totalHosts = len(ips)
// Create a channel to receive scan results
results := make(chan Result, totalHosts)
// Create a semaphore to limit concurrent scans
sem := semaphore.NewWeighted(int64(*concurrency))
// Start scanning each IP address
for _, ip := range ips {
// Acquire the semaphore to limit concurrency
sem.Acquire(1)
// Start a goroutine for each scan
go func(ip string) {
defer sem.Release(1)
checkVulnerability(ip, *port, *timeout, results)
}(ip)
}
// Wait for all scans to complete
sem.Acquire(int64(*concurrency))
// Print the final progress
fmt.Printf("\rProgress: %d/%d hosts scanned\n", progressCount, totalHosts)
// Close the results channel to indicate that no more results will be sent
close(results)
// Process and print the scan results
var (
notVulnerable []Result
vulnerable []Result
unknown []Result
closedPorts int
)
// Iterate over the results channel
for result := range results {
// Categorize results based on their status
switch result.Status {
case "closed":
closedPorts++
case "unknown":
unknown = append(unknown, result)
case "vulnerable":
vulnerable = append(vulnerable, result)
case "not_vulnerable":
notVulnerable = append(notVulnerable, result)
}
}
// Print the scan summary
fmt.Printf("\n🛡️ Servers not vulnerable: %d\n", len(notVulnerable))
for _, r := range notVulnerable {
fmt.Printf(" [+] Server at %s%s%s %s\n", GREEN, r.IP, ENDC, r.Message)
}
fmt.Printf("\n🚨 Servers likely vulnerable: %d\n", len(vulnerable))
for _, r := range vulnerable {
fmt.Printf(" [+] Server at %s%s%s %s\n", RED, r.IP, ENDC, r.Message)
}
fmt.Printf("\n⚠️ Servers with unknown SSH version: %d\n", len(unknown))
for _, r := range unknown {
fmt.Printf(" [+] Server at %s%s%s %s\n", ORANGE, r.IP, ENDC, r.Message)
}
fmt.Printf("\n🔒 Servers with port %d closed: %d\n", *port, closedPorts)
fmt.Printf("\n📊 Total scanned targets: %d\n\n", totalHosts)
}
How to run the RegreSSHion ip scanner:
- Save the code: Save the code as
ssh_scanner.go
. - Install dependencies:
go get github.com/spf13/pflag
- Compile and run:
go build ssh_scanner.go ./ssh_scanner -t 192.168.1.1 -t 192.168.1.2 -t 192.168.1.0/24 -t ip_list.txt
Command-line options:
-t
,--target
: Specify one or more target IP addresses, CIDR ranges, or file paths containing a list of IP addresses. This flag can be used multiple times.-p
,--port
: Specify the port number to scan (default: 22).-T
,--timeout
: Specify the connection timeout (default: 1s).-c
,--concurrency
: Specify the number of concurrent scans (default: 100).
Example usage:
- Scan a single IP address:
./ssh_scanner -t 192.168.1.1
- Scan multiple IP addresses:
./ssh_scanner -t 192.168.1.1 -t 192.168.1.2 -t 192.168.1.3
- Scan a CIDR range:
./ssh_scanner -t 192.168.1.0/24
- Scan IP addresses from a file:
./ssh_scanner -t ip_addresses.txt
- Specify a different port:
./ssh_scanner -t 192.168.1.1 -p 2222
- Set a custom timeout:
./ssh_scanner -t 192.168.1.1 -T 2s
- Limit concurrent scans:
./ssh_scanner -t 192.168.1.0/24 -c 50
This Go version of the script provides similar functionality to the Python version, allowing you to scan for potentially vulnerable OpenSSH servers. Remember to use this RegreSSHion ip scanner responsibly and only on systems you have permission to test.
Leave a Reply