NamePros
Welcome, Guest! Ready to make a name for yourself in the domain business? We welcome both the hobbyist and professional domainer to join the discussion as part of the NamePros community.

Click here to create your profile to start earning reputation for posting, and trader ratings for buying & selling in our free e-marketplace. Build your trader rating with each successful sale. Our system has tracked over 100,000 sales and counting!
FAQ & TOS Register Search Today's Posts Mark Forums Read

Go Back   NamePros.com > Website Development Discussion Forums > Programming > CODE
Reload this Page PHP Security Class

CODE This forum is for posting code snippets and example scripts that aren't quite tutorials, but could be useful for others. You may post code snippets and/or completed scripts that you've written and want to share here.

Advanced Search


Closed Thread
 
LinkBack Thread Tools
Old 09-18-2008, 01:40 PM THREAD STARTER               #1 (permalink)
Senior Member
 
Dave's Avatar
Join Date: Jun 2007
Location: NamePros.com
Posts: 1,400
Dave has much to be proud ofDave has much to be proud ofDave has much to be proud ofDave has much to be proud ofDave has much to be proud ofDave has much to be proud ofDave has much to be proud ofDave has much to be proud ofDave has much to be proud of
 


Cancer

Smile PHP Security Class


This class will help you sanitize global data and protect against well known vulnerabilities like register globals and such. I know these are deprecated but it doesn't mean they are obsolete.

Security.php
PHP Code:
<?php
/**
 * Provides static functions to help protect against cross site scripting
 * attacks and helps clean up the php environment upon initializing.
 *
 * Based upon Security library by http://kohanaphp.com/
 *
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 */

class Security
{
    
// Instance of the security class.
    
protected static $instance;
    protected 
$magic_quotes_gpc FALSE;
    
    
/**
     * Gets the instance of the Security class.
     *
     * @return object Instance of Security
     */
    
public static function instance()
    {
        if(
self::$instance === NULL)
        {
            return new 
Security;
        }
        
        return 
self::$instance;
    }
    
    
    
/**
     * Constructor. Sanitizes global data GET, POST and COOKIE data.
     * Also makes sure those pesty magic quotes and register globals
     * don't bother us. This is protected because it really only needs
     * to be run once.
     *
     * @return void
     */
    
protected function __construct()
    {
        if(
self::$instance === NULL)
        {
            
// Check for magic quotes
            
if(get_magic_quotes_runtime())
            {
                
// Dear lord!! This is bad and deprected. Sort it out ;)
                
set_magic_quotes_runtime(0);
            }
            
            if(
get_magic_quotes_gpc())
            {
                
// This is also bad and deprected. See http://php.net/magic_quotes for more information.
                
$this->magic_quotes_gpc TRUE;
            }
            
            
// Check for register globals and prevent security issues from arising.
            
if(ini_get('register_globals'))
            {
                if(isset(
$_REQUEST['GLOBALS']))
                {
                    
// No no no.. just kill the script here and now
                    
exit('Illegal attack on global variable.');
                }
                
                
// Get rid of REQUEST
                
$_REQUEST = array();
                
                
// The following globals are standard and shouldn't really be removed
                
$preserve = array('GLOBALS''_REQUEST''_GET''_POST''_FILES''_COOKIE''_SERVER''_ENV''_SESSION');
                
                
// Same effect as disabling register_globals
                
foreach($GLOBALS as $key => $value)
                {
                    if( ! 
in_array($key$preserve))
                    {
                        global $
$key;
                        $
$key NULL;
                        
                        unset(
$GLOBALS[$key], $$key);
                    }
                }
            }
            
            
// Sanitize global data
            
            
if(is_array($_POST))
            {
                foreach(
$_POST as $key => $value)
                {
                    
$_POST[$this->clean_input_keys($key)] = $this->clean_input_data($value);
                }
            }
            else
            {
                
$_POST = array();
            }
            
            if(
is_array($_GET))
            {
                foreach(
$_GET as $key => $value)
                {
                    
$_GET[$this->clean_input_keys($key)] = $this->clean_input_data($value);
                }
            }
            else
            {
                
$_GET = array();
            }
            
            if(
is_array($_COOKIE))
            {
                foreach(
$_COOKIE as $key => $value)
                {
                    
$_COOKIE[$this->clean_input_keys($key)] = $this->clean_input_data($value);
                }
            }
            else
            {
                
$_COOKIE = array();
            }
            
            
// Just make REQUEST a merge of POST and GET. Who really wants cookies in it anyway?
            
$_REQUEST array_merge($_GET$_POST);
????: NamePros.com http://www.namepros.com/code/515465-php-security-class.html
            
            
self::$instance $this;
        }
    }
    
    
/**
     * Cross site filtering (XSS). Recursive.
     *
     * @param  string Data to be cleaned
     * @return mixed
     */
    
public function xss_clean($data)
    {
        
// If its empty there is no point cleaning it :\
        
if(empty($data))
            return 
$data;
            
        
// Recursive loop for arrays
        
if(is_array($data))
        {
            foreach(
$data as $key => $value)
            {
                
$data[$key] = $this->xss_clean($data);
            }
            
            return 
$data;
        }
        
        
// http://svn.bitflux.ch/repos/public/popoon/trunk/classes/externalinput.php
        // +----------------------------------------------------------------------+
        // | Copyright (c) 2001-2006 Bitflux GmbH                                 |
        // +----------------------------------------------------------------------+
        // | Licensed under the Apache License, Version 2.0 (the "License");      |
        // | you may not use this file except in compliance with the License.     |
        // | You may obtain a copy of the License at                              |
        // | http://www.apache.org/licenses/LICENSE-2.0                           |
        // | Unless required by applicable law or agreed to in writing, software  |
        // | distributed under the License is distributed on an "AS IS" BASIS,    |
        // | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or      |
????: NamePros.com http://www.namepros.com/showthread.php?t=515465
        // | implied. See the License for the specific language governing         |
        // | permissions and limitations under the License.                       |
        // +----------------------------------------------------------------------+
        // | Author: Christian Stocker <chregu@bitflux.ch>                        |
        // +----------------------------------------------------------------------+
        
        // Fix &entity\n;
        
$data str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
        
$data preg_replace('/(&#*\w+)[\x00-\x20]+;/u''$1;'$data);
        
$data preg_replace('/(&#x*[0-9A-F]+);*/iu''$1;'$data);
        
$data html_entity_decode($dataENT_COMPAT'UTF-8');

        
// Remove any attribute starting with "on" or xmlns
        
$data preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu''$1>'$data);

        
// Remove javascript: and vbscript: protocols
        
$data preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu''$1=$2nojavascript...'$data);
        
$data preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu''$1=$2novbscript...'$data);
        
$data preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u''$1=$2nomozbinding...'$data);

        
// Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
        
$data preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i''$1>'$data);
        
$data preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i''$1>'$data);
        
$data preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu''$1>'$data);

        
// Remove namespaced elements (we do not need them)
        
$data preg_replace('#</*\w+:\w[^>]*+>#i'''$data);

        do
        {
            
// Remove really unwanted tags
            
$old_data $data;
            
$data preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i'''$data);
        }
        while (
$old_data !== $data);
        
        return 
$data;
    }
    
    
/**
     * Enforces W3C specifications to prevent malicious exploitation.
     *
     * @param  string Key to clean
     * @return string
     */
    
protected function clean_input_keys($data)
    {
        
$chars PCRE_UNICODE_PROPERTIES '\pL' 'a-zA-Z';
        
        if ( ! 
preg_match('#^[' $chars '0-9:_.-]++$#uD'$data))
        {
            exit(
'Illegal key characters in global data');
        }
        
        return 
$data;
    }
    
    
/**
     * Escapes data.
     *
     * @param  mixed Data to clean
     * @return mixed
     */
    
protected function clean_input_data($data)
    {
        if(
is_array($data))
        {
            
$new_array = array();
            foreach(
$data as $key => $value)
            {
                
$new_array[$this->clean_input_keys($key)] = $this->clean_input_data($value);
            }
            
            return 
$new_array;
        }
        
        if(
$this->magic_quotes_gpc === TRUE)
        {
            
// Get rid of those pesky magic quotes!
            
$data stripslashes($data);
        }
        
        
$data $this->xss_clean($data);
        
        return 
$data;
    }
}
?>
Example
PHP Code:
<?php

require_once('Security.php');

// Obviously you wouldn't do this but for the sake of testing i just put it here
$_POST = array('username' => "<script>alert('boop');</script>"'password' => 'rqqwrwqr');

// Just run the instance if you want to clean up global data
Security::instance();

print_r($_POST);

/**
 Displays:

 Array
 (
     [username] => alert('boop');
     [password] => rqqwrwqr;
 )
*/
?>
You can also use it like...

Example Two
PHP Code:
<?php

require_once('Security.php');

$data "some_data_to_clean";

// Like this..
$data Security::instance()->xss_clean($data);

// ..or like this, whichever you prefer
$security Security::instance();
$data $security->xss_clean($data);
?>
Enjoy.

NOTE: This is only to be used for helping to secure the environment and xss filtering on either global data or other data in your script. It is not to be used for validating the format of global data (like valid ip addresses, length of usernames etc). I will submit a validation class for this soon.
Last edited by Dave; 09-18-2008 at 01:46 PM.
Dave is offline  
Old 09-19-2008, 05:17 PM   #2 (permalink)
NamePros Regular
 
Richard's Avatar
Join Date: Jan 2006
Posts: 571
Richard is a name known to allRichard is a name known to allRichard is a name known to allRichard is a name known to allRichard is a name known to allRichard is a name known to allRichard is a name known to allRichard is a name known to all
 


Save a Life Tsunami Relief AIDS/HIV Save a Life
Your security class looks good

Would you mind explaining clean_input_keys, and what it does in a bit more depth?

Thanks.
__________________
"Failure is not the only punishment for laziness; there is also the success of others."
Richard is offline  
Closed Thread


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools


Liquid Web Smart Servers  
All times are GMT -7. The time now is 11:56 PM.

Managed Web Hosting by Liquid Web
Domain name forum recommended by Domaining.com Powered by: vBulletin® Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.6.0 Ad Management plugin by RedTyger