프로그래밍백엔드 개발자

Perl에서 eval BLOCK과 eval STRING을 사용하는 것의 차이점은 무엇이며, 각각의 오류 처리 및 보안에 대한 특성은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변

Perl에는 eval 구문의 두 가지 문법이 있습니다:

  1. eval BLOCK — 코드 블록을 보호된 블록으로 실행하여 치명적인 런타임 오류(실행 예외)를 포착합니다. 기존 변수 범위를 사용하며 실행 중 코드 컴파일을 요구하지 않습니다.
  2. eval STRING — 문자열을 Perl 코드로 컴파일하고 실행합니다. 동적으로 생성된 코드를 실행할 수 있으며, 동적 서브루틴 생성을 위해 사용되지만 보안 측면에서 위험합니다(외부 데이터에서 형성된 문자열로 임의의 잠재적으로 위험한 코드를 실행할 수 있음).

오류 처리의 특성:

  • 두 경우 모두 치명적인 오류가 포착되고 전역 변수 $@에 오류 메시지(오류가 발생한 경우)가 포함됩니다. 그렇지 않으면 $@는 비어 있습니다.
  • 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 코드만 포함하는지 확인하는 것을 잊어버렸습니다 — 사용자가 입력 주입을 통해 실행 가능한 코드를 추가하여 서버에서 악성 명령이 실행되는 결과를 초래했습니다.