Web Development

Sessions

Prevent Hijacking of Another User's Session

Pass session IDs in cookies only. Generate an additional session token to be passed by URI. If users do not allow cookies then session hijacking can not be prevented because the session id is sent through urls and hidden input elements on forms.

output_add_rewrite_var will add the token to every link and form.

<?php
	if(!ini_get('session.use_only_cookies')) {
		// set sessions to use cookies only
		ini_set('session.use_only_cookies', true);
	}
	session_start();
	$secret = 'k38n47fb47widfb7538idj';
	$string = strval(date('z')).$secret; // 'z' will expire at midnight
	$token = md5($string);
	if(!isset($_REQUEST['token']) || $_REQUEST['token'] != $token) {
		// display login form
		print 'login form here';
		exit;
	} else {
		$_SESSION['token'] = $token;
		output_add_rewrite_var('token', $token);
		print '<a href="'.$_SERVER['SCRIPT_NAME'].'">link #1</a>';
	}
?>
	<a href="<?php echo $_SERVER['SCRIPT_NAME'] ?>">link #2</a>

Prevent Session Fixation Attacks

Assign a new session id to prevent this.

<?php
	if(!ini_get('session.use_only_cookies')) {
		// set sessions to use cookies only
		ini_set('session.use_only_cookies', true);
	}
	session_start();
	if(!isset($_SESSION['last_regenerated']) || $_SESSION['last_regenerated'] < (time() - 30)) {
		session_regenerate_id();
		$_SESSION['last_regenerated'] = time();
	}
?>

Session Tracking

Track users as they navigate the website. If the user does not accept cookies then add this line of code: ini_set('session.use_trans_sid', true);

The problem with session.use_trans_sid is that users can see the session id.

<?php
	if(!ini_get('session.auto_start')) {
		// set sessions to automatically start
		ini_set('session.auto_start', true);
		session_start();
	}
	if(!isset($_SESSION['visit_count'])) {
		$_SESSION['visit_count'] = 0;
	}
	$_SESSION['visit_count']++;
	print $_SESSION['visit_count'].' visits';
?>

Manipulating HTML

Extracting Links from HTML

Extract links from an HTML file using a custom function. This function simply extracts the link's href value which will include relative paths.

<?php
	$html = '
	<html>
		<head><title></title></head>
	<body>
	<a href="../../phpinfo.php"><img src="php.jpg" />PHP Info</a>

	<p>PHP is a scripting language.</p>

	<a href="http://www.prowaretech.com">Actors read from scripts</a>

	<php>PHP is the real deal when it comes to scripting languages.</php>
	</body>
	</html>';

	$links = link_extractor($html);
	foreach($links as $link) {
		print $link[0].'<br />';
	}

	function link_extractor($html) {
		$links = array();
		preg_match_all('/<a\s+.*?href=[\"\']?([^\"\' >]*)[\"\']?[^>]*>(.*?)<\/a>/i', $html, $matches, PREG_SET_ORDER);
		foreach($matches as $match) {
			$links[] = array($match[1], $match[2]);
		}
		return $links;
	}

?>

Repairing Nonstandard HTML

Correct malformed HTML using tidy_repair_string (or tidy_repair_file).

<?php
	$html = '
	<html>
		<head><title></head>
	<body>
	<a href="phpinfo.php"><img src="php.jpg" />PHP Info</a>

	<p>PHP is a <em>scripting language.</p></em>

	Actors read from scripts

	<php>PHP is the real deal when it comes to scripting languages.</php>
	';
	$corrected = tidy_repair_string($html);
	print $corrected;
?>

Highlighting Keywords in an HTML Document

A website with a custom search function will want to highlight the search words within each HTML document.

<?php
	$html = '
	<html>
		<head><title></title></head>
	<body>
	<a href="phpinfo.php"><img src="php.jpg" />PHP Info</a>

	<p>PHP is a scripting language.</p>

	Actors read from scripts

	<php>PHP is the real deal when it comes to scripting languages.</php>
	</body>
	</html>';

	// wrap each search word with mark tags
	$search_words = array('php','script');
	$replacements = array();
	foreach($search_words as $index => $search_word) {
		$patterns[] = '/'.preg_quote($search_word).'/i';
		$replacements[] = "<mark>\\0</mark>";
	}

	// split the page into chunks delimited by HTML elements
	$html_parts = preg_split("{(<(?:\"[^\"]*\"|'[^']*'|[^'\">])*>)}", $html, -1, PREG_SPLIT_DELIM_CAPTURE);

	foreach($html_parts as $index => $html_part) {
		// skip if HTML element
		if(isset($html_part[0]) && ($html_part[0] == '<')) {
			continue;
		}
		$html_parts[$index] = preg_replace($patterns, $replacements, $html_part);
	}

	$html = implode('', $html_parts);

	print $html;
?>

Convert Plain Text into HTML

<?php
	$text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec egestas imperdiet purus, sit amet aliquet sapien gravida quis.

Curabitur sed velit eu est HTTP://www.finibus.com malesuada et eu nisl. Curabitur vel sapien et massa suscipit rhoncus.';

	print text2html($text);

	function text2html($text) {
		$text = htmlentities($text);
		$grafs = split("\r\n\r\n", $text);
		for($i = 0, $j = count($grafs); $i < $j; $i++) {
			// http or ftp urls
			$grafs[$i] = preg_replace('/((ht|f)tp:\/\/[^\s&]+)/i', '<a href="$1">$1</a>', $grafs[$i]);

			$grafs[$i] = '<p>'.$grafs[$i].'</p>';
		}
		return implode("\r\n", $grafs);
	}
?>

Connecting to Websites

file_get_contents can retrieve documents on the Internet as simply as it does local files. Also, it follows redirects which greatly simplifies the usage.

Use this page for testing these practices.

<!-- print.php -->
<?php
	print "<pre>COOKIES\r\n";
	print_r($_COOKIE);
	print "REQUEST\r\n";
	print_r($_REQUEST);
	print '</pre>';
?>

HTTP "GET" a URI

For a GET request, just specify the URI as the file in file_get_contents. Optionally, build a query string to include.

<?php
	$query = array('search' => 'brown & cow', 'option' => 'two');
	$query_string = http_build_query($query);
	$page_data = file_get_contents('http://localhost/print.php?'.$query_string);
	print $page_data;
?>

To specify that file_get_contents not follow redirects, specify an additional parameter.

<?php
	$options = array('max_redirects' => 0);
	$stream_context = stream_context_create(array('http' => $options));
	$page_data = file_get_contents('http://localhost/print.php', false, $stream_context);
	print $page_data;
?>

To specify a user and password just add it to the URI.

<?php
	$secure_page_data = file_get_contents('http://username:password@localhost/print.php');
	print $secure_page_data;
?>

HTTP "POST" to a URI

For a POST request, file_get_contents still works great.

<?php
	$query = array('firstname' => 'brown & cow', 'lastname' => 'to whom it matters');
	$request_body = http_build_query($query);
	$options = array('method' => 'POST', 'content' => $request_body, 'header' => 'Content-type: application/x-www-form-urlencoded');
	$stream_context = stream_context_create(array('http' => $options));
	$page_data = file_get_contents('http://localhost/print.php', false, $stream_context);
	print $page_data;
?>

HTTP GET with Cookies

The key here is to include the Cookie header.

<?php
	$options = array('method' => 'GET', 'header' => "Cookie: username=mrsmith");
	$stream_context = stream_context_create(array('http' => $options));
	$page_data = file_get_contents('http://localhost/print.php', false, $stream_context);
	print $page_data;
?>

HTTP POST with Cookies

Like the GET request, include a Cookie header.

<?php
	$query = array('firstname' => 'brown & cow', 'lastname' => 'to whom it matters');
	$request_body = http_build_query($query);
	$options = array('method' => 'POST', 'content' => $request_body, 'header' => "Cookie: username=mrsmith\r\nContent-type: application/x-www-form-urlencoded");
	$stream_context = stream_context_create(array('http' => $options));
	$page_data = file_get_contents('http://localhost/print.php', false, $stream_context);
	print $page_data;
?>
<< < [Page 6 of 6] > >>