summaryrefslogtreecommitdiffstats
path: root/system/libraries/Security.php
diff options
context:
space:
mode:
authorPascal Kriete <pascal.kriete@ellislab.com>2010-11-04 22:59:52 +0100
committerPascal Kriete <pascal.kriete@ellislab.com>2010-11-04 22:59:52 +0100
commite917f9be8b05c81357c1c2c9730d5060685d644d (patch)
treeb6a7d5ce8ba57b69ba61454f77829b04f2ce5974 /system/libraries/Security.php
parent5b2d2da5ae2e97043c6bef53e565d30e50196e2b (diff)
parente1f6e9ddff788f6a154f5f35dc117d14aeb0c484 (diff)
Automated merge with http://hg.ellislab.com/CodeIgniter2
Diffstat (limited to 'system/libraries/Security.php')
-rw-r--r--system/libraries/Security.php152
1 files changed, 78 insertions, 74 deletions
diff --git a/system/libraries/Security.php b/system/libraries/Security.php
index 9a1590b5c..fa5317ea3 100644
--- a/system/libraries/Security.php
+++ b/system/libraries/Security.php
@@ -25,12 +25,12 @@
* @link http://codeigniter.com/user_guide/libraries/sessions.html
*/
class CI_Security {
- var $xss_hash = '';
- var $csrf_hash = '';
+ var $xss_hash = '';
+ var $csrf_hash = '';
var $csrf_expire = 7200; // Two hours (in seconds)
var $csrf_token_name = 'ci_csrf_token';
var $csrf_cookie_name = 'ci_csrf_token';
-
+
/* never allowed, string replacement */
var $never_allowed_str = array(
'document.cookie' => '[removed]',
@@ -63,7 +63,7 @@ class CI_Security {
}
// --------------------------------------------------------------------
-
+
/**
* Verify Cross Site Request Forgery Protection
*
@@ -92,7 +92,7 @@ class CI_Security {
// We kill this since we're done and we don't want to polute the _POST array
unset($_POST[$this->csrf_token_name]);
-
+
// Nothing should last forever
unset($_COOKIE[$this->csrf_cookie_name]);
$this->_csrf_set_hash();
@@ -100,9 +100,9 @@ class CI_Security {
log_message('debug', "CSRF token verified ");
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Set Cross Site Request Forgery Protection Cookie
*
@@ -114,12 +114,12 @@ class CI_Security {
$expire = time() + $this->csrf_expire;
setcookie($this->csrf_cookie_name, $this->csrf_hash, $expire, config_item('cookie_path'), config_item('cookie_domain'), 0);
-
- log_message('debug', "CRSF cookie Set");
+
+ log_message('debug', "CRSF cookie Set");
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Set Cross Site Request Forgery Protection Cookie
*
@@ -146,7 +146,7 @@ class CI_Security {
}
// --------------------------------------------------------------------
-
+
/**
* Show CSRF Error
*
@@ -159,7 +159,7 @@ class CI_Security {
}
// --------------------------------------------------------------------
-
+
/**
* XSS Clean
*
@@ -198,7 +198,7 @@ class CI_Security {
{
$str[$key] = $this->xss_clean($str[$key]);
}
-
+
return $str;
}
@@ -210,9 +210,9 @@ class CI_Security {
/*
* Protect GET variables in URLs
*/
-
+
// 901119URL5918AMP18930PROTECT8198
-
+
$str = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-]+)|i', $this->xss_hash()."\\1=\\2", $str);
/*
@@ -225,7 +225,7 @@ class CI_Security {
$str = preg_replace('#(&\#?[0-9a-z]{2,})([\x00-\x20])*;?#i', "\\1;\\2", $str);
/*
- * Validate UTF16 two byte encoding (x00)
+ * Validate UTF16 two byte encoding (x00)
*
* Just as above, adds a semicolon if missing.
*
@@ -248,9 +248,9 @@ class CI_Security {
*
*/
$str = rawurldecode($str);
-
+
/*
- * Convert character entities to ASCII
+ * Convert character entities to ASCII
*
* This permits our tests below to work reliably.
* We only convert entities that are within tags since
@@ -259,14 +259,14 @@ class CI_Security {
*/
$str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str);
-
+
$str = preg_replace_callback("/<\w+.*?(?=>|<|$)/si", array($this, '_decode_entity'), $str);
/*
* Remove Invisible Characters Again!
*/
$str = remove_invisible_characters($str);
-
+
/*
* Convert all tabs to spaces
*
@@ -276,29 +276,29 @@ class CI_Security {
* so we use str_replace.
*
*/
-
+
if (strpos($str, "\t") !== FALSE)
{
$str = str_replace("\t", ' ', $str);
}
-
+
/*
* Capture converted string for later comparison
*/
$converted_string = $str;
-
+
/*
* Not Allowed Under Any Conditions
*/
-
+
foreach ($this->never_allowed_str as $key => $val)
{
- $str = str_replace($key, $val, $str);
+ $str = str_replace($key, $val, $str);
}
-
+
foreach ($this->never_allowed_regex as $key => $val)
{
- $str = preg_replace("#".$key."#i", $val, $str);
+ $str = preg_replace("#".$key."#i", $val, $str);
}
/*
@@ -321,7 +321,7 @@ class CI_Security {
{
$str = str_replace(array('<?', '?'.'>'), array('&lt;?', '?&gt;'), $str);
}
-
+
/*
* Compact any exploded words
*
@@ -333,7 +333,7 @@ class CI_Security {
foreach ($words as $word)
{
$temp = '';
-
+
for ($i = 0, $wordlen = strlen($word); $i < $wordlen; $i++)
{
$temp .= substr($word, $i, 1)."\s*";
@@ -343,7 +343,7 @@ class CI_Security {
// That way valid stuff like "dealer to" does not become "dealerto"
$str = preg_replace_callback('#('.substr($temp, 0, -3).')(\W)#is', array($this, '_compact_exploded_words'), $str);
}
-
+
/*
* Remove disallowed Javascript in links or img tags
* We used to do some version comparisons and use of stripos for PHP5, but it is dog slow compared
@@ -352,17 +352,17 @@ class CI_Security {
do
{
$original = $str;
-
+
if (preg_match("/<a/i", $str))
{
$str = preg_replace_callback("#<a\s+([^>]*?)(>|$)#si", array($this, '_js_link_removal'), $str);
}
-
+
if (preg_match("/<img/i", $str))
{
$str = preg_replace_callback("#<img\s+([^>]*?)(\s?/?>|$)#si", array($this, '_js_img_removal'), $str);
}
-
+
if (preg_match("/script/i", $str) OR preg_match("/xss/i", $str))
{
$str = preg_replace("#<(/*)(script|xss)(.*?)\>#si", '[removed]', $str);
@@ -385,14 +385,14 @@ class CI_Security {
if ($is_image === TRUE)
{
/*
- * Adobe Photoshop puts XML metadata into JFIF images, including namespacing,
+ * Adobe Photoshop puts XML metadata into JFIF images, including namespacing,
* so we have to allow this for images. -Paul
*/
unset($event_handlers[array_search('xmlns', $event_handlers)]);
}
$str = preg_replace("#<([^><]+?)(".implode('|', $event_handlers).")(\s*=\s*[^><]*)([><]*)#i", "<\\1\\4", $str);
-
+
/*
* Sanitize naughty HTML elements
*
@@ -420,7 +420,7 @@ class CI_Security {
*
*/
$str = preg_replace('#(alert|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2&#40;\\3&#41;", $str);
-
+
/*
* Final clean up
*
@@ -430,9 +430,9 @@ class CI_Security {
*/
foreach ($this->never_allowed_str as $key => $val)
{
- $str = str_replace($key, $val, $str);
+ $str = str_replace($key, $val, $str);
}
-
+
foreach ($this->never_allowed_regex as $key => $val)
{
$str = preg_replace("#".$key."#i", $val, $str);
@@ -457,13 +457,13 @@ class CI_Security {
return FALSE;
}
}
-
+
log_message('debug', "XSS Filtering completed");
return $str;
}
// --------------------------------------------------------------------
-
+
/**
* Random Hash for protecting URLs
*
@@ -471,22 +471,22 @@ class CI_Security {
* @return string
*/
function xss_hash()
- {
+ {
if ($this->xss_hash == '')
{
if (phpversion() >= 4.2)
mt_srand();
else
mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);
-
+
$this->xss_hash = md5(time() + mt_rand(0, 1999999999));
}
-
+
return $this->xss_hash;
}
// --------------------------------------------------------------------
-
+
/**
* Compact Exploded Words
*
@@ -501,9 +501,9 @@ class CI_Security {
{
return preg_replace('/\s+/s', '', $matches[1]).$matches[2];
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Sanitize Naughty HTML
*
@@ -517,15 +517,15 @@ class CI_Security {
{
// encode opening brace
$str = '&lt;'.$matches[1].$matches[2].$matches[3];
-
+
// encode captured opening or closing brace to prevent recursive vectors
$str .= str_replace(array('>', '<'), array('&gt;', '&lt;'), $matches[4]);
-
+
return $str;
}
-
+
// --------------------------------------------------------------------
-
+
/**
* JS Link Removal
*
@@ -543,7 +543,7 @@ class CI_Security {
$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));
return str_replace($match[1], preg_replace("#href=.*?(alert\(|alert&\#40;|javascript\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);
}
-
+
/**
* JS Image Removal
*
@@ -563,7 +563,7 @@ class CI_Security {
}
// --------------------------------------------------------------------
-
+
/**
* Attribute Conversion
*
@@ -577,7 +577,7 @@ class CI_Security {
{
return str_replace(array('>', '<', '\\'), array('&gt;', '&lt;', '\\\\'), $match[0]);
}
-
+
// --------------------------------------------------------------------
/**
@@ -644,35 +644,35 @@ class CI_Security {
function entity_decode($str, $charset='UTF-8')
{
if (stristr($str, '&') === FALSE) return $str;
-
+
// The reason we are not using html_entity_decode() by itself is because
// while it is not technically correct to leave out the semicolon
// at the end of an entity most browsers will still interpret the entity
// correctly. html_entity_decode() does not convert entities without
// semicolons, so we are left with our own little solution here. Bummer.
-
+
if (function_exists('html_entity_decode') && (strtolower($charset) != 'utf-8' OR is_php('5.0.0')))
{
$str = html_entity_decode($str, ENT_COMPAT, $charset);
$str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str);
return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str);
}
-
+
// Numeric Entities
$str = preg_replace('~&#x(0*[0-9a-f]{2,5});{0,1}~ei', 'chr(hexdec("\\1"))', $str);
$str = preg_replace('~&#([0-9]{2,4});{0,1}~e', 'chr(\\1)', $str);
-
+
// Literal Entities - Slightly slow so we do another check
if (stristr($str, '&') === FALSE)
{
$str = strtr($str, array_flip(get_html_translation_table(HTML_ENTITIES)));
}
-
+
return $str;
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Filename Security
*
@@ -680,11 +680,10 @@ class CI_Security {
* @param string
* @return string
*/
- function sanitize_filename($str)
+ function sanitize_filename($str, $relative_path = FALSE)
{
$bad = array(
"../",
- "./",
"<!--",
"-->",
"<",
@@ -701,22 +700,27 @@ class CI_Security {
'=',
';',
'?',
- '/',
"%20",
"%22",
"%3c", // <
- "%253c", // <
- "%3e", // >
- "%0e", // >
- "%28", // (
- "%29", // )
- "%2528", // (
- "%26", // &
- "%24", // $
- "%3f", // ?
- "%3b", // ;
+ "%253c", // <
+ "%3e", // >
+ "%0e", // >
+ "%28", // (
+ "%29", // )
+ "%2528", // (
+ "%26", // &
+ "%24", // $
+ "%3f", // ?
+ "%3b", // ;
"%3d" // =
);
+
+ if ( ! $relative_path)
+ {
+ $bad[] = './';
+ $bad[] = '/';
+ }
return stripslashes(str_replace($bad, '', $str));
}