댓글 검색 목록

[php] PHP 8.1의 디렉토리 업로드

페이지 정보

작성자 운영자 작성일 21-07-31 16:14 조회 1,960 댓글 0

PHP 8.1의 새로운 기능 중 하나는 이제 PHP의 $_FILES 슈퍼 전역 변수에 사용자가 업로드한 파일의 경로가 포함된다는 것입니다. 

이 정보는 전체 디렉토리 업로드를 지원하는 브라우저에서 제공되며 PHP 8.1부터 이 정보는 PHP 애플리케이션에서 디렉토리 업로드를 지원하는 데 사용할 수 있습니다.


webkitdirectory 속성을 포함하는 파일 필드가 있는 HTML 양식은 디렉토리 업로드 필드로 간주됩니다. 

이 기능을 지원하는 브라우저를 사용하면 개별 파일 대신 전체 디렉토리를 선택할 수 있습니다. 

사용자가 업로드할 디렉토리를 선택하면 브라우저는 모든 하위 디렉토리와 해당 파일을 포함하여 해당 디렉토리 내의 모든 파일을 서버에 제출합니다.


PHP 8.1 이상을 실행하는 PHP 응용 프로그램에서 파일 경로는 $_FILES 슈퍼 전역에서 사용할 수 있으며 응용 프로그램은 파일 이름, 크기 등과 같은 다른 정보와 함께 파일 경로를 저장할 수 있습니다.


브라우저에서 제공하는 파일 경로는 사용자 입력이므로 그대로 처리해야 합니다. 이러한 필드는 드문 일이 아닌 경로 탐색 공격에 취약합니다.


웹킷디렉토리 속성 


webkitdirectory는 type=file인 입력 HTML 요소에서 사용할 수 있는 HTML 속성입니다. 브라우저 표준은 아니지만 Chrome 6+, Firefox 50+, Edge 13+ 및 Safari 11.1+를 포함한 모든 주요 브라우저에서 지원합니다.


HTML directory upload field 


디렉토리 업로드는 type=file인 표준 입력 요소를 재사용합니다. webkitdirectory를 지원하는 브라우저는 디렉토리 업로드 창을 제공하고 나머지는 표준 파일 업로드 창을 제공합니다.


<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="dir_upload[]" webkitdirectory multiple />
    <input type="submit" value="Upload"/>
</form>


Directory-uploads in field rendered in browser 


Directory-uploads window 


PHP에서 파일 경로 액세스 


사용자가 디렉토리 업로드 필드를 사용하여 디렉토리를 업로드하면 브라우저는 파일 이름, 파일 크기 및 파일 내용과 함께 해당 파일에 대한 상대 경로를 제출합니다.


PHP에서 파일 업로드 정보는 $_FILES 슈퍼 글로벌에서 접근합니다. PHP 8.1 이전에는 브라우저에서 제공하는 상대 파일 경로가 $_FILES로 전달되지 않아 디렉토리 업로드의 디렉토리 계층 구조를 결정할 수 없었습니다.


PHP 8.1에서 이 정보는 $_FILES로 전달되며 디렉토리 업로드를 상대 경로와 함께 저장하거나 서버에서 디렉토리를 재생성하는 데 사용할 수 있습니다.


$_FILES 배열에는 HTML 입력 필드의 이름 속성으로 인덱싱된 파일 업로드 정보가 포함됩니다. 위의 예에서 입력 필드의 이름은 name=dir_upload[]입니다. 이는 $_FILES 배열에 직접 $_FILES['dir_upload'] 배열이 포함되어 있으며 이 배열에는 name, tmp_name 등과 같은 키가 있는 연관 배열이 포함되어 있음을 의미합니다.


project_files
    ├── data
    │   └── data.csv
    ├── outlines
    │   ├── intro.doc
    │   └── welcome.doc
    ├── presentation.pdf
    ├── presentations
    │   ├── ayesh.ppt
    │   ├── mentor.doc
    │   └── phpwatch.ppt
    └── report.xls


위와 유사한 디렉토리 구조에서 $_FILES 배열은 $_FILES['dir_upload']['name']에서 기본 파일 이름만 반환합니다.


var_dump($_FILES);
array(1) {
  ["dir_upload"]=> array(6) {
    ["name"]=> array(8) {
      [0]=> string(8) "data.csv"
      [1]=> string(16) "presentation.pdf"
      [2]=> string(9) "intro.doc"
      [3]=> string(11) "welcome.doc"
      [4]=> string(10) "report.xls"
      [5]=> string(12) "phpwatch.ppt"
      [6]=> string(9) "ayesh.ppt"
      [7]=> string(10) "mentor.doc"
    }
    ...type, tmp_name, error, size


$_FILES['dir_upload']['name'] 배열에서 상대 경로가 누락되어 사용자 파일 시스템에서 파일에 대한 상대 경로를 검색할 수 없게 하는 방법에 주목하십시오.


PHP 8.1 이상부터 파일에 대한 상대 경로를 포함하는 $_FILES의 각 파일 업로드 필드에 새 배열이 추가됩니다.


var_dump($_FILES);
array(1) {
  ["dir_upload"]=> array(6) {
    ["name"]=> array(8) {
      [0]=> string(8) "data.csv"
      [1]=> string(16) "presentation.pdf"
      ...
    }
+    ["full_path"]=> array(8) {
+      [0]=> string(27) "project-files/data/data.csv"
+      [1]=> string(30) "project-files/presentation.pdf"
+      [2]=> string(32) "project-files/outlines/intro.doc"
+      [3]=> string(34) "project-files/outlines/welcome.doc"
+      [4]=> string(24) "project-files/report.xls"
+      [5]=> string(40) "project-files/presentations/phpwatch.ppt"
+      [6]=> string(37) "project-files/presentations/ayesh.ppt"
+      [7]=> string(38) "project-files/presentations/mentor.doc"
    }
    ...type, tmp_name, error, size


각 파일 업로드 필드의 새로운 full_path 배열은 파일의 전체 경로를 나열합니다.


디렉토리 업로드 시 이제 각 업로드된 파일의 전체 경로를 저장할 수 있습니다. 업로드된 파일을 업로드한 사용자와 동일한 디렉토리 구조에 저장하는 것을 선호하는 응용 프로그램은 파일을 서버의 관련 디렉토리로 재귀적으로 이동하여 저장할 수 있습니다.


Security Hardening 


각 $_FILES 필드의 full_path 배열은 사용자가 직접 입력하기 때문에 안전하지 않습니다. 이 배열의 모든 값은 특히 서버의 하위 디렉터리에 업로드된 파일을 저장할 때 잠재적인 취약점을 방지하기 위해 유효성을 검사해야 합니다.


  • 제출된 full_path 값은 경로 순회를 트리거할 수 있습니다. 예를 들어 서버가 사용자가 업로드한 파일을 저장하는 경우 경로 탐색을 시도할 수 있는 값을 거부해야 합니다.
  • 파일 경로의 중첩 수준과 길이를 확인합니다. 깊게 중첩된 하위 디렉토리 또는 지나치게 긴 파일 경로는 오류를 발생시키고 파일 시스템 오류를 유발할 수 있습니다.

출처 : https://php.watch/articles/php81-directory-uploads



댓글목록 0

등록된 댓글이 없습니다.

웹학교 로고

온라인 코딩학교

코리아뉴스 2001 - , All right reserved.