Merge pull request #1124 from guardicore/dlint

Add dlint to flake8
This commit is contained in:
Mike Salvatore 2021-04-28 13:24:41 -04:00 committed by GitHub
commit c67ed63cc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 156 additions and 133 deletions

View File

@ -19,6 +19,7 @@ repos:
rev: 3.9.1 rev: 3.9.1
hooks: hooks:
- id: flake8 - id: flake8
additional_dependencies: [dlint]
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0 rev: v3.4.0
hooks: hooks:

View File

@ -25,3 +25,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed ### Fixed
- Attempted to delete a directory when monkey config reset was called. #1054 - Attempted to delete a directory when monkey config reset was called. #1054
### Security
- Address minor issues discovered by Dlint. #1075

View File

@ -66,8 +66,8 @@ class MonkeyIslandRequests(object):
return request_function_wrapper return request_function_wrapper
def get_jwt_from_server(self): def get_jwt_from_server(self):
resp = requests.post( resp = requests.post( # noqa: DUO123
self.addr + "api/auth", # noqa: DUO123 self.addr + "api/auth",
json={"username": NO_AUTH_CREDS, "password": NO_AUTH_CREDS}, json={"username": NO_AUTH_CREDS, "password": NO_AUTH_CREDS},
verify=False, verify=False,
) )
@ -75,8 +75,8 @@ class MonkeyIslandRequests(object):
@_Decorators.refresh_jwt_token @_Decorators.refresh_jwt_token
def get(self, url, data=None): def get(self, url, data=None):
return requests.get( return requests.get( # noqa: DUO123
self.addr + url, # noqa: DUO123 self.addr + url,
headers=self.get_jwt_header(), headers=self.get_jwt_header(),
params=data, params=data,
verify=False, verify=False,
@ -84,25 +84,25 @@ class MonkeyIslandRequests(object):
@_Decorators.refresh_jwt_token @_Decorators.refresh_jwt_token
def post(self, url, data): def post(self, url, data):
return requests.post( return requests.post( # noqa: DUO123
self.addr + url, data=data, headers=self.get_jwt_header(), verify=False # noqa: DUO123 self.addr + url, data=data, headers=self.get_jwt_header(), verify=False
) )
@_Decorators.refresh_jwt_token @_Decorators.refresh_jwt_token
def post_json(self, url, data: Dict): def post_json(self, url, data: Dict):
return requests.post( return requests.post( # noqa: DUO123
self.addr + url, json=data, headers=self.get_jwt_header(), verify=False # noqa: DUO123 self.addr + url, json=data, headers=self.get_jwt_header(), verify=False
) )
@_Decorators.refresh_jwt_token @_Decorators.refresh_jwt_token
def patch(self, url, data: Dict): def patch(self, url, data: Dict):
return requests.patch( return requests.patch( # noqa: DUO123
self.addr + url, data=data, headers=self.get_jwt_header(), verify=False # noqa: DUO123 self.addr + url, data=data, headers=self.get_jwt_header(), verify=False
) )
@_Decorators.refresh_jwt_token @_Decorators.refresh_jwt_token
def delete(self, url): def delete(self, url):
return requests.delete( # noqa: DOU123 return requests.delete( # noqa: DUO123
self.addr + url, headers=self.get_jwt_header(), verify=False self.addr + url, headers=self.get_jwt_header(), verify=False
) )

View File

@ -23,9 +23,9 @@ class GCPHandler(object):
subprocess.call(GCPHandler.get_auth_command(key_path), shell=True) # noqa: DUO116 subprocess.call(GCPHandler.get_auth_command(key_path), shell=True) # noqa: DUO116
LOGGER.info("GCP Handler passed key") LOGGER.info("GCP Handler passed key")
# set project # set project
subprocess.call( subprocess.call( # noqa: DUO116
GCPHandler.get_set_project_command(project_id), shell=True GCPHandler.get_set_project_command(project_id), shell=True
) # noqa: DUO116 )
LOGGER.info("GCP Handler set project") LOGGER.info("GCP Handler set project")
LOGGER.info("GCP Handler initialized successfully") LOGGER.info("GCP Handler initialized successfully")
except Exception as e: except Exception as e:
@ -39,18 +39,18 @@ class GCPHandler(object):
""" """
LOGGER.info("Setting up all GCP machines...") LOGGER.info("Setting up all GCP machines...")
try: try:
subprocess.call( subprocess.call( # noqa: DUO116
(GCPHandler.MACHINE_STARTING_COMMAND % (machine_list, self.zone)), shell=True (GCPHandler.MACHINE_STARTING_COMMAND % (machine_list, self.zone)), shell=True
) # noqa: DUO116 )
LOGGER.info("GCP machines successfully started.") LOGGER.info("GCP machines successfully started.")
except Exception as e: except Exception as e:
LOGGER.error("GCP Handler failed to start GCP machines: %s" % e) LOGGER.error("GCP Handler failed to start GCP machines: %s" % e)
def stop_machines(self, machine_list): def stop_machines(self, machine_list):
try: try:
subprocess.call( subprocess.call( # noqa: DUO116
(GCPHandler.MACHINE_STOPPING_COMMAND % (machine_list, self.zone)), shell=True (GCPHandler.MACHINE_STOPPING_COMMAND % (machine_list, self.zone)), shell=True
) # noqa: DUO116 )
LOGGER.info("GCP machines stopped successfully.") LOGGER.info("GCP machines stopped successfully.")
except Exception as e: except Exception as e:
LOGGER.error("GCP Handler failed to stop network machines: %s" % e) LOGGER.error("GCP Handler failed to stop network machines: %s" % e)

View File

@ -64,8 +64,8 @@ class ControlClient(object):
if ControlClient.proxies: if ControlClient.proxies:
monkey["tunnel"] = ControlClient.proxies.get("https") monkey["tunnel"] = ControlClient.proxies.get("https")
requests.post( requests.post( # noqa: DUO123
"https://%s/api/monkey" % (WormConfiguration.current_server,), # noqa: DUO123 "https://%s/api/monkey" % (WormConfiguration.current_server,),
data=json.dumps(monkey), data=json.dumps(monkey),
headers={"content-type": "application/json"}, headers={"content-type": "application/json"},
verify=False, verify=False,
@ -92,8 +92,8 @@ class ControlClient(object):
if ControlClient.proxies: if ControlClient.proxies:
debug_message += " through proxies: %s" % ControlClient.proxies debug_message += " through proxies: %s" % ControlClient.proxies
LOG.debug(debug_message) LOG.debug(debug_message)
requests.get( requests.get( # noqa: DUO123
f"https://{server}/api?action=is-up", # noqa: DUO123 f"https://{server}/api?action=is-up",
verify=False, verify=False,
proxies=ControlClient.proxies, proxies=ControlClient.proxies,
timeout=TIMEOUT_IN_SECONDS, timeout=TIMEOUT_IN_SECONDS,
@ -130,9 +130,8 @@ class ControlClient(object):
monkey = {} monkey = {}
if ControlClient.proxies: if ControlClient.proxies:
monkey["tunnel"] = ControlClient.proxies.get("https") monkey["tunnel"] = ControlClient.proxies.get("https")
requests.patch( requests.patch( # noqa: DUO123
"https://%s/api/monkey/%s" "https://%s/api/monkey/%s" % (WormConfiguration.current_server, GUID),
% (WormConfiguration.current_server, GUID), # noqa: DUO123
data=json.dumps(monkey), data=json.dumps(monkey),
headers={"content-type": "application/json"}, headers={"content-type": "application/json"},
verify=False, verify=False,
@ -155,8 +154,8 @@ class ControlClient(object):
return return
try: try:
telemetry = {"monkey_guid": GUID, "telem_category": telem_category, "data": json_data} telemetry = {"monkey_guid": GUID, "telem_category": telem_category, "data": json_data}
requests.post( requests.post( # noqa: DUO123
"https://%s/api/telemetry" % (WormConfiguration.current_server,), # noqa: DUO123 "https://%s/api/telemetry" % (WormConfiguration.current_server,),
data=json.dumps(telemetry), data=json.dumps(telemetry),
headers={"content-type": "application/json"}, headers={"content-type": "application/json"},
verify=False, verify=False,
@ -174,8 +173,8 @@ class ControlClient(object):
return return
try: try:
telemetry = {"monkey_guid": GUID, "log": json.dumps(log)} telemetry = {"monkey_guid": GUID, "log": json.dumps(log)}
requests.post( requests.post( # noqa: DUO123
"https://%s/api/log" % (WormConfiguration.current_server,), # noqa: DUO123 "https://%s/api/log" % (WormConfiguration.current_server,),
data=json.dumps(telemetry), data=json.dumps(telemetry),
headers={"content-type": "application/json"}, headers={"content-type": "application/json"},
verify=False, verify=False,
@ -192,9 +191,8 @@ class ControlClient(object):
if not WormConfiguration.current_server: if not WormConfiguration.current_server:
return return
try: try:
reply = requests.get( reply = requests.get( # noqa: DUO123
"https://%s/api/monkey/%s" "https://%s/api/monkey/%s" % (WormConfiguration.current_server, GUID),
% (WormConfiguration.current_server, GUID), # noqa: DUO123
verify=False, verify=False,
proxies=ControlClient.proxies, proxies=ControlClient.proxies,
timeout=MEDIUM_REQUEST_TIMEOUT, timeout=MEDIUM_REQUEST_TIMEOUT,
@ -230,9 +228,8 @@ class ControlClient(object):
if not WormConfiguration.current_server: if not WormConfiguration.current_server:
return return
try: try:
requests.patch( requests.patch( # noqa: DUO123
"https://%s/api/monkey/%s" "https://%s/api/monkey/%s" % (WormConfiguration.current_server, GUID),
% (WormConfiguration.current_server, GUID), # noqa: DUO123
data=json.dumps({"config_error": True}), data=json.dumps({"config_error": True}),
headers={"content-type": "application/json"}, headers={"content-type": "application/json"},
verify=False, verify=False,
@ -292,9 +289,9 @@ class ControlClient(object):
if (monkeyfs.isfile(dest_file)) and (size == monkeyfs.getsize(dest_file)): if (monkeyfs.isfile(dest_file)) and (size == monkeyfs.getsize(dest_file)):
return dest_file return dest_file
else: else:
download = requests.get( download = requests.get( # noqa: DUO123
"https://%s/api/monkey/download/%s" "https://%s/api/monkey/download/%s"
% (WormConfiguration.current_server, filename), # noqa: DUO123 % (WormConfiguration.current_server, filename),
verify=False, verify=False,
proxies=ControlClient.proxies, proxies=ControlClient.proxies,
timeout=MEDIUM_REQUEST_TIMEOUT, timeout=MEDIUM_REQUEST_TIMEOUT,
@ -322,9 +319,8 @@ class ControlClient(object):
if not WormConfiguration.current_server: if not WormConfiguration.current_server:
return None, None return None, None
try: try:
reply = requests.post( reply = requests.post( # noqa: DUO123
"https://%s/api/monkey/download" "https://%s/api/monkey/download" % (WormConfiguration.current_server,),
% (WormConfiguration.current_server,), # noqa: DUO123
data=json.dumps(host_dict), data=json.dumps(host_dict),
headers={"content-type": "application/json"}, headers={"content-type": "application/json"},
verify=False, verify=False,
@ -370,8 +366,8 @@ class ControlClient(object):
@staticmethod @staticmethod
def get_pba_file(filename): def get_pba_file(filename):
try: try:
return requests.get( return requests.get( # noqa: DUO123
PBA_FILE_DOWNLOAD % (WormConfiguration.current_server, filename), # noqa: DUO123 PBA_FILE_DOWNLOAD % (WormConfiguration.current_server, filename),
verify=False, verify=False,
proxies=ControlClient.proxies, proxies=ControlClient.proxies,
timeout=LONG_REQUEST_TIMEOUT, timeout=LONG_REQUEST_TIMEOUT,
@ -382,9 +378,9 @@ class ControlClient(object):
@staticmethod @staticmethod
def get_T1216_pba_file(): def get_T1216_pba_file():
try: try:
return requests.get( return requests.get( # noqa: DUO123
urljoin( urljoin(
f"https://{WormConfiguration.current_server}/", # noqa: DUO123 f"https://{WormConfiguration.current_server}/",
T1216_PBA_FILE_DOWNLOAD_PATH, T1216_PBA_FILE_DOWNLOAD_PATH,
), ),
verify=False, verify=False,
@ -416,7 +412,9 @@ class ControlClient(object):
f"https://{WormConfiguration.current_server}/api/monkey_control" f"https://{WormConfiguration.current_server}/api/monkey_control"
f"/check_remote_port/{port}" f"/check_remote_port/{port}"
) )
response = requests.get(url, verify=False, timeout=SHORT_REQUEST_TIMEOUT) response = requests.get( # noqa: DUO123
url, verify=False, timeout=SHORT_REQUEST_TIMEOUT
)
response = json.loads(response.content.decode()) response = json.loads(response.content.decode())
return response["status"] == "port_visible" return response["status"] == "port_visible"
except requests.exceptions.RequestException: except requests.exceptions.RequestException:
@ -424,7 +422,7 @@ class ControlClient(object):
@staticmethod @staticmethod
def report_start_on_island(): def report_start_on_island():
requests.post( requests.post( # noqa: DUO123
f"https://{WormConfiguration.current_server}/api/monkey_control/started_on_island", f"https://{WormConfiguration.current_server}/api/monkey_control/started_on_island",
data=json.dumps({"started_on_island": True}), data=json.dumps({"started_on_island": True}),
verify=False, verify=False,

View File

@ -4,6 +4,7 @@ import filecmp
import logging import logging
import os import os
import pprint import pprint
import shlex
import shutil import shutil
import subprocess import subprocess
import sys import sys
@ -13,11 +14,7 @@ from ctypes import c_char_p
from common.utils.attack_utils import ScanStatus, UsageEnum from common.utils.attack_utils import ScanStatus, UsageEnum
from infection_monkey.config import WormConfiguration from infection_monkey.config import WormConfiguration
from infection_monkey.exploit.tools.helpers import build_monkey_commandline_explicitly from infection_monkey.exploit.tools.helpers import build_monkey_commandline_explicitly
from infection_monkey.model import ( from infection_monkey.model import MONKEY_CMDLINE_LINUX, MONKEY_CMDLINE_WINDOWS
GENERAL_CMDLINE_LINUX,
MONKEY_CMDLINE_LINUX,
MONKEY_CMDLINE_WINDOWS,
)
from infection_monkey.system_info import OperatingSystem, SystemInfoCollector from infection_monkey.system_info import OperatingSystem, SystemInfoCollector
from infection_monkey.telemetry.attack.t1106_telem import T1106Telem from infection_monkey.telemetry.attack.t1106_telem import T1106Telem
@ -146,33 +143,46 @@ class MonkeyDrops(object):
) )
if OperatingSystem.Windows == SystemInfoCollector.get_os(): if OperatingSystem.Windows == SystemInfoCollector.get_os():
# TODO: Replace all of this string templating with a function that accepts
# the necessary parameters and returns a list of arguments.
monkey_cmdline = ( monkey_cmdline = (
MONKEY_CMDLINE_WINDOWS % {"monkey_path": self._config["destination_path"]} MONKEY_CMDLINE_WINDOWS % {"monkey_path": self._config["destination_path"]}
+ monkey_options + monkey_options
) )
monkey_cmdline_split = shlex.split(
monkey_cmdline,
posix=False, # won't try resolving "\" in paths as part of escape sequences
)
monkey_process = subprocess.Popen(
monkey_cmdline_split,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True,
creationflags=DETACHED_PROCESS,
)
else: else:
dest_path = self._config["destination_path"] dest_path = self._config["destination_path"]
# In linux we have a more complex commandline. There's a general outer one, # In Linux, we need to change the directory first, which is done
# and the inner one which actually # using thw `cwd` argument in `subprocess.Popen` below
# runs the monkey # TODO: Replace all of this string templating with a function that accepts
inner_monkey_cmdline = ( # the necessary parameters and returns a list of arguments.
monkey_cmdline = (
MONKEY_CMDLINE_LINUX % {"monkey_filename": dest_path.split("/")[-1]} MONKEY_CMDLINE_LINUX % {"monkey_filename": dest_path.split("/")[-1]}
+ monkey_options + monkey_options
) )
monkey_cmdline = GENERAL_CMDLINE_LINUX % { monkey_cmdline_split = shlex.split(monkey_cmdline)
"monkey_directory": dest_path[0 : dest_path.rfind("/")],
"monkey_commandline": inner_monkey_cmdline,
}
monkey_process = subprocess.Popen( monkey_process = subprocess.Popen(
monkey_cmdline, monkey_cmdline_split,
shell=True, stdin=subprocess.PIPE,
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stderr=subprocess.PIPE, close_fds=True,
close_fds=True, cwd="/".join(dest_path.split("/")[0:-1]),
creationflags=DETACHED_PROCESS, creationflags=DETACHED_PROCESS,
) )
LOG.info( LOG.info(
"Executed monkey process (PID=%d) with command line: %s", "Executed monkey process (PID=%d) with command line: %s",

View File

@ -82,8 +82,8 @@ class DrupalExploiter(WebRCE):
""" """
payload = build_exploitability_check_payload(url) payload = build_exploitability_check_payload(url)
response = requests.get( response = requests.get( # noqa: DUO123
f"{url}?_format=hal_json", # noqa: DUO123 f"{url}?_format=hal_json",
json=payload, json=payload,
headers={"Content-Type": "application/hal+json"}, headers={"Content-Type": "application/hal+json"},
verify=False, verify=False,
@ -102,8 +102,8 @@ class DrupalExploiter(WebRCE):
base = remove_port(url) base = remove_port(url)
payload = build_cmd_execution_payload(base, cmd) payload = build_cmd_execution_payload(base, cmd)
r = requests.get( r = requests.get( # noqa: DUO123
f"{url}?_format=hal_json", # noqa: DUO123 f"{url}?_format=hal_json",
json=payload, json=payload,
headers={"Content-Type": "application/hal+json"}, headers={"Content-Type": "application/hal+json"},
verify=False, verify=False,
@ -157,9 +157,9 @@ def find_exploitbale_article_ids(base_url: str, lower: int = 1, upper: int = 100
articles = set() articles = set()
while lower < upper: while lower < upper:
node_url = urljoin(base_url, str(lower)) node_url = urljoin(base_url, str(lower))
response = requests.get( response = requests.get( # noqa: DUO123
node_url, verify=False, timeout=LONG_REQUEST_TIMEOUT node_url, verify=False, timeout=LONG_REQUEST_TIMEOUT
) # noqa: DUO123 )
if response.status_code == 200: if response.status_code == 200:
if is_response_cached(response): if is_response_cached(response):
LOG.info(f"Found a cached article at: {node_url}, skipping") LOG.info(f"Found a cached article at: {node_url}, skipping")

View File

@ -7,8 +7,8 @@
import json import json
import logging import logging
import posixpath import posixpath
import random
import string import string
from random import SystemRandom
import requests import requests
@ -69,8 +69,9 @@ class HadoopExploiter(WebRCE):
resp = json.loads(resp.content) resp = json.loads(resp.content)
app_id = resp["application-id"] app_id = resp["application-id"]
# Create a random name for our application in YARN # Create a random name for our application in YARN
safe_random = SystemRandom()
rand_name = ID_STRING + "".join( rand_name = ID_STRING + "".join(
[random.choice(string.ascii_lowercase) for _ in range(self.RAN_STR_LEN)] [safe_random.choice(string.ascii_lowercase) for _ in range(self.RAN_STR_LEN)]
) )
payload = self.build_payload(app_id, rand_name, command) payload = self.build_payload(app_id, rand_name, command)
resp = requests.post( resp = requests.post(

View File

@ -3,7 +3,7 @@
import logging import logging
import string import string
from random import choice from random import SystemRandom
import requests import requests
@ -37,8 +37,9 @@ class ShellShockExploiter(HostExploiter):
def __init__(self, host): def __init__(self, host):
super(ShellShockExploiter, self).__init__(host) super(ShellShockExploiter, self).__init__(host)
self.HTTP = [str(port) for port in self._config.HTTP_PORTS] self.HTTP = [str(port) for port in self._config.HTTP_PORTS]
safe_random = SystemRandom()
self.success_flag = "".join( self.success_flag = "".join(
choice(string.ascii_uppercase + string.digits) for _ in range(20) safe_random.choice(string.ascii_uppercase + string.digits) for _ in range(20)
) )
self.skip_exist = self._config.skip_exploit_if_file_exist self.skip_exist = self._config.skip_exploit_if_file_exist
@ -242,9 +243,9 @@ class ShellShockExploiter(HostExploiter):
try: try:
LOG.debug("Header is: %s" % header) LOG.debug("Header is: %s" % header)
LOG.debug("Attack is: %s" % attack) LOG.debug("Attack is: %s" % attack)
r = requests.get( r = requests.get( # noqa: DUO123
url, headers={header: attack}, verify=False, timeout=TIMEOUT url, headers={header: attack}, verify=False, timeout=TIMEOUT
) # noqa: DUO123 )
result = r.content.decode() result = r.content.decode()
return result return result
except requests.exceptions.RequestException as exc: except requests.exceptions.RequestException as exc:

View File

@ -52,7 +52,7 @@ class Struts2Exploiter(WebRCE):
request = urllib.request.Request(url, headers=headers) request = urllib.request.Request(url, headers=headers)
try: try:
return urllib.request.urlopen( return urllib.request.urlopen(
request, context=ssl._create_unverified_context() request, context=ssl._create_unverified_context() # noqa: DUO122
).geturl() ).geturl()
except urllib.error.URLError: except urllib.error.URLError:
LOG.error("Can't reach struts2 server") LOG.error("Can't reach struts2 server")

View File

@ -83,9 +83,9 @@ class WebLogic201710271(WebRCE):
else: else:
payload = self.get_exploit_payload("cmd", "/c", command + " 1> NUL 2> NUL") payload = self.get_exploit_payload("cmd", "/c", command + " 1> NUL 2> NUL")
try: try:
post( post( # noqa: DUO123
url, data=payload, headers=HEADERS, timeout=EXECUTION_TIMEOUT, verify=False url, data=payload, headers=HEADERS, timeout=EXECUTION_TIMEOUT, verify=False
) # noqa: DUO123 )
except Exception as e: except Exception as e:
LOG.error("Connection error: %s" % e) LOG.error("Connection error: %s" % e)
return False return False
@ -121,9 +121,9 @@ class WebLogic201710271(WebRCE):
def check_if_exploitable_weblogic(self, url, httpd): def check_if_exploitable_weblogic(self, url, httpd):
payload = self.get_test_payload(ip=httpd.local_ip, port=httpd.local_port) payload = self.get_test_payload(ip=httpd.local_ip, port=httpd.local_port)
try: try:
post( post( # noqa: DUO123
url, data=payload, headers=HEADERS, timeout=REQUEST_DELAY, verify=False url, data=payload, headers=HEADERS, timeout=REQUEST_DELAY, verify=False
) # noqa: DUO123 )
except exceptions.ReadTimeout: except exceptions.ReadTimeout:
# Our request will not get response thus we get ReadTimeout error # Our request will not get response thus we get ReadTimeout error
pass pass

View File

@ -1,7 +1,7 @@
import itertools import itertools
import socket import socket
import struct import struct
from random import randint from random import randint # noqa: DUO102
from subprocess import check_output from subprocess import check_output
import netifaces import netifaces

View File

@ -1,5 +1,5 @@
from itertools import zip_longest from itertools import zip_longest
from random import shuffle from random import shuffle # noqa: DUO102
import infection_monkey.config import infection_monkey.config
from infection_monkey.network.HostFinger import HostFinger from infection_monkey.network.HostFinger import HostFinger

View File

@ -46,8 +46,8 @@ class ClearCommandHistory(PBA):
def run(self): def run(self):
if self.command: if self.command:
try: try:
output = subprocess.check_output( output = subprocess.check_output( # noqa: DUO116
self.command, stderr=subprocess.STDOUT, shell=True # noqa: DUO116 self.command, stderr=subprocess.STDOUT, shell=True
).decode() ).decode()
return output, True return output, True
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:

View File

@ -52,8 +52,8 @@ class CommunicateAsNewUser(PBA):
@staticmethod @staticmethod
def get_random_new_user_name(): def get_random_new_user_name():
return USERNAME_PREFIX + "".join( return USERNAME_PREFIX + "".join(
random.choice(string.ascii_lowercase) for _ in range(5) random.choice(string.ascii_lowercase) for _ in range(5) # noqa: DUO102
) # noqa: DUO102 )
@staticmethod @staticmethod
def get_commandline_for_http_request(url, is_windows=is_windows_os()): def get_commandline_for_http_request(url, is_windows=is_windows_os()):

View File

@ -58,8 +58,8 @@ class ModifyShellStartupFiles(PBA):
def run(self): def run(self):
if self.command: if self.command:
try: try:
output = subprocess.check_output( output = subprocess.check_output( # noqa: DUO116
self.command, stderr=subprocess.STDOUT, shell=True # noqa: DUO116 self.command, stderr=subprocess.STDOUT, shell=True
).decode() ).decode()
return output, True return output, True
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:

View File

@ -21,10 +21,9 @@ class SignedScriptProxyExecution(PBA):
try: try:
original_comspec = "" original_comspec = ""
if is_windows_os(): if is_windows_os():
original_comspec = subprocess.check_output( original_comspec = subprocess.check_output( # noqa: DUO116
"if defined COMSPEC echo %COMSPEC%", shell=True "if defined COMSPEC echo %COMSPEC%", shell=True
).decode() # noqa: DUO116 ).decode()
super().run() super().run()
except Exception as e: except Exception as e:
LOG.warning( LOG.warning(

View File

@ -90,7 +90,7 @@ class PBA(Plugin):
:return: Tuple of command's output string and boolean, indicating if it succeeded :return: Tuple of command's output string and boolean, indicating if it succeeded
""" """
try: try:
output = subprocess.check_output( output = subprocess.check_output( # noqa: DUO116
self.command, stderr=subprocess.STDOUT, shell=True self.command, stderr=subprocess.STDOUT, shell=True
).decode() ).decode()
return output, True return output, True

View File

@ -13,8 +13,10 @@ def get_windows_commands_to_modify_shell_startup_files():
# get list of usernames # get list of usernames
USERS = ( USERS = (
subprocess.check_output("dir C:\\Users /b", shell=True).decode().split("\r\n")[:-1] subprocess.check_output("dir C:\\Users /b", shell=True) # noqa: DUO116
) # noqa: DUO116 .decode()
.split("\r\n")[:-1]
)
USERS.remove("Public") USERS.remove("Public")
STARTUP_FILES_PER_USER = [ STARTUP_FILES_PER_USER = [

View File

@ -15,7 +15,7 @@ def get_commands_to_proxy_execution_using_signed_script():
def cleanup_changes(original_comspec): def cleanup_changes(original_comspec):
if is_windows_os(): if is_windows_os():
subprocess.run( subprocess.run( # noqa: DUO116
get_windows_commands_to_reset_comspec(original_comspec), shell=True get_windows_commands_to_reset_comspec(original_comspec), shell=True
) # noqa: DUO116 )
subprocess.run(get_windows_commands_to_delete_temp_comspec(), shell=True) # noqa: DUO116 subprocess.run(get_windows_commands_to_delete_temp_comspec(), shell=True) # noqa: DUO116

View File

@ -1,4 +1,5 @@
import logging import logging
import shlex
import subprocess import subprocess
import sys import sys
@ -51,10 +52,10 @@ class WindowsInfoCollector(InfoCollector):
def get_installed_packages(self): def get_installed_packages(self):
LOG.info("Getting installed packages") LOG.info("Getting installed packages")
packages = subprocess.check_output("dism /online /get-packages", shell=True) packages = subprocess.check_output(shlex.split("dism /online /get-packages"))
self.info["installed_packages"] = packages.decode("utf-8", errors="ignore") self.info["installed_packages"] = packages.decode("utf-8", errors="ignore")
features = subprocess.check_output("dism /online /get-features", shell=True) features = subprocess.check_output(shlex.split("dism /online /get-features"))
self.info["installed_features"] = features.decode("utf-8", errors="ignore") self.info["installed_features"] = features.decode("utf-8", errors="ignore")
LOG.debug("Got installed packages") LOG.debug("Got installed packages")

View File

@ -126,7 +126,7 @@ class HTTPConnectProxyHandler(http.server.BaseHTTPRequestHandler):
LOG.info("Received bootloader's request: {}".format(post_data)) LOG.info("Received bootloader's request: {}".format(post_data))
try: try:
dest_path = self.path dest_path = self.path
r = requests.post( r = requests.post( # noqa: DUO123
url=dest_path, url=dest_path,
data=post_data, data=post_data,
verify=False, verify=False,

View File

@ -26,9 +26,9 @@ def get_commands_to_hide_folders():
def cleanup_hidden_files(is_windows=is_windows_os()): def cleanup_hidden_files(is_windows=is_windows_os()):
subprocess.run( subprocess.run( # noqa: DUO116
get_windows_commands_to_delete() get_windows_commands_to_delete()
if is_windows # noqa: DUO116 if is_windows
else " ".join(get_linux_commands_to_delete()), else " ".join(get_linux_commands_to_delete()),
shell=True, shell=True,
) )

View File

@ -1,6 +1,6 @@
import datetime import datetime
import logging import logging
import os import shlex
import subprocess import subprocess
from infection_monkey.utils.auto_new_user import AutoNewUser from infection_monkey.utils.auto_new_user import AutoNewUser
@ -43,18 +43,16 @@ class AutoNewLinuxUser(AutoNewUser):
logger.debug( logger.debug(
"Trying to add {} with commands {}".format(self.username, str(commands_to_add_user)) "Trying to add {} with commands {}".format(self.username, str(commands_to_add_user))
) )
_ = subprocess.check_output( _ = subprocess.check_output(commands_to_add_user, stderr=subprocess.STDOUT)
" ".join(commands_to_add_user), stderr=subprocess.STDOUT, shell=True
)
def __enter__(self): def __enter__(self):
return self # No initialization/logging on needed in Linux return self # No initialization/logging on needed in Linux
def run_as(self, command): def run_as(self, command):
command_as_new_user = "sudo -u {username} {command}".format( command_as_new_user = shlex.split(
username=self.username, command=command "sudo -u {username} {command}".format(username=self.username, command=command)
) )
return os.system(command_as_new_user) return subprocess.call(command_as_new_user)
def __exit__(self, exc_type, exc_val, exc_tb): def __exit__(self, exc_type, exc_val, exc_tb):
# delete the user. # delete the user.
@ -64,6 +62,4 @@ class AutoNewLinuxUser(AutoNewUser):
self.username, str(commands_to_delete_user) self.username, str(commands_to_delete_user)
) )
) )
_ = subprocess.check_output( _ = subprocess.check_output(commands_to_delete_user, stderr=subprocess.STDOUT)
" ".join(commands_to_delete_user), stderr=subprocess.STDOUT, shell=True
)

View File

@ -39,7 +39,7 @@ class AutoNewWindowsUser(AutoNewUser):
windows_cmds = get_windows_commands_to_add_user(self.username, self.password, True) windows_cmds = get_windows_commands_to_add_user(self.username, self.password, True)
logger.debug("Trying to add {} with commands {}".format(self.username, str(windows_cmds))) logger.debug("Trying to add {} with commands {}".format(self.username, str(windows_cmds)))
_ = subprocess.check_output(windows_cmds, stderr=subprocess.STDOUT, shell=True) _ = subprocess.check_output(windows_cmds, stderr=subprocess.STDOUT)
def __enter__(self): def __enter__(self):
# Importing these only on windows, as they won't exist on linux. # Importing these only on windows, as they won't exist on linux.
@ -127,9 +127,7 @@ class AutoNewWindowsUser(AutoNewUser):
self.username, str(commands_to_deactivate_user) self.username, str(commands_to_deactivate_user)
) )
) )
_ = subprocess.check_output( _ = subprocess.check_output(commands_to_deactivate_user, stderr=subprocess.STDOUT)
commands_to_deactivate_user, stderr=subprocess.STDOUT, shell=True
)
except Exception as err: except Exception as err:
raise NewUserError("Can't deactivate user {}. Info: {}".format(self.username, err)) raise NewUserError("Can't deactivate user {}. Info: {}".format(self.username, err))
@ -141,8 +139,6 @@ class AutoNewWindowsUser(AutoNewUser):
self.username, str(commands_to_delete_user) self.username, str(commands_to_delete_user)
) )
) )
_ = subprocess.check_output( _ = subprocess.check_output(commands_to_delete_user, stderr=subprocess.STDOUT)
commands_to_delete_user, stderr=subprocess.STDOUT, shell=True
)
except Exception as err: except Exception as err:
raise NewUserError("Can't delete user {}. Info: {}".format(self.username, err)) raise NewUserError("Can't delete user {}. Info: {}".format(self.username, err))

View File

@ -1,4 +1,5 @@
import logging import logging
import shlex
import shutil import shutil
import subprocess import subprocess
import sys import sys
@ -45,14 +46,20 @@ class WindowsUpgrader(object):
opts.parent, opts.tunnel, opts.server, opts.depth opts.parent, opts.tunnel, opts.server, opts.depth
) )
# TODO: Replace all of this string templating with a function that accepts
# the necessary parameters and returns a list of arguments.
monkey_cmdline = ( monkey_cmdline = (
MONKEY_CMDLINE_WINDOWS % {"monkey_path": WormConfiguration.dropper_target_path_win_64} MONKEY_CMDLINE_WINDOWS % {"monkey_path": WormConfiguration.dropper_target_path_win_64}
+ monkey_options + monkey_options
) )
monkey_process = subprocess.Popen( monkey_cmdline_split = shlex.split(
monkey_cmdline, monkey_cmdline,
shell=True, posix=False, # won't try resolving "\" in paths as part of escape sequences
)
monkey_process = subprocess.Popen(
monkey_cmdline_split,
stdin=None, stdin=None,
stdout=None, stdout=None,
stderr=None, stderr=None,

View File

@ -36,6 +36,7 @@ mongomock = "==3.19.0"
pytest = ">=5.4" pytest = ">=5.4"
requests-mock = "==1.8.0" requests-mock = "==1.8.0"
black = "==20.8b1" black = "==20.8b1"
dlint = "==0.11.0"
flake8 = "==3.9.0" flake8 = "==3.9.0"
pytest-cov = "*" pytest-cov = "*"
isort = "==5.8.0" isort = "==5.8.0"

View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "9d575bcb35dba0389e8a68dd285f9ed7015fbcc4a42cffff5301777497337616" "sha256": "4fdfe90af14139cf855a0363ad0acbe7fb307b35b038e2c099c4d1227322a13b"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -171,7 +171,7 @@
"sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff", "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff",
"sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1" "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"
], ],
"markers": "python_version != '3.4' and sys_platform == 'win32'", "markers": "python_version != '3.4'",
"version": "==0.4.3" "version": "==0.4.3"
}, },
"coloredlogs": { "coloredlogs": {
@ -1076,7 +1076,7 @@
"sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff", "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff",
"sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1" "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"
], ],
"markers": "python_version != '3.4' and sys_platform == 'win32'", "markers": "python_version != '3.4'",
"version": "==0.4.3" "version": "==0.4.3"
}, },
"coverage": { "coverage": {
@ -1144,6 +1144,13 @@
], ],
"version": "==0.3.1" "version": "==0.3.1"
}, },
"dlint": {
"hashes": [
"sha256:e7297325f57e6b5318d88fba2497f9fea6830458cd5aecb36150856db010f409"
],
"index": "pypi",
"version": "==0.11.0"
},
"filelock": { "filelock": {
"hashes": [ "hashes": [
"sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59",

View File

@ -33,9 +33,9 @@ class BootloaderHTTPRequestHandler(BaseHTTPRequestHandler):
# The island server doesn't always have a correct SSL cert installed # The island server doesn't always have a correct SSL cert installed
# (By default it comes with a self signed one), # (By default it comes with a self signed one),
# that's why we're not verifying the cert in this request. # that's why we're not verifying the cert in this request.
r = requests.post( r = requests.post( # noqa: DUO123
url=island_server_path, data=post_data, verify=False, timeout=SHORT_REQUEST_TIMEOUT url=island_server_path, data=post_data, verify=False, timeout=SHORT_REQUEST_TIMEOUT
) # noqa: DUO123 )
try: try:
if r.status_code != 200: if r.status_code != 200:

View File

@ -9,7 +9,7 @@ TEST_USER = "test_user"
@pytest.fixture @pytest.fixture
def subprocess_check_output_spy(monkeypatch): def subprocess_check_output_spy(monkeypatch):
def mock_check_output(command, stderr, shell): def mock_check_output(command, stderr):
mock_check_output.command = command mock_check_output.command = command
mock_check_output.command = "" mock_check_output.command = ""
@ -21,11 +21,11 @@ def subprocess_check_output_spy(monkeypatch):
def test_new_user_expires(subprocess_check_output_spy): def test_new_user_expires(subprocess_check_output_spy):
with (AutoNewLinuxUser(TEST_USER, "password")): with (AutoNewLinuxUser(TEST_USER, "password")):
assert "--expiredate" in subprocess_check_output_spy.command assert "--expiredate" in " ".join(subprocess_check_output_spy.command)
assert "--inactive 0" in subprocess_check_output_spy.command assert "--inactive 0" in " ".join(subprocess_check_output_spy.command)
def test_new_user_try_delete(subprocess_check_output_spy): def test_new_user_try_delete(subprocess_check_output_spy):
with (AutoNewLinuxUser(TEST_USER, "password")): with (AutoNewLinuxUser(TEST_USER, "password")):
pass pass
assert f"deluser {TEST_USER}" in subprocess_check_output_spy.command assert f"deluser {TEST_USER}" in " ".join(subprocess_check_output_spy.command)