PHP 에서 파일 업로드 기능을 구현할때 가장 안전한 방법

망치의 이미지

간단하게 파일 업로드 해둘 수 있는 페이지를 만들어뒀습니다.

업로드된 파일의 mime type 을 판별해서 허용할지 안할지 판단하게 해두었는데 이렇게 해두니 같은 확장자여도 업로드 되는 파일이 있고.. 안되는 파일도 있더군요.
단순히 확장자만 판별하게 하는방법도 생각해봤는데 이럴 경우 보안 문제가 발생할 수 있다고 해서 선뜻 방식을 바꾸지 못하고 있습니다..

업로드된 파일로 인해 보안문제가 발생할 여지를 최소화 하고, php 내장 mime type 을 통하지 않고도 원하는 파일 타입을 구분해서 허용할 수 있는.. 조금은 구체적으로 실제 사용되고 있는 방법에 대해 조언을 부탁드립니다.

익명사용자의 이미지

1. 파일 타입은 확장자로 구분
2. 파일 이름을 안전한 확장자를 가진 이름으로 변환해서 저장. 1234_abc.data
3. 파일을 저장할때 퍼미션을 반드시 644, 666 등으로 저장.
4. 파일을 다운받을 때는 URL로 직접 접근하게 하지 말고 php의 fpassthru함수를 통해 전송.
5. URL로 직접 접근할 수 없는 곳에 파일 저장. 웹 디렉토리가 home/user/public_html이면 home/user/data 쪽에 저장.
6. 성능의 손해를 감수할 수 있다면, 파일 내용을 검사해서 필터링한다. #!/bin/sh 나 #!/bin/bash 같은거.

송효진의 이미지

아무 검사 하지 않습니다.
다운로드된 파일의 파일명은 테이블에 보관하고,
실제 파일은 시퀀스나 MD5 HASH 를 파일명으로 저장합니다.
파일은 public_html 밖에 (../files/) 빼 두고,
(파일 관리를 위해 1000 개마다 디렉토리를 바꿔주는 등의 로직이 있으면 더욱 좋습니다.)

다운로드는 http://www.site.com/files.php/(md5hash or sequence)/원래파일명.jpg
이런식의 링크로 해결합니다. (혹은 헤더에 파일명을 명시할 수도 있겠지요.)
files.php 에는 이어받기가 되도록 헤더처리를 해 주면 더욱 효과적입니다.

md5hash 를 선택하실 때는 파일의 용량도 함께 표기가 되는것이 좋습니다.
만에 하나 있을지 모를 같은해쉬를 가지는 다른 파일의 위협을 줄이기 위해...

emerge money

익명사용자의 이미지

이 경우의 단점은
1. ftp등과 같이 쓸 수 없다.
2. ftp를 쓸 수 없기 때문에 한꺼번에 많은 파일을 올릴 수 없다. (이미지 파일이 1000여개라고 할 때)

송효진의 이미지

php 의 업로드 기능을 이용하는것에 대한 글입니다.
ftp 를 이용하는것은 어차피 php 에서 제어가 안되는데요.;p

꼭 해야 한다면 tarball 해서 올리고, php 스크립트 짜서 돌리지요.
제가 위에 적은 기능이 구현되었다면,
짤 코드는 몇줄 안되죠. :)

emerge money

송효진의 이미지

php 로 넘어오는 $_FILES 의 mime type 은 신뢰하지 마세요.
순전히 브라우저가 보내는 정보를 믿어주는거라,
신뢰도 0 입니다.
실제로 몇년전의 모질라 같은 경우 그냥 확장자로 mime type 을 선택해서 보내더군요.

mime type 을 구분해야 할 일이 있다면,
php 의 mime_content_type() 이나 pear 의 MIME_Type 같은것을 이용하세요.

emerge money

망치의 이미지

아, 현재 상태가 mime_content_type() 를 이용하는 중이었습니다.

조언주신대로 구현할 방법을 고민해보겠습니다.

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

망치의 이미지

php 내부에서 아래와 같은 파일뒤 파라미터는 Request_URI 같은걸 이용해서 파싱하는건가요?

http://www.site.com/files.php/(md5hash or sequence)/원래파일명.jpg

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

송효진의 이미지

/phpinfo.php
/phpinfo.php/asdf/zxcv

지금 해 보니 좋은게 보이네요.
PATH_INFO

얼른 고쳐야겠습니다.

emerge money

망치의 이미지

PATH_INFO 좋네요. ㅎㅎ

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

사랑천사의 이미지

x.php/aaa/bbb/ccc

이거... PHP에서 처리가 가능하단 말이죠??? PHP는 아니어도 저런 비슷한 것을 많이 본 거 같은데 가능하단 소리군요... 음... 좀 더 저걸 활용하는 자세한 예가 잇으면 보여 주실 수 있을런지.. 뭔가 해서 봤더니 재미 있는 것이 있네요...
----
일어나라! 싸워라! 그리고 이겨라!
다만!!! 의미 있는 것에 그 힘을!!!
그 능력과 노력을!!!

사람천사

익명사용자의 이미지

모니위키에서 PATH_INFO 사용합니다. PATH_INFO를 직접 파싱하는데, 이 경우 AcceptPathInfo On으로 설정되어 있어야 합니다. 이 경우 mod_rewrite를 쓸 필요 없다는 장점이 있는데, 반대로 mod_rewrite를 함께 쓰려고 하는 경우 (예를 들어 스크립트 이름을 감추려고 한다거나) PATH_INFO를 제대로 파싱하는데 특별 처리를 하거나 해야하죠.

망치의 이미지

    // 테스트로 다운로드될 파일들이 저장된 디렉토리 (웹접근불가)
    // /home/research/files
 
    // 본 파일이 위치한곳
    // /home/research/www/test.php
 
    function Sendfile($name)
    {
        $FileDir = "/home/research/files/";
        $filename = $name;
        $fileString = $FileDir . $name;
 
        if(!$fdl=@fopen($fileString,'r')){
           die("Cannot Open File!");
        } else {
          header("Content-type: application/octet-stream");
          header("Content-length:".(string)(filesize($fileString)));
          fpassthru($fdl);
        }
        return;
    }
 
    $fname = split("/", $_SERVER["PATH_INFO"]);
    Sendfile($fname[1]);

ex> http://research.com/test.php/imagefile1.jpg

메뉴얼을 참고해서 간단하게나마 파일을 땡겨오는 함수를 만들어봤습니다.
IE 에선 이미지 접근시 바로 표시가 되는데, FF 에선 다운로드창이 떠버리네요.. 컨텐츠 타입 문제인것같기도하고..

이건 어떻게 해결해야하나요?;;

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

ironiris의 이미지

이미지가 웹브라우저에서 보여지길 원하시면 application/octet-streamimage/jpeg로 하시면 될듯.

망치의 이미지

파일 컨텐츠가 항상 이미지만 있진 않을것같거든요..
동영상도 있을테고.. 문서도 있을테고.. 압축파일 등등..

그렇다고 mime_content_type 을 쓰면 지금과 마찬가지로 제대로 판별 안되는 파일이 종종 있을거구요..

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

송효진의 이미지

이미 보안이 강화 되었으므로,
$_FILES 의 mime type 을 테이블에 함께 저장하고,
다운로드시 그것을 헤더에 뿌리세요.

emerge money

망치의 이미지

아.. 그게 좋겠네요. ㅎ
감사~!

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

사랑천사의 이미지

아래와 같은 부분을 어떻게 잘 활용 해 보심이...

                Header("Content-Type: application/octet-stream; name=$file_name");
                Header("Content-Disposition: attachment; filename=$file_name");

RG-Board에서 사용된 헤더입니다. (전 웹프로그래밍이 주업이 아니기 때문에 전부 저 헤더의 뜻을 이해 하진 못 했습니다.)

그리고 파싱을 직접 하면 되겠군요. x.php/xxx.html 이런건 이해 했습니다.

그리고 저기에 파일명을 MD5로 암호화 해서 저장하고 받을 때 그 MD5 문자열을 대입 하게 하면 보안이 강화 되겠군요.(어떤 분이 말씀 해 주신 내용인 듯...)
----
일어나라! 싸워라! 그리고 이겨라!
다만!!! 의미 있는 것에 그 힘을!!!
그 능력과 노력을!!!

사람천사

사랑천사의 이미지

DB에 자료를 넣고 그걸 그냥 뿌린다는 말씀이신가요??? 무서운 방법이군요. 바이너리로 집어 놓고 다시 빼와서 뿌리면 되겠군요.(뭐 저도 저런걸 언젠가는 구현 해야 할 날이 올 거기 때문에...)

뭐, 스트림으로 보내는 것 만 해도 상당히 보안에 신경을 쓴 것이 되 버리겠군요. 거기다가 일반적인 방법으론 접근조차 할 수가 없으니 더 보안성이 높아 지고, 뭐 좋은 방법이네요.(근대 아무레도 DB에 파일 내용을 직접 저장 한다고 생각 한 것은 잘못 이해 한 듯...)

아무튼 좋은거 잘 만드세요 ㅎㅎㅎ.
----
일어나라! 싸워라! 그리고 이겨라!
다만!!! 의미 있는 것에 그 힘을!!!
그 능력과 노력을!!!

사람천사

망치의 이미지

업로드된파일은 DB 가 아니라 아파치가 접근할 수 없는 디렉토리에 저장됩니다. PHP 가 내부적으로 접근해서 파일을 읽어다가 뿌려주는식이구요.

그나저나 이걸 만들어서 서비스할 녀석이 문제가 생겨서 걱정이 큽니다.. 아무래도 하드웨어문제같은데.. 곤란하게됐네요 ㅡ.,ㅡ;

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

사랑천사의 이미지

제가 좀 전에 답글 단 서버 같군요 ㅋㅋㅋ... 서버 죽은게.. 저도 한 두 번이 아니기 때문에 흑흑흑... 어느정도 이해가 갑니다. message 어쩌고 체크 해 볼 시간적 여유도 없었습니다 윽.
----
일어나라! 싸워라! 그리고 이겨라!
다만!!! 의미 있는 것에 그 힘을!!!
그 능력과 노력을!!!

사람천사

사랑천사의 이미지

다나와.. 그리고 Gmarket를 잘 이용 하면 싸게 살 수 있습니다. 욕션 같은건 안 해 봐서 모르겠고, 제가 지금까지 물건을 사면서 용산을 직접 탐방한 경우를 제외하곤 거의 다가 다나와를 통해서 산 것들입니다. Gmarket은 써 보진 않았는데 물건 가격만 한번 구경 해 본 적이 있습니다. 가격 면에선 괸찮은 것이 많더군요.

그리고 P3용 보드가 꼭 필요 하시다 싶으시면... 매일 주소로 매일을 주세요 ㅋㅋㅋ. 근대 이게 좀 불안하네요... 정말 P3가 들어 가는진. 라이저 카드 같은걸 써야만 들어 가는 거라면 불안하지 않을 수가 없겠쬬 흠.(지금 이게 슬롯에 꽂는 겁니다.)
----
Lee Yeosong(이여송 사도요한)
E-Mail: yeosong@gmail.com
MSN: ysnglee2000@hotmail.com
----
웃음... 행복... 평화... (진정한...) 희망... 사랑... 이 세상 모든것이 그렇다면 얼마나 좋을까...(꿈 속의 바램일 뿐인가...)

사람천사

망치의 이미지

말씀은 감사 ^^;
그냥 제 컴터 본체 새로 마련하면서 쓰던걸 갖다둘까도 생각중입니다. 안정적으로 사용하던 녀석이니 이녀석은 문제 없을듯하네요. ㅎ

요즘 추세대로 듀얼코어에 맞춰서 나름대로 저렴하게 견적 내봐도 가격이 꽤 나가네요..

Intel DG965RY 132,000
G.SKILL DDR2 PC2-6400(512M x 2EA) 145,000
Intel E6300 173,000

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

wkpark의 이미지

그냥 메모리 1GB에 보드/cpu 모두 9만원 안쪽으로 하시면 부담이 훨씬 덜하지요~ (단지 웹서버로 쓰실 생각이라면 CPU속도보다는 좋은 HDD와 메모리에 투자하시는게 더 낫다에 한표)

온갖 참된 삶은 만남이다 --Martin Buber

망치의 이미지

아.. 새로 구매하는건 제가 메인으로 쓸 녀석입니다. 서버로 돌릴건 기존에 제가 쓰던 (P4-2.0) 이구요. ㅎ

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

사랑천사의 이미지

솔직히... 엄청난 양의 데이터 처리가 필요한 프로세스를 돌리실 것이 아니라면 듀얼코어도 필요 없지 않을 까요. 서버가 2.4G 셀D로 잘 돌아 가고 있습니다.(저의 경우)

그리고 데스크탑에 2000과 젠투를 깔아서 쓰는데.. (젠투는 얼마 전에 시작 했죠.) 이게 P4도 아닌데.. 그렇게 딸린다는 생각은.. 안 해 봤습니다. (스크린 리더만 안 띄우면...) (젠투 컴파일 엄청 느린것도 일단은 넘어감...)

뭐.. 저는 항상 돈이 쪼달리므로 저가형 장비들만 씁니다... 셀러론, (메모리는 어쩔 수 없죠. 그래도 비싸더군요.) ASRock 보드나 VIA 칩 같은걸 사용한 저가형 보드...(아니면 BX에도 조립 합니다. 그것도 아니면 I815같은게 들어간...) Ethernet은 누구나 잘 쓰는..(아닌가?) RTL-8139호환 기종... 하드는 어디서 남아 도는거 거저 얻어다 쓰거나..(사야 한다면?) 사야 되면 그냥 간단하게 삽니다. 쓸만 하다면 5년? 6년도 업그레이드를 안 하고 쓰죠.(근대 지금까지 자꾸 문제가 생겨서 바꾸는 김에 업그레이드도 계속 해 왔습니다.)

아무튼 만드시는 프로그램이 잘 돌아 가길 바라겠습니다 ㅎㅎㅎ.
----
Lee Yeosong(이여송 사도요한)
E-Mail: yeosong@gmail.com
MSN: ysnglee2000@hotmail.com
----
웃음... 행복... 평화... (진정한...) 희망... 사랑... 이 세상 모든것이 그렇다면 얼마나 좋을까...(꿈 속의 바램일 뿐인가...)

사람천사

망치의 이미지

제가 쓰던걸(P4-2.0) 갖다놓고 제 메인컴 본체를 새로 마련하는걸 고민중입니다 ^^ 가격 알아본것 역시 그런 이유에서 알아본것이구요

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

사랑천사의 이미지

쓰시는 컴퓨터를 업그레이드 하시려는 생각이신가 보군요.(그리고 제가 데스크탑 이야기를 한 것도.. 데스크탑이 너무 좋을 필요가 없다는 뭐 그런 소리를 하고 싶었습니다. ㅋㅋㅋ.) 뭐 아무튼... 전 될 때 까지 P3 550으로 버텨 볼랍니다... 자료는 간간히 백업을 해 줘야 겠군요 음. 그럼 잘 되시기를... 아 참. 듀얼코어나 775소켓 쓰는 것들은 열 많이 받아서 골아픕니다 윽...
----
Lee Yeosong(이여송 사도요한)
E-Mail: yeosong@gmail.com
MSN: ysnglee2000@hotmail.com
----
웃음... 행복... 평화... (진정한...) 희망... 사랑... 이 세상 모든것이 그렇다면 얼마나 좋을까...(꿈 속의 바램일 뿐인가...)

사람천사

망치의 이미지

이렇게 구현하고 다음과 같이 이미지를 표현했을때 IE 에서 다른이름 저장시에 BMP 로 저장되는 문제가 발생합니다. 익스에서 보안문제로 일부러 그렇게 막아둔것인지.. 아니면 다른 방법이 있을까요? 파폭에선 문제없이 저장되더군요.

<img src="http://www.test.com/test.php/코드~~/asdf.gif">

수정했습니다.;;

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

송효진의 이미지

'다음과 같이' 가 안보이는데요,
어쨌든, 익스플로러에서 이미지의 '헤더' 나 '주소' 에 그림이 아닌듯한 느낌(?)이 들도록 표현됐는지 확인해보세요.-_-;

파일명 헤더가 포함되었는데 확장자가 없다던가,
파일타입 헤더가 엉뚱 혹은 없다던가,

url 의 파일명에 그림다운 확장자가 붙지 않았다던가... 등등...

img 태그에 적은 것이기 때문에 좀 틀려도 그림인줄 알고 보여주기는 합니다만,
저장시에 좀 이상한짓을 하는 경우를 겪어본 적이 있습니다.

emerge money

망치의 이미지

헤더는 조언해주셨던대로 처음 업로드시 넘어오는 mime type 을 그대로 넘겨주었기 때문에 문제 없을테고..

희한한건 Firefox 에선 잘 되는데, IE 에서만 문제가 생깁니다. img 태그로 이미지 표시는 잘 되는데 다른이름 저장시엔 원본파일 종류와 관계없이 무조건 BMP 로 저장되더군요.

---------------------------------------
http://www.waitfor.com/
http://www.textmud.com/

xx1의 이미지

다음 기사를 참고하시기 바랍니다.
http://support.microsoft.com/default.aspx?scid=kb;ko;810978
http://qaos.com/article.php?sid=1363

제 기억으로는 인터넷 임시 폴더의 크기를 너무키워놔도 발생했었던 것 같습니다. 20-100MB 정도면 될 것 같습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.