PHP HTTP Request, Session, Cookie & Security

Http Request Parameters

Accessing HTTP Get Parameter

$_GET['category'];
  • Will return an array (instead of string) for URL query string like category[]=a&category[]=b

Accessing HTTP Post Parameter

$_POST['category'];

Accessing the combined contents of $_GET, $_POST & $_COOKIE

$_REQUEST['category'];

$_SERVER is an array containing information such as headers, paths, and script locations

$_SERVER['REQUEST_METHOD'] == 'POST';

Cookie

Set cookies in PHP

setcookie("MyCookie[category]", 'C1', time()+3600);
setcookie('total', 5, time()+3600);

Retrieve cookie in PHP

$_COOKIE['MyCookie'];              # array(1) { ["category"]=> string(2) "C1" }
$_COOKIE['MyCookie']['category'];  # 'C1'
$_COOKIE['total'];                 # 5

Like HTTP header, cookie must be set before output any HTML data

Session

Start and set HTTP session data in PHP

session_start();                   # Create a session if none exists
$_SESSION['count'] = $_SESSION['count'] + 1;

Register PHP session data

session_start(  );
session_register('uid');

$uid = 'myid';

Load all registered session data

session_start(  );

echo $uid;

Un-register session data

session_unregister(uid);           # Un-register
session_is_registered('uid');      # Is it register

Destroy a HTTP session

session_destroy();

Security

To avoid cross site script attack

Strip away all HTML tags

$s = strip_tags($s);                                  # Remove HTML tag
$s = strip_tags($s, '<b><p>');                        # Remove all HTML tag except <b> or <p> element

Escape HTML elements

$string = htmlentities("<font>hi</font>");       # Escape HTML elements

Escaping Special HTML characters to avoid attack (Less aggressive but also less secure)

htmlspecialchars($s)                             # Escape Special HTML characters & " ' < >

Verify whether the PHP data is alphabetical or numerical

ctype_alnum($_POST['name']);                     # Check if input is alphabetical/numerical

Session Fixation

Avoid Session Fixation in PHP by re-generating the HTTP Session

  • Session Fixation allows one person to set another person's session identifier (SID)
  • Using link like http://othersite.com/?SID=fixation_id
    session_regenerate_id();                         # Use this to regenerate session ID after authentication
                                                     # This prevents session fixation attack

Prevent PHP File System Attack

  • When user provides a file name in the file upload, a hacker can hack the system by provide a file name with a path like ../../etc/password instead of simply photo.jpg
    • To avoid the hacking, strip out any possible file path and then make sure it is the same as the user input
      $filename = $_POST['file'];
      $fname = basename(realpath($filename));
      if ($filename !== $fname) {
        die("Hacking through relative path");
      }
    • Preferable, use an internal generated filename rather than using the filename supplied by users
  • Allow file operation in specific directory/sub-directories
    php.ini
    open_basedir = /allow/only/path/under/this
  • Disable register_globals, magic_quotes_gpc, and allow_url_fopen
  • Limit file privilege
    umask(077);                               # Disable group and other access
    $f = fopen("/some/path/myfile", "w");

".inc" usually store PHP class file. add this to apache configuration to avoid direct download from a Web server

<Files ~ "\.inc$">
  Order allow,deny
  Deny from all
</Files>

Alternatively, a better approach is to put class files outside document root and add it to the include_path

php.ini
include_path = "...";

PHP URL function

Encode URL

$query = 'Book Department'         # ?dept=Book+Department
urlencode($query);                 # Escape the query parameter to 'Book+Department'

Encode and decode text to escape illegal URL character like " "

rawurlencode($s);                  # Escape illegal URL character
rawurldecode($e);                  # Decode it back
Function Description
base64_decode Decodes base64
base64_encode Encodes base64
get_headers Get HTTP Header
get_meta_tags Get Meta Tag
http_build_query URL Encoded Query
parse_url Return components of a URL
rawurldecode Decode URL encoded strings
rawurlencode URL-encode
urldecode Decodes URL encoded string
urlencode URL-encodes string

URL Parsing

Extract the URL parameters into an array

$r = parse_url('http://www.yahoo.com/index/abc.html?a=1#loc_a');

Returns

Array ( [scheme] => http [host] => www.yahoo.com
        [path] => /index/abc.html
        [query] => a=1
        [fragment] => loca_a)

The query string can be further parsed by

$str = "p1=v1&param[]=v2&param[]=v3";
parse_str($str);

echo $p1;       // v1
echo $param[0]; // v2
echo $param[1]; // v3

parse_str($str, $data);
echo $data['p1'];       // v1
echo $data['param'][0]; // v2
echo $data['param'][1]; // v3

Server

$_SERVER contains the following parameters

SERVER_SOFTWARE
SERVER_NAME
GATEWAY_INTERFACE
SERVER_PROTOCOL
SERVER_PORT
REQUEST_METHOD
PATH_INFO
PATH_TRANSLATED
SCRIPT_NAME
QUERY_STRING
REMOTE_HOST
REMOTE_ADDR
AUTH_TYPE
REMOTE_USER
REMOTE_IDENT
CONTENT_TYPE
CONTENT_LENGTH
HTTP_USER_AGENT
HTTP_REFERER

Manipulate HTTP Header using PHP

Setting HTTP header with PHP

header('Content-Type: text/plain');

header('Location: http://www.yahoo.com');            # Redirect

$now = time();
$expire = gmstrftime("%a, %d %b %Y %H:%M:%S GMT", $now + 60*60);   # Expire in 1 hour
header("Expires: $expire");

Use PHP to set no caching for HTTP

header("Expires: Mon, 10 Jan 2009 00:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

Content Post Processing in PHP

Post Processing HTML data with a callback

<?php

function process($buffer)
{
  return (str_replace("old_data", "new_data", $buffer));
}
ob_start("process");
?>
<html>
  <body>
    <p>old_data</p>
  </body>
</html>
<?php
ob_end_flush();
?>

Post Processing HTML data inline

ob_start( );                             # Start the output buffering
...                                      # All output will pipe to the buffer
$data = ob_get_contents( );              # Get the output from the buffer
ob_end_clean( );                         # Reset the buffer

...

echo $data                               # Post process $data and output the new data

Post Back

Post back to the same form (Same URL)

<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="POST">

Produce something like:

<form action="this_page.php" method="POST">