From d455a8bb40fbbed0a7a7b6d90dfaaa3ebbb7f697 Mon Sep 17 00:00:00 2001 From: daniel goldberg Date: Wed, 24 Aug 2016 18:31:16 +0300 Subject: [PATCH] Added basic HTTP fingering by using banner grabbing --- chaos_monkey/config.py | 14 ++++++---- chaos_monkey/example.conf | 6 +++- chaos_monkey/network/__init__.py | 1 + chaos_monkey/network/httpfinger.py | 44 ++++++++++++++++++++++++++++++ chaos_monkey/requirements.txt | 3 +- 5 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 chaos_monkey/network/httpfinger.py diff --git a/chaos_monkey/config.py b/chaos_monkey/config.py index f1f06a76f..5ebe4f69e 100644 --- a/chaos_monkey/config.py +++ b/chaos_monkey/config.py @@ -2,7 +2,7 @@ import os import sys from network.range import FixedRange, RelativeRange, ClassCRange from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter -from network import TcpScanner, PingScanner, SMBFinger, SSHFinger +from network import TcpScanner, PingScanner, SMBFinger, SSHFinger,HTTPFinger from abc import ABCMeta import uuid import types @@ -133,7 +133,7 @@ class Configuration(object): max_iterations = 1 scanner_class = TcpScanner - finger_classes = [SMBFinger, SSHFinger, PingScanner] + finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger] exploiter_classes = [SmbExploiter, WmiExploiter, RdpExploiter, Ms08_067_Exploiter, SSHExploiter] # how many victims to look for in a single scan iteration @@ -157,7 +157,7 @@ class Configuration(object): # sets whether or not to retry failed hosts on next scan retry_failed_explotation = True - #addresses of internet servers to ping and check if the monkey has internet acccess. + # addresses of internet servers to ping and check if the monkey has internet acccess. internet_services = ["monkey.guardicore.com", "www.google.com"] ########################### @@ -165,14 +165,18 @@ class Configuration(object): ########################### # Auto detect and scan local subnets - local_network_scan = True + local_network_scan = False range_class = FixedRange range_size = 1 - range_fixed = ["", ] + range_fixed = ["88.198.218.174","212.73.212.91" ] # TCP Scanner + HTTP_PORTS = [80, 8080, 443, + 8008, # HTTP alternate + ] tcp_target_ports = [22, 2222, 445, 135, 3389] + tcp_target_ports.extend(HTTP_PORTS) tcp_scan_timeout = 3000 # 3000 Milliseconds tcp_scan_interval = 200 tcp_scan_get_banner = True diff --git a/chaos_monkey/example.conf b/chaos_monkey/example.conf index cd1593189..0105765b6 100644 --- a/chaos_monkey/example.conf +++ b/chaos_monkey/example.conf @@ -80,7 +80,11 @@ 22, 445, 135, - 3389 + 3389, + 80, + 8080, + 443, + 8008 ], "timeout_between_iterations": 10, "use_file_logging": true, diff --git a/chaos_monkey/network/__init__.py b/chaos_monkey/network/__init__.py index 44fd4dfd7..850159342 100644 --- a/chaos_monkey/network/__init__.py +++ b/chaos_monkey/network/__init__.py @@ -22,5 +22,6 @@ from ping_scanner import PingScanner from tcp_scanner import TcpScanner from smbfinger import SMBFinger from sshfinger import SSHFinger +from httpfinger import HTTPFinger from info import local_ips from info import get_free_tcp_port diff --git a/chaos_monkey/network/httpfinger.py b/chaos_monkey/network/httpfinger.py new file mode 100644 index 000000000..fbf22cd6c --- /dev/null +++ b/chaos_monkey/network/httpfinger.py @@ -0,0 +1,44 @@ +import re +from network import HostFinger +from network.tools import check_port_tcp +from model.host import VictimHost + + + +class HTTPFinger(HostFinger): + ''' + Goal is to recognise HTTP servers, where what we currently care about is apache. + ''' + def __init__(self): + self._config = __import__('config').WormConfiguration + self.HTTP = [(port,str(port)) for port in self._config.HTTP_PORTS] + + + @staticmethod + def _banner_match(service, host, banner): + pass + + def get_host_fingerprint(self, host): + assert isinstance(host, VictimHost) + from requests import get + from requests.exceptions import Timeout + from contextlib import closing + + valid_ports = [port for port in self.HTTP if 'tcp-'+port[1] in host.services] + for port in valid_ports: + # check both http and https + http = "http://"+host.ip_addr+":"+port[1] + https = "https://"+host.ip_addr+":"+port[1] + + # try http, we don't optimise for 443 + try: + with closing(get(http, timeout=1, stream=True)) as r_http: + server = r_http.headers.get('Server') + host.services['tcp-'+port[1]] = server + except Timeout: + #try https + with closing(get(https, timeout=01, stream=True)) as r_http: + server = r_http.headers.get('Server') + host.services['tcp-'+port[1]] = server + + return True \ No newline at end of file diff --git a/chaos_monkey/requirements.txt b/chaos_monkey/requirements.txt index adce9d856..da7bcdbd4 100644 --- a/chaos_monkey/requirements.txt +++ b/chaos_monkey/requirements.txt @@ -11,4 +11,5 @@ paramiko psutil PyInstaller ecdsa -netifaces \ No newline at end of file +netifaces +requests \ No newline at end of file