Bash 스크립트의 산술 연산 문제 | 잘못된 산술 연산자 |

Bash 스크립트의 산술 연산 문제 | 잘못된 산술 연산자 |

Bash 스크립트에서 call을 사용하여 서버에서 파일을 다운로드합니다 curl. 이제 파일이 완전히 다운로드되었는지 확인하고 싶습니다. 이를 위해 다운로드 파일과 헤더 크기를 비교했습니다 Content-Length. 둘 다 동일하지만 다음 오류가 발생합니다.

")syntax error: invalid arithmetic operator (error token is "

Bash 스크립트의 일부:

remote_size=$(curl -kI "${HEADERS[@]}" "$url" | grep -i content-length | awk '{print $2}')
                local_size=$(stat --format=%s "$dest/$file")
                if (( remote_size == local_size )); then
                        echo "File is complete" >&2
                elif (( remote_size > local_size )); then
                        echo "Download is incomplete" >&2
                elif (( remote_size < local_size )); then
                        echo "Remote file shrunk -- probably should delete local and start over" >&2
                fi

에서 영감을 받다:https://stackoverflow.com/questions/37885503/check-if-curl-incremental-continue-at-download-is-successful/37885681?

누구든지 여기에 문제가 무엇인지, 해결 방법을 말해 줄 수 있습니까?

미리 감사드립니다

추신: 우분투(WSL)에서 테스트 중이지만 스크립트는 결국 임베디드 플랫폼의 Linux에 포함될 것입니다. 누락된 정보가 있으면 알려주세요.

답변1

$ curl -sI https://google.com | sed -n '/content-length/l'
content-length: 220\r$

줄 끝에 있는 캐리지 리턴 문자(일명 CR, \r, )를 참조하세요(줄 끝을 나타내는 방법). HTTP 헤더^M$sedCRLF로 구분, Unix 줄 구분 기호는 LF입니다.

반품Bash 및 기타 Korn 유사 셸의 산술 표현식에서 삭제되지 않은 데이터를 사용하는 것은 명령 주입 취약점입니다., 여기에는 또 다른 문제가 있습니다. 즉, -kaka --insecure옵션을 사용하면 MitM 공격자가 응답에 임의의 헤더를 삽입할 수 있습니다.

GNU 시스템에서는 다음을 사용할 수 있습니다.

local_size=$(stat -Lc %s -- "$dest/$file") || die
remote_size=$(curl -sI -- "$url" | LC_ALL=C grep -Piom1 '^content-length:\s*\K\d+') ||
  die "No content-length"
case $((local_size - remote_size)) in
  (0) echo same;;
  (-*) echo remote bigger;;
  (*) echo local bigger;;
esac

\d+C 로케일에서 일치하는 항목 만 반환함으로써 remote_size십진수 ASCII 숫자만 포함되도록 하여 ACE 취약성을 제거합니다.

이 GNU 명령에 해당하는 표준은 grep다음과 같습니다.

LC_ALL=C sed '/^[Cc][Oo][Nn][Tt][Ee][Nn][Tt]-[Ll][Ee][Nn][Gg][Tt][Hh]:[[:space:]]*\([0-9]\{1,\}\).*/!d;s//\1/;q'

헤더를 찾을 수 없으면 반환되지 않습니다.잘못된종료 상태는 grep이와 같은 작업을 수행하므로 추가로 확인해야 합니다 [ -n "$remote_size" ].

die위의 내용은 다음과 같습니다.

die() {
  [ "$#" -eq 0 ] || printf>&2 '%s\n' "$@"
  exit 1
}

(사용하려는 로깅 메커니즘에 맞게 조정하세요).

또한 실제로는 이런 일이 발생할 가능성이 낮지만 헤더가 접힐 수 있다는 점에 유의하세요. 예를 들어 콘텐츠 길이 헤더는 다음과 같이 반환될 수 있습니다.

Content-Length:<CR>
 123456<CR>

헤더 값을 추출하는 한 가지 방법은 formailRFC822 헤더를 처리하도록 특별히 설계된 도구를 사용하는 것입니다.

remote_size=$(curl... | formail -zcx content-length -U content-length)

의 경우 헤더가 -U content-length여러 개인 경우 Content-Length 마지막 헤더가 반환됩니다. 위와 같이 첫 번째 항목을 반환 -U하도록 변경합니다 .-ugrep -m1

ACE 취약점을 방지 하려면 결과를 삭제하거나 대신 ['s( [[...]]'s! 아님) -lt// -eq연산자를 사용해야 합니다.-gt((...))

버전 7.84.0 이상을 사용 하면 다음을 사용하여 이 헤더의 값을 직접 제공 curl할 수도 있습니다 .curl

remote_size=$(curl -w '%header{content-length}' -sIo /dev/null -- "$url") || die

테스트를 통해 알아낸 것은

  • 헤더가 여러 번 나타나는 경우 첫 번째 헤더의 값만 반환됩니다.
  • 값이 숫자로 시작하지 않으면(선택적으로 a로 시작) 불평 +하지만 그 뒤에 전달된 모든 문자를 삭제해야 합니다.
  • 헤더 축소를 지원하지만 첫 번째 행에 null 값이 있는 콘텐츠 길이는 거부됩니다.

관련 정보