{"id":197,"date":"2026-02-11T16:39:57","date_gmt":"2026-02-11T15:39:57","guid":{"rendered":"https:\/\/helloblog.io\/pl\/krytyczna-luka-wpvivid-backup-nieautoryzowany-upload-plikow-cve-2026-1357\/"},"modified":"2026-02-11T16:39:57","modified_gmt":"2026-02-11T15:39:57","slug":"krytyczna-luka-wpvivid-backup-nieautoryzowany-upload-plikow-cve-2026-1357","status":"publish","type":"post","link":"https:\/\/helloblog.io\/pl\/krytyczna-luka-wpvivid-backup-nieautoryzowany-upload-plikow-cve-2026-1357\/","title":{"rendered":"Krytyczna luka w WPvivid Backup: nieautoryzowany upload plik\u00f3w i potencjalne RCE (CVE-2026-1357)"},"content":{"rendered":"\n<p>W ekosystemie WordPressa co jaki\u015b czas wraca ten sam, wyj\u0105tkowo niebezpieczny scenariusz: <em>arbitrary file upload<\/em>, czyli mo\u017cliwo\u015b\u0107 wgrania na serwer pliku wybranego przez atakuj\u0105cego. W praktyce cz\u0119sto ko\u0144czy si\u0119 to zdalnym wykonaniem kodu (RCE, <em>Remote Code Execution<\/em>) i przej\u0119ciem ca\u0142ej witryny. Dok\u0142adnie taki problem opisano dla wtyczki <strong>WPvivid Backup &#038; Migration<\/strong> (slug: <code>wpvivid-backuprestore<\/code>) \u2013 i to w kontek\u015bcie funkcji, kt\u00f3ra ma u\u0142atwia\u0107 transfer kopii zapasowych mi\u0119dzy serwisami.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Co si\u0119 sta\u0142o i kogo dotyczy problem<\/h2>\n\n\n\n<p>Do programu bug bounty Wordfence 12 stycznia 2026 zg\u0142oszono podatno\u015b\u0107 typu <strong>Unauthenticated Arbitrary File Upload<\/strong> we wtyczce WPvivid Backup. Wtyczka ma <strong>ponad 800 000 aktywnych instalacji<\/strong>, wi\u0119c temat jest istotny operacyjnie dla wielu admin\u00f3w i os\u00f3b utrzymuj\u0105cych WordPressy.<\/p>\n\n\n\n<p>Najwa\u017cniejszy niuans: wg opisu Wordfence podatno\u015b\u0107 <strong>krytycznie dotyka przede wszystkim te instalacje<\/strong>, na kt\u00f3rych w ustawieniach wtyczki <strong>wygenerowano klucz<\/strong> umo\u017cliwiaj\u0105cy <em>innemu serwisowi<\/em> wys\u0142anie backupu na t\u0119 stron\u0119. Ta funkcja jest <strong>domy\u015blnie wy\u0142\u0105czona<\/strong>, a czas wa\u017cno\u015bci klucza da si\u0119 ustawi\u0107 maksymalnie na <strong>24 godziny<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Identyfikatory i zakres podatno\u015bci (Wordfence Intelligence)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Nazwa w bazie: <strong>Migration, Backup, Staging <= 0.9.123 - Unauthenticated Arbitrary File Upload<\/strong><\/li>\n\n\n<li>CVSS: <strong>9.8 (Critical)<\/strong><\/li>\n\n\n<li>CVE: <strong>CVE-2026-1357<\/strong><\/li>\n\n\n<li>Wersje podatne: <strong><= 0.9.123<\/strong><\/li>\n\n\n<li>Wersja z poprawk\u0105: <strong>0.9.124<\/strong><\/li>\n\n\n<li>Bounty: <strong>2,145.00 USD<\/strong><\/li>\n\n\n<li>Wtyczka: <strong>Migration, Backup, Staging &#8211; WPvivid Backup &#038; Migration<\/strong><\/li>\n\n\n<li>Slug wtyczki: <strong>wpvivid-backuprestore<\/strong><\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Dlaczego to jest gro\u017ane: od uploadu do przej\u0119cia strony<\/h2>\n\n\n\n<p>Podatno\u015bci z tej klasy zwykle nie ko\u0144cz\u0105 si\u0119 na samym \u201ewgraniu pliku\u201d. Je\u015bli atakuj\u0105cy mo\u017ce umie\u015bci\u0107 na serwerze plik <code>.php<\/code> w publicznie dost\u0119pnym katalogu, to cz\u0119sto wystarczy jedno wej\u015bcie w URL, \u017ceby uruchomi\u0107 payload \u2013 a dalej w gr\u0119 wchodz\u0105 webshell\u2019e, kradzie\u017c danych, pivotowanie po \u015brodowisku czy trwa\u0142e backdoory.<\/p>\n\n\n\n<p>W omawianym przypadku scenariusz jest jeszcze gorszy z perspektywy obro\u0144cy, bo atak nie wymaga uwierzytelnienia (unauthenticated). Wed\u0142ug Wordfence to mog\u0142o prowadzi\u0107 do <strong>zdalnego wykonania kodu<\/strong> i w efekcie do <strong>pe\u0142nego przej\u0119cia witryny<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Techniczne t\u0142o: jak powsta\u0142 \u0142a\u0144cuch b\u0142\u0119d\u00f3w<\/h2>\n\n\n\n<p>Problem dotyczy\u0142 \u015bcie\u017cki odpowiedzialnej za odbieranie backupu z innego serwisu. WPvivid ma funkcj\u0119 \u201ereceive a backup from another site\u201d, kt\u00f3ra opiera si\u0119 o kr\u00f3tkotrwa\u0142y, wygenerowany w ustawieniach klucz. W kodzie za odbi\u00f3r pliku odpowiada metoda <code>send_to_site()<\/code> w klasie <code>WPvivid_Send_to_site<\/code>.<\/p>\n\n\n\n<p>Z opisu analizy wynika, \u017ce \u0142a\u0144cuch prowadz\u0105cy do wykorzystania podatno\u015bci sk\u0142ada\u0142 si\u0119 z kilku element\u00f3w:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Wtyczka odszyfrowywa\u0142a dane przesy\u0142ane w <code>$_POST['wpvivid_content']<\/code> (base64) przy u\u017cyciu mechanizmu opartego o RSA + szyfr symetryczny (w opisie pojawia si\u0119 Rijndael\/AES przez <code>phpseclib<\/code>).<\/li>\n\n\n<li>Klucz sesyjny by\u0142 odszyfrowywany, a nast\u0119pnie wykorzystywany do inicjalizacji szyfru symetrycznego. Klucz generowany w ustawieniach mia\u0142 pos\u0142u\u017cy\u0107 do bezpiecznej wymiany\/odbioru danych.<\/li>\n\n\n<li>B\u0142\u0105d w obs\u0142udze przypadku niepowodzenia: gdy odszyfrowanie klucza prywatnym kluczem (w praktyce wskazano <code>openssl_private_decrypt()<\/code> jako punkt niepowodzenia w procesie) si\u0119 nie uda\u0142o, wykonanie <strong>nie by\u0142o przerywane<\/strong>, a w miejsce klucza przekazywana by\u0142a warto\u015b\u0107 logiczna <code>false<\/code>.<\/li>\n\n\n<li>Biblioteka szyfruj\u0105ca (phpseclib) traktowa\u0142a <code>false<\/code> jak ci\u0105g bajt\u00f3w o warto\u015bci <code>0x00<\/code> (null bytes). W efekcie powstawa\u0142 <strong>przewidywalny klucz<\/strong> do szyfrowania\/odszyfrowywania, kt\u00f3ry atakuj\u0105cy m\u00f3g\u0142 odtworzy\u0107 i u\u017cy\u0107 do przygotowania poprawnie \u201ezaszyfrowanego\u201d payloadu.<\/li>\n\n\n<li>Po odszyfrowaniu wtyczka przyjmowa\u0142a nazw\u0119 pliku z payloadu <strong>bez sanitizacji \u015bcie\u017cki<\/strong>, co umo\u017cliwia\u0142o <strong>directory traversal<\/strong> i \u201ewyj\u015bcie\u201d poza chroniony katalog backup\u00f3w.<\/li>\n\n\n<li>Na ko\u0144cu brakowa\u0142o skutecznych ogranicze\u0144 typu\/rozszerzenia wgrywanego pliku, wi\u0119c mo\u017cliwe by\u0142o umieszczenie np. pliku PHP w publicznie dost\u0119pnym katalogu i uruchomienie go w przegl\u0105darce.<\/li>\n\n\n<li>Wektor wykorzystania by\u0142 wi\u0105zany z parametrem akcji <code>wpvivid_action=send_to_site<\/code> (wektor odbioru pliku).<\/li>\n\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Fragmenty kodu, kt\u00f3re pokazuj\u0105 sedno problemu<\/h3>\n\n\n\n<p>Poni\u017cej \u2013 dla kontekstu \u2013 kluczowy fragment przep\u0142ywu z <code>send_to_site()<\/code>, w kt\u00f3rym pobierane s\u0105 ustawienia tokenu\/klucza i wykonywane jest odszyfrowanie danych z <code>wpvivid_content<\/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>public function send_to_site()\n{\n    include_once WPVIVID_PLUGIN_DIR . '\/includes\/class-wpvivid-crypt.php';\n    $test_log = new WPvivid_Log();\n    $test_log-&gt;CreateLogFile('test_backup','no_folder','transfer');\n    $test_log-&gt;WriteLog('test upload.','notice');\n    try\n    {\n        if(isset($_POST['wpvivid_content']))\n        {\n            global $wpvivid_plugin;\n            $wpvivid_plugin-&gt;wpvivid_log = new WPvivid_Log();\n\n            $default = array();\n            $option = get_option('wpvivid_api_token',$default);\n            if(empty($option))\n            {\n                die();\n            }\n            if($option['expires'] != 0 &amp;&amp; $option['expires'] &lt; time())\n            {\n                die();\n            }\n            $crypt = new WPvivid_crypt(base64_decode($option['private_key']));\n            $body  = base64_decode($_POST['wpvivid_content']);\n            $data  = $crypt-&gt;decrypt_message($body);\n            \/\/ ... dalsza obs\u0142uga\n        }\n    }\n    catch (Exception $e)\n    {\n        \/\/ ...\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:#F97583\">public<\/span><span style=\"color:#F97583\"> function<\/span><span style=\"color:#B392F0\"> send_to_site<\/span><span style=\"color:#E1E4E8\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">    include_once<\/span><span style=\"color:#79B8FF\"> WPVIVID_PLUGIN_DIR<\/span><span style=\"color:#F97583\"> .<\/span><span style=\"color:#9ECBFF\"> '\/includes\/class-wpvivid-crypt.php'<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $test_log <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#F97583\"> new<\/span><span style=\"color:#79B8FF\"> WPvivid_Log<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $test_log<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">CreateLogFile<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">'test_backup'<\/span><span style=\"color:#E1E4E8\">,<\/span><span style=\"color:#9ECBFF\">'no_folder'<\/span><span style=\"color:#E1E4E8\">,<\/span><span style=\"color:#9ECBFF\">'transfer'<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $test_log<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">WriteLog<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">'test upload.'<\/span><span style=\"color:#E1E4E8\">,<\/span><span style=\"color:#9ECBFF\">'notice'<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">    try<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">        if<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#79B8FF\">isset<\/span><span style=\"color:#E1E4E8\">($_POST[<\/span><span style=\"color:#9ECBFF\">'wpvivid_content'<\/span><span style=\"color:#E1E4E8\">]))<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">            global<\/span><span style=\"color:#E1E4E8\"> $wpvivid_plugin;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">            $wpvivid_plugin<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#E1E4E8\">wpvivid_log <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#F97583\"> new<\/span><span style=\"color:#79B8FF\"> WPvivid_Log<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">            $default <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> array<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">            $option <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#B392F0\"> get_option<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">'wpvivid_api_token'<\/span><span style=\"color:#E1E4E8\">,$default);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">            if<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#79B8FF\">empty<\/span><span style=\"color:#E1E4E8\">($option))<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">            {<\/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 style=\"color:#F97583\">            if<\/span><span style=\"color:#E1E4E8\">($option[<\/span><span style=\"color:#9ECBFF\">'expires'<\/span><span style=\"color:#E1E4E8\">] <\/span><span style=\"color:#F97583\">!=<\/span><span style=\"color:#79B8FF\"> 0<\/span><span style=\"color:#F97583\"> &#x26;&#x26;<\/span><span style=\"color:#E1E4E8\"> $option[<\/span><span style=\"color:#9ECBFF\">'expires'<\/span><span style=\"color:#E1E4E8\">] <\/span><span style=\"color:#F97583\">&#x3C;<\/span><span style=\"color:#79B8FF\"> time<\/span><span style=\"color:#E1E4E8\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">            {<\/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 style=\"color:#E1E4E8\">            $crypt <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#F97583\"> new<\/span><span style=\"color:#79B8FF\"> WPvivid_crypt<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#79B8FF\">base64_decode<\/span><span style=\"color:#E1E4E8\">($option[<\/span><span style=\"color:#9ECBFF\">'private_key'<\/span><span style=\"color:#E1E4E8\">]));<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">            $body  <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> base64_decode<\/span><span style=\"color:#E1E4E8\">($_POST[<\/span><span style=\"color:#9ECBFF\">'wpvivid_content'<\/span><span style=\"color:#E1E4E8\">]);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">            $data  <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#E1E4E8\"> $crypt<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">decrypt_message<\/span><span style=\"color:#E1E4E8\">($body);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#6A737D\">            \/\/ ... dalsza obs\u0142uga<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">    catch<\/span><span style=\"color:#E1E4E8\"> (<\/span><span style=\"color:#79B8FF\">Exception<\/span><span style=\"color:#E1E4E8\"> $e)<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color:#6A737D\">        \/\/ ...<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Z kolei w <code>decrypt_message()<\/code> kluczow\u0105 rol\u0119 odgrywa\u0142a sytuacja, w kt\u00f3rej odszyfrowanie klucza RSA zwraca\u0142o <code>false<\/code>, ale kod i tak przechodzi\u0142 do <code>setKey()<\/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>public function decrypt_message($message)\n{\n    $len = substr($message, 0, 3);\n    $len = hexdec($len);\n    $key = substr($message, 3, $len);\n\n    $cipherlen = substr($message, ($len + 3), 16);\n    $cipherlen = hexdec($cipherlen);\n\n    $data = substr($message, ($len + 19), $cipherlen);\n\n    $rsa = new Crypt_RSA();\n    $rsa-&gt;loadKey($this-&gt;public_key);\n    $key = $rsa-&gt;decrypt($key);\n\n    $rij = new Crypt_Rijndael();\n    $rij-&gt;setKey($key);\n    return $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:#F97583\">public<\/span><span style=\"color:#F97583\"> function<\/span><span style=\"color:#B392F0\"> decrypt_message<\/span><span style=\"color:#E1E4E8\">($message)<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $len <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, <\/span><span style=\"color:#79B8FF\">0<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#79B8FF\">3<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $len <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> hexdec<\/span><span style=\"color:#E1E4E8\">($len);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $key <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, <\/span><span style=\"color:#79B8FF\">3<\/span><span style=\"color:#E1E4E8\">, $len);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $cipherlen <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, ($len <\/span><span style=\"color:#F97583\">+<\/span><span style=\"color:#79B8FF\"> 3<\/span><span style=\"color:#E1E4E8\">), <\/span><span style=\"color:#79B8FF\">16<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $cipherlen <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> hexdec<\/span><span style=\"color:#E1E4E8\">($cipherlen);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $data <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, ($len <\/span><span style=\"color:#F97583\">+<\/span><span style=\"color:#79B8FF\"> 19<\/span><span style=\"color:#E1E4E8\">), $cipherlen);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $rsa <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#F97583\"> new<\/span><span style=\"color:#79B8FF\"> Crypt_RSA<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $rsa<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">loadKey<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#79B8FF\">$this<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#E1E4E8\">public_key);<\/span><\/span>\n<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:#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 style=\"color:#E1E4E8\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Jak to naprawiono: co zmieniono w 0.9.124<\/h2>\n\n\n\n<p>Deweloper wyda\u0142 poprawk\u0119 w wersji <strong>0.9.124<\/strong>. Z opisu Wordfence wynika, \u017ce \u0142atka sk\u0142ada si\u0119 z dw\u00f3ch istotnych zmian.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1) Zatrzymanie procesu, gdy klucz RSA nie zosta\u0142 odszyfrowany<\/h3>\n\n\n\n<p>Dodano sprawdzenie, czy <code>$key<\/code> jest fa\u0142szywe\/puste. Je\u015bli tak, funkcja przerywa i zwraca <code>false<\/code>, zamiast inicjalizowa\u0107 szyfr symetryczny przewidywalnym kluczem:<\/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>public function decrypt_message($message)\n{\n    $len = substr($message, 0, 3);\n    $len = hexdec($len);\n    $key = substr($message, 3, $len);\n\n    $cipherlen = substr($message, ($len + 3), 16);\n    $cipherlen = hexdec($cipherlen);\n\n    $data = substr($message, ($len + 19), $cipherlen);\n\n    $rsa = new Crypt_RSA();\n    $rsa-&gt;loadKey($this-&gt;public_key);\n    $key = $rsa-&gt;decrypt($key);\n\n    if ($key === false || empty($key))\n    {\n        return false;\n    }\n\n    $rij = new Crypt_Rijndael();\n    $rij-&gt;setKey($key);\n    return $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:#F97583\">public<\/span><span style=\"color:#F97583\"> function<\/span><span style=\"color:#B392F0\"> decrypt_message<\/span><span style=\"color:#E1E4E8\">($message)<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $len <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, <\/span><span style=\"color:#79B8FF\">0<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#79B8FF\">3<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $len <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> hexdec<\/span><span style=\"color:#E1E4E8\">($len);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $key <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, <\/span><span style=\"color:#79B8FF\">3<\/span><span style=\"color:#E1E4E8\">, $len);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $cipherlen <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, ($len <\/span><span style=\"color:#F97583\">+<\/span><span style=\"color:#79B8FF\"> 3<\/span><span style=\"color:#E1E4E8\">), <\/span><span style=\"color:#79B8FF\">16<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $cipherlen <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> hexdec<\/span><span style=\"color:#E1E4E8\">($cipherlen);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $data <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, ($len <\/span><span style=\"color:#F97583\">+<\/span><span style=\"color:#79B8FF\"> 19<\/span><span style=\"color:#E1E4E8\">), $cipherlen);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $rsa <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#F97583\"> new<\/span><span style=\"color:#79B8FF\"> Crypt_RSA<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $rsa<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">loadKey<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#79B8FF\">$this<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#E1E4E8\">public_key);<\/span><\/span>\n<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:#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:#E1E4E8\">    {<\/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 style=\"color:#E1E4E8\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">2) Ograniczenie typu plik\u00f3w w send_to_site() + bezpieczniejsza nazwa<\/h3>\n\n\n\n<p>Po stronie uploadu dodano mechanizm \u201eutwardzenia\u201d nazwy oraz walidacj\u0119 rozszerzenia. W praktyce: nazwa pliku jest sprowadzana do <code>basename()<\/code>, czyszczona regexem z niedozwolonych znak\u00f3w, a nast\u0119pnie sprawdzane jest, czy rozszerzenie nale\u017cy do listy dozwolonych format\u00f3w backupu:<\/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$allowed_extensions = array('zip', 'gz', 'tar', 'sql');\n$file_ext = strtolower(pathinfo($safe_name, PATHINFO_EXTENSION));\nif (!in_array($file_ext, $allowed_extensions, true))\n{\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<\/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 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 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\">{<\/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><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Reakcja ekosystemu: Wordfence, firewall i terminy<\/h2>\n\n\n\n<p>Zg\u0142oszenie i obs\u0142uga odby\u0142y si\u0119 w ramach Wordfence Bug Bounty Program. Podatno\u015b\u0107 zosta\u0142a odkryta i odpowiedzialnie zg\u0142oszona przez <strong>Lucas Montes (NiRoX)<\/strong>, zaledwie <strong>pi\u0119\u0107 dni po tym, jak b\u0142\u0105d zosta\u0142 wprowadzony<\/strong> (wg opisu Wordfence). Badacz otrzyma\u0142 nagrod\u0119 <strong>2,145.00 USD<\/strong>.<\/p>\n\n\n\n<p>Je\u015bli korzystasz z Wordfence, istotne s\u0105 te\u017c terminy dystrybucji regu\u0142 WAF (firewall). U\u017cytkownicy <strong>Wordfence Premium<\/strong>, <strong>Wordfence Care<\/strong> i <strong>Wordfence Response<\/strong> dostali regu\u0142\u0119 blokuj\u0105c\u0105 pr\u00f3by wykorzystania podatno\u015bci <strong>22 stycznia 2026<\/strong>. W przypadku <strong>Wordfence Free<\/strong> ta sama ochrona mia\u0142a trafi\u0107 z op\u00f3\u017anieniem 30 dni \u2013 <strong>21 lutego 2026<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Timeline ujawnienia (disclosure) \u2013 konkretne daty<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>January 12, 2026<\/strong> &#8211; zg\u0142oszenie podatno\u015bci (Arbitrary File Upload) do Wordfence Bug Bounty Program.<\/li>\n\n\n<li><strong>January 22, 2026<\/strong> &#8211; weryfikacja zg\u0142oszenia i potwierdzenie PoC; kontakt z producentem i zaproszenie do u\u017cycia <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; u\u017cytkownicy Wordfence Premium\/Care\/Response otrzymali regu\u0142\u0119 WAF chroni\u0105c\u0105 przed exploitami.<\/li>\n\n\n<li><strong>January 23, 2026<\/strong> &#8211; producent odpowiedzia\u0142 i wybra\u0142 komunikacj\u0119 mailow\u0105 w ramach disclosure.<\/li>\n\n\n<li><strong>January 23, 2026<\/strong> &#8211; przekazanie pe\u0142nych szczeg\u00f3\u0142\u00f3w; producent potwierdzi\u0142 i rozpocz\u0105\u0142 prace nad poprawk\u0105.<\/li>\n\n\n<li><strong>January 28, 2026<\/strong> &#8211; wydanie w pe\u0142ni za\u0142atanej wersji wtyczki: <strong>0.9.124<\/strong>.<\/li>\n\n\n<li><strong>February 21, 2026<\/strong> &#8211; planowana data udost\u0119pnienia ochrony tak\u017ce dla Wordfence Free.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Co powiniene\u015b zrobi\u0107 jako admin\/dev (checklista)<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li>Sprawd\u017a, czy na stronie jest zainstalowana wtyczka <strong>WPvivid Backup &#038; Migration<\/strong> (slug <code>wpvivid-backuprestore<\/code>).<\/li>\n\n\n<li>Zweryfikuj wersj\u0119: podatne s\u0105 <strong><= 0.9.123<\/strong>.<\/li>\n\n\n<li>Zaktualizuj wtyczk\u0119 do wersji <strong>0.9.124<\/strong> (lub nowszej, je\u015bli jest dost\u0119pna).<\/li>\n\n\n<li>Je\u015bli u\u017cywasz funkcji odbierania kopii z innej witryny: przejrzyj ustawienia i upewnij si\u0119, \u017ce generowane klucze s\u0105 u\u017cywane tylko wtedy, gdy faktycznie tego potrzebujesz, oraz \u017ce maj\u0105 kr\u00f3tk\u0105 wa\u017cno\u015b\u0107 (wtyczka i tak ogranicza j\u0105 do 24h).<\/li>\n\n\n<li>Je\u017celi masz podejrzenie kompromitacji (np. nietypowe pliki w <code>wp-content\/uploads<\/code>, nieznane pliki <code>.php<\/code> w katalogach publicznych, niepokoj\u0105ce logi), potraktuj to jako incydent bezpiecze\u0144stwa i przeprowad\u017a pe\u0142n\u0105 analiz\u0119 oraz czyszczenie.<\/li>\n\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Podsumowanie<\/h2>\n\n\n\n<p>CVE-2026-1357 w WPvivid Backup to klasyczny przyk\u0142ad tego, jak pozornie drobna decyzja w obs\u0142udze b\u0142\u0119du kryptograficznego (kontynuowanie wykonania po nieudanym odszyfrowaniu i przekazanie <code>false<\/code>) mo\u017ce doprowadzi\u0107 do przewidywalnego klucza i dalej do pe\u0142nego \u0142a\u0144cucha ataku. Do tego doszed\u0142 brak sanitizacji \u015bcie\u017cek\/nazw plik\u00f3w i brak twardych ogranicze\u0144 typu plik\u00f3w. Wersja <strong>0.9.124<\/strong> adresuje problem: zatrzymuje proces przy b\u0142\u0119dnym kluczu i dopuszcza wy\u0142\u0105cznie rozszerzenia typowe dla backup\u00f3w (<code>zip<\/code>, <code>gz<\/code>, <code>tar<\/code>, <code>sql<\/code>).<\/p>\n\n\n<div class=\"references-section\">\n                <h2>Odniesienia \/ \u0179r\u00f3d\u0142a<\/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 (wpvivid-backuprestore)<\/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><\/ul>\n            <\/div>","protected":false},"excerpt":{"rendered":"<p>WPvivid Backup &#038; Migration (ponad 800 tys. aktywnych instalacji) mia\u0142 krytyczn\u0105 podatno\u015b\u0107 umo\u017cliwiaj\u0105c\u0105 wgranie dowolnego pliku bez logowania i w konsekwencji wykonanie kodu na serwerze. Ryzyko jest najwy\u017csze, je\u015bli wtyczka mia\u0142a wygenerowany klucz do odbierania kopii z innej strony.<\/p>\n","protected":false},"author":24,"featured_media":196,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[35,115,15,10,116],"class_list":["post-197","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-bezpieczenstwo","tag-bezpieczenstwo","tag-cve-2026-1357","tag-wordfence","tag-wordpress","tag-wpvivid"],"_links":{"self":[{"href":"https:\/\/helloblog.io\/pl\/wp-json\/wp\/v2\/posts\/197","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helloblog.io\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/helloblog.io\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/helloblog.io\/pl\/wp-json\/wp\/v2\/users\/24"}],"replies":[{"embeddable":true,"href":"https:\/\/helloblog.io\/pl\/wp-json\/wp\/v2\/comments?post=197"}],"version-history":[{"count":0,"href":"https:\/\/helloblog.io\/pl\/wp-json\/wp\/v2\/posts\/197\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/helloblog.io\/pl\/wp-json\/wp\/v2\/media\/196"}],"wp:attachment":[{"href":"https:\/\/helloblog.io\/pl\/wp-json\/wp\/v2\/media?parent=197"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/helloblog.io\/pl\/wp-json\/wp\/v2\/categories?post=197"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/helloblog.io\/pl\/wp-json\/wp\/v2\/tags?post=197"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}