diff options
Diffstat (limited to 'iv/orodja/napad/exploit.sh')
-rwxr-xr-x | iv/orodja/napad/exploit.sh | 130 |
1 files changed, 98 insertions, 32 deletions
diff --git a/iv/orodja/napad/exploit.sh b/iv/orodja/napad/exploit.sh index 729bb68..b482c06 100755 --- a/iv/orodja/napad/exploit.sh +++ b/iv/orodja/napad/exploit.sh @@ -1,84 +1,150 @@ #!/bin/sh if [ x$1 = x ] then -echo >&2 <<EOF -No command. Subcommands: - $0 once <service> <exploit> [team=$GAME_NOP_TEAM] # runs exploit once - $0 loop <service> <exploit> # runs an exploit in a loop once per round +cat >&2 <<EOF +No command. Usage: $0 <subcommand> [args ...] Subcommands: + once <service> <exploit> [team=$GAME_NOP_TEAM] # runs exploit once + loop <service> <exploit> # once per team per round, waits for next round <exploit> is an executable file. Flags, grepped from stdout, are submitted. -It is called for every target. Args are target IP and flag IDs JSON object. - Example: <exploit> 10.1.2.3 '{"user": "root", "pass": "hunter2"}' -Flag IDs are also available in the environment as variables FLAG_ID_<key>: - {"user": "root", "pass": "hunter2"} will be in environment as vars - FLAG_ID_user=root and FLAG_ID_pass=hunter2 +It is called for every target with the following environment variables: + TARGET_IP: target IP address (uses game_target_ip from config) + TARGET_EXTRA: Flag IDs JSON object (uses game_flag_ids_url in config) + FLAG_ID_<key>: Every JSON value from flag IDs individually +Example environment is therefore: + TARGET_IP=1.1.1.1 TARGET_EXTRA='{"a": "1", "b": "2"}' FLAG_ID_a=1 FLAG_ID_b=2 In loop mode, exploit is first exec'd rapidly for still valid old rounds. Max execution time is $EXPLOIT_TIMEOUT seconds (EXPLOIT_TIMEOUT in config) -Exploits are NOT executed in parallel. +Exploits are not run in parallel. Make sure that your system time is set CORRECTLY TO THE SECOND, it's used - to get the current round id. Current time: `date`. + to get the current round id. Check this on http://time.is Configuration values are also available in environment of exploits. <service> is the name of the service (used for getting flag IDs) -If the env. var EXPLOIT_STDOUT is set, stdout of exploit will be printed to stderr: - "EXPLOIT_STDOUT=1 $0 loop <service> <exploit>" will also print stdout to term -If the env. var EXPLOIT_LOOP_ONCE is set (only valid for loop mode), looping will - stop after looping through all valid rounds and teams: - "EXPLOIT_LOOP_ONCE=1 $0 loop <service> <exploit>" won't wait for next round +Set the following environment variables to alter behaviour: + EXPLOIT_STDOUT=1: stdout of exploit will be printed to stderr/terminal + EXPLOIT_LOOP_ONCE=1: exit after executing for all valid rounds instead of + waiting for the next round. Only valid for loop subcommand. + EXPLOIT_VERBOSE=1: print _every_ line executed by $0 (set -x) + EXPLOIT_NOTPARALLEL=1: disable parallel even if parallel is available EOF exit 1 fi -set -xeuo pipefail -startunix=`date +%s --utc --date $GAME_START` -current=`date +%s --utc` +[ ${EXPLOIT_VERBOSE:-false} = false ] || set -x +set -euo pipefail +current_round_id() +{ # BREAKS WHEN THERE ARE LEAP SECONDS DURING GAME + startunix=`date +%s --utc --date $GAME_START` + current=`date +%s --utc` + echo $((($current-$startunix)/$ROUND_DURATION)) +} if [ ${ROUND_ID:-x} = x ] then - export ROUND_ID=`$((($current-$startunix)/$ROUND_DURATION))` # BREAKS WHEN THERE ARE LEAP SECONDS DURING GAME + export ROUND_ID=`current_round_id` fi subcommand=$1 service=$2 exploit=$3 # tees stdout, collects flags, puts stdout to stderr, prints counts +# args: team exploit_pipe() { stdoutwhere=/dev/null - [ ${EXPLOIT_STDOUT:-x} = x ] && stdoutwhere=/dev/stderr - tee $stdoutwhere | grep -Eo "$FLAG_REGEX" | while read line + [ ! ${EXPLOIT_STDOUT:-false} = false ] && stdoutwhere=/dev/stderr + tee $stdoutwhere | { grep -Eo "$FLAG_REGEX_SEARCH" || :; } | while read -r line do - echo $line `whoami`@`hostname``pwd` $exploit $service - done | nc -v $SUBMISSION_HOST $SUBMISSION_PORT | cut -d\ -f1 | sort | uniq -c | tr $'\n' ' ' | cat /dev/stdin <(echo $'\t<= izkupiček poslanih zastavic') + echo $line $1 $ROUND_ID $service $exploit `whoami`@`hostname``pwd` + done | { nc -N $SUBMISSION_HOST $SUBMISSION_PORT || return $((200+$?)); } | cut -d\ -f1,2 | sort | uniq -c | tr $'\n' ' ' | cat <(printf "team=%-2d round=%d: " $1 $ROUND_ID) /dev/stdin <(echo) >&2 } # args: team round get_flag_ids() { - output_flagids=$(curl --fail-with-body --no-progress-bar `game_flag_ids_url $service $1 $2`) - echo [$0] ERROR: failed to get flag ids: $output_flagids >&2 + set +e + output_flagids=$(curl --fail-with-body --no-progress-meter "`game_flag_ids_url "$service" $1 $2`") + curl_exit_code=$? + set -e + echo $output_flagids + if [ ! $curl_exit_code -eq 0 ] + then + send_error $1 "round=$round failed to get flag ids: $output_flagids" >&2 + return 99 + fi } # args: team message send_error() { echo [$0] ERROR: team=$1: $2 - exploit_error_handler $service $1 `pwd` `whoami`@`hostname` $2 + exploit_error_handler "$service" $1 `pwd` `whoami`@`hostname` $2 } case $subcommand in once) target_team=$GAME_NOP_TEAM - if [ $# -ge 3 ] + if [ $# -ge 4 ] then - target_team=$3 + target_team=$4 fi - timeout $EXPLOIT_TIMEOUT $exploit `game_target_ip $target_team` `get_flag_ids $target_team $ROUND_ID` | expoit_pipe $subcommand + export TARGET_IP=`game_target_ip $target_team` + export TARGET_EXTRA="`get_flag_ids $target_team $ROUND_ID`" + source <(echo "$TARGET_EXTRA" | jq -r 'to_entries|map("export FLAG_ID_\(.key|sub("'"'"'";""))='"'"'\(.value|tostring|sub("'"'"'";"'"'\\\"'\\\"'"'"))'"'"'")|.[]') + set +e + timeout $EXPLOIT_TIMEOUT $exploit | exploit_pipe $target_team exit_code=$? + set -e + if [ $exit_code -gt 200 ] + then + send_error $target_team "submission netcat failed with $(($exit_code-200))" + exit $exit_code + fi if [ ! $exit_code -eq 0 ] && [ ! $exit_code -eq 124 ] then send_error $target_team "$exploit exited with $exit_code" fi + if [ $exit_code -eq 124 ] + then + echo [$0] team=$target_team $exploit timed out >&2 + fi + exit $exit_code ;; loop) - for round in {$ROUND_ID..} + if parallel --version > /dev/null && [ ${EXPLOIT_NOTPARALLEL:-false} = false ] + then + commands_evaluator="parallel --color-failed" + commands_output="/dev/stdout" + have_parallel=true + echo "[$0] using parallel executions (:" >&2 + else + commands_evaluator="cat /dev/stdin" + commands_output="/dev/null" + have_parallel=false + echo "[$0] parallel not found or disabled! zaporedno izvajanje ):" >&2 + fi + round=$(($ROUND_ID-$GAME_VALID_ROUNDS)) + while : do for target_team in $GAME_TEAMS do - ROUND_ID=$round $0 once $target_team + cmd2exec="ROUND_ID=$round $0 once '$service' $exploit $target_team" + if $have_parallel + then + echo $cmd2exec + else + eval $cmd2exec + fi + done | $commands_evaluator > $commands_output + round=$(($round+1)) + we_slept=false + while [ `current_round_id` -lt $round ] + do # oh no we pollin thats ugly af, who cares we have + if [ ! ${EXPLOIT_LOOP_ONCE:-false} = false ] + then + echo [$0] breaking due to EXPLOIT_LOOP_ONCE + break + fi + we_slept=true + sleep 1 # INFINITE CPU POWAH! done + if $we_slept + then # execute exploit at random time instead of at start + sleep $(($RANDOM%$ROUND_DURATION/2)) + fi done ;; esac |