I have the following hacking-challenge, where we don't know, if there is a valid solution.
We have the following server script:
read s # read user input into var s
echo "$s"
# tests if it starts with 'a-f'
echo "$s" > "/home/user/${s}.txt"
We only control the input "$s". Is there a possibility to send OS-commands like uname
or do you think "no way"?
I don't see any avenue for executing arbitrary commands. The script quotes $s
every time it is referenced, so that limits what you can do.
The only serious attack vector I see is that the echo
statement writes to a file name based on $s
. Since you control $s
, you can cause the script to write to some unexpected locations.
$s
could contain a string like bob/important.txt
. This script would then overwrite /home/user/bob/important.txt
if executed with sufficient permissions. Sorry, Bob!
Or, worse, $s
could be bob/../../../etc/passwd
. The script would try to write to /home/user/bob/../../../etc/passwd
. If the script is running as root... uh oh!
It's important to note that the script can only write to these places if it has the right permissions.
You could embed unusual characters in $s
that would cause irregular file names to be created. Un-careful scripts could be taken advantage of. For example, if $s
were foo -rf . bar
foo -rf . bar
, then the file /home/user/foo -rf . bar.txt
/home/user/foo -rf . bar.txt
would be created.
If someone ran for file in /home/user; rm $file; done
for file in /home/user; rm $file; done
for file in /home/user; rm $file; done
they'd have a surprise on their hands. They would end up running rm /home/user/foo -rf . bar.txt
rm /home/user/foo -rf . bar.txt
, which is a disaster. If you take out /home/user/foo
and bar.txt
you're left with rm -rf .
— everything in the current directory is deleted. Oops!
(They should have quoted "$file"
!)
And there are two other minor things which, while I don't know how to take advantage of them maliciously, do cause the script to behave slightly differently than intended.
read
allows backslashes to escape characters like space and newline. You can enter \\ space to embed spaces and \\ enter to have read
parse multiple lines of input.
echo
accepts a couple of flags. If $s
is -n
or -e
then it won't actually echo $s
; rather, it will interpret $s
as a command-line flag.
Use read -rs
or any \\
will be lost/missinterpreted by your command.
read -r s?"Your input: "
if [ -n "${s}" ]
then
# "filter" file name from command
echo "${s##*/}" | sed 's|^ *\([[:alnum:]_]\{1,\}\)[[:blank:]].*|/home/user/\1.txt|' | read Output
(
# put any limitation on user here
ulimit -t 5 1>/dev/null 2>&1
`${read}`
) > ${OutPut}
else
echo "Bad command" > /home/user/Error.txt
fi
Sure:
read s
$s > /home/user/"$s".txt
If I enter uname
, this prints Linux
. But beware: this is a security nightmare. What if someone enters rm -rf $HOME
? You'd also have issues with commands containing a slash.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.