Search code examples
bashposixexploit

Bash Child/Parent Pipe Inheritance Exploit


#!/bin/bash 
ipaddr=${1}
rdlnk=$(readlink /proc/$$/fd/0)
user="" 
passwd=""   
function get_input() {
 if grep -Eq "^pipe:|deleted" <<< "${rdlnk}" || [[ -p "${rdlnk}" ]]; then 
  while IFS= read -r piped_input || break; do 
  [[ -z "${ipaddr}" ]] && ipaddr="${piped_input}" && continue
  [[ -z "${user}" ]]   && user="${piped_input}"   && continue
  [[ -z "${passwd}" ]] && passwd="${piped_input}" && continue  
  done  
 fi 
 echo "Got that IP address you gave me to work on: ${ipaddr}" 
 [[ -n "${user}" ]] && echo "[... and that user: ${user}]" 
 [[ -n "${user}" ]] && echo "[... and that users password: ${passwd}]" 
}
get_input 
exit 0

Normally it's fine:

$> process_ip.bsh 71.123.123.3
Got that IP address you gave me to work on: 71.123.123.3

But, put the parent into a piped loop and watch out:

$ echo -en "71.123.123.3\nroot\ntoor\n" | while read a; do echo "Parent loop, processing: ${a}"; grep -q '^[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}' <<< "${a}" && ./process_ip.bsh "$a"; done

Parent loop, processing: 71.123.123.3
Got that IP address you gave me to work on: 71.123.123.3
[... and that user: root]
[... and that users password: toor]

Ouch. The parent only wanted to provide the IP Address from its pipe to the child. Presuming that the parent must maintain an open pipe with sensitive data in it at the time of the fork to the child process. How can this be prevented?


Solution

  • process_ip.bsh, like any other process, inherits its standard input from its parent. This line

    rdlnk=$(readlink /proc/$$/fd/0)
    

    doesn't do exactly what you think it does. It only contains the name of the file the parent is using for standard input because the script is inheriting its standard input from the parent. ($$ is the process ID of the current shell because .process_ip.bsh is a separate process, not merely a subshell started by the parent.)

    If you redirect input to process_ip.bsh, you are in complete control of what it receives.

    while read a; do
        echo "Parent loop, processing: ${a}"
        grep -q '^[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}' <<< "${a}" &&
          ./process_ip.bsh "$a" < /dev/null
    done <<EOF
    71.123.123.3
    root
    toor
    EOF