Skip to content

1r0BIT/WinSSHound

Repository files navigation

WinSSHound

Python 3.11+ Linux MIT License Version 0.2.0

Windows SSH Misconfiguration Discovery Tool — Map lateral movement paths through misconfigured SSH services in Active Directory environments.

The Problem

Windows servers and workstations can run SSH services — whether it's the built-in OpenSSH Server (Server 2019+), Bitvise SSH Server, an IBM mainframe SSH bridge, or any number of third-party SFTP solutions. When these services are misconfigured (and the defaults are generous), the result is the same:

  • Any authenticated domain user can log in. Regular users, service accounts, computer accounts. No special group membership required.
  • On default Windows OpenSSH installations (pre-Server 2025), GPO "Deny Logon" policies are ignored entirely by the SSH daemon.
  • SSH logon events use Type 8 (NetworkCleartext), which may not be covered by existing detection rules depending on the environment.

These SSH access paths are invisible to standard BloodHound collection. WinSSHound finds them.

What WinSSHound Does

  1. Discovers targets with SSH enabled (via LDAP, manual targeting, or nmap XML import)
  2. Tests SSH authentication with provided credentials across multiple ports
  3. Reads sshd_config to determine who can actually SSH in (--invasive mode)
  4. Generates BloodHound CE OpenGraph JSON with WinSSH_CanSSH edges
  5. Uploads findings to BloodHound CE for attack path visualization

Quick Start

# Install
git clone https://github.com/1r0BIT/WinSSHound.git
cd WinSSHound
pip install -e .

# Basic scan
winsshound -u cloud.strife -p 'Buster$word97!' -d shinra.local -t reactor01.shinra.local

# Auto-discover targets via LDAP, scan multiple ports
winsshound -u cloud.strife -p 'Buster$word97!' -d shinra.local \
  --auto-targets --dc-ip 10.0.0.1 --port 22,2222,8022

# Invasive mode — read sshd_config to determine actual access policy
winsshound -u cloud.strife -p 'Buster$word97!' -d shinra.local \
  --auto-targets --dc-ip 10.0.0.1 --invasive --no-confirm

# Full scan with BloodHound CE upload
winsshound -u cloud.strife -p 'Buster$word97!' -d shinra.local \
  --auto-targets --dc-ip 10.0.0.1 --invasive --no-confirm \
  --bh-url http://localhost:8080 --bh-username admin --bh-password 'bhpass'

# Import nmap results (targets + ports from service scan)
nmap -sV -p- --open -oX ssh_scan.xml 192.168.1.0/24
winsshound -u cloud.strife -p 'Buster$word97!' -d shinra.local --nmap-xml ssh_scan.xml

Requires Python 3.11+ and a Linux attack box.

--invasive Mode

This is the flag that matters. Without it, you learn "this user can SSH here." With it, WinSSHound reads sshd_config from each target and determines whether access is restricted or wide open. The edges change accordingly:

  • Default sshd_config (no restrictions) -> Edge from Authenticated Users to Computer
  • AllowGroups configured -> Edge from each allowed group to Computer
  • AllowUsers configured -> Edge from each allowed user to Computer

--invasive executes a command on the target (reading the config file), so it comes with an OPSEC warning and confirmation prompt. Use --no-confirm to skip the prompt in scripts.

Policy parsing only covers OpenSSH-syntax configs (Microsoft's OpenSSH for Windows + Cygwin / copssh). Bitvise stores its policy in the registry; Tectia uses its own sshd2_config syntax; MFT products like Serv-U, MOVEit, GoAnywhere and Globalscape EFT are GUI / DB administered. WinSSHound still detects these from the SSH banner and tags every CanSSH edge with an ssh_product property — but for non-OpenSSH products, the edge stays at user→computer (the scanning user's access path) and is flagged policy_unparseable: true so you know you're looking at it blind. See docs/bloodhound-integration.md for the full product table.

The parser does not follow Include directives (Windows OpenSSH 9.5+) — if the real access policy lives in included config fragments, the tool overstates access. Check for Include lines manually if results look too permissive.

Choosing the Right Account

For the most accurate results, scan with the lowest-privilege account you have:

  • Bare domain user (member of Domain Users only): If this account can SSH in, everyone can.
  • Computer account: If MachineAccountQuota is > 0, create one with Impacket or PowerMad. A computer account is about as unprivileged as it gets — unless Domain Computers has been granted additional rights, in which case the customer has bigger problems than SSH.

Use a separate privileged account for --auto-targets LDAP discovery if needed.

Documentation

Guide Description
BloodHound Integration Setup, --invasive edge semantics, starter queries
OpenGraph Nodes & Edges WinSSH_CanSSH edge reference — abuse info, remediation, OPSEC
OPSEC Considerations Protocol impact, detection footprint, scan profiles
Starter Queries Pre-built Cypher queries for BloodHound CE
Attack Path Diagram Import into arrows.app

CLI Reference

Usage: winsshound [-h] [-V] -u USERNAME -p PASSWORD -d DOMAIN [-t TARGET]
                  [--targets-file FILE] [--nmap-xml FILE] [--auto-targets]
                  [--dc-ip HOST] [--ldaps] [--resolve-hostnames] [--ns IP]
                  [--port PORTS] [--timeout TIMEOUT] [--threads THREADS] [-v]
                  [--invasive] [--no-confirm]
                  [--bh-url URL] [--bh-username USER] [--bh-password PASS]
                  [--bh-api-key KEY] [--bh-api-key-id ID] [--no-upload]
                  [--allow-orphans] [--output FILE] [--json-only]

Authentication:
  -u, --username        Username for SSH authentication
  -p, --password        Password for SSH authentication
  -d, --domain          Domain name (e.g., corp.local)

Targets:
  -t, --target          Target(s): single IP, comma-separated, CIDR, or hostname
  --targets-file        File containing targets (one per line)
  --nmap-xml            Import targets from nmap XML (hosts with open SSH ports)
  --auto-targets        Discover Windows computers via LDAP
  --dc-ip               Domain controller IP for LDAP queries
  --ldaps               Use LDAPS (port 636) instead of LDAP
  --resolve-hostnames   Resolve IP addresses to hostnames via reverse DNS
  --ns                  DNS server for reverse lookups

Options:
  --port                SSH port(s), comma-separated (default: 22)
  --timeout             Connection timeout in seconds (default: 5)
  --threads             Number of parallel threads (default: 10)
  --invasive            Read sshd_config to determine who can actually SSH in
  --no-confirm          Skip confirmation prompts
  -v, --verbose         Enable verbose output

BloodHound Integration:
  --bh-url              BloodHound CE URL (default: http://localhost:8080)
  --bh-username         BloodHound username
  --bh-password         BloodHound password
  --bh-api-key          BloodHound API key
  --bh-api-key-id       BloodHound API key ID
  --no-upload           Generate JSON but don't upload
  --allow-orphans       Include edges with placeholder SIDs

Output Options:
  --output              Write OpenGraph JSON to file
  --json-only           Only output JSON, skip console table

Defensive Recommendations

  1. Add AllowGroups or AllowUsers to sshd_config — This is the direct fix for default-open SSH access. Applies to OpenSSH; third-party SSH servers have their own ACL mechanisms.
  2. Use the OpenSSH Users group (Server 2025+) — Verify the group name matches your locale. Non-English Windows localizes the group name but the config references the English one.
  3. Monitor Type 8 logon events (Event ID 4624) — SSH's logon type. Worth adding to detection rules if not already present.
  4. Disable SSH services that aren't in use — Applies to both built-in OpenSSH and third-party SSH/SFTP servers.
  5. Network segmentation — Can't attack what you can't reach. Restrict SSH ports between VLANs that don't need SSH connectivity.

References

Contributing

Contributions welcome. Please feel free to submit a Pull Request.

License

MIT License — see LICENSE.

Author

0xr0BIT


WinSSHound is intended for authorized security testing and research only. Always obtain proper authorization before testing.

About

Windows SSH Misconfiguration Discovery Tool - Map lateral movement paths through misconfigured SSH services in Active Directory environments

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages