Skip to content

MelHiour/network_crawler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Network crawler

A small script with a big name. How to send several commands to some devices if you do not know exact credential pair? This script is responding to this challenge.

Usage

$ python crawler.py -h
usage: crawler.py [-h] (-d DEVICE_FILE | -l DEVICE_LIST) -c CREDS_FILE -r
                  COMMAND_FILE [-t CONNECT_THREADS] [-p PING_PROCESS]
                  [--ping | --no-ping] [--debug | --no-debug]
                  [--brief | --no-brief]

optional arguments:
  -h, --help          show this help message and exit
  -d DEVICE_FILE      Path to device file
  -l DEVICE_LIST      List of IP addresses (ex. "10.10.1.2, 10.10.1.3")
  -c CREDS_FILE       Path to file with credentials
  -r COMMAND_FILE     Path to file with comamnds list to be executed
  -t CONNECT_THREADS  The amount of simultanious SSH connections (30 by
                      default)
  -p PING_PROCESS     The amount of ping processes (30 by default)
  --ping              Enable ping test (default)
  --no-ping           Skip ping test
  --debug             Enable debug.yml
  --no-debug          Disable debug.yml (default)
  --brief             Enable brief output with summary information
  --no-brief          Returning output of commands per device (default)

Catalog and files structure

├── crawler_modules.py      # All functions are stored here
├── crawler.py              # The script itself
├── data                    # Folder with all supporting files
│   ├── commands            # List of commands to be executed on every device
│   ├── creds.yml           # YAML file with credentials
│   └── devices             # Device list
└── debug.yml               # Debug file which is generated by --debug argument

data/commands

username user1 secret user1

data/creds.yml

usernames:
    - melhiour
    - user1
    - user2
passwords:
    - password1
    - password2
    - melhiour

data/devices

192.168.30.1
192.168.30.2
192.168.30.3
192.168.30.4
192.168.30.5
192.168.30.6
192.168.30.7
192.168.30.8

debug.yml is a dictionary with the following keys and values

{'ARGS':      provided arguments,
'PINGED_IPS': result of ping check,
'DEVICES':    provided device list or the result of file parsing,
'RESULT':     result of the script execution (list of dictionaries {IP:OUTPUT},
'TIME':       [Start time, end time]}

Execution examples

Try to exhaust the list of credentials data/creds.yml on all devices from file data/devices and run commands specified in data/commands

python crawler.py -d data/devices -c data/creds.yml -r data/commads

Specify the list of devices insted of file.

python crawler.py -l "192.168.0.1, 192.168.0.2" -c data/creds.yml -r data/commads

Same as above but excluding ping check.

python crawler.py -l "192.168.0.1, 192.168.0.2" -c data/creds.yml -r data/commads --no-ping

Brief output instead of full output table.

python crawler.py -l "192.168.0.1, 192.168.0.2" -c data/creds.yml -r data/commads --no-ping --brief

Creating debug.yml file with some usefull information (could be easily parsed)

python crawler.py -l "192.168.0.1, 192.168.0.2" -c data/creds.yml -r data/commads --no-ping --brief

Result example

--no-brief (default)

$ python crawler.py -l 192.168.0.1,192.168.30.3,192.168.30.27 -c data/creds.yml -r data/commands
+-------------------+----------------------+
| "Network crawler" | @2019-01-19 23:19:46 |
+-------------------+----------------------+
DONE | Arguments parsed and validated
DONE | Processing devices from provided list "['192.168.0.1', '192.168.30.3', '192.168.30.27']"
DONE | Pinging devices...
INFO | There are 2 alive devices noticed... Processing...
WARN | These devices are dead: ['192.168.0.1']
DONE | Connecting to devices and sending commands...
INFO | The following commands have been sent

╒═══════════════╤═══════════════════════════════════════════════════════════════╕
│ IP            │ OUTPUT                                                        │
╞═══════════════╪═══════════════════════════════════════════════════════════════╡
│ 192.168.30.3  │ config term                                                   │
│               │ Enter configuration commands, one per line.  End with CNTL/Z. │
│               │ R3(config)#username user priv 15 secret secret                │
│               │ R3(config)#end                                                │
│               │ R3#                                                           │
├───────────────┼───────────────────────────────────────────────────────────────┤
│ 192.168.30.27 │ config term                                                   │
│               │ Enter configuration commands, one per line.  End with CNTL/Z. │
│               │ R27(config)#username user priv 15 secret secret               │
│               │ R27(config)#end                                               │
│               │ R27#                                                          │
╘═══════════════╧═══════════════════════════════════════════════════════════════╛

INFO | Showing statistics

STATUS         COUNT
-----------  -------
Succeeded          2
Unreachable        1

Execution time: 0:02:58.232124

--brief

$ python crawler.py -l 192.168.0.1,192.168.30.3,192.168.30.27 -c data/creds.yml -r data/commands --brief
+-------------------+----------------------+
| "Network crawler" | @2019-01-19 23:16:10 |
+-------------------+----------------------+
DONE | Arguments parsed and validated
DONE | Processing devices from provided list "['192.168.0.1', '192.168.30.3', '192.168.30.27']"
DONE | Pinging devices...
INFO | There are 2 alive devices noticed... Processing...
WARN | These devices are dead: ['192.168.0.1']
DONE | Connecting to devices and sending commands...
INFO | Showing summary information

=============  ===========
IP             STATUS
=============  ===========
192.168.0.1    Unreachable
192.168.30.3   Succeeded
192.168.30.27  Succeeded
=============  ===========

INFO | Showing statistics

STATUS         COUNT
-----------  -------
Unreachable        1
Succeeded          2

Execution time: 0:02:56.778946

Requirements

- python3
- pyyaml      # For file parsing
- tabulate    # For output printing
- netmiko     # For connecting to devices
- halo        # For damn good spinners...

Performance

It's not that bad, but it's not very quick either. The performance mostly depends on the amount of credentials to check. Currently, script uses multiprocessing for device connection. It's "parallelized" by devices (not credential pairs). Script starts to gently "brute force" some devices simultaneously trying to use credentials in one-by-one manner on each device. Why? Because the script has been designed for old IOS devices which have around 4 vty lines... Probably, I will add that feature latter, but not sure.

Here are some metrics for 50 devices, 4 usernames, 4 passwords

STATUS         COUNT
-----------  -------
Timeout            2
Unreachable        1
Succeeded         47

Execution time: 0:04:50.479534

Limitation

  1. Only Cisco IOS devices are currently supported.
  2. Only configuration mode commands are accepted. Show commands will be rejected by device if "do" keyword is not specified.

About

Gentle IOS brute force

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages