简体   繁体   中英

How to execute Linux shell variables within double quotes?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM