{"id":174,"date":"2026-01-19T00:00:00","date_gmt":"2026-01-18T23:00:00","guid":{"rendered":"https:\/\/helloblog.io\/fr\/acf-extended-faille-critique-escalade-privileges-acces-admin\/"},"modified":"2026-01-19T00:00:00","modified_gmt":"2026-01-18T23:00:00","slug":"acf-extended-faille-critique-escalade-privileges-acces-admin","status":"publish","type":"post","link":"https:\/\/helloblog.io\/fr\/acf-extended-faille-critique-escalade-privileges-acces-admin\/","title":{"rendered":"ACF Extended : une faille critique d\u2019escalade de privil\u00e8ges peut donner un acc\u00e8s admin sans authentification"},"content":{"rendered":"\n<p>Une alerte s\u00e9curit\u00e9 publi\u00e9e par Wordfence vise <strong>Advanced Custom Fields: Extended (ACF Extended)<\/strong>, un addon populaire d\u2019Advanced Custom Fields. Le point cl\u00e9 : une <strong>escalade de privil\u00e8ges non authentifi\u00e9e<\/strong> permettrait, dans certaines configurations, de se cr\u00e9er un utilisateur avec le r\u00f4le <code>administrator<\/code> et donc de prendre le contr\u00f4le du site.<\/p>\n\n\n\n<p>Le plugin compte <strong>100 000+ installations actives<\/strong> sur WordPress.org, mais l\u2019exploitation n\u2019est pas \u00ab automatique \u00bb sur tous les sites : elle d\u00e9pend d\u2019un cas d\u2019usage pr\u00e9cis autour des formulaires et d\u2019un champ de r\u00f4le mapp\u00e9.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">R\u00e9sum\u00e9 de la vuln\u00e9rabilit\u00e9 (CVE-2025-14533)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Produit : <a href=\"https:\/\/wordpress.org\/plugins\/acf-extended\/\">Advanced Custom Fields: Extended<\/a><\/li>\n\n\n<li>Gravit\u00e9 : <strong>Critique (CVSS 9.8)<\/strong><\/li>\n\n\n<li>CVE : <strong>CVE-2025-14533<\/strong><\/li>\n\n\n<li>Versions affect\u00e9es : <strong><= 0.9.2.1<\/strong><\/li>\n\n\n<li>Version corrig\u00e9e : <strong>0.9.2.2<\/strong><\/li>\n\n\n<li>Type : <strong>Privilege escalation<\/strong> (\u00e9l\u00e9vation de privil\u00e8ges) <strong>sans authentification<\/strong><\/li>\n\n<\/ul>\n\n\n\n<p>D\u2019apr\u00e8s l\u2019analyse de Wordfence, le probl\u00e8me vient d\u2019une action de formulaire c\u00f4t\u00e9 ACF Extended qui cr\u00e9e (ou met \u00e0 jour) un utilisateur \u00e0 partir de champs soumis. Si un champ <code>role<\/code> est pr\u00e9sent et mapp\u00e9, un attaquant peut fournir la valeur <code>administrator<\/code> lors de la soumission et obtenir un compte admin.<\/p>\n\n\n\n<div class=\"wp-block-group callout callout-warning is-style-warning is-layout-flow wp-block-group-is-layout-flow\" style=\"border-width:1px;border-radius:8px;padding-top:1rem;padding-right:1.5rem;padding-bottom:1rem;padding-left:1.5rem\">\n\n<h4 class=\"wp-block-heading callout-title\">Point important : tous les sites avec ACF Extended ne sont pas expos\u00e9s<\/h4>\n\n\n<p>Le sc\u00e9nario critique concerne surtout les sites ayant mis en place un formulaire ACF Extended avec une action \u00ab Create user \u00bb \/ \u00ab Update user \u00bb <strong>et<\/strong> un champ de r\u00f4le (<code>role<\/code>) effectivement mapp\u00e9 sur ce formulaire. Sans ce mapping, l\u2019attaque d\u00e9crite ne s\u2019applique pas telle quelle.<\/p>\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Pourquoi c\u2019est dangereux : \u00ab admin = contr\u00f4le total \u00bb<\/h2>\n\n\n\n<p>Une fois un compte administrateur obtenu, l\u2019attaquant se retrouve avec un \u00e9ventail d\u2019actions classiques mais catastrophiques : installation de plugins\/th\u00e8mes (y compris des archives ZIP malveillantes), modification de contenu pour injecter du spam ou des redirections, ajout de backdoors, cr\u00e9ation d\u2019autres comptes, etc. Bref, c\u2019est une compromission compl\u00e8te du site dans le mod\u00e8le WordPress.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ce qui s\u2019est pass\u00e9 techniquement (sans entrer dans l\u2019exploitation)<\/h2>\n\n\n\n<p>ACF Extended fournit notamment un <strong>form manager<\/strong> : tu d\u00e9finis un groupe de champs (email, login, mot de passe\u2026 et \u00e9ventuellement r\u00f4le), puis tu relies ces champs \u00e0 une action de formulaire du type \u00ab cr\u00e9er un utilisateur \u00bb. L\u2019id\u00e9e est pratique pour faire un formulaire d\u2019inscription front sans recoder un flux complet.<\/p>\n\n\n\n<p>Wordfence indique que la classe <code>acfe_module_form_action_user<\/code> utilise une fonction <code>insert_user()<\/code> pour construire les arguments d\u2019un utilisateur, puis appelle <code>wp_insert_user($args)<\/code>.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#e1e4e8;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/\/ Construction des args \u00e0 partir des champs mapp\u00e9s\n$args = apply_filters('acfe\/form\/submit_user_args', $args, $form, $action);\n\n\/\/ Insertion de l'utilisateur\n$user_id = wp_insert_user($args);\n\n\/\/ Probl\u00e8me d\u00e9crit : si un champ 'role' est mapp\u00e9,\n\/\/ une valeur non restreinte (ex: 'administrator') peut \u00eatre accept\u00e9e.\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#6A737D\">\/\/ Construction des args \u00e0 partir des champs mapp\u00e9s<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">$args <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#B392F0\"> apply_filters<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">'acfe\/form\/submit_user_args'<\/span><span style=\"color:#E1E4E8\">, $args, $form, $action);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#6A737D\">\/\/ Insertion de l'utilisateur<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">$user_id <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#B392F0\"> wp_insert_user<\/span><span style=\"color:#E1E4E8\">($args);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#6A737D\">\/\/ Probl\u00e8me d\u00e9crit : si un champ 'role' est mapp\u00e9,<\/span><\/span>\n<span class=\"line\"><span style=\"color:#6A737D\">\/\/ une valeur non restreinte (ex: 'administrator') peut \u00eatre accept\u00e9e.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Le point subtil mentionn\u00e9 : ACF Extended propose une option de configuration sur le champ de r\u00f4le (par exemple \u00ab Allow User Role \u00bb), ce qui laisse penser qu\u2019on peut limiter les r\u00f4les possibles. Or, sur les versions vuln\u00e9rables, la restriction ne serait pas appliqu\u00e9e correctement au niveau de l\u2019action de formulaire, ce qui laisse la porte ouverte \u00e0 un r\u00f4le arbitraire.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1600\" src=\"https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-1-scaled-1.png\" alt=\"\u00c9cran de configuration d\u2019un groupe de champs ACF Extended incluant un champ de r\u00f4le avec une option de restriction\" class=\"wp-image-172\" srcset=\"https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-1-scaled-1.png 2560w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-1-scaled-1-300x188.png 300w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-1-scaled-1-1024x640.png 1024w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-1-scaled-1-768x480.png 768w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-1-scaled-1-1536x960.png 1536w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-1-scaled-1-2048x1280.png 2048w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-1-scaled-1-400x250.png 400w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><figcaption class=\"wp-element-caption\">Exemple de configuration d\u2019un champ \u00ab role \u00bb dans un groupe de champs ACF Extended. \u2014 <em>Forr\u00e1s: Wordfence.com<\/em><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1599\" src=\"https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-2-scaled-1.png\" alt=\"Configuration d\u2019un formulaire ACF Extended avec une action de cr\u00e9ation d\u2019utilisateur et mapping des champs\" class=\"wp-image-173\" srcset=\"https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-2-scaled-1.png 2560w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-2-scaled-1-300x187.png 300w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-2-scaled-1-1024x640.png 1024w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-2-scaled-1-768x480.png 768w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-2-scaled-1-1536x959.png 1536w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-2-scaled-1-2048x1279.png 2048w, https:\/\/helloblog.io\/app\/uploads\/sites\/4\/2026\/01\/acfe-2-scaled-1-400x250.png 400w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><figcaption class=\"wp-element-caption\">Mise en place d\u2019un formulaire \u00ab Create user \u00bb avec mapping des champs vers l\u2019action. \u2014 <em>Forr\u00e1s: Wordfence.com<\/em><\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Qui doit r\u00e9agir en priorit\u00e9 ?<\/h2>\n\n\n\n<p>Tu es particuli\u00e8rement concern\u00e9 si tu coches au moins un de ces points :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>ACF Extended est install\u00e9 <strong>et<\/strong> sa version est <strong><= 0.9.2.1<\/strong>.<\/li>\n\n\n<li>Tu utilises les formulaires ACF Extended avec une action <strong>Create user<\/strong> ou <strong>Update user<\/strong>.<\/li>\n\n\n<li>Un champ de r\u00f4le (<code>role<\/code>) est pr\u00e9sent dans le groupe de champs et <strong>mapp\u00e9<\/strong> sur l\u2019action du formulaire (par exemple via une s\u00e9lection de r\u00f4le c\u00f4t\u00e9 front).<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Mesures imm\u00e9diates : patcher et auditer<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li>Mettre \u00e0 jour <strong>ACF Extended en 0.9.2.2<\/strong> (version corrig\u00e9e mentionn\u00e9e dans l\u2019avis).<\/li>\n\n\n<li>Identifier les formulaires ACF Extended en production qui cr\u00e9ent\/mettent \u00e0 jour des utilisateurs, et v\u00e9rifier si un champ <code>role<\/code> est mapp\u00e9.<\/li>\n\n\n<li>Si tu as besoin d\u2019un choix de r\u00f4le c\u00f4t\u00e9 front (cas rare), <strong>\u00e9viter de l\u2019exposer directement<\/strong> : privil\u00e9gier un r\u00f4le fixe c\u00f4t\u00e9 serveur ou une whitelisting stricte.<\/li>\n\n\n<li>Contr\u00f4ler la liste des utilisateurs WordPress : rep\u00e9rer des comptes admin r\u00e9cents et inattendus, et v\u00e9rifier l\u2019historique des actions si tu as des logs.<\/li>\n\n\n<li>Si un doute existe, r\u00e9voquer les comptes suspects, r\u00e9g\u00e9n\u00e9rer les secrets (mots de passe, cl\u00e9s), et inspecter plugins\/th\u00e8mes upload\u00e9s r\u00e9cemment.<\/li>\n\n<\/ol>\n\n\n\n<div class=\"wp-block-group callout callout-info is-style-info is-layout-flow wp-block-group-is-layout-flow\" style=\"border-width:1px;border-radius:8px;padding-top:1rem;padding-right:1.5rem;padding-bottom:1rem;padding-left:1.5rem\">\n\n<h4 class=\"wp-block-heading callout-title\">Protection c\u00f4t\u00e9 WAF (Wordfence)<\/h4>\n\n\n<p>Selon Wordfence, une r\u00e8gle de pare-feu a \u00e9t\u00e9 d\u00e9ploy\u00e9e le <strong>11 d\u00e9cembre 2025<\/strong> pour Wordfence Premium\/Care\/Response, puis le <strong>10 janvier 2026<\/strong> pour Wordfence Free. \u00c7a r\u00e9duit le risque, mais \u00e7a ne remplace pas la mise \u00e0 jour du plugin : le correctif applicatif reste la r\u00e9f\u00e9rence.<\/p>\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Chronologie de divulgation (selon Wordfence)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>10 d\u00e9cembre 2025 : soumission via le Bug Bounty Program Wordfence.<\/li>\n\n\n<li>11 d\u00e9cembre 2025 : validation + preuve de concept confirm\u00e9e ; r\u00e8gle firewall distribu\u00e9e aux offres Premium\/Care\/Response ; divulgation au vendor via le portail de gestion des vuln\u00e9rabilit\u00e9s.<\/li>\n\n\n<li>14 d\u00e9cembre 2025 : correctif publi\u00e9 (ACF Extended <strong>0.9.2.2<\/strong>).<\/li>\n\n\n<li>10 janvier 2026 : r\u00e8gle firewall distribu\u00e9e aux utilisateurs Wordfence Free.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\u00c0 retenir<\/h2>\n\n\n\n<p>Cette faille rappelle un classique : d\u00e8s qu\u2019un formulaire front manipule des objets sensibles (comptes utilisateurs, r\u00f4les\/capabilities), il faut une validation serveur stricte, ind\u00e9pendante des options d\u2019UI. Si tu utilises ACF Extended et que tu as construit un flux d\u2019inscription\/\u00e9dition d\u2019utilisateur via ses actions de formulaire, <strong>mets \u00e0 jour en 0.9.2.2<\/strong> et v\u00e9rifie imm\u00e9diatement le mapping du champ <code>role<\/code>.<\/p>\n\n\n<div class=\"references-section\">\n                <h2>R\u00e9f\u00e9rences \/ Sources<\/h2>\n                <ul class=\"references-list\"><li><a href=\"https:\/\/www.wordfence.com\/blog\/2026\/01\/100000-wordpress-sites-affected-by-privilege-escalation-vulnerability-in-advanced-custom-fields-extended-wordpress-plugin\/\" target=\"_blank\" rel=\"noopener noreferrer\">100,000 WordPress Sites Affected by Privilege Escalation Vulnerability in Advanced Custom Fields: Extended WordPress Plugin<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/wordpress-plugins\/acf-extended\/advanced-custom-fields-extended-0921-unauthenticated-privilege-escalation-via-insert-user-form-action\" target=\"_blank\" rel=\"noopener noreferrer\">Advanced Custom Fields: Extended &lt;= 0.9.2.1 &#8212; Unauthenticated Privilege Escalation via Insert User Form Action<\/a><\/li><li><a href=\"https:\/\/wordpress.org\/plugins\/acf-extended\/\" target=\"_blank\" rel=\"noopener noreferrer\">Advanced Custom Fields: Extended<\/a><\/li><li><a href=\"https:\/\/www.cve.org\/CVERecord?id=CVE-2025-14533\" target=\"_blank\" rel=\"noopener noreferrer\">CVE-2025-14533<\/a><\/li><\/ul>\n            <\/div>","protected":false},"excerpt":{"rendered":"<p>Si tu utilises ACF Extended pour g\u00e9rer des formulaires c\u00f4t\u00e9 front, un mauvais mapping d\u2019un champ \u00ab role \u00bb peut suffire \u00e0 offrir un compte administrateur \u00e0 un attaquant. Voici ce qu\u2019il faut comprendre, qui est r\u00e9ellement expos\u00e9, et quoi v\u00e9rifier tout de suite.<\/p>\n","protected":false},"author":14,"featured_media":171,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[74,11,13,15,10],"class_list":["post-174","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-securite","tag-acf-extended","tag-securite","tag-vulnerabilite","tag-wordfence","tag-wordpress"],"_links":{"self":[{"href":"https:\/\/helloblog.io\/fr\/wp-json\/wp\/v2\/posts\/174","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helloblog.io\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/helloblog.io\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/helloblog.io\/fr\/wp-json\/wp\/v2\/users\/14"}],"replies":[{"embeddable":true,"href":"https:\/\/helloblog.io\/fr\/wp-json\/wp\/v2\/comments?post=174"}],"version-history":[{"count":0,"href":"https:\/\/helloblog.io\/fr\/wp-json\/wp\/v2\/posts\/174\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/helloblog.io\/fr\/wp-json\/wp\/v2\/media\/171"}],"wp:attachment":[{"href":"https:\/\/helloblog.io\/fr\/wp-json\/wp\/v2\/media?parent=174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/helloblog.io\/fr\/wp-json\/wp\/v2\/categories?post=174"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/helloblog.io\/fr\/wp-json\/wp\/v2\/tags?post=174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}