{"id":190,"date":"2026-02-11T16:39:46","date_gmt":"2026-02-11T15:39:46","guid":{"rendered":"https:\/\/helloblog.io\/sk\/kriticka-chyba-wpvivid-backup-neautentifikovany-upload-suborov-cve-2026-1357\/"},"modified":"2026-02-11T16:39:46","modified_gmt":"2026-02-11T15:39:46","slug":"kriticka-chyba-wpvivid-backup-neautentifikovany-upload-suborov-cve-2026-1357","status":"publish","type":"post","link":"https:\/\/helloblog.io\/sk\/kriticka-chyba-wpvivid-backup-neautentifikovany-upload-suborov-cve-2026-1357\/","title":{"rendered":"Kritick\u00e1 chyba vo WPvivid Backup: neautentifikovan\u00fd upload s\u00faborov a potenci\u00e1lne RCE (CVE-2026-1357)"},"content":{"rendered":"\n<p>WordPress ekosyst\u00e9m m\u00e1 jednu nepr\u00edjemn\u00fa vlastnos\u0165: aj u\u017eito\u010dn\u00e9 pluginy, ktor\u00e9 rie\u0161ia \u201e\u0165a\u017ek\u00e9\u201c veci ako migr\u00e1cie a z\u00e1lohy, musia pracova\u0165 so s\u00fabormi a (niekedy) aj s kryptografiou. A to je kombin\u00e1cia, pri ktorej aj mal\u00e1 chyba v o\u0161etren\u00ed okrajov\u00fdch stavov m\u00f4\u017ee skon\u010di\u0165 ve\u013emi zle.<\/p>\n\n\n\n<p>Wordfence zverejnil detailn\u00fd rozbor kritickej zranite\u013enosti v plugine <strong>WPvivid Backup &#038; Migration<\/strong> (na WordPress.org veden\u00fd ako <em>Migration, Backup, Staging<\/em>). Ide o <strong>neautentifikovan\u00fd arbitrary file upload<\/strong>, ktor\u00fd sa d\u00e1 zneu\u017ei\u0165 na <strong>Remote Code Execution (RCE)<\/strong> \u2013 typicky cez nahratie \u0161kodliv\u00e9ho PHP s\u00faboru do verejne pr\u00edstupn\u00e9ho adres\u00e1ra a jeho n\u00e1sledn\u00e9 spustenie. Zranite\u013enos\u0165 m\u00e1 pridelen\u00e9 <strong>CVE-2026-1357<\/strong> a CVSS <strong>9.8 (Critical)<\/strong>.<\/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\">D\u00f4le\u017eit\u00fd kontext: net\u00fdka sa \u00faplne ka\u017ed\u00e9ho<\/h4>\n\n\n<p>Pod\u013ea zverejnen\u00fdch inform\u00e1ci\u00ed je probl\u00e9m <strong>kritick\u00fd najm\u00e4 pre weby, ktor\u00e9 maj\u00fa v nastaveniach WPvivid vygenerovan\u00fd k\u013e\u00fa\u010d<\/strong> pre funkciu prijatia z\u00e1lohy z in\u00e9ho webu (\u201esend backup to site\u201c). T\u00e1to funkcia je <strong>defaultne vypnut\u00e1<\/strong> a expir\u00e1ciu k\u013e\u00fa\u010da je mo\u017en\u00e9 nastavi\u0165 maxim\u00e1lne na <strong>24 hod\u00edn<\/strong>.<\/p>\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Koho a \u010do to presne ovplyv\u0148uje (verzie, sk\u00f3re, patch)<\/h2>\n\n\n\n<p>Zranite\u013enos\u0165 sa t\u00fdka pluginu na slugu <strong><a href=\"https:\/\/wordpress.org\/plugins\/wpvivid-backuprestore\/\">wpvivid-backuprestore<\/a><\/strong> a pod\u013ea Wordfence Intelligence plat\u00ed:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>N\u00e1zov v datab\u00e1ze: <strong>Migration, Backup, Staging &#8211; WPvivid Backup &#038; Migration<\/strong><\/li>\n\n\n<li>Typ: <strong>Unauthenticated Arbitrary File Upload<\/strong><\/li>\n\n\n<li>CVE: <strong><a href=\"https:\/\/www.cve.org\/CVERecord?id=CVE-2026-1357\">CVE-2026-1357<\/a><\/strong><\/li>\n\n\n<li>CVSS: <strong>9.8 (Critical)<\/strong><\/li>\n\n\n<li>Zasiahnut\u00e9 verzie: <strong><= 0.9.123<\/strong><\/li>\n\n\n<li>Opraven\u00e1 verzia: <strong>0.9.124<\/strong><\/li>\n\n<\/ul>\n\n\n\n<p>Wordfence z\u00e1rove\u0148 uv\u00e1dza, \u017ee v\u00fdskumn\u00edk <strong>Lucas Montes (NiRoX)<\/strong> nahl\u00e1sil probl\u00e9m cez Wordfence <strong><a href=\"https:\/\/www.wordfence.com\/threat-intel\/bug-bounty-program\/\">Bug Bounty Program<\/a><\/strong>, a to iba p\u00e4\u0165 dn\u00ed po tom, \u010do sa zranite\u013enos\u0165 v plugine objavila. Za n\u00e1lez bola vyplaten\u00e1 odmena <strong>2 145 USD<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Pre\u010do je arbitrary file upload v praxi tak\u00fd nebezpe\u010dn\u00fd<\/h2>\n\n\n\n<p>Arbitrary file upload je jedna z t\u00fdch kateg\u00f3ri\u00ed ch\u00fdb, ktor\u00e9 sa \u010dasto kon\u010dia \u00fapln\u00fdm kompromitovan\u00edm webu. Ak \u00fato\u010dn\u00edk dok\u00e1\u017ee bez prihl\u00e1senia nahra\u0165 vlastn\u00fd s\u00fabor na server, typick\u00fd \u010fal\u0161\u00ed krok je nahratie <strong>webshellu<\/strong> (jednoduch\u00fd skript na sp\u00fa\u0161\u0165anie pr\u00edkazov alebo \u010fal\u0161ieho k\u00f3du) a n\u00e1sledne:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>z\u00edskanie perzistencie (\u010fal\u0161ie backdoory)<\/li>\n\n\n<li>kr\u00e1de\u017e datab\u00e1zov\u00fdch pr\u00edstupov z <code>wp-config.php<\/code><\/li>\n\n\n<li>vkladanie \u0161kodliv\u00e9ho JavaScriptu do \u0161abl\u00f3n alebo pluginov<\/li>\n\n\n<li>vytv\u00e1ranie nov\u00fdch admin \u00fa\u010dtov<\/li>\n\n\n<li>zneu\u017eitie servera na \u010fal\u0161ie \u00fatoky (spam, phishing, botnet)<\/li>\n\n<\/ul>\n\n\n\n<p>V tomto pr\u00edpade je d\u00f4le\u017eit\u00e9, \u017ee pod\u013ea rozboru sa \u00fato\u010dn\u00edk vie dosta\u0165 aj mimo \u201ebezpe\u010dn\u00e9ho\u201c adres\u00e1ra pre z\u00e1lohy a nahra\u0165 s\u00fabor do verejne pr\u00edstupnej cesty, \u010do je pre RCE spravidla rozhoduj\u00face.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Technick\u00e9 pozadie: kde presne vznikol probl\u00e9m<\/h2>\n\n\n\n<p>WPvivid Backup m\u00e1 funkciu prijatia z\u00e1lohy z in\u00e9ho webu. T\u00e1to komunik\u00e1cia pou\u017e\u00edva kr\u00e1tkodobo generovan\u00fd k\u013e\u00fa\u010d. K\u013e\u00fa\u010dov\u00e1 \u010das\u0165 spracovania prijat\u00e9ho obsahu ide pod\u013ea Wordfence cez met\u00f3du <code>send_to_site()<\/code> v triede <code>WPvivid_Send_to_site<\/code>, ktor\u00e1 na\u010d\u00edta \u0161ifrovan\u00fd payload z <code>$_POST['wpvivid_content']<\/code>, dek\u00f3duje ho (Base64) a n\u00e1sledne ho de\u0161ifruje.<\/p>\n\n\n\n<p>Probl\u00e9m je kombin\u00e1ciou dvoch zlyhan\u00ed:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li><strong>Nespr\u00e1vne o\u0161etrenie chyby pri RSA de\u0161ifrovan\u00ed session k\u013e\u00fa\u010da<\/strong> (konkr\u00e9tne stav, ke\u010f de\u0161ifrovanie zlyh\u00e1 a vr\u00e1ti <code>false<\/code>).<\/li>\n\n\n<li><strong>Ch\u00fdbaj\u00faca sanitiz\u00e1cia cesty\/n\u00e1zvu s\u00faboru<\/strong> pri zapisovan\u00ed nahran\u00e9ho obsahu, \u010do umo\u017e\u0148uje <em>directory traversal<\/em> a \u00fanik z chr\u00e1nen\u00e9ho backup adres\u00e1ra.<\/li>\n\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">1) RSA zlyh\u00e1, ale k\u00f3d pokra\u010duje \u2013 a vznikne predv\u00eddate\u013en\u00fd \u0161ifrovac\u00ed k\u013e\u00fa\u010d<\/h3>\n\n\n\n<p>Wordfence popisuje, \u017ee plugin sa pok\u00fa\u0161a RSA de\u0161ifrova\u0165 hodnotu <code>$key<\/code>. Ak je hodnota nespr\u00e1vna, v\u00fdsledok de\u0161ifrovania je <code>false<\/code>. Namiesto toho, aby sa vykon\u00e1vanie ukon\u010dilo, tento <code>false<\/code> prejde do inicializ\u00e1cie symetrick\u00e9ho \u0161ifrovania (Rijndael\/AES cez phpseclib). Kni\u017enica <code>false<\/code> interpretuje ako re\u0165azec nulov\u00fdch bajtov, \u010d\u00edm vznikne <strong>predv\u00eddate\u013en\u00fd \u201enull-byte\u201c k\u013e\u00fa\u010d<\/strong>.<\/p>\n\n\n\n<p>To je presne ten typ chyby, ktor\u00fd \u00fato\u010dn\u00edkovi d\u00e1 do ruky stabiln\u00fd vektor: vie si pripravi\u0165 payload za\u0161ifrovan\u00fd k\u013e\u00fa\u010dom z nulov\u00fdch bajtov a plugin ho bude pova\u017eova\u0165 za legit\u00edmne de\u0161ifrovan\u00fd obsah.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2) N\u00e1zov s\u00faboru z payloadu bez sanitiz\u00e1cie \u2192 directory traversal<\/h3>\n\n\n\n<p>Druh\u00e1 \u010das\u0165 re\u0165azca je, \u017ee plugin akceptoval n\u00e1zvy s\u00faborov z de\u0161ifrovan\u00e9ho payloadu bez dostato\u010dnej kontroly\/sanitiz\u00e1cie. To pod\u013ea Wordfence umo\u017enilo <em>directory traversal<\/em> \u2013 teda pou\u017ei\u0165 <code>..\/<\/code> a dosta\u0165 sa mimo ur\u010den\u00fd adres\u00e1r pre z\u00e1lohy.<\/p>\n\n\n\n<p>V\u00fdsledok: neautentifikovan\u00fd \u00fato\u010dn\u00edk vedel nahra\u0165 \u013eubovo\u013en\u00fd s\u00fabor (vr\u00e1tane <code>.php<\/code>) do verejne pr\u00edstupnej lok\u00e1cie, a n\u00e1sledne ho zavola\u0165 cez web, \u010d\u00edm sa dosiahne <strong>Remote Code Execution<\/strong>.<\/p>\n\n\n\n<p>Wordfence uv\u00e1dza aj konkr\u00e9tny parameter, cez ktor\u00fd sa \u00fatok realizuje: <strong><code>wpvivid_action=send_to_site<\/code><\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u010co opravili v 0.9.124: dve d\u00f4le\u017eit\u00e9 brzdy<\/h2>\n\n\n\n<p>Vendor vydal opravu v <strong>0.9.124<\/strong>. Pod\u013ea zverejnen\u00e9ho diffu ide o dve podstatn\u00e9 zmeny:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Oprava v <code>decrypt_message()<\/code>: kontrola pr\u00e1zdneho\/nespr\u00e1vneho k\u013e\u00fa\u010da<\/h3>\n\n\n\n<p>Do de\u0161ifrovacej funkcie pribudla kontrola, \u010di RSA de\u0161ifrovanie vr\u00e1tilo <code>false<\/code> alebo pr\u00e1zdnu hodnotu. Ak \u00e1no, funkcia skon\u010d\u00ed a vr\u00e1ti <code>false<\/code>, namiesto toho, aby pokra\u010dovala so symetrick\u00fdm \u0161ifrovan\u00edm na \u201enulovom\u201c k\u013e\u00fa\u010di.<\/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>$key = $rsa-&gt;decrypt($key);\n\n\/\/ Patch: nepokra\u010duj, ak RSA de\u0161ifrovanie zlyhalo\nif ($key === false || empty($key)) {\n    return false;\n}\n\n$rij = new Crypt_Rijndael();\n$rij-&gt;setKey($key);\nreturn $rij-&gt;decrypt($data);\n\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:#E1E4E8\">$key <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#E1E4E8\"> $rsa<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">decrypt<\/span><span style=\"color:#E1E4E8\">($key);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#6A737D\">\/\/ Patch: nepokra\u010duj, ak RSA de\u0161ifrovanie zlyhalo<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">if<\/span><span style=\"color:#E1E4E8\"> ($key <\/span><span style=\"color:#F97583\">===<\/span><span style=\"color:#79B8FF\"> false<\/span><span style=\"color:#F97583\"> ||<\/span><span style=\"color:#79B8FF\"> empty<\/span><span style=\"color:#E1E4E8\">($key)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">    return<\/span><span style=\"color:#79B8FF\"> false<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">$rij <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#F97583\"> new<\/span><span style=\"color:#79B8FF\"> Crypt_Rijndael<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">$rij<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">setKey<\/span><span style=\"color:#E1E4E8\">($key);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">return<\/span><span style=\"color:#E1E4E8\"> $rij<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">decrypt<\/span><span style=\"color:#E1E4E8\">($data);<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Oprava v <code>send_to_site()<\/code>: kontrola pr\u00edpony a \u201ebezpe\u010dn\u00fd\u201c n\u00e1zov s\u00faboru<\/h3>\n\n\n\n<p>Druh\u00e1 zmena prid\u00e1va kontrolu typu\/pr\u00edpony s\u00faboru a z\u00e1rove\u0148 rob\u00ed n\u00e1zov s\u00faboru bezpe\u010dnej\u0161\u00edm: pou\u017e\u00edva <code>basename()<\/code> a n\u00e1sledne odfiltruje ne\u017eiaduce znaky regexom. Plugin n\u00e1sledne povol\u00ed len vybran\u00e9 pr\u00edpony typick\u00e9 pre z\u00e1lohy.<\/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>$safe_name = basename($params['name']);\n$safe_name = preg_replace('\/[^a-zA-Z0-9._-]\/', '', $safe_name);\n\n$allowed_extensions = array('zip', 'gz', 'tar', 'sql');\n$file_ext = strtolower(pathinfo($safe_name, PATHINFO_EXTENSION));\n\nif (!in_array($file_ext, $allowed_extensions, true)) {\n    $ret['result'] = WPVIVID_FAILED;\n    $ret['error']  = 'Invalid file type - only backup files allowed.';\n    echo wp_json_encode($ret);\n    die();\n}\n\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:#E1E4E8\">$safe_name <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> basename<\/span><span style=\"color:#E1E4E8\">($params[<\/span><span style=\"color:#9ECBFF\">'name'<\/span><span style=\"color:#E1E4E8\">]);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">$safe_name <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> preg_replace<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">'\/<\/span><span style=\"color:#DBEDFF\">[^a-zA-Z0-9._-]<\/span><span style=\"color:#9ECBFF\">\/'<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">''<\/span><span style=\"color:#E1E4E8\">, $safe_name);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">$allowed_extensions <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> array<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">'zip'<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">'gz'<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">'tar'<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">'sql'<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">$file_ext <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> strtolower<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#79B8FF\">pathinfo<\/span><span style=\"color:#E1E4E8\">($safe_name, <\/span><span style=\"color:#79B8FF\">PATHINFO_EXTENSION<\/span><span style=\"color:#E1E4E8\">));<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">if<\/span><span style=\"color:#E1E4E8\"> (<\/span><span style=\"color:#F97583\">!<\/span><span style=\"color:#79B8FF\">in_array<\/span><span style=\"color:#E1E4E8\">($file_ext, $allowed_extensions, <\/span><span style=\"color:#79B8FF\">true<\/span><span style=\"color:#E1E4E8\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $ret[<\/span><span style=\"color:#9ECBFF\">'result'<\/span><span style=\"color:#E1E4E8\">] <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> WPVIVID_FAILED<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $ret[<\/span><span style=\"color:#9ECBFF\">'error'<\/span><span style=\"color:#E1E4E8\">]  <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#9ECBFF\"> 'Invalid file type - only backup files allowed.'<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#79B8FF\">    echo<\/span><span style=\"color:#B392F0\"> wp_json_encode<\/span><span style=\"color:#E1E4E8\">($ret);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">    die<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>T\u00e1to druh\u00e1 \u010das\u0165 je d\u00f4le\u017eit\u00e1 najm\u00e4 preto, \u017ee v p\u00f4vodnom stave pod\u013ea Wordfence neexistovali ani z\u00e1kladn\u00e9 kontroly typu s\u00faboru \u010di roz\u0161\u00edrenia. V kombin\u00e1cii s directory traversal to bola priama cesta k nahratiu spustite\u013en\u00e9ho PHP.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u010casov\u00e1 os zverejnenia (Disclosure Timeline)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>January 12, 2026<\/strong> &#8211; Wordfence dostal hl\u00e1senie cez Bug Bounty Program.<\/li>\n\n\n<li><strong>January 22, 2026<\/strong> &#8211; Wordfence report overil, potvrdil proof-of-concept a oslovil vendor (s ponukou pou\u017ei\u0165 <a href=\"https:\/\/www.wordfence.com\/threat-intel\/vendor\/vulnerability-management-portal\/\">Wordfence Vulnerability Management Portal<\/a>).<\/li>\n\n\n<li><strong>January 22, 2026<\/strong> &#8211; Wordfence Premium \/ Care \/ Response dostali firewall rule na mitig\u00e1ciu.<\/li>\n\n\n<li><strong>January 23, 2026<\/strong> &#8211; Vendor odpovedal a zvolil komunik\u00e1ciu e-mailom.<\/li>\n\n\n<li><strong>January 23, 2026<\/strong> &#8211; Wordfence poslal pln\u00e9 detaily zranite\u013enosti, vendor potvrdil a za\u010dal pracova\u0165 na oprave.<\/li>\n\n\n<li><strong>January 28, 2026<\/strong> &#8211; Vy\u0161la opraven\u00e1 verzia pluginu <strong>0.9.124<\/strong>.<\/li>\n\n\n<li><strong>February 21, 2026<\/strong> &#8211; Wordfence Free m\u00e1 (pod\u013ea ozn\u00e1menia) dosta\u0165 rovnak\u00fa ochranu.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Wordfence ochrana: kto dostal pravidlo a kedy<\/h2>\n\n\n\n<p>Wordfence nasadil ochranu na \u00farovni WAF (web application firewall) formou pravidla, ktor\u00e9 blokuje pokusy o exploitovanie tejto zranite\u013enosti:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Pou\u017e\u00edvatelia <strong>Wordfence Premium<\/strong>, <strong>Wordfence Care<\/strong> a <strong>Wordfence Response<\/strong> dostali firewall rule <strong>January 22, 2026<\/strong>.<\/li>\n\n\n<li>Pou\u017e\u00edvatelia <strong>Wordfence Free<\/strong> maj\u00fa dosta\u0165 rovnak\u00fa ochranu <strong>February 21, 2026<\/strong> (30-d\u0148ov\u00e9 oneskorenie oproti platen\u00fdm pl\u00e1nom).<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\u010co spravi\u0165 na weboch, ktor\u00e9 WPvivid pou\u017e\u00edvaj\u00fa<\/h2>\n\n\n\n<p>Ak WPvivid Backup pou\u017e\u00edva\u0161 (alebo ho spravuje\u0161 klientom), minimum je jasn\u00e9: <strong>aktualizova\u0165<\/strong>. Wordfence pri publikovan\u00ed odpor\u00fa\u010da prejs\u0165 na <strong>WPvivid Backup 0.9.124<\/strong> \u010do najsk\u00f4r.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li>Skontroluj verziu pluginu WPvivid Backup &#038; Migration (Migration, Backup, Staging).<\/li>\n\n\n<li>Ak je verzia <strong>0.9.123 alebo ni\u017e\u0161ia<\/strong>, aktualizuj na <strong>0.9.124<\/strong>.<\/li>\n\n\n<li>Over, \u010di nem\u00e1\u0161 zapnut\u00fa funkcionalitu prij\u00edmania z\u00e1loh z in\u00fdch webov cez generovan\u00fd k\u013e\u00fa\u010d (feature je defaultne vypnut\u00e1, ale v niektor\u00fdch nasadeniach sa pou\u017e\u00edva).<\/li>\n\n\n<li>Ak pou\u017e\u00edva\u0161 Wordfence, skontroluj, \u010di m\u00e1\u0161 akt\u00edvne WAF pravidl\u00e1 (a r\u00e1taj s t\u00fdm, \u017ee Wordfence Free dost\u00e1va niektor\u00e9 pravidl\u00e1 nesk\u00f4r).<\/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\">Pozn\u00e1mka k riziku v praxi<\/h4>\n\n\n<p>Aj ke\u010f je k\u013e\u00fa\u010d v WPvivid \u010dasovo obmedzen\u00fd (max 24 hod\u00edn) a funkcia je defaultne vypnut\u00e1, v re\u00e1lnych projektoch sa t\u00e1to vo\u013eba \u010dasto zap\u00edna kv\u00f4li migr\u00e1ci\u00e1m alebo centralizovan\u00fdm z\u00e1loh\u00e1m. Pr\u00e1ve vtedy sa z \u201eteoretickej\u201c chyby st\u00e1va ve\u013emi praktick\u00fd incident.<\/p>\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Zhrnutie<\/h2>\n\n\n\n<p>CVE-2026-1357 v plugine WPvivid Backup ukazuje klasick\u00fd pattern: kryptografick\u00e1 chyba v o\u0161etren\u00ed zlyhania (RSA de\u0161ifrovanie \u2192 <code>false<\/code>) + slab\u00e1 pr\u00e1ca s cestami\/n\u00e1zvami s\u00faborov = neautentifikovan\u00fd upload s\u00faborov a potenci\u00e1lne RCE. Oprava je dostupn\u00e1 vo verzii <strong>0.9.124<\/strong> a zmysel d\u00e1va rie\u0161i\u0165 ju okam\u017eite, najm\u00e4 ak pou\u017e\u00edva\u0161 funkciu prij\u00edmania z\u00e1loh cez generovan\u00fd k\u013e\u00fa\u010d.<\/p>\n\n\n<div class=\"references-section\">\n                <h2>Referencie \/ Zdroje<\/h2>\n                <ul class=\"references-list\"><li><a href=\"https:\/\/www.wordfence.com\/blog\/2026\/02\/800000-wordpress-sites-affected-by-arbitrary-file-upload-vulnerability-in-wpvivid-backup-wordpress-plugin\/\" target=\"_blank\" rel=\"noopener noreferrer\">800,000 WordPress Sites Affected by Arbitrary File Upload Vulnerability in WPvivid Backup WordPress Plugin<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/wordpress-plugins\/wpvivid-backuprestore\/migration-backup-staging-09123-unauthenticated-arbitrary-file-upload\" target=\"_blank\" rel=\"noopener noreferrer\">Migration, Backup, Staging &lt;= 0.9.123 &#8212; Unauthenticated Arbitrary File Upload<\/a><\/li><li><a href=\"https:\/\/www.cve.org\/CVERecord?id=CVE-2026-1357\" target=\"_blank\" rel=\"noopener noreferrer\">CVE-2026-1357<\/a><\/li><li><a href=\"https:\/\/wordpress.org\/plugins\/wpvivid-backuprestore\/\" target=\"_blank\" rel=\"noopener noreferrer\">WPvivid Backup &amp; Migration \u2013 plugin page<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/bug-bounty-program\/\" target=\"_blank\" rel=\"noopener noreferrer\">Wordfence Bug Bounty Program<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vendor\/vulnerability-management-portal\/\" target=\"_blank\" rel=\"noopener noreferrer\">Wordfence Vulnerability Management Portal<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/products\/wordfence-premium\/\" target=\"_blank\" rel=\"noopener noreferrer\">Wordfence Premium<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/products\/wordfence-care\/\" target=\"_blank\" rel=\"noopener noreferrer\">Wordfence Care<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/products\/wordfence-response\/\" target=\"_blank\" rel=\"noopener noreferrer\">Wordfence Response<\/a><\/li><\/ul>\n            <\/div>","protected":false},"excerpt":{"rendered":"<p>WPvivid Backup (viac ne\u017e 800 000 in\u0161tal\u00e1ci\u00ed) rie\u0161il kritick\u00fa zranite\u013enos\u0165, ktor\u00e1 m\u00f4\u017ee pri \u0161pecifickom nastaven\u00ed umo\u017eni\u0165 neautentifikovan\u00e9mu \u00fato\u010dn\u00edkovi nahra\u0165 \u013eubovo\u013en\u00fd s\u00fabor a spusti\u0165 k\u00f3d na serveri.<\/p>\n","protected":false},"author":36,"featured_media":189,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[117,15,10,116],"class_list":["post-190","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-bezpecnost","tag-rce","tag-wordfence","tag-wordpress","tag-wpvivid"],"_links":{"self":[{"href":"https:\/\/helloblog.io\/sk\/wp-json\/wp\/v2\/posts\/190","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helloblog.io\/sk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/helloblog.io\/sk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/helloblog.io\/sk\/wp-json\/wp\/v2\/users\/36"}],"replies":[{"embeddable":true,"href":"https:\/\/helloblog.io\/sk\/wp-json\/wp\/v2\/comments?post=190"}],"version-history":[{"count":0,"href":"https:\/\/helloblog.io\/sk\/wp-json\/wp\/v2\/posts\/190\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/helloblog.io\/sk\/wp-json\/wp\/v2\/media\/189"}],"wp:attachment":[{"href":"https:\/\/helloblog.io\/sk\/wp-json\/wp\/v2\/media?parent=190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/helloblog.io\/sk\/wp-json\/wp\/v2\/categories?post=190"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/helloblog.io\/sk\/wp-json\/wp\/v2\/tags?post=190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}