En genererad abstrakt illustration på ett blekt gråblått fält, ritad som platt vektorgeometri. Till vänster representerar ett tätt rutnät av identiska små konturerade kvadrater en härdad kodbas; en ruta vid den bortre kanten är ritad i bärnstensgult och sänder ut en hårfin linje. Linjen korsar en svag vertikal gräns och delar sig sedan i två parallella hårfina linjer som löper genom ett lösare nätverk av tunna förbindelser och noder till höger, och konvergerar mot en enda liten solid bärnstensgul nod ovanför ett genomskinligt cyanfärgat fält. En kort svag streckad linje markerar där två förbindelser inte längre ligger i linje med sina grannar. Ingen text, inga siffror, människor, varumärkesmärken eller organisationslogotyper visas. OrcaRouter-logotypen är komponerad i det nedre högra hörnet.
AI Safety Incidents

wp2shell: Ett RCE i standard-WordPress, hittat på tio timmar för 25 dollar

Författare

Rowan Sterling

Publiceringsdatum

Senaste modellerna · 20Visa alla modeller →
Benchmarks: Artificial Analysis · uppdateras dagligen
Tillbaka till alla inlägg

Den 17 juli 2026 publicerade Searchlight Cyber wp2shell, en kedja för fjärrkodkörning före autentisering i WordPress-kärnan som inte kräver något plugin, något tema eller någon inloggning. En anonym begäran mot en standardinstallation räcker: "Attacken har inga förutsättningar och kan utnyttjas av en anonym användare i en standardinstallation av WordPress utan plugin", uppger företaget i sin säkerhetsbulletin. Kedjan kombinerar två buggar – CVE-2026-63030, ett routningsförvirringsfel i batch-slutpunkten i WordPress REST API som projektets säkerhetsbulletin betecknar som kritiskt, och CVE-2026-60137, en SQL-injektion i author__not_in-parametern i WP_Query som den betecknar som måttlig. WordPress släppte WordPress 7.0.2 samma dag, och projektets säkerhetsbulletiner anger WordPress 6.9.5, WordPress 6.8.6 och WordPress 7.1 beta2 som versioner med samma rättningar. Searchlight hänvisar till uppskattningar på fler än 500 miljoner WordPress-webbplatser. Forskaren bakom kedjan, Adam Kues, säger att den kom ur en GPT-5.6 Sol Ultra-körning byggd på en prompt som OpenAI hade publicerat för ett matematikproblem: upp till fyra agenter, minst sex timmar på jakten och ungefär fyra timmar mer på eskaleringen, cirka 25 dollar i modulanvändning. Posten är registrerad som en forskningsupptäckt – hög allvarlighetsgrad på arkivets egen skala, A-klassad tillförlitlighet, ingen dokumenterad verklig skada, daterad till en enda dag – och Orca AI Incident Archive har den med primärdokumenten länkade under sig.

Avslöjandet var samordnat. Searchlight höll inne med mekanismerna den 17 juli och gav försvararna helgen på sig att uppgradera; Kues publicerade den fullständiga tekniska redogörelsen den 20 juli. Vid det laget hade den kedjade exploateringen redan reproducerats oberoende: Searchlight säger att Calif och Hacktron återuppbyggde hela kedjan innan andra proof of concept dök upp på GitHub. WordPress egna två säkerhetsmeddelanden anger samma åtgärdade versioner, och CISA lade till båda CVE:erna i sin katalog över kända utnyttjade sårbarheter (Known Exploited Vulnerabilities) den 21 juli.

Två buggar, och arrayerna som hamnar i otakt

Ingångspunkten är en funktion snarare än ett misstag. WordPress 5.6 introducerade batchslutpunkten 2020 så att en klient kunde skicka flera virtuella REST-förfrågningar inom en och samma HTTP-förfrågan, till exempel för att ge en uppsättning inlägg nya titlar på en gång. Slutpunkten är nåbar oavsett om anroparen är autentiserad eller inte, och varje underförfrågan bär den autentisering som anroparen angav. En direkt förfrågan till en WordPress REST-route kör en pipeline i fyra steg: kontrollera obligatoriska och giltiga parametrar, sanera dem, kör behörighetscallbacken och kör sedan slutpunktens callback. Slutpunkter förlitar sig på den pipelinen för sina typantaganden – att ett inläggs-ID är ett heltal, att en titel är en sträng.

Batch-API:et delar upp pipeline i två steg, validerar varje underförfrågan i en loop och kör dem i en andra, och det håller två arrayer, $matches och $validation, vars poster ska stämma överens index för index. I class-wp-rest-server.php, som Kues beskriver det, läggs en underförfrågan som i sig är ett WordPress-fel till i $validation och möter sedan en continue, vilket hoppar över raden som lägger till i $matches. Från den punkten skiftas varje matchning bakåt en position. Körloopen parar underförfrågan vid ett index med valideringen som registrerats vid det indexet, men hanteraren matchades mot en annan rutt — så en parameter kontrolleras mot en slutpunkts regler och körs sedan av en annan slutpunkts kod.

Det är det som förvandlar en till synes vanlig listparameter till injektion. Posts-samlingens rutt mappar sitt offentliga author_exclude-argument till author__not_in. När värdet är en array kör WordPress absint över varje element och sorterar dem; när värdet är en skalär sammanfogas det oförändrat till SQL-fragmentet som blir NOT IN ($author__not_in). En sträng som 0) OR 1=1 -- hamnar därför i frågetexten. Vid ett normalt anrop skulle rutten avvisa den, eftersom author_exclude måste vara en array av heltal; det desynkroniserade batchanropet är det som släpper igenom en sträng.

Två hinder återstod, och båda löstes genom att nästla tricket. Batch-API:et avvisar GET-förfrågningar, och injektionen ligger på en GET-rutt; och valideringen av förfrågningsmetoden är i sig implementerad som parametervalidering, som samma desynkronisering kan kringgå. Kues offentliggjorda payload skickar en felformad yttre underförfrågan för att desynkronisera metodkontrollen, sedan en inre batch vars andra underförfrågan bär den skadliga author_exclude mot en hanterare som inte validerar den, sedan GET-förfrågan som kör den. En UNION-baserad injektion returnerar godtyckliga databasvärden inuti rader utformade som vanliga inlägg.

A self-built HTML card headed 'wp2shell: what is affected and what fixes it', laying out two columns of version ranges as a scannable table. The left column, labelled CVE-2026-63030, batch route confusion, critical, CVSS 9.8, lists affected WordPress 6.9.0 to 6.9.4 and 7.0.0 to 7.0.1, fixed in WordPress 6.9.5 and WordPress 7.0.2. The right column, labelled CVE-2026-60137, author__not_in SQL injection, moderate, CVSS 5.9, lists affected WordPress 6.8.0 to 6.8.5, 6.9.0 to 6.9.4 and 7.0.0 to 7.0.1, fixed in WordPress 6.8.6, WordPress 6.9.5 and WordPress 7.0.2. A footer strip notes that 7.1 beta2 also carries the fixes and that the full chain needs WordPress 6.9 or later. Small print at the bottom credits the version ranges to the two WordPress security advisories and the scores to the WPScan-assigned CVSS vectors.

Modellkörningen: en matematikprompt, riktad mot en kodbas

Kues skrev inte prompten från grunden. OpenAI hade publicerat prompten som det använde när det arbetade med Cycle Double Cover-förmodan, och Kues skrev att han hade läst att modellen nyligen hade löst den förmodan och att ingen i säkerhetscommunityn verkade prata om prompten. Hans resonemang var att om den var tillräckligt bra för svår matematik var den förmodligen tillräckligt bra för säkerhetsforskning. Han anpassade den och riktade den mot WordPress.

Uppsättningen var avsiktligt snäv. Han klonade den senaste stabila WordPress-utgåvan till en katalog som hette main/ och raderade dess .git-katalog, och instruerade modellen att inte använda ändringsloggar, git-historik eller det öppna internet för att diffa koden mot en patchad version – hans angivna skäl var att vid upptäckt av nya sårbarheter är det slöseri med tokens att konsultera historik eller webben. En tom third_party/-katalog erbjöds så att modellen kunde klona beroenden som PHP- eller MySQL-källkod om den bedömde att kedjan behövde buggar i biblioteken under WordPress. Uppgiften angavs som RCE före autentisering i en typisk produktionsdriftsättning med MySQL, med upp till fyra agenter och minst sex timmar. Kues skrev att han uttryckligen anger konfigurationskravet eftersom modellerna annars "fuskar" – genom att välja extremt osannolika konfigurationsalternativ eller genom att fabricera förutsättningar som en angripare aldrig skulle kunna uppnå.

Det som kom tillbaka, i den löpande utdata, var ett påstående om en SQL-injektion före autentisering. Kues tvivlade på det: WordPress är bland de mest granskade målen genom tiderna, skrev han, och hade inte haft någon betydelsefull sårbarhet före autentisering under det decenniet. Han installerade en standardinstans av WordPress på en fjärrserver och bad modellen att stjäla administratörens e-postadress; inom ett par minuter skrev den ut den adress han hade använt för att sätta upp instansen. Han frågade sedan om den skrivskyddade injektionen kunde eskaleras, och ungefär fyra timmar senare svarade modellen att den kunde det – till administratör, utan att knäcka något lösenord och utan offlineberäkning.

Hans egen kostnadsberäkning: 50 % av en veckovis användningskvot, som han uppskattade till ungefär $25 pro rata på en prenumeration på $200, för ett exploit som framställts på drygt tio timmar. Den mänskliga delen var inte gratis – Kues tillbringade följande dag med att reda ut vad modellen hade gjort och skrev att arbetet efter exploateringen tog honom mycket längre tid att förstå än det hade tagit att generera. Hans slutsats är ovanligt rak och snävt avgränsad: "Jag gör inga allmänna påståenden, men jag kan säga med fullständig visshet att ingen säkerhetsforskare kunde ha hittat och fullbordat den här exploitkedjan på 10 timmar utan AI."

Från ett skrivskyddat SELECT till administratör

Eskaleringen är den del av redogörelsen som är viktigast, eftersom det är där en databasläsning blev kontroll över servern. Kues redogörelse beskriver den som en sekvens av sex steg, där varje steg använder en vanlig WordPress-funktion mot en annan.

Först, förgifta cacheminnet för inlägg. WordPress har en cache per förfrågan för WP_Post-objekt så att samma inlägg som refereras flera gånger i en förfrågan bara kostar en databasrunda. SQL-injektionen kan fabricera inlägg, så angriparen styr exakt vad som cachas – men de fabricerade inläggen är inte rader i databasen, och cachen dör med förfrågan.

För det andra: förvandla fabricerade inlägg till riktiga rader. WordPress funktion för inbäddning cachar upplösta inbäddningar i databasen som inlägg av typen oembed_cache. Att bädda in ett lokalt inlägg med relativ sökväg, som i [embed]/?p=S[/embed], gör att WordPress hoppar över HTTP-hämtningen och aldrig kontrollerar att det refererade inlägget finns, så en rad skapas. Tre sådana inbäddningar med olika token i frågesträngen ger tre olika cache-hashar, vilket är hur angriparen får flera rader att arbeta med.

För det tredje, kringgå det enda fältet som förblir fast. När minnesversionen och databasversionen av ett inlägg inte stämmer överens, avstämmer WordPress dem med ett anrop som uttryckligen anger post_content från embed-utdata. Allt i inlägget är kontrollerat av angriparen utom dess innehåll, som är exakt det fält som en customize_changeset använder för att lagra JSON:en för väntande tema- och webbplatsändringar.

För det fjärde: cykelgadgeten. Inlägg har föräldrar, och WordPress tillåter inte cykler: wp_insert_post_parent-filtret går uppåt i trädet och anropar, när det hittar en loop, en uppdatering som sätter post_parent till noll. Det anropet skriver inte över post_content, så den fabricerade versionen i minnet överlever avstämningen – en ändringsuppsättning med sin JSON intakt, som har en verklig rad bakom sig.

För det femte: låna administratörens behörighet. En ändringsuppsättning vars status anger att den är schemalagd för framtiden, men vars datum ligger i det förflutna, tillämpas omedelbart. Varje post i dess JSON anger en user_id, och posten i Kues kedja anger user_id 1, administratören, så WordPress antar tillfälligt den identiteten för att tillämpa ändringen. Den första ändringen är en till synes harmlös uppdatering av nav_menus_created_posts.

För det sjätte: återspela begäran som den identiteten. Att publicera ett inlägg utlöser en dynamiskt namngiven åtgärd, {status}_{post_type}. Eftersom inlägget är konstruerat kan status och typ vara vad som helst – inklusive parse och request, vilket ger parse_request-hooken och startar om begärandepipelinen från början medan den lånade administratörsidentiteten fortfarande gäller. Den ursprungliga batchbegäran innehöll en underbegäran som skapade en ny administratör; den misslyckades vid första passeringen som gäst och lyckas vid återspelandet. Därifrån loggar angriparen in som det nya kontot och laddar upp ett bakdörrsplugin från en ZIP-fil, vilket är kodkörning.

A self-built HTML card titled 'Six moves from a SELECT to a shell', drawn as six numbered panels in two columns of three. Panel 1, fabricate posts: a UNION injection over the posts collection returns attacker-shaped rows, which WordPress stores in its per-request WP_Post cache. Panel 2, seed embed rows: embedding a local post by relative path writes stored oembed_cache rows, and WordPress never checks that the referenced post exists. Panel 3, content stays fixed: reconciling memory against the database overwrites post_content, the one field a changeset needs for its JSON. Panel 4, break the cycle check: a fabricated parent loop triggers WordPress's own cycle fix, an update that resets post_parent without touching post_content. Panel 5, borrow admin authority: a past-dated customize_changeset whose entries carry user_id 1 is applied as the administrator. Panel 6, replay as admin: a fabricated post with status parse and type request fires the parse_request hook, rerunning the batch so the admin-creation subrequest succeeds. A dark footer bar states that the new administrator then logs in and uploads a backdoor plugin from a ZIP file, which is code execution. No photographs, logos or personal names appear.

Tekniken har ett villkor kopplat till sig. Hacker News rapporterade, med hänvisning till Cloudflare, att CVE-2026-63030 ger fjärrkodkörning endast när en persistent objekttcache inte används; själva injektionen finns från och med WordPress 6.8, medan den fullständiga kedjan kräver 6.9 eller senare. En standardinstallation har ingen persistent objekttcache, vilket är varför Searchlights formulering "inga förutsättningar" och Cloudflares förbehåll beskriver samma standardfall från olika håll.

Vad primärdokumenten fastställer

WordPress egna säkerhetsmeddelanden är den starkaste bekräftelsen, eftersom det är leverantören som erkänner mekaniken och levererar rättningen. GHSA-ff9f-jf42-662q, klassad som kritisk, beskriver en svaghet med förväxling av batchrutter i REST API i WordPress 6.9 och senare som kombineras med injektionen för att uppnå kodkörning, och tillskriver Adam Kues på Assetnote och Searchlight Cyber. GHSA-fpp7-x2x2-2mjf, klassad som måttlig, beskriver author__not_in-injektionen från WordPress 6.8 och senare, och anger att båda problemen är åtgärdade i WordPress 7.0.2, WordPress 6.9.5, WordPress 6.8.6 och WordPress 7.1 beta2. NVD-posterna för de två CVE:erna, poängsatta av WPScan-CNA:n i stället för av NIST, har 9,8 för CVE-2026-63030 med vektorn AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H, och 5,9 för CVE-2026-60137 med AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N – en nätverksnåbar bugg som inte kräver behörigheter i det första fallet, och en som kräver hög attackkomplexitet och endast ger konfidentialitetspåverkan i det andra. Arkivets eget allvarlighetsfält för denna post anger hög medan WordPress märker batchfelet som kritiskt; de två är separata skalor som tillämpas på en hel kedja och på en enskild komponent, inte en oenighet om själva buggarna.

CISA:s katalogposter, såsom de återspeglas i NVD:s berikningsfält, lades till den 21 juli 2026 med åtgärdsfrister den 24 juli för CVE-2026-63030 och den 4 augusti för CVE-2026-60137. CISA benämner den första "WordPress Core Interpretation Conflict Vulnerability" och den andra "WordPress Core SQL Injection Vulnerability". Searchlight publicerade också en offentlig kontrollfunktion på wp2shell.com så att operatörer kunde testa en instans utan att vänta på en skannersignatur.

Den oberoende reproduktionen dokumenteras av {{1}}Searchlight{{/1}} själva och är därför ett påstående om tredje parter snarare än en tredjepartsredogörelse: enligt rapporten från 20 juli återuppbyggde {{2}}Calif och Hacktron{{/2}} hela kedjan innan andra konceptbevis dök upp på GitHub. Det som går att verifiera oberoende är effekten – konceptbevis, exploateringstrafik och leverantörstelemetri inom loppet av dagar, som beskrivs nedan.

A self-built HTML card titled 'Four days from advisory to catalog', drawn as a vertical timeline of five dated rows against a blue rule, the last row in amber. 17 July 2026, disclosure: Searchlight Cyber publishes the wp2shell advisory with the mechanics withheld and WordPress releases 7.0.2, with 6.9.5, 6.8.6 and 7.1 beta2 listed as carrying the same fixes. 18 July 2026, first exploitation: watchTowr reports that by the early hours of Saturday morning UTC successful exploitation was already well underway, initially to exfiltrate hashed credentials. 20 July 2026, full account: Kues publishes the GPT-5.6 Sol Ultra write-up while Wiz publishes an in-the-wild report, with 60 percent of WordPress-using organisations holding a vulnerable instance and 25 percent exposed to the internet, falling to 50 and 10 percent within 24 hours. 21 July 2026, CISA KEV: both CVEs enter the Known Exploited Vulnerabilities catalog. 24 July and 4 August, remediation due: CISA's two deadlines. A source line at the bottom names the WordPress advisories, The Hacker News for watchTowr, Wiz, and the cisaExploitAdd and cisaActionDue fields in NVD records. No photographs, logos or personal names appear.

Vad som påstås men inte fastställs

Två erkännanden för en och samma injektion går inte att förena i det offentliga protokollet. WordPress säkerhetsmeddelande för CVE-2026-60137 anger att sårbarheten "upptäcktes och ansvarsfullt offentliggjordes av teamet TF1T, dtro och haongo". Searchlights redogörelse framställer samma injektion före autentisering som den som dess modellkörning lyfte fram, och nämner inte det teamet; WordPress säkerhetsmeddelande tillerkänner Kues endast för batch-ruttförvirringen och nämner ingen modell. Inget av dokumenten förklarar överlappningen, och inget som den här artikeln har hittat löser det – möjligheten att de två var oberoende upptäckter av samma bugg utesluts inte, och möjligheten att en rapport är en senare återupptäckt är inte heller fastställd. Protokollet avgör det inte, och det gör inte heller den här artikeln.

Siffran i rubriken i Searchlights inlägg den 20 juli stöds inte av själva brödtexten. Den lyder: ”Exploitmäklare betalar 500 000 dollar för en WordPress RCE. Jag hittade en med GPT5.6 Sol Ultra och 25 dollar”. Brödtexten dokumenterar de 25 dollarna och de tio timmarna i konkreta ordalag; den innehåller inga mäklarnamn, inga erbjudanden, ingen korrespondens och ingen källa till siffran 500 000 dollar. Ingen oberoende rapport som påträffats för den här artikeln styrker att ett pris betalats eller erbjudits för wp2shell. Betrakta 500 000 dollar som rubrikens inramning, inte som ett etablerat marknadspris.

Arkivpostens egen omfattning är snävare än historien kring den. Den registrerar en forskningsupptäckt på dagen för offentliggörandet, flaggar ingen verklig skada och är daterad till en enda dag, den 17 juli 2026. Det är inte ett påstående att ingenting hände efteråt: exploateringstrafik rapporterades inom några timmar efter rådgivningen, och CISA katalogiserade båda CVE:erna fyra dagar senare. Flaggan täcker det som posten beskriver – upptäckten och det koordinerade offentliggörandet – och den efterföljande exploateringen dokumenteras av andra parter utifrån deras egna bevis, nedan.

Utnyttjande efter rådgivningen

Jake Knott, chefsäkerhetsforskare på watchTowr, sade till The Hacker News att "redan under de tidiga timmarna på lördagsmorgonen (UTC) var framgångsrik exploatering i full gång; initialt användes offentlig exploitkod för att exfiltrera hashade autentiseringsuppgifter, och fjärrkodskörning följde när ytterligare detaljer hade offentliggjorts." Samma rapport citerar KEVIntel-telemetri som kopplar 13 unika IP-adresser, från Schweiz, Tyskland, Storbritannien, Indonesien, Litauen, Nederländerna och Singapore, till exploatering av CVE-2026-63030, och citerar KEVIntel-grundaren Ryan Dewhurst som säger att förfrågningarna matchade offentligt tillgängliga proof of concept och att blinda, UNION-baserade och boolean-baserade payloads alla användes.

Wiz-forskarna Shahar Dorfman och Gili Tikochinski kvantifierade omfattningen i en publikation den 20 juli: 60 % av organisationerna som använde WordPress hade minst en sårbar instans när CVE:erna publicerades, och 25 % exponerade en sårbar server mot internet; inom 24 timmar, när patchningen började, föll siffrorna till 50 % och 10 %. De registrerade skadliga pluginuppladdningar via admininstallatören, användarenumrering mot användarslutpunkten, försök till lokal filinkludering mot wp-config, och åtkomst till adminpanelen som returnerade HTTP 200 – signaturen för en lyckad inloggning snarare än en sond. Malwaren de hittade omfattade allt från en minimal enradig PHP-backdoor till en 150 KB webshell förklädd till ett legitimt WordPress-säkerhetsplugin som hette CMSmap, med moduler för filhantering, databasåtkomst, portskanning och privilegieeskalering.

Wiz noterade också en begränsning för vad som kan dras för slutsatser. Högvolymskanning utan efterexploatering var vanlig, i linje med opportunistisk masskanning och med legitim säkerhetsskanning, och företaget uppgav att det inte hade identifierat lateral förflyttning eller dataexfiltrering. Det är ett uttalande om vad en leverantörs telemetri visade, inte ett konstaterande att ingenting togs.

Vad förändrades efteråt, och vad förblev öppet

För operatörer var åtgärdsvägen kort. Att uppdatera till WordPress 7.0.2, WordPress 6.9.5 eller WordPress 6.8.6 är lösningen. Searchlights nödalternativ, för webbplatser som inte kunde uppdatera omedelbart, var att blockera anonym åtkomst till batch-API:et – antingen genom att installera ett plugin som blockerar anonym åtkomst till REST-API:et helt och hållet, eller genom att blockera /wp-json/batch/v1 och ?rest_route=/batch/v1 i en brandvägg för webbapplikationer. Företaget varnade för att båda kan påverka legitim användning av webbplatsen och bör betraktas som tillfälliga åtgärder tills uppdateringen är på plats. Den offentliga kontrollfunktionen på wp2shell.com testar en instans direkt. CISA:s katalogposter lade till en tidsfrist för efterlevnad: åtgärd senast 24 juli för CVE-2026-63030 och senast 4 augusti för CVE-2026-60137.

För forskningsfrågan är den del som inte gick att avgöra vad modellen faktiskt bidrog med i förhållande till sin operatör. Kues är precis om fördelningen: modellen producerade kedjan på ungefär tio timmar, och det tog honom längre tid att förstå den än att generera den. Han avstår från generella påståenden och säger bara att tio-timmarsresultatet inte var uppnåeligt för en människa utan hjälp. Prompten själv är inte hemlig — den härstammar från en som OpenAI publicerade, och Searchlight återgav dess struktur i skrivningen, inklusive instruktionen att ignorera versionshistorik och kravet att exploiten fungerar i en typisk produktionskonfiguration. Om det receptet låter sig överföras till andra kodbaser är exakt den fråga Kues säger att han inte besvarar, och ingen andra körning har publicerats.

Det som underlaget inte fastställer är därför snävt men betydelsefullt: vilken av de två erkända parterna som först hittade injektionen, om någon broker någonsin betalade beloppet i rubriken, och vad, om något, de webbshells som Wiz observerade faktiskt tog från de webbplatser de landade på. När det gäller den sista punkten är det enda offentliga uttalandet Wizs, att det inte har identifierat någon lateral rörelse eller dataexfiltrering – en avsaknad av bevis från en synvinkel, framförd som just det.