표면 이미지 파일이 실제 이미지 파일인지 확인하는 스크립트

표면 이미지 파일이 실제 이미지 파일인지 확인하는 스크립트

이미지 파일(즉, .jpg, .bmp 등과 같은 일반적인 이미지 파일 확장자를 가짐)로 나타나는 디렉터리의 모든 파일이 실제로 이미지 파일인지 확인하는 쉘 스크립트를 만들고 싶습니다.

최근 해커가 디렉터리에 파일을 생성하고 이를 .jpg 파일로 마스킹할 수 있는 문제가 발생했습니다. 디렉토리의 모든 파일이 실제 jpg, gif 또는 png 파일인지 확인하는 쉘 스크립트를 만들고 싶습니다.

답변1

file완전히 신뢰할 수 없는 입력을 제공할 때는 매우 주의해서 사용해야 한다고 생각합니다. 예를 들어 RHEL 5는 file다음을 인식합니다.

GIF87a
<?php
echo "Hello from PHP!\n";
?>

"GIF 이미지 데이터, 버전 87a, 15370 x 28735"로. PHP 인터프리터는 아무런 문제 없이 이 입력을 실행합니다. 문제없어요"로컬 파일에 다음이 포함되어 있습니다.“(LFI) 문제.

둘째, file(심지어 strings) 실제로 입력 파일을 구문 분석하여 알고 싶은 내용을 알려줍니다. 이것들파서가 복잡하다그리고문제가 있다.

나는 identify명령 을 제안 할 것이다이미지 마술사모음곡. 위의 간단한 예에 속지 않고 이미지 파일을 올바르게 구문 분석하므로 file.

답변2

빠른 첫 번째 패스로,file이미지 캡션을 빠르게 감지하는 명령:

if file "$FILE" |grep -qE 'image|bitmap'; then
  echo "File '$FILE' has the headers of an image"
fi

bitmap(식별하려면 두 번째 교대가 필요합니다.윈도우 BMP 파일libmagic은 비트맵 이미지를 설명하기 위해 "이미지"라는 단어를 사용하지 않기 때문입니다. )

하지만, filePHP 기반 가짜 이미지를 사용하여 속일 수 있습니다.브루스 에디거의 답변:

$ echo 'GIF87a<?php echo "Hello from PHP!"; ?>' > fake.gif
$ file fake.gif && echo image detected || echo no image detected
fake.gif: GIF image data, version 87a, 16188 x 26736
image detected

Imagemagick을 사용하여 식별

이것이미지 마술사스위트룸의 특징확인하다CLI 프런트엔드가 있는 스크립트는 특정 이미지에 대한 일부 메타데이터를 반환합니다. 예상되는 메타데이터가 없으면 실패하므로 이 목적에 적합합니다.

$ identify fake.gif && echo image detected || echo no image detected
identify-im6.q16: negative or zero image size `fake.gif' @ error/gif.c/ReadGIFImage/1402.
no image detected

많은 수의 파일을 더 빠르게 검사하려면 두 파일을 함께 사용하는 것이 좋습니다.

if file "$FILE" |grep -qE 'image|bitmap' \
&& ! identify "$FILE" >/dev/null 2>&1; then
  echo "File '$FILE' is a fake image!"
fi

(이렇게 하면 출력이 identifyOblivion으로 리디렉션됩니다. 종료 코드로 캡처되는 성공적으로 완료되었는지 여부에만 관심이 있기 때문입니다.)

그래도 속일 수는 있지

다음 예에서는 끝에 동일한 PHP 코드가 추가된 간단한 1x1 흰색 GIF를 사용합니다. 나는 PHP를 모르고 이것이 실제로 실행될지 확실하지 않지만 PHP는 <?php … ?>마크업 외부의 모든 것에 문자 그대로 "텍스트"를 인쇄하는 템플릿 언어이기 때문에 주어진 코드가 다음과 같이 실행될 것이라고 가정합니다. 페이로드 앞에 약간의 쓰레기가 있습니다.

$ { echo 'R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBAD'
    echo 's8P3BocCBlY2hvICJIZWxsbyBmcm9tIFBIUCEiOyA/Pgo='
  } | base64 -d > fake2.gif
$ strings fake2.gif
GIF87a
;<?php echo "Hello from PHP!"; ?>
$ file fake2.gif
fake2.gif: GIF image data, version 87a, 1 x 1
$ identify fake2.gif
fake2.gif GIF 1x1 1x1+0+0 8-bit sRGB 2c 68B 0.000u 0:00.000

GIF 주석을 통해서도 이 작업을 수행할 수 있으므로 이미지로 완전히 유효해집니다.

$ hd fake3.gif
00000000  47 49 46 38 39 61 01 00  01 00 80 00 00 ff ff ff  |GIF89a..........|
00000010  ff ff ff 21 fe 20 3c 3f  70 68 70 20 65 63 68 6f  |...!. <?php echo|
00000020  20 22 48 65 6c 6c 6f 20  66 72 6f 6d 20 50 48 50  | "Hello from PHP|
00000030  21 22 3b 20 3f 3e 00 2c  00 00 00 00 01 00 01 00  |!"; ?>.,........|
00000040  00 02 02 44 01 00 3b                              |...D..;|
00000047

저는 GIF를 선택하고 해당 댓글 시스템을 활용했지만 단순히 이미지 뒤에 페이로드를 연결하는 것만으로도 이 탐지 기술을 우회할 수 있습니다. 속이는 것보다 어렵고 file(구현에 따라)가능한증거를 남겨주세요(이미지의 정크).

답변3

@Adam Katz가 함께 작성한 명령에 따라 -qgrep 출력을 억제하는 데 사용된 옵션으로 인해 항상 반환 코드 0이 제공되었기 때문에 시스템이 계속 실패하는 것을 발견했습니다. 이를 제거하면 작동하지만 인식 명령의 출력이 화면 전체에 퍼져 있음을 의미합니다.

저는 기본적으로 Xubuntu 22.04.1 LTS와 함께 제공되는 GNU bash 버전 5.1.16(1) 릴리스(x86_64-pc-linux-gnu) 및 GNU grep 3.7을 사용하고 있습니다.

내 솔루션은 테스트 내에서 필요한 명령을 실행하는 Adams의 솔루션과 동일한 방식으로 작동합니다.

[[ ( $(file "$file" | grep -E 'image|bitmap') != ""  ) \
&& ( $(identify $file | grep error) -eq 0 ) ]] \
&& echo "File $file appears to be an image" \
|| echo "File $file appears to be a fake"

Adam의 게시물이 저에게 도움이 된 것처럼 누군가에게도 도움이 되기를 바랍니다.

관련 정보