lockdev 1.0.0 local exploit that escalates privileges to group lock. Tested against RedHat 7.3, 8.0, and 9.0.
d0afaca473e2a2cea7605ae7ca0fee0eb61359d67f42b7273ea99dfa14d03b2b
- 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 : https://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 <dev_unlock>: push %ebp
0x8049b81 <dev_unlock+1>: mov %esp,%ebp
0x8049b83 <dev_unlock+3>: push %edi
0x8049b84 <dev_unlock+4>: push %esi
0x8049b85 <dev_unlock+5>: push %ebx
0x8049b86 <dev_unlock+6>: sub $0x407c,%esp
0x8049b8c <dev_unlock+12>: call 0x8048d10 <main+528>
0x8049b91 <dev_unlock+17>: add $0x56f,%ebx
0x8049b97 <dev_unlock+23>: cmpl $0xffffffff,0xffffff1c(%ebx)
0x8049b9e <dev_unlock+30>: jne 0x8049bb3 <dev_unlock+51>
0x8049ba0 <dev_unlock+32>: sub $0xc,%esp
0x8049ba3 <dev_unlock+35>: push $0x2
0x8049ba5 <dev_unlock+37>: call 0x804882c <umask>
0x8049baa <dev_unlock+42>: mov %eax,0xffffff1c(%ebx)
0x8049bb0 <dev_unlock+48>: add $0x10,%esp
0x8049bb3 <dev_unlock+51>: mov 0x8(%ebp),%eax
0x8049bb6 <dev_unlock+54>: sub $0xc,%esp
0x8049bb9 <dev_unlock+57>: push %eax
0x8049bba <dev_unlock+58>: call 0x8049110 <_dl_check_devname>
0x8049bbf <dev_unlock+63>: mov %eax,%edi
0x8049bc1 <dev_unlock+65>: add $0x10,%esp
0x8049bc4 <dev_unlock+68>: test %edi,%edi
---Type <return> to continue, or q <return> 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 <dev_unlock+63>: mov %eax,%edi>
(gdb) disas strrchr
Dump of assembler code for function strrchr:
0x42080e90 <strrchr>: push %edi
0x42080e91 <strrchr+1>: push %esi
0x42080e92 <strrchr+2>: xor %eax,%eax
0x42080e94 <strrchr+4>: mov 0xc(%esp,1),%esi
0x42080e98 <strrchr+8>: mov 0x10(%esp,1),%ecx
0x42080e9c <strrchr+12>: mov %cl,%ch
0x42080e9e <strrchr+14>: mov %ecx,%edx
0x42080ea0 <strrchr+16>: shl $0x10,%ecx
0x42080ea3 <strrchr+19>: mov %dx,%cx
0x42080ea6 <strrchr+22>: test $0x3,%esi
0x42080eac <strrchr+28>: je 0x42080f33 <strrchr+163>
0x42080eb2 <strrchr+34>: mov (%esi),%dl
0x42080eb4 <strrchr+36>: cmp %dl,%cl
0x42080eb6 <strrchr+38>: jne 0x42080eba <strrchr+42>
0x42080eb8 <strrchr+40>: mov %esi,%eax
0x42080eba <strrchr+42>: or %dl,%dl
0x42080ebc <strrchr+44>: je 0x42081046 <strrchr+438>
0x42080ec2 <strrchr+50>: inc %esi
0x42080ec3 <strrchr+51>: test $0x3,%esi
0x42080ec9 <strrchr+57>: je 0x42080f33 <strrchr+163>
0x42080ecb <strrchr+59>: mov (%esi),%dl
0x42080ecd <strrchr+61>: cmp %dl,%cl
---Type <return> to continue, or q <return> to quit---
0x42080ecf <strrchr+63>: jne 0x42080ed3 <strrchr+67>
0x42080ed1 <strrchr+65>: mov %esi,%eax
0x42080ed3 <strrchr+67>: or %dl,%dl
0x42080ed5 <strrchr+69>: je 0x42081046 <strrchr+438>
0x42080edb <strrchr+75>: inc %esi
0x42080edc <strrchr+76>: test $0x3,%esi
0x42080ee2 <strrchr+82>: je 0x42080f33 <strrchr+163>
0x42080ee4 <strrchr+84>: mov (%esi),%dl
0x42080ee6 <strrchr+86>: cmp %dl,%cl
0x42080ee8 <strrchr+88>: jne 0x42080eec <strrchr+92>
0x42080eea <strrchr+90>: mov %esi,%eax
0x42080eec <strrchr+92>: or %dl,%dl
0x42080eee <strrchr+94>: je 0x42081046 <strrchr+438>
0x42080ef4 <strrchr+100>: inc %esi
0x42080ef5 <strrchr+101>: jmp 0x42080f33 <strrchr+163>
0x42080ef7 <strrchr+103>: add %al,(%eax)
0x42080ef9 <strrchr+105>: add %al,0xee8304ee(%ebx)
0x42080eff <strrchr+111>: add $0x83,%al
0x42080f01 <strrchr+113>: out %al,(%dx)
0x42080f02 <strrchr+114>: add $0xf7,%al
0x42080f04 <strrchr+116>: ret $0x0
0x42080f07 <strrchr+119>: add %bh,%bh
0x42080f09 <strrchr+121>: jne 0x42080f19 <strrchr+137>
---Type <return> to continue, or q <return> to quit---
0x42080f0b <strrchr+123>: lea 0xf(%esi),%eax
0x42080f0e <strrchr+126>: jmp 0x42080f30 <strrchr+160>
0x42080f10 <strrchr+128>: sub $0x4,%esi
0x42080f13 <strrchr+131>: sub $0x4,%esi
0x42080f16 <strrchr+134>: sub $0x4,%esi
0x42080f19 <strrchr+137>: test $0xff0000,%edx
0x42080f1f <strrchr+143>: jne 0x42080f26 <strrchr+150>
0x42080f21 <strrchr+145>: lea 0xe(%esi),%eax
0x42080f24 <strrchr+148>: jmp 0x42080f30 <strrchr+160>
0x42080f26 <strrchr+150>: lea 0xc(%esi),%eax
0x42080f29 <strrchr+153>: test %dh,%dh
0x42080f2b <strrchr+155>: jne 0x42080f30 <strrchr+160>
0x42080f2d <strrchr+157>: lea 0xd(%esi),%eax
0x42080f30 <strrchr+160>: add $0x10,%esi
0x42080f33 <strrchr+163>: mov (%esi),%edx
(gdb)
.......................................
[0x4] Exploit
....
EOF