Perl에는 eval 구문의 두 가지 문법이 있습니다:
오류 처리의 특성:
$@에 오류 메시지(오류가 발생한 경우)가 포함됩니다. 그렇지 않으면 $@는 비어 있습니다.eval BLOCK은 더 빠르고 안전하며 동적 코드를 실행할 필요가 없을 때 선호됩니다.eval STRING은 동적으로 코드를 생성하는 데 편리하지만 문자열을 추가로 컴파일하므로 더 느리고 잠재적으로 위험합니다.# eval BLOCK 사용 예시 my $result = eval { die "Error!" unless 1 + 1 == 2; return "OK"; }; if ($@) { warn "Error caught: $@"; } # eval STRING 사용 예시 my $code = '$x = 1 + 2; $x;'; my $res = eval $code; if ($@) { warn "Eval string error: $@"; }
eval STRING 내부에 동적으로 대입되는 변수를 적절히 에스케이프하지 않으면 추가적인 위험이 발생할 수 있나요?
예, 대입되는 문자열이 특히 외부에서 얻은 변수로 형성되는 경우 (예: 사용자 입력에서) 보안/주입 위협이 발생합니다. 항상 에스케이프를 사용하거나 타인의 데이터에 대해 eval STRING을 사용하지 않아야 합니다.
my $user_code = 'system("rm -rf /");'; eval $user_code; # 매우 위험함!
이야기
가상 머신의 매개변수를 확인하기 위한 감사 스크립트에서 eval STRING을 사용했으며, "실수로" 외부 구성 파일에서 읽은 데이터가 포함되었습니다. 어느 날 파일이 변조되어 악의적인 코드를 실행하게 되었고 서버가 손상되었습니다.
이야기
개발자는 잠재적으로 치명적인 코드 부분을 eval BLOCK으로 감싸놓고, 런타임 오류뿐만 아니라 컴파일 오류(예: 구문 오류)도 "포착할 것"이라고 기대했습니다. 그러나 구문 오류(예: 변수 이름의 오타)는 eval BLOCK에서 포착되지 않아서 프로세스가 중단되었습니다.
이야기
Dumper 덤프를 통해 eval STRING으로 복잡한 데이터 구조를 역직렬화하는 과정에서 문자열이 유효한 Perl 코드만 포함하는지 확인하는 것을 잊어버렸습니다 — 사용자가 입력 주입을 통해 실행 가능한 코드를 추가하여 서버에서 악성 명령이 실행되는 결과를 초래했습니다.