perl -ne '...' 실행의 보안 위험 *

perl -ne '...' 실행의 보안 위험 *

분명히 다음을 실행하십시오.

perl -n -e 'some perl code' *

또는

find . ... -exec perl -n -e '...' {} +

( -p대체와 동일 -n)

또는

perl -e 'some code using <>' *

이 사이트에 게시된 농담에 자주 나타나며 보안 위험을 초래합니다. 어떻게 되어가나요? 그것을 피하는 방법?

답변1

문제는 무엇입니까

첫째, 많은 유틸리티와 마찬가지로 -.

sh -c 'inline sh script here' other args

에 전달된 다른 인수는 다음과 같습니다 inline sh script.perl

perl -e 'inline perl script here' other args

더 많은 옵션을 보려면 다른 매개변수를 스캔하세요.진주우선, 인라인 스크립트가 아닙니다. 예를 들어 -eBEGIN{do something evil}현재 디렉터리에 호출된 파일이 있는 경우

perl -ne 'inline perl script here;' *

(가 있든 없든 -n) 나쁜 일을 할 것입니다.

--다른 유틸리티와 마찬가지로 해결 방법은 닫는 태그( ) 옵션을 사용하는 것입니다 .

perl -ne 'inline perl script here;' -- *

그러나 그럼에도 불구하고 (in-place) 없이 ( 모드), ( 모드), / ( 모드) 중 하나를 사용할 <>때마다 어떤 연산자를 사용하는지 에 따라 여전히 위험합니다 .-nsed -n-psed-a-Fawk-i

문제는 perldoc perlop설명서에 설명되어 있습니다.

이 특수 연산자는 시퀀스에 전달된 각 인수에서 입력의 한 줄(기본적으로 레코드는 행임)을 읽는 데 사용됩니다 @ARGV.

존재하다:

perl -pe '' a b

-pwhile (<>)코드 주위에 루프가 있음을 의미합니다 (여기서는 비어 있음).

<>먼저 a파일을 열고 파일이 모두 소진될 때까지 한 번에 한 줄씩 레코드를 읽은 다음 엽니다 b.

문제는 파일을 열 때 첫 번째 안전하지 않은 형식을 사용한다는 것입니다 open.

open ARGV, "the file as provided"

인수가 다음과 같은 경우 이 형식을 사용하세요.

  • "> afile", afile쓰기 모드로 열립니다.
  • "cmd|", 실행되고 cmd출력을 읽습니다.
  • "|cmd", 에 쓸 입력 스트림을 엽니다 cmd.

예를 들어:

perl -pe '' 'uname|'

라는 파일의 내용 uname|(완전히 유효한 파일 이름)을 출력하지 않고 명령의 출력을 출력합니다 uname.

실행 중인 경우:

perl -ne 'something' -- *

누군가가 현재 디렉터리에 (역시 완벽하게 유효한 파일 이름)이라는 이름의 파일을 생성했습니다 rm -rf "$HOME"|(예를 들어, 디렉터리에 다른 사람이 한 번 쓴 경우, 신뢰할 수 없는 아카이브를 추출한 경우, 신뢰할 수 없는 명령을 실행한 경우, 또는 다른 취약점이 있는 경우). 다른 소프트웨어가 악용되고 있는 경우) 큰 문제가 발생합니다. 문제 영역은 자동으로 파일을 처리하는 도구라는 점을 인식하는 것이 중요합니다.사람들유사한 영역 /tmp(또는 이러한 도구가 호출할 수 있는 도구).

> foo이름이 인 foo|파일 |foo에 문제가 있습니다. 그러나 어느 정도는 < foofoo이나 뒤에 ASCII 공백 문자(공백, 탭, 줄 바꿈, cr... 포함)가 있으면 이러한 파일이 처리되지 않거나 잘못된 파일이 생성된다는 의미입니다.

또한 일부 멀티바이트 문자 세트(예: ǖBIG5-HKSCS)의 일부 문자는 바이트 0x7c로 끝납니다 |.

$ printf ǖ | iconv -t BIG5-HKSCS | od -tx1 -tc
0000000  88  7c
        210   |
0000002

따라서 이 문자 집합을 사용하는 로캘에서는

 perl -pe '' ./nǖ

./n\x88명령을 실행하려고 시도합니다perl아니요사용자의 로캘로 파일 이름을 해석해 보세요!

수정/해결 방법

perlAFAIK, 시스템 전체의 안전하지 않은 기본 동작을 완전히 변경할 수는 없습니다 .

첫째, 파일 이름의 시작과 끝 부분에 있는 문자에서만 문제가 발생합니다. 그렇다면 언제 perl -ne '' *또는 perl -ne '' *.txt질문이 있습니까?

perl -ne 'some code' ./*.txt

이제 모든 매개변수가 ./, , , 공백이 아닌 것으로 시작하고 끝나기 때문이 아닙니다. 보다 일반적으로는 접두사를 추가하는 것이 좋습니다..txt-<>|구체그리고 ./. 이는 또한 처음에 다른 많은 유틸리티 호출이나 파일과 관련된 -문제를 방지합니다 -(여기서는 더 이상 옵션 닫는( --) 태그가 필요하지 않음을 의미합니다).

-T개방형 모드를 사용하면 taint도움이 될 수 있습니다. 이러한 악성 파일이 발견되면 명령이 중단됩니다( >and |케이스 에만 해당되고 <or 공백에는 해당되지 않음).

이는 위험한 일이 진행되고 있음을 경고하므로 이러한 명령을 대화식으로 사용할 때 매우 유용합니다. 그러나 일부 자동화된 처리를 수행할 때는 이상적이지 않을 수 있습니다. 누군가가 이를 수행할 수 있다는 의미이기 때문입니다.처리파일을 생성하는 것만으로는 실패합니다.

이름에 관계없이 모든 파일을 처리하려면 다음을 사용할 수 있습니다.ARGV::readonly perlCPAN의 모듈(불행히도 일반적으로 기본적으로 설치되지 않습니다.) 이것은 매우 짧은 모듈이며, 수행되는 작업은 다음과 같습니다.

sub import{
   # Tom Christiansen in Message-ID: <24692.1217339882@chthon>
   # reccomends essentially the following:
   for (@ARGV){
       s/^(\s+)/.\/$1/;   # leading whitespace preserved
       s/^/< /;       # force open for input
       $_.=qq/\0/;    # trailing whitespace preserved & pipes forbidden
   };
};

기본적으로 예를 들어 " foo|"변환하여 @ARGV를 정리합니다 ."< ./ foo|\0"

BEGIN명령문에서도 동일한 작업을 수행할 수 있습니다 perl -n/-p.

perl -pe 'BEGIN{$_.="\0" for @ARGV} your code here' ./*

여기서는 우리가 사용하는 가정을 기반으로 이를 단순화합니다 ./.

그러나 이것(and)의 부작용은 후행 NUL 문자가 에 표시된다는 것 ARGV::readonly입니다 .$ARGVyour code here

업데이트 2015-06-03

perlv5.21.5 이상에는 <<>>유사하게 작동하는 새로운 연산자가 <>있지만아니요특별대우를 받습니다. 매개변수는 파일 이름으로만 처리됩니다. 따라서 이러한 버전을 사용하면 이제 다음과 같이 작성할 수 있습니다.

perl -e 'while(<<>>){ ...;}' -- *

--(잊 거나 사용 하지 마세요 ./*) 파일을 덮어쓰거나 예상치 못한 명령을 실행하게 될 것을 걱정하지 마세요.

-n/그러나 -p여전히 위험한 <>형식을 사용합니다. 그리고 심볼릭 링크가 여전히 추적되고 있으므로 신뢰할 수 없는 디렉토리에서 사용해도 안전하다는 의미는 아닙니다.

답변2

또한@Stéphane Chazelas의 답변-i, 명령줄 옵션을 사용하면 이에 대해 걱정할 필요가 없습니다.

$ perl -pe '' 'uname|'
Linux

$ perl -i -pe '' 'uname|'
Can't open uname|: No such file or directory.

-i옵션을 perl사용할 때통계자료파일을 처리하기 전에 파일 상태를 확인하십시오.

$ strace -fe trace=stat perl -pe '' 'uname|'
stat("/home/cuonglm/perl5/lib/perl5/5.20.1/x86_64-linux", 0x7fffd44dff90) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/5.20.1", 0x7fffd44dff90) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/x86_64-linux", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
Process 6106 attached
Linux
Process 6105 suspended
Process 6105 resumed
Process 6106 detached
--- SIGCHLD (Child exited) @ 0 (0) ---

$ strace -fe trace=stat perl -i -pe '' 'uname|'
stat("/home/cuonglm/perl5/lib/perl5/5.20.1/x86_64-linux", 0x7fffdbaf2e50) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/5.20.1", 0x7fffdbaf2e50) = -1 ENOENT (No such file or directory)
stat("/home/cuonglm/perl5/lib/perl5/x86_64-linux", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("uname|", 0x785f40)                = -1 ENOENT (No such file or directory)
Can't open uname|: No such file or directory.

관련 정보