고급 PHP 프로그래밍 – 웹 보안 – 3 – 파일 업로드 보안

고급 PHP 프로그래밍 - 웹 보안 - 3 - 파일 업로드 보안
고급 PHP 프로그래밍 – 웹 보안 – 3 – 파일 업로드 보안

고급 PHP 프로그래밍 – 웹 보안 – 파일 업로드 보안

안녕하세요~ 😊
이번에는 웹 보안의 실전 필드에서 자주 다루는 핵심 이슈, 파일 업로드 보안에 대해 알아보겠습니다!

파일 업로드는 사용자와 서버 간의 양방향 소통을 가능하게 해주는 아주 유용한 기능이지만,
잘못된 처리로 인해 해커가 웹쉘을 업로드해 서버 전체를 장악하는 무서운 공격 통로가 될 수 있어요 😱

하지만 걱정 마세요!
이번 포스팅에서는 PHP에서 안전하게 파일을 업로드하는 방법과 주의할 점을 아주 친절하게 알려드릴게요~ 😊


파일 업로드가 위험한 이유는?

파일 업로드는 입력값과 달리, 서버에 실제 파일을 저장하고 실행 가능성까지 존재하기 때문에
보안 사고 발생 시 피해 규모가 매우 커질 수 있어요.

💥 예시: 공격자가 업로드한 악성 파일

<?php system($_GET['cmd']); ?>

이런 PHP 파일을 .php 확장자로 업로드하고 실행하면?

https://example.com/uploads/shell.php?cmd=rm -rf /

→ 서버가 통째로 날아갈 수도 있어요! 😨


안전한 파일 업로드의 핵심 전략

보안 원칙 설명
1. 확장자 제한 이미지, 문서 등 허용된 확장자만 업로드 허용
2. MIME 타입 검사 실제 파일 종류와 일치하는지 확인
3. 파일명 무작위화 공격자가 예상할 수 없도록 변경
4. 실행 불가능한 디렉토리에 저장 웹 루트 밖 또는 실행권한 제거
5. 크기 제한 무한 용량 공격 방지
6. 업로드 후 재확인 이미지인지 체크, 악성 코드 포함 여부 검사

실전 코드 예제: 안전한 파일 업로드 처리

<?php
session_start();

$uploadDir = __DIR__ . '/uploads/';
$maxFileSize = 2 * 1024 * 1024; // 2MB
$allowedExt = ['jpg', 'jpeg', 'png', 'gif', 'pdf'];
$allowedMime = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf'];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $file = $_FILES['upload'];

    if ($file['error'] !== UPLOAD_ERR_OK) {
        die('파일 업로드 오류가 발생했습니다.');
    }

    // 확장자 검사
    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    if (!in_array($ext, $allowedExt)) {
        die('허용되지 않은 파일 확장자입니다.');
    }

    // MIME 검사
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime = finfo_file($finfo, $file['tmp_name']);
    if (!in_array($mime, $allowedMime)) {
        die('파일 형식이 올바르지 않습니다.');
    }

    // 크기 제한
    if ($file['size'] > $maxFileSize) {
        die('파일 크기가 너무 큽니다.');
    }

    // 파일명 무작위로 저장
    $safeName = uniqid('file_', true) . '.' . $ext;
    $destination = $uploadDir . $safeName;

    if (!move_uploaded_file($file['tmp_name'], $destination)) {
        die('파일 저장에 실패했습니다.');
    }

    echo "파일 업로드 성공! 파일명: $safeName";
}
?>

업로드 디렉터리 설정 시 주의사항

🛡️ 업로드 폴더는 반드시 웹 루트 밖 또는 실행되지 않는 디렉토리로 설정해야 해요.

📁 디렉토리 구조 예시

/var/www/html/             ← 웹 루트
/var/www/uploads/          ← 업로드 파일 저장 (웹에서 직접 접근 금지)

또는 .htaccess로 업로드 폴더의 PHP 실행을 차단할 수도 있어요:

# uploads/.htaccess
php_flag engine off

이미지인지 확인하는 추가 보안

공격자는 .jpg 확장자를 쓰더라도 안에 PHP 코드를 심을 수 있어요.
그래서 파일 내부를 분석해서 실제 이미지인지 확인하는 절차도 중요해요!

if (!getimagesize($file['tmp_name'])) {
    die('이미지 파일이 아닙니다.');
}

업로드 시 주의해야 할 요소 정리 ✅

항목 설명
파일명 변경 사용자가 지정한 파일명은 절대 그대로 쓰지 말 것
경로 탐색 방지 ../ 같은 경로 조작 요소 제거
확장자 검사만 의존 금지 MIME, getimagesize 등 중복 확인
클라이언트 검증만 믿지 않기 자바스크립트 검사는 서버에서 반드시 재검증
디렉터리 접근 제한 .htaccess, 실행 권한 제거 등 조치 필요

요약 🎯

구분 설명
위험요소 웹쉘 업로드, 악성 스크립트 실행, 디렉토리 탐색 등
방어법 확장자 제한, MIME 확인, 실행권한 차단, 파일명 무작위화
최우선 원칙 “모든 업로드 파일은 무조건 의심하라!”

마무리하며 😊

파일 업로드는 사용자 편의성을 크게 높여주는 기능이지만,
보안 없이 방치할 경우, 해커가 열어두고 들어오는 정문이 될 수도 있어요.

**“서버에 저장한다는 건, 그만큼 책임도 따른다”**는 사실을 꼭 기억해 주세요!

PHP의 강력한 내장 함수들과 방어 기법을 잘 활용한다면,
사용자에게는 편리함을, 개발자에게는 안심을 줄 수 있는 업로드 기능을 만들 수 있어요. 😄

다음 시간에는 디렉토리 탐색(Directory Traversal)과 경로 조작 방지에 대해 이어서 설명드릴게요!
오늘도 똑똑하고 안전한 개발 되세요~! 💻🔐🧠✨

답글 남기기