내 스크립트에 대한 구성 파일을 만들어야 합니다.
예는 다음과 같습니다.
스크립트:
#!/bin/bash
source /home/myuser/test/config
echo "Name=$nam" >&2
echo "Surname=$sur" >&2
콘텐츠 /home/myuser/test/config
:
nam="Mark"
sur="Brown"
작동합니다!
내 질문:이 방법이 맞는 건가요, 아니면 다른 방법이 있는 건가요?
답변1
source
임의의 코드를 실행할 수 있으므로 안전하지 않습니다. 이는 문제가 되지 않을 수 있지만 파일 권한이 잘못된 경우 파일 시스템 액세스 권한이 있는 공격자가 init 스크립트와 같은 다른 보안 스크립트에 의해 생성된 파일에 코드를 삽입하여 잠재적으로 액세스 권한을 얻을 수 있습니다.
지금까지 제가 찾아낸 최고의 솔루션은 휠 솔루션을 서투르게 재창조한 것입니다.
myscript.conf
password=bar
echo rm -rf /
PROMPT_COMMAND='echo "Sending your last command $(history 1) to my email"'
hostname=localhost; echo rm -rf /
를 사용하면 이 작업이 두 번 source
실행되고 대신에 다음을 수행합니다.echo rm -rf /
$PROMPT_COMMAND
myscript.sh(펀치 4)
#!/bin/bash
typeset -A config # init array
config=( # set default values in config array
[username]="root"
[password]=""
[hostname]="localhost"
)
while read line
do
if echo $line | grep -F = &>/dev/null
then
varname=$(echo "$line" | cut -d '=' -f 1)
config[$varname]=$(echo "$line" | cut -d '=' -f 2-)
fi
done < myscript.conf
echo ${config[username]} # should be loaded from defaults
echo ${config[password]} # should be loaded from config file
echo ${config[hostname]} # includes the "injected" code, but it's fine here
echo ${config[PROMPT_COMMAND]} # also respects variables that you may not have
# been looking for, but they're sandboxed inside the $config array
myscript.sh(Mac/Bash 3과 호환 가능)
#!/bin/bash
config() {
val=$(grep -E "^$1=" myscript.conf 2>/dev/null || echo "$1=__DEFAULT__" | head -n 1 | cut -d '=' -f 2-)
if [[ $val == __DEFAULT__ ]]
then
case $1 in
username)
echo -n "root"
;;
password)
echo -n ""
;;
hostname)
echo -n "localhost"
;;
esac
else
echo -n $val
fi
}
echo $(config username) # should be loaded from defaults
echo $(config password) # should be loaded from config file
echo $(config hostname) # includes the "injected" code, but it's fine here
echo $(config PROMPT_COMMAND) # also respects variables that you may not have
# been looking for, but they're sandboxed inside the $config array
내 코드에서 보안 취약점을 발견하면 회신해 주세요.
답변2
구성 파일을 구문 분석하고 실행하지 마십시오.
저는 현재 매우 간단한 XML 구성을 사용하는 애플리케이션을 작성 중입니다.
<config>
<username>username-or-email</username>
<password>the-password</password>
</config>
쉘 스크립트("응용 프로그램")에서 사용자 이름을 얻는 방법은 다음과 같습니다(대부분 쉘 함수에 넣습니다).
username=$( xmlstarlet sel -t -v '/config/username' "$config_file" )
명령 xmlstarlet
은XML 스타, 대부분의 Unices에 적용됩니다. 일부 시스템에서는 xml
.
애플리케이션의 다른 부분도 XML 파일로 인코딩된 데이터를 처리하므로 XML을 사용하는 것이 가장 쉽습니다.
JSON을 선호한다면 다음과 같습니다.jq
이것은 사용하기 쉬운 쉘 JSON 파서입니다.
내 구성 파일은 JSON에서 다음과 같습니다.
{
"username": "username-or-email",
"password": "the-password"
}
그런 다음 스크립트에서 사용자 이름을 가져옵니다.
username=$( jq -r .username "$config_file" )
TOML(“톰의 최소한의 언어인 것 같아요”), 여러 언어에 대한 파서 포함. 배포판의 tomlq
일부로 개인적으로 가장 좋아하는 파서yq
https://kislyuk.github.io/yq/( jq
무대 뒤에서 사용됨).
구성 파일의 TOML 버전은 다음과 같습니다.
username = "username-or-email"
password = "the-password"
(문자열은 JSON으로 인코딩됩니다.)...여기에서 데이터를 가져오는 것은 JSON 사례만큼 간단합니다(문자열은 JSON tomlq
위에 구축 되므로 jq
).
username=$( tomlq -r .username "$config_file" )
답변3
이것은 Mac 및 Linux에서 Bash 3 이상과 호환되는 깨끗하고 이식 가능한 버전입니다.
모든 쉘 스크립트에서 크고 혼란스럽고 중복된 "기본" 구성 기능을 사용하지 않아도 되도록 단일 파일에 모든 기본값을 지정합니다. 기본 대체를 포함하거나 포함하지 않고 읽기를 선택할 수 있습니다.
구성 파일:
myvar=Hello World
config.cfg.default:
myvar=Default Value
othervar=Another Variable
구성 파일(이것은 라이브러리이므로 shebang-line이 없습니다):
config_read_file() {
(grep -E "^${2}=" -m 1 "${1}" 2>/dev/null || echo "VAR=__UNDEFINED__") | head -n 1 | cut -d '=' -f 2-;
}
config_get() {
val="$(config_read_file config.cfg "${1}")";
if [ "${val}" = "__UNDEFINED__" ]; then
val="$(config_read_file config.cfg.defaults "${1}")";
fi
printf -- "%s" "${val}";
}
test.sh(또는 구성 값을 읽으려는 스크립트):
#!/usr/bin/env bash
source config.shlib; # load the config library functions
echo "$(config_get myvar)"; # will be found in user-cfg
printf -- "%s\n" "$(config_get myvar)"; # safer way of echoing!
myvar="$(config_get myvar)"; # how to just read a value without echoing
echo "$(config_get othervar)"; # will fall back to defaults
echo "$(config_get bleh)"; # "__UNDEFINED__" since it isn't set anywhere
테스트 스크립트 설명:
- 알아채다모두test.sh에서 config_get 사용법은 큰따옴표로 묶입니다. 각 config_get을 큰따옴표로 묶어서 변수 값의 텍스트가안 돼요플래그로 오해됨. 이는 구성 값의 연속된 여러 공백과 같이 공백을 올바르게 보존하도록 보장합니다.
printf
그 줄은 무엇입니까? 글쎄, 당신은 이것에 주목해야 합니다:echo
이것은 당신이 제어할 수 없는 텍스트를 인쇄하기 위한 잘못된 명령입니다. 큰따옴표를 사용하더라도 플래그를 해석합니다.myvar
(에서config.cfg
)를 로 설정하면 플래그로 간주되므로-e
빈 줄이 표시됩니다 .echo
그러나printf
그런 문제는 없습니다.printf --
"이것을 인쇄하고 아무것도 플래그로 해석하지 마십시오"라고 말하고 ""%s\n"
출력을 후행 줄 바꿈이 있는 문자열로 형식화합니다. printf의 마지막 인수는 형식화할 값입니다.- 값을 화면에 표시하지 않으려면 정상적으로 할당하면 됩니다
myvar="$(config_get myvar)";
. 예를 들어 화면에 인쇄하려면 printf를 사용하여 다음과 같은 모든 것에 대해 완전히 안전하도록 권장합니다. 호환되지 않는 문자열을 에코하는 것과 관련된 사용자 구성에 존재할 수 있습니다. 하지만 사용자가 제공한 변수 echo가아니요에코하는 문자열의 첫 번째 문자는 "플래그"가 해석될 수 있는 유일한 경우이기 때문에echo "foo: $(config_get myvar)";
"foo"는 대시로 시작하지 않으므로 이와 같은 문자는 안전합니다. 따라서 문자열의 나머지 부분도 대시로 시작한다고 echo에 알립니다. 로고도 아닙니다. :-)
답변4
내 스크립트에서는 이것을 사용합니다.
sed_escape() {
sed -e 's/[]\/$*.^[]/\\&/g'
}
cfg_write() { # path, key, value
cfg_delete "$1" "$2"
echo "$2=$3" >> "$1"
}
cfg_read() { # path, key -> value
test -f "$1" && grep "^$(echo "$2" | sed_escape)=" "$1" | sed "s/^$(echo "$2" | sed_escape)=//" | tail -1
}
cfg_delete() { # path, key
test -f "$1" && sed -i "/^$(echo $2 | sed_escape).*$/d" "$1"
}
cfg_haskey() { # path, key
test -f "$1" && grep "^$(echo "$2" | sed_escape)=" "$1" > /dev/null
}
구분 기호를 포함 할 수 없는 키 입력을 제외한 모든 문자 조합이 지원되어야 합니다 =
. 다른 것은 모두 작동합니다.
% cfg_write test.conf mykey myvalue
% cfg_read test.conf mykey
myvalue
% cfg_delete test.conf mykey
% cfg_haskey test.conf mykey || echo "It's not here anymore"
It's not here anymore
source
게다가 or 를 사용하지 않으므로 완전히 안전합니다 eval
.