Search code examples
bashdirectory-traversal

Prevent directory traversal vulnerability in bash script


How can I prevent directory traversal attacks in a bash script, where arguments contain directory names?

Example:

$STAGE=$1
$APP=$2
deploy.sh dist/ /opt/apps/"$STAGE"/"$APP"

The $STAGE and $APP variables are set from outside. An attacker could change this to an arbitrary path with "..".

I know the usual solution is to compare the directory string with the result of a function that returns the absolute path. But I couldn't find a ready solution and don't want to come up with my own.


Solution

  • Something like this?

    #! /bin/bash
    
    STAGE=$1
    APP=$2
    
    expectedParentDir="/opt/apps/"
    
    function testDir(){
      arg=$1
      if [[ ! -f $arg ]]
      then
          echo "File $arg does not exist."
          exit 1
      fi
      rpath=$(realpath $arg)
      if [[ $rpath != ${expectedParentDir}* ]]
      then
       echo "Please only reference files under $expectedParentDir directory."   
       exit 2
      fi
    }
    
    testDir /opt/apps/"$STAGE"/"$APP"
    
    ... deploy ...
    

    Example Call

    test.sh "../../etc/" "passwd"
    Please only reference files under /opt/apps/ directory.
    ------------
    test.sh "../../etc/" "secret"
    File /opt/apps/../../etc//secret does not exist.
    
    1. Test existence of file with -f or use -d if target must be a directory
    2. Use realpath to resolve path
    3. Use == ${expectedParentDir}* to find out if resolved path starts with expected string