RegreSSHion Ip Scanner Tool

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.

regreSSHion Ip scanner

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:

  1. Save the code: Save the code as ssh_scanner.go.
  2. Install dependencies: go get github.com/spf13/pflag
  3. 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.