플러그인의 업로드 검증이 뚫려 PHP 파일이 wp-content/uploads/ 에 올라갔다고 합시다. 여기서 두 갈래로 갈립니다. 서버가 그 파일을 실행해 주면 원격 코드 실행(RCE)이고, 실행을 거부하면 그냥 파일 하나입니다. 이 차단 규칙 한 줄이 그 갈림길입니다.
nginx 설정
location ~* /wp-content/uploads/.*.php$ {
deny all;
}
순서가 중요합니다. 이 블록은 PHP 를 fastcgi 로 넘기는 location ~ .php$ 보다 먼저 매칭돼야 합니다. nginx 는 정규식 location 을 선언 순서로 평가하므로, 차단 블록을 PHP 처리 블록 위에 둡니다.
왜 업로드 검증만으로는 부족한가
- 업로드 검증은 플러그인마다 다시 구현됩니다 — 하나만 실수해도 뚫립니다.
- 이 차단은 서버에서 한 번 선언하면 모든 플러그인에 적용됩니다.
- 확장자 위장(
shell.php.jpg) · 이중 확장자 같은 우회 시도도, 실행 계층에서.php로 끝나는 요청 자체를 거부하면 의미가 없어집니다.
검증
# 아무 텍스트나 담은 php 파일을 uploads 에 두고
curl -s -o /dev/null -w '%{http_code}' https://example.com/wp-content/uploads/probe.php
# 403 이어야 한다 — 200 이면 지금 이 글의 규칙이 없는 것
비슷한 원리로 코드 계층에서 닫아야 할 문이 DISALLOW_FILE_EDIT 입니다. 방어는 서버와 애플리케이션 양쪽에 겹으로 있어야 한 겹이 빠져도 뚫리지 않습니다 — 저희 보안 취약점 해결 작업이 항상 두 계층을 함께 손보는 이유입니다.