- 0x333 OUTSIDERS SECURITY LABS - - www.0x333.org - lockdev in redhat 7.3 ,8.0 ,9.0 possible all linux os has Segmentation fault ~~~ contents ~~~ [0x0] Info [0x1] Description [0x2] Vulnerable code [0x3] Debug session [0x4] Exploit [0x0] Info Author : nic Email : nic0x333@hotmail.com Date : 28 July 2003 Advisory : outsiders-004.txt Vender URL : http://www.hklpg.org/RPM/rawhide/1.0/ia64/RedHat/RPMS/lockdev-1.0.0-21.ia64.html Category : vul bug OS affected : redhat 7.3 8.0 possible 9.0 --> all redhat [0x1] Description lockdev is defaultly installed in all redhat os, or other linux os. our team find a bug. it is affected by a vul bug. it is +s lock group. The exploit will spawn a shell with gid=xx(lock). [0x2] Vulnerable code In setup.c we found : /* * local function list_setups */ /* exported by the interface file lockdev.h */ main() case 'u': i = dev_unlock( dev, 0); break; ............................. /* exported by the interface file lockdev.h */ pid_t dev_unlock( devname, pid) const char * devname; const pid_t pid; { const char * p; char device[MAXPATHLEN+1]; char lock0[MAXPATHLEN+1]; char lock1[MAXPATHLEN+1]; char lock2[MAXPATHLEN+1]; struct stat statbuf; pid_t wpid; #if DEBUG if ( env_var_debug == -1 ) { char *value; if ( value=getenv( _env_var ) ) env_var_debug = liblockdev_debug = atoi( value); signal( SIGUSR1, _dl_sig_handler); signal( SIGUSR2, _dl_sig_handler); } #endif /* DEBUG */ _debug( 3, "dev_unlock(%s, %d)\n", devname, (int)pid); if (oldmask == -1 ) oldmask = umask( 0); /* give full permissions to files created */ if ( ! (p=_dl_check_devname( devname)) ) close_n_return( -1); strcpy( device, DEV_PATH); strcat( device, p); /* now device has a copy of the pathname */ _debug( 2, "dev_unlock() device = %s\n", device); /* check the device name for existence and retrieve the major * and minor numbersn if ( stat( device, &statbuf) == -1 ) { close_n_return( -1); } /* first remove the FSSTND-1.2 lock, get the pid of the * owner of the lock and test for its existence; in case, * return the pid of the owner of the lock. */ /* lockfile of type /var/lock/LCK..ttyS2 */ _dl_filename_2( lock2, p); wpid = _dl_check_lock( lock2); if ( pid && wpid && pid != wpid ) close_n_return( wpid); /* error or locked by someone else */ /* lockfile of type /var/lock/LCK.004.064 */ _dl_filename_1( lock1, &statbuf); wpid = _dl_check_lock( lock1); if ( pid && wpid && pid != wpid ) close_n_return( wpid); /* error or locked by someone else */ _dl_filename_0( lock0, wpid); if ( wpid == _dl_check_lock( lock0)) unlink( lock0); /* anyway now we remove the files, in the reversed order than * they have been built. */ unlink( lock2); unlink( lock1); _debug( 2, "dev_unlock() unlocked\n"); close_n_return( 0); /* successfully unlocked */ } .......................................................................... _dl_check_devname( devname) const char * devname; { int l; const char * p; char *m; /* devname can be absolute, relative to PWD or a single * filename, in any case we assume that the file is in /dev; * maybe we should check it and do something if not? */ p = devname; /* only a filename */ while ( (m=strrchr( p, '/')) != 0 ) { ....................pointer p = m+1; /* was pointing to the slash */ ..................................................................................... [0x3] Debug session bash-2.05a$ gdb ./lockdev GNU gdb Red Hat Linux (5.1.90CVS-5) Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux"... (no debugging symbols found)... (gdb) r -u Starting program: /usr/sbin/lockdev -u (no debugging symbols found)...(no debugging symbols found)... Program received signal SIGSEGV, Segmentation fault. 0x42080f33 in strrchr () from /lib/i686/libc.so.6 (gdb) disas dev_unlock Dump of assembler code for function dev_unlock: 0x8049b80 : push %ebp 0x8049b81 : mov %esp,%ebp 0x8049b83 : push %edi 0x8049b84 : push %esi 0x8049b85 : push %ebx 0x8049b86 : sub $0x407c,%esp 0x8049b8c : call 0x8048d10 0x8049b91 : add $0x56f,%ebx 0x8049b97 : cmpl $0xffffffff,0xffffff1c(%ebx) 0x8049b9e : jne 0x8049bb3 0x8049ba0 : sub $0xc,%esp 0x8049ba3 : push $0x2 0x8049ba5 : call 0x804882c 0x8049baa : mov %eax,0xffffff1c(%ebx) 0x8049bb0 : add $0x10,%esp 0x8049bb3 : mov 0x8(%ebp),%eax 0x8049bb6 : sub $0xc,%esp 0x8049bb9 : push %eax 0x8049bba : call 0x8049110 <_dl_check_devname> 0x8049bbf : mov %eax,%edi 0x8049bc1 : add $0x10,%esp 0x8049bc4 : test %edi,%edi ---Type to continue, or q to quit---q Quit (gdb) b *0x8049bba Breakpoint 1 at 0x8049bba (gdb) r -u The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /usr/sbin/lockdev -u (no debugging symbols found)...(no debugging symbols found)... Breakpoint 1, 0x08049bba in dev_unlock () (gdb) b *0x8049bbf Breakpoint 2 at 0x8049bbf (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /usr/sbin/lockdev -u (no debugging symbols found)...(no debugging symbols found)... Breakpoint 1, 0x08049bba in dev_unlock () (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x42080f33 in strrchr () from /lib/i686/libc.so.6 (gdb) so i can deside bug is in <0x8049bbf : mov %eax,%edi> (gdb) disas strrchr Dump of assembler code for function strrchr: 0x42080e90 : push %edi 0x42080e91 : push %esi 0x42080e92 : xor %eax,%eax 0x42080e94 : mov 0xc(%esp,1),%esi 0x42080e98 : mov 0x10(%esp,1),%ecx 0x42080e9c : mov %cl,%ch 0x42080e9e : mov %ecx,%edx 0x42080ea0 : shl $0x10,%ecx 0x42080ea3 : mov %dx,%cx 0x42080ea6 : test $0x3,%esi 0x42080eac : je 0x42080f33 0x42080eb2 : mov (%esi),%dl 0x42080eb4 : cmp %dl,%cl 0x42080eb6 : jne 0x42080eba 0x42080eb8 : mov %esi,%eax 0x42080eba : or %dl,%dl 0x42080ebc : je 0x42081046 0x42080ec2 : inc %esi 0x42080ec3 : test $0x3,%esi 0x42080ec9 : je 0x42080f33 0x42080ecb : mov (%esi),%dl 0x42080ecd : cmp %dl,%cl ---Type to continue, or q to quit--- 0x42080ecf : jne 0x42080ed3 0x42080ed1 : mov %esi,%eax 0x42080ed3 : or %dl,%dl 0x42080ed5 : je 0x42081046 0x42080edb : inc %esi 0x42080edc : test $0x3,%esi 0x42080ee2 : je 0x42080f33 0x42080ee4 : mov (%esi),%dl 0x42080ee6 : cmp %dl,%cl 0x42080ee8 : jne 0x42080eec 0x42080eea : mov %esi,%eax 0x42080eec : or %dl,%dl 0x42080eee : je 0x42081046 0x42080ef4 : inc %esi 0x42080ef5 : jmp 0x42080f33 0x42080ef7 : add %al,(%eax) 0x42080ef9 : add %al,0xee8304ee(%ebx) 0x42080eff : add $0x83,%al 0x42080f01 : out %al,(%dx) 0x42080f02 : add $0xf7,%al 0x42080f04 : ret $0x0 0x42080f07 : add %bh,%bh 0x42080f09 : jne 0x42080f19 ---Type to continue, or q to quit--- 0x42080f0b : lea 0xf(%esi),%eax 0x42080f0e : jmp 0x42080f30 0x42080f10 : sub $0x4,%esi 0x42080f13 : sub $0x4,%esi 0x42080f16 : sub $0x4,%esi 0x42080f19 : test $0xff0000,%edx 0x42080f1f : jne 0x42080f26 0x42080f21 : lea 0xe(%esi),%eax 0x42080f24 : jmp 0x42080f30 0x42080f26 : lea 0xc(%esi),%eax 0x42080f29 : test %dh,%dh 0x42080f2b : jne 0x42080f30 0x42080f2d : lea 0xd(%esi),%eax 0x42080f30 : add $0x10,%esi 0x42080f33 : mov (%esi),%edx (gdb) ....................................... [0x4] Exploit .... EOF