명령을 표시하고 코드 삽입을 방지하는 방법

명령을 표시하고 코드 삽입을 방지하는 방법

나는 놀면서 wget기본적으로 페이지를 다운로드하고 해당 페이지의 일부 정보를 검색한 다음 wget해당 정보를 기반으로 다른 페이지를 표시하는 스크립트를 만들었습니다. 기본적으로 내 코드는 다음과 같습니다.

defautltCommand="wget -v"
formValue=$(cat myfileA.html | get_field_value )
command="${defaultCommand} --post-data=\"myfield=${formValue}\""
echo "Command 3: ${command}"
echo "${command}" | bash

그러나 이 솔루션에는 몇 가지 문제가 있습니다. 가장 큰 문제는 html 파일에 일부 사악한 값(예 " google.com; <evil command>; ls ": . 내 스크립트는 NetworkManager 스크립트로서 루트로 실행되어야 하기 때문에... 코드를 삽입할 수 없는지 확인하고 싶습니다. 하지만 사용될 명령을 작성한다는 아이디어는 마음에 듭니다. 이는 오류가 발생할 때 디버깅하는 데 매우 유용합니다.

코드 삽입을 방지할 수 있는 좋은 방법이 있습니까? 아니면 더 좋은 방법이 있나요? 내 첫 번째 생각은 모든 참조를 다음과 같이 바꾸는 것이었지만 ... | sed 's/"/\\/g"'코드를 삽입하는 가능한 모든 방법을 찾았는지 확실하지 않습니다.

감사합니다!

답변1

코드를 셸에 파이프하는 것은 거의 항상 오류입니다. 여기에서는 이미 셸에서 코드를 실행하고 있으므로 다른 셸을 실행할 이유가 전혀 없습니다.

또한 해당 부분을 문자열에 넣어 명령을 작성하지 마십시오. 명령은 문자열 목록입니다. 이를 문자열로 채우려고 하면 인수를 구분하는 공백과 인수 내의 공백 간의 구분이 손실됩니다.그리고 문자열을 분할하여 실행하려고 하면 다른 문제가 발생합니다., 그 중 일부는보안 영향. 하지만 어쨌든 여기서는 필요하지 않습니다. 당신은 일을 너무 복잡하게 만들고 있습니다.

form_value=$(cat myfileA.html | get_field_value )
wget -v --post-data="$form_value"

wget -v해당 부분을 변경할 수 있기를 원 하지만스크립트의 통제하에, 해당 부분에 공백이나 어떤 것도 포함되지 않는다는 것을 알고 있으면 \[*?해당 부분을 변수에 넣을 수 있습니다.

wget='wget'
if [ -n "$verbose" ]; then
  wget="$wget -v"
fi
form_value=$(cat myfileA.html | get_field_value )
$wget --post-data="$form_value"

스크립트가 ksh, bash 또는 zsh에서 실행되지만 일반 sh에서는 실행되지 않는 경우 명령을 배열에 넣을 수 있습니다.

#!/bin/ksh
download=(wget -v --post-data="$form_value")
"${download[@]}"

내용을 반향할 때,제어 문자에 주의하십시오. 이로 인해 터미널이 작업을 수행하게 되거나 실제로 인쇄된 내용이 왜곡될 수 있습니다..

echo "$wget --post-data=$form_value" | tr -c '[:print:]' '?'

답변2

명령을 기록하려면 다음과 같은 표준 xtrace메커니즘을 사용할 수 있습니다.

log_cmd() {
  local - # assuming ash-based shells or bash-4.4+
          # see set -o localoptions in zsh or use
          # function log_cmd { syntax in AT&T ksh
          # or replace {...;} with (...) POSIXly (but
          # spawns a subshell)

  typeset PS4="$1"; shift
  set -o xtrace

  "$@"
}

# here assuming a shell with arrays like ksh93, zsh, bash, yash
defautltCommand=(wget -v)
formValue=$(<myfileA.html get_field_value)
command=("${defaultCommand[@]}" "--post-data=myfield=$formValue")
log_cmd 'Command 3: ' "${command[@]}"

이렇게 하면 임의의 데이터에 대해 쉘의 인터프리터를 호출하지 않습니다.

답변3

매개변수가 "A5h4f121SDEfdsZPfkshf457dsFJqsd"와 같은 경우 sed를 사용하여 영숫자가 아닌 모든 항목을 제거할 수 있습니다.

이 같은:

#!/bin/bash

# sample function just not to think how to process your form
get_field_value () {
   echo "ls -la; ps -ef;\"find . -iname test.txt\";  \`date +%Y%m%d\`"
}

# out of the bad command will be:
get_field_value
# >> ls -la; ps -ef;"find . -iname test.txt";  `date +%Y%m%d`

# your script begins here

#sample url
url="www.google.com"

# suggesting you have your file near your script
formValue=$(cat myfileA.html | get_field_value )

# remove all non-alphanumerics using sed
# formValue=$(echo "$formValue" | sed -e "s/[^a-zA-Z0-9]//g")
formValue=$(echo "$formValue" | sed -e "s/[^[:alnum:]]//g")
echo "Command 3: wget -v --post-data=\"$formValue\""
# >> Command 3: wget -v --post-data="lslapseffindinametesttxtdateYmd"


# run your command
wget -v --post-data="myfield=${formValue}" "$url"

이 경우 영숫자가 아닌 모든 숫자가 제거되고 코드는 아무런 해를 끼치지 않습니다.

관련 정보