문자열 변수를 사용하여 셸 명령 보호

문자열 변수를 사용하여 셸 명령 보호

프로그래밍 언어에서는 간단한 쉘 명령을 실행합니다.

cd var; echo > create_a_file_here

그리고변하기 쉬운"create_a_file_here" 파일을 생성할 디렉터리 문자열을 포함하는 변수입니다. 이제 누구든지 이 코드 줄을 본다면 다음과 같은 할당을 통해 이를 악용할 수 있습니다.

var = "; rm -rf /"

상황이 정말 추악해질 수 있습니다. 위 상황을 피하는 한 가지 방법은 문자열을 검색하는 것입니다.변하기 쉬운쉘 명령을 실행하기 전에 ";"와 같은 일부 특수 문자에 대해 설명했지만 이것이 가능한 모든 취약점을 다루는 것으로 의심됩니다.

"cd var"가 디렉토리만 변경하고 다른 것은 변경하지 않도록 하는 좋은 방법을 아는 사람이 있습니까?

답변1

간단한 해결책: 프로그램 내에서 셸을 호출하지 마세요. 절대적으로하지.

여기의 예는 간단하며 어떤 프로그래밍 언어를 사용하든 디렉터리 변경과 파일 생성이 쉬워야 합니다. 그러나 외부 명령을 실행해야 하는 경우에도 일반적으로 셸을 통해 실행할 필요는 없습니다.

예를 들어 Python에서는 실행하는 대신 os.system("somecmd " + somearg)를 사용합니다 subprocess.run(["somecmd", somearg]). C에서는 대신 and (또는 이를 수행하는 라이브러리를 찾으세요)를 system()사용하세요 .fork()exec()

셸을 사용해야 하는 경우 명령줄 인수를 인용하거나 다음과 같이 환경을 통해 전달하세요.스티븐의 대답. 또한, 특수문자가 걱정된다면 올바른 해결 방법은 다음과 같습니다.아니요잠재적으로 위험한 문자를 필터링(블랙리스트)해 보세요.유지하다알려진 안전한 문자(허용 목록).

기능을 확실히 알고 있는 캐릭터만 허용하면 뭔가를 놓칠 위험이 줄어듭니다. 최종 결과는 단지 허용하기로 결정하는 것일 수도 있지만 [a-zA-Z0-9_], 이는 작업을 완료하는 데 충분할 수 있습니다. 또한 로케일과 도구 세트에 ä및 같은 ö악센트 문자가 포함되어 있지 않은지 확인할 수도 있습니다 . 어떤 쉘에서도 특별하다고 간주되지 않을 수 있지만, 통과하는지 확인하는 것이 가장 좋습니다.

답변2

내가 올바르게 이해했다면 var프로그래밍 언어의 변수입니다.

"cd "프로그래밍 언어에서는 , 변수의 내용 및 의 연결인 문자열을 해석하도록 쉘에 요청합니다 "; echo > create_a_file_here".

그렇다면 콘텐츠가 var엄격하게 제어되지 않는다면 이는 명령 주입 취약점입니다.

cd내장 함수 에 단일 인수로 전달되도록 쉘 구문에서 변수 1의 내용을 적절하게 인용할 수 있습니다 .

또 다른 접근 방식은 변수의 내용을 다른 방식으로 전달하는 것입니다. 한 가지 확실한 방법은 환경 변수에 전달하는 것입니다. 예를 들어 C에서는 다음과 같습니다.

char *var =  "; rm -rf /";
setenv("DIR", var, 1);
system("CDPATH= cd -P -- \"$DIR\" && echo something > create_a_file_here");

이번에는 셸에 해석을 요청한 코드가 수정되었으므로 셸의 구문에서 이를 올바르게 작성해야 합니다(여기서는 POSIX 호환 셸이라고 가정).

  • 분할+글로브를 방지하려면 쉘 변수 확장을 인용해야 합니다.
  • 간단하게 -P만드 셔야 합니다cdchdir()
  • --(또는 일부 셸에서) var시작하는 문제를 방지하려면 옵션의 끝을 표시 해야 합니다 .-+
  • CDPATH환경에 있는 경우 빈 문자열로 설정합니다.
  • echo성공할 경우 에만 명령을 실행합니다.cd

(적어도) 한 가지 문제가 더 있습니다. 만약 var그렇다면 -, 호출된 디렉토리로 chdir을 실행하지 않을 것입니다 -.더 일찍디렉터리( 에 저장된 경우 $OLDPWD)이며 OLDPWD=- CDPATH= cd -P -- "$DIR"해결된다는 보장은 없습니다. 따라서 다음과 같은 것이 필요합니다.

system(
  "case $DIR in\n"
  " (-) CDPATH= cd -P ./-;;\n"
  " (*) CDPATH= cd -P -- \"$DIR\";;\n"
  "esac && ....");

¹ 단순히 system(concat("cd \"", var, "\"; echo..."));다음을 수행한다는 점에 유의하세요.아니요가야 할 길, 당신은 단지 문제를 편향시키는 것뿐입니다.

예를 들어, a는 var = "$(rm -rf /)"여전히 문제입니다.

이것오직Bourne과 같은 쉘에서 텍스트를 인용하는 신뢰할 수 있는 방법은 작은따옴표를 사용하는 것입니다.그리고또한 문자열 내에 가능한 작은따옴표를 기록해 두십시오. 예를 들어 a를 char *var = "ab'cd"로 이동합니다 char *escaped_var = "'ab'\\''cd'". 즉, all 을 '로 바꾸고 '\''그 안에 전체를 래핑합니다 '...'.

이것은 여전히 ​​백틱 내부에 인용된 문자열이 사용되지 않는다고 가정하며 여전히 --, -P, &&, CDPATH=... 가 필요합니다.

답변3

프로그래밍 언어에는 셸 명령을 실행하는 것보다 작업을 수행하는 더 좋은 방법이 있어야 합니다. 예를 들어, cd var프로그래밍 언어에 해당하는 것으로 대체 chdir (var);하면 값이 var.

또한 디렉터리를 변경하는 대신 절대 경로를 사용할 수 있습니다. 사용하려는 디렉토리 이름, 슬래시 및 파일 이름을 연결하기만 하면 됩니다.

C에서는 다음과 같이 할 수 있습니다.

char filepath[PATH_MAX];  /* alternative constant: MAXPATHLEN */

/* Join directory name in var and the filename, guarding against exceeding PATH_MAX */
snprintf (filepath, PATH_MAX, "%s/%s", var, "create_a_file_here");

/* create an empty file/truncate an existing one */
fclose (fopen (filepath, "w") );

확실히 당신의 프로그래밍 언어가 비슷한 일을 할 수 있습니까?

관련 정보