프로그래밍 언어 내에서 간단한 쉘 명령을 실행합니다.
cd var; echo > create_a_file_here
와 var에 내가 파일 “create_a_file_here”을 만들려는 장소 (희망) 디렉토리의 문자열을 포함하는 변수 인. 이제 누군가가이 코드 라인을 보게되면, 예를 들어 다음과 같이 할당하여 코드를 이용할 수 있습니다.
var = "; rm -rf /"
상황이 꽤 추악해질 수 있습니다. 위의 경우를 피하는 한 가지 방법은 var 에서 문자열을 검색하여 ‘;’와 같은 특수 문자 를 찾는 것입니다 . 셸 명령을 실행하기 전에 가능한 모든 악용 가능성이 의심 스럽습니다.
“cd var”가 디렉토리 만 변경하고 다른 것은 변경하지 않는 좋은 방법을 아는 사람이 있습니까?
답변
내가 올바르게 이해하면 var
프로그래밍 언어의 변수입니다.
그리고 프로그래밍 언어에서,을 연결하는 문자열 "cd "
, 변수의 내용 및 을 해석하도록 쉘에 요청합니다 "; echo > create_a_file_here"
.
그렇다면 내용이 var
엄격하게 통제되지 않으면 명령 삽입 취약점입니다.
쉘 구문에서 변수 ¹의 내용을 올바르게 인용하면 cd
내장에 단일 인수로 전달되도록 보장 할 수 있습니다 .
다른 방법은 해당 변수의 내용을 다른 방식으로 전달하는 것입니다. 확실한 방법은 환경 변수에서 전달하는 것입니다. 예를 들어, C에서 :
char *var = "; rm -rf /";
setenv("DIR", var, 1);
system("CDPATH= cd -P -- \"$DIR\" && echo something > create_a_file_here");
이번에는 셸이 해석하도록 요청하는 코드가 수정되었으므로 여전히 셸의 구문으로 작성해야합니다 (여기서는 POSIX 호환 셸이라고 가정).
- split + glob를 방지하기 위해 쉘 변수 확장을 인용해야합니다.
- 당신은 필요
-P
에 대한cd
간단한 작업을 수행하는chdir()
- (또는 일부 쉘에서) 시작하는 데
--
문제가 발생하지 않도록 옵션 끝을 표시 해야 합니다.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..."));
예를 들어, var = "$(rm -rf /)"
여전히 문제가 될 수 있습니다.
만을 위한 인용 텍스트 신뢰할 수있는 방법 본쉘 작은 따옴표를 사용하는 것입니다 및 문자열에 발생할 수있는 작은 따옴표를 돌봐도. 예를 들어, a char *var = "ab'cd"
를로 설정하십시오 char *escaped_var = "'ab'\\''cd'"
. 즉, 모두 '
를 바꾸고 '\''
안에있는 모든 것을 감싸십시오 '...'
.
즉, 여전히 인용 문자열이 역 따옴표 내에서 사용되지 않는 것으로 간주하고 여전히 필요한 것 --
, -P
, &&
, CDPATH=
…
답변
간단한 해결책 : 프로그램에서 쉘을 호출하지 마십시오. 조금도.
이 예제는 사소한 것이며 디렉토리를 변경하고 파일을 작성하는 것은 프로그래밍 언어에 관계없이 쉽습니다. 그러나 외부 명령을 실행해야하더라도 일반적으로 셸을 통해 수행 할 필요는 없습니다.
예를 들어 Python에서는을 실행하는 대신을 os.system("somecmd " + somearg)
사용하십시오 subprocess.run(["somecmd", somearg])
. 에서 C 대신 system()
사용 fork()
및 exec()
(또는 그것을 수행하는 라이브러리를 찾을 수).
쉘을 사용해야 할 경우, 스테판의 답변 에서처럼 명령 행 인수를 인용하거나 환경을 통해 전달하십시오 . 또한 특수 문자에 대해 걱정하는 경우 올바른 해결책은 잠재적으로 위험한 문자를 걸러 내지 않고 (블랙리스트) 안전한 것으로 알려진 문자 만 유지 하는 것입니다 (허용 목록).
기능을 알고있는 캐릭터 만 허용하면 무언가를 놓칠 위험이 줄어 듭니다. 최종 결과는 허용하기로 결정 [a-zA-Z0-9_]
했지만 작업을 완료하기에 충분할 수 있습니다. 당신은 또한 당신의 로케일 확인하고 같은 악센트 문자를 포함하지 않는 도구 모음 할 수 있습니다 ä
와 ö
그의를. 그것들은 아마도 어떤 쉘에서도 특별한 것으로 간주되지는 않지만 다시 통과하는지 여부를 확인하는 것이 좋습니다.
답변
프로그래밍 언어에는 쉘 명령을 실행하는 것보다 더 나은 방법이 있습니다. 예를 들어, 교체 cd var
의 프로그래밍 언어의 해당과 chdir (var);
의 값을 어떤 속임수 있는지 확인해야합니다 var
A의 결과 만 오류가 아니라 의도하지 않은 악의적 인 행동을 “디렉토리가 없습니다 발견”.
또한 디렉토리를 변경하지 않고 절대 경로를 사용할 수 있습니다. 사용하려는 디렉토리 이름, 슬래시 및 파일 이름을 연결하십시오.
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") );
분명히 프로그래밍 언어가 비슷한 것을 할 수 있습니까?