어떻게 확인할 수 있습니 파일의 진정한 확장자/유형 프로그래밍 방식으로?

StackOverflow https://stackoverflow.com/questions/481743

문제

나는 스크립트는 프로세스는 사용자에 업로드하는 서버,그리고 한층의 보안 알고 싶:

는 방법이 있을 감지하는 파일의 진정한 확장자/파일 형식,그리고 있지 않은지 확인 또 다른 파일 형식 마스크와 다른 확장?

가 바이트 스탬프 또는 몇 가지 독특한 식별자를 위해 각형/확장?

고 싶을 검출할 수 있는 누군가가 되지 않았 적용되는 다른 확장자는 파일에 그들은 업로드에 있습니다.

감사합니다,

도움이 되었습니까?

해결책

실제로는 아닙니다.

각 파일의 처음 몇 바이트를 읽고 유한 한 필수품 세트의 헤더로 해석해야합니다. 대부분의 파일에는 별개의 파일 헤더가 있으며 MP3의 경우 처음 몇 바이트 또는 처음 몇 킬로 바이트의 메타 데이터가 있습니다.

귀하의 프로그램은 허용되는 각 필레 타입에 대해 파일을 구문 분석하기 만하면됩니다.

내 프로그램의 경우, 업로드 된 이미지를 Try-Catch 블록으로 ImageMagick에 보냅니다. 임의의 (사용자 제공) 이진 데이터를 외부 프로그램에로드하고 있는데, 이는 일반적으로 공격 벡터 인 외부 프로그램에로드하기 때문에 불안한 것으로 간주되어야합니다. 여기, 나는 Imagemagick이 내 시스템에 아무것도하지 않는다고 믿고 있습니다.

공격 벡터를 피하기 위해 사용하려는 중요한 파일 타입에 대해 자신의 핸들러를 작성하는 것이 좋습니다.

편집 : PHP에서는이 작업을 수행 할 수있는 도구가 있습니다.

또한 MIME 유형은 사용자의 브라우저가 파일을 주장하는 것입니다. 코드로 읽고 행동하는 것이 편리하고 유용하지만, 나쁜 파일을 보내는 사람은 MIME 헤더를 쉽게 속일 것이기 때문에 안전한 방법은 아닙니다. JPEG가 PNG에서 바 핑을 예상하는 코드를 유지하는 것은 일종의 일선 방어입니다. 그러나 누군가가 .Exe에 바이러스를 포함시키고 JPEG라는 이름을 지정하면 MIME 유형을 스푸핑하지 않았을 이유가 없습니다.

다른 팁

PHP는 사용중인 PHP 버전에 따라 마임 유형을 결정하기 위해 파일 내용을 읽는 몇 가지 방법이 있습니다.

살펴보십시오 FileInfo 함수 PHP 5.3+를 실행하는 경우

$finfo = finfo_open(FILEINFO_MIME); 
$type = finfo_file($finfo, $filepath);
finfo_close($finfo);  

또는 체크 아웃하십시오 mime_content_type 이전 버전의 경우.

$type = mime_content_type($filepath);

진정으로 안전하고 싶다면 파일 유형을 확인하는 것만으로는 충분하지 않습니다. 예를 들어 누군가가 공통 렌더러에서 취약점을 악용하는 유효한 JPEG 파일을 업로드 할 수 있습니다. 이를 막으려면 잘 관리 된 바이러스 스캐너가 필요합니다.

PHP에는 a가 있습니다 슈퍼 글로벌 $ _files 크기 및 파일 유형과 같은 정보가 있습니다. 유형이 확장자가 아닌 일종의 헤더를 형성하는 것처럼 보이지만 틀릴 수 있습니다.

그것의 예가 있습니다 W3Schools 사이트.

기회가 생길 때 속임수가 될 수 있는지 테스트 할 것입니다.

업데이트:

다른 모든 사람들은 아마 이것을 알고 있었지만 $ _files는 속일 수 있습니다. 이런 식으로 결정할 수있었습니다.

$arg = escapeshellarg( $_FILES["file"]["tmp_name"] );
system( "file $arg", $type );
echo "Real type:  " . $type;

기본적으로 유닉스를 사용합니다 파일 명령. 더 나은 방법이있을 수 있지만 한동안 PHP를 사용하지 않았습니다. 나는 일반적으로 가능한 경우 시스템 명령을 사용하지 않습니다.

할 수 있는 여전히 위조했다.나는지 확인할 수 있는지(또는하지 않습니다)실행 파일을 서버에 업로드 자동으로 합니다.

또한 것가 바이러스/스파이웨어 스캐너, 게 하고 그렇게 당신을 위해 작업을 수행합니다.

확장자를 변경 한 경우 마임 유형을 제공하는 아래 코드를 사용할 수 있습니다.

$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo $mime = finfo_file($finfo, $_FILES['userfile']['tmp_name']);
finfo_close($finfo);

Windows 사용자 : Php.ini를 편집 하고이 라인을 해결하십시오.

extension=php_fileinfo.dll

새로운 php.ini가 적용되도록 Apache를 다시 시작하십시오.

*nix에서 파일의 첫 두 바이트가 알려줍니다 ( "Magic Number"참조). Windows에서 ... 때로는 이것이 사실이 될 것입니다 ( "헤더 정보"). 궁극적으로 OS 의존적입니다.

일반적으로 실행 파일에는 첫 번째 바이트에 "서명"이 있습니다. 파일 유형이 실제로 무엇인지 확인하는 것이 어렵다는 것을 알게됩니다.

어떤 파일 유형을 기대하십니까? 어쩌면 당신은 그것이 당신이 기대하는 것을 준수하고 다른 모든 것을 거부하는지 확인할 수 있습니다.

다른 사람들은 이미 FileInfo를 언급 한 것입니다. 나는 올바른 솔루션이라고 생각하지만 어떤 이유로 든 그것을 사용할 수없는 경우에만 추가하겠습니다. 대부분의 (모두?) *nix 배포판은 file 파일에서 실행되면 유형을 출력합니다. 사람이 읽기 쉬운 형식 (기본값) 또는 MIME 유형으로 출력으로 전환하는 스위치가 있습니다. 업로드 된 파일에서 스크립트 가이 프로그램을 호출하고 결과를 읽을 수 있습니다. 다시, 이것은 선호되는 접근법이 아닙니다. Windows에있는 경우이 유틸리티는 Cygwin을 통해 제공됩니다.

마임 유형을 확인하는 것이 충분합니까? 파일의 확장을 변경하는 것이 마임 유형이 변경되지 않는다고 가정합니다.

Mime Type A가 여기로 갈 수있는 충분한 지표입니까?

지금까지 모든 답변에 감사드립니다.

마임 유형을 확인하는 것이 충분합니까? 파일의 확장을 변경하는 것이 마임 유형이 변경되지 않는다고 가정합니다. Mime Type A가 여기로 갈 수있는 충분한 지표입니까?

실제로 사용되는 방식에 달려 있습니다.

  • 업로드 및 다운로드를 제공하면 실행되지 않기 때문에 아무런 중요하지 않습니다.
  • 웹 서버에서 처리 된 경우 웹 서버가 구성되는 방식에 따라 다르지만 나머지 대부분의 주석에 따라 달라집니다.
  • 이미지 인 경우 이미지 라이브러리 익스플로잇의 대상이되거나 표시되지 않습니다. 그러나 그것들 만.
  • PDF 파일과 같은 것은 서버에 영향을 미치지 않고 파일에 액세스하는 사람의 컴퓨터에 영향을 줄 수 있습니다.
  • "System ()"과 같은 함수로 전달되면 "두 번 클릭 된"경우와 같이 OS 동작으로 돌아 왔으며 파일 확장자도 고려 될 수 있습니다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top