Security Issues - Improvements

- Se añadieron validaciones para sanitizar los valores enviados.
This commit is contained in:
Marco Antonio Nina
2013-11-15 15:29:07 -04:00
parent 096480f308
commit e40ca19dcc
6 changed files with 393 additions and 6 deletions

View File

@@ -5230,6 +5230,23 @@ class G
} }
return in_array(strtolower($functionName), $allFunctions['user']); return in_array(strtolower($functionName), $allFunctions['user']);
} }
/**
* Constructor for inputFilter class. Only first parameter is required.
* @access constructor
* @data Mixed - input string/array-of-string to be 'cleaned'
* @param Array $tagsArray - list of user-defined tags
* @param Array $attrArray - list of user-defined attributes
* @param int $tagsMethod - 0= allow just user-defined, 1= allow all but user-defined
* @param int $attrMethod - 0= allow just user-defined, 1= allow all but user-defined
* @param int $xssAuto - 0= only auto clean essentials, 1= allow clean blacklisted tags/attr
*/
public function sanitizeInput($data, $tagsArray = array(), $attrArray = array(), $tagsMethod = 0, $attrMethod = 0, $xssAuto = 1)
{
G::LoadSystem('inputfilter');
$filtro = new InputFilter($tagsArray , $attrArray, $tagsMethod, $attrMethod, $xssAuto);
return $filtro->process($data);
}
} }
/** /**

View File

@@ -0,0 +1,368 @@
<?php
/** @class: InputFilter (PHP4 & PHP5, with comments)
* @project: PHP Input Filter
* @date: 10-05-2005
* @version: 1.2.2_php4/php5
* @author: Daniel Morris
* @contributors: Gianpaolo Racca, Ghislain Picard, Marco Wandschneider, Chris Tobin and Andrew Eddie.
* @copyright: Daniel Morris
* @email: dan@rootcube.com
* @license: GNU General Public License (GPL)
*/
class InputFilter
{
public $tagsArray;// default = empty array
public $attrArray;// default = empty array
public $tagsMethod;// default = 0
public $attrMethod;// default = 0
public $xssAuto; // default = 1
public $tagBlacklist = array('applet', 'body', 'bgsound', 'base', 'basefont', 'embed', 'frame', 'frameset', 'head', 'html', 'id', 'iframe', 'ilayer', 'layer', 'link', 'meta', 'name', 'object', 'script', 'style', 'title', 'xml');
public $attrBlacklist = array('action', 'background', 'codebase', 'dynsrc', 'lowsrc'); // also will strip ALL event handlers
/**
* Constructor for inputFilter class. Only first parameter is required.
* @access constructor
* @param Array $tagsArray - list of user-defined tags
* @param Array $attrArray - list of user-defined attributes
* @param int $tagsMethod - 0= allow just user-defined, 1= allow all but user-defined
* @param int $attrMethod - 0= allow just user-defined, 1= allow all but user-defined
* @param int $xssAuto - 0= only auto clean essentials, 1= allow clean blacklisted tags/attr
*/
public function inputFilter($tagsArray = array(), $attrArray = array(), $tagsMethod = 0, $attrMethod = 0, $xssAuto = 1)
{
// make sure user defined arrays are in lowercase
for ($i = 0; $i < count($tagsArray); $i++) {
$tagsArray[$i] = strtolower($tagsArray[$i]);
}
for ($i = 0; $i < count($attrArray); $i++) {
$attrArray[$i] = strtolower($attrArray[$i]);
}
// assign to member vars
$this->tagsArray = (array) $tagsArray;
$this->attrArray = (array) $attrArray;
$this->tagsMethod = $tagsMethod;
$this->attrMethod = $attrMethod;
$this->xssAuto = $xssAuto;
}
/**
* Method to be called by another php script. Processes for XSS and specified bad code.
* @access public
* @param Mixed $source - input string/array-of-string to be 'cleaned'
* @return String $source - 'cleaned' version of input parameter
*/
public function process($source)
{
// clean all elements in this array
if (is_array($source)) {
foreach ($source as $key => $value) {
// filter element for XSS and other 'bad' code etc.
if (is_string($value)) {
$source[$key] = $this->remove($this->decode($value));
}
}
return $source;
// clean this string
} elseif (is_string($source)) {
// filter source for XSS and other 'bad' code etc.
return $this->remove($this->decode($source));
} else {
// return parameter as given
return $source;
}
}
/**
* Internal method to iteratively remove all unwanted tags and attributes
* @access protected
* @param String $source - input string to be 'cleaned'
* @return String $source - 'cleaned' version of input parameter
*/
public function remove($source)
{
$loopCounter=0;
// provides nested-tag protection
while ($source != $this->filterTags($source)) {
$source = $this->filterTags($source);
$loopCounter++;
}
return $source;
}
/**
* Internal method to strip a string of certain tags
* @access protected
* @param String $source - input string to be 'cleaned'
* @return String $source - 'cleaned' version of input parameter
*/
public function filterTags($source)
{
// filter pass setup
$preTag = null;
$postTag = $source;
// find initial tag's position
$tagOpen_start = strpos($source, '<');
// interate through string until no tags left
while ($tagOpen_start !== false) {
// process tag interatively
$preTag .= substr($postTag, 0, $tagOpen_start);
$postTag = substr($postTag, $tagOpen_start);
$fromTagOpen = substr($postTag, 1);
// end of tag
$tagOpen_end = strpos($fromTagOpen, '>');
if ($tagOpen_end === false) {
break;
}
// next start of tag (for nested tag assessment)
$tagOpen_nested = strpos($fromTagOpen, '<');
if (($tagOpen_nested !== false) && ($tagOpen_nested < $tagOpen_end)) {
$preTag .= substr($postTag, 0, ($tagOpen_nested+1));
$postTag = substr($postTag, ($tagOpen_nested+1));
$tagOpen_start = strpos($postTag, '<');
continue;
}
$tagOpen_nested = (strpos($fromTagOpen, '<') + $tagOpen_start + 1);
$currentTag = substr($fromTagOpen, 0, $tagOpen_end);
$tagLength = strlen($currentTag);
if (!$tagOpen_end) {
$preTag .= $postTag;
$tagOpen_start = strpos($postTag, '<');
}
// iterate through tag finding attribute pairs - setup
$tagLeft = $currentTag;
$attrSet = array();
$currentSpace = strpos($tagLeft, ' ');
// is end tag
if (substr($currentTag, 0, 1) == "/") {
$isCloseTag = true;
list($tagName) = explode(' ', $currentTag);
$tagName = substr($tagName, 1);
// is start tag
} else {
$isCloseTag = false;
list($tagName) = explode(' ', $currentTag);
}
// excludes all "non-regular" tagnames OR no tagname OR remove if xssauto is on and tag is blacklisted
if ((!preg_match("/^[a-z][a-z0-9]*$/i",$tagName)) || (!$tagName) || ((in_array(strtolower($tagName), $this->tagBlacklist)) && ($this->xssAuto))) {
$postTag = substr($postTag, ($tagLength + 2));
$tagOpen_start = strpos($postTag, '<');
// don't append this tag
continue;
}
// this while is needed to support attribute values with spaces in!
while ($currentSpace !== false) {
$fromSpace = substr($tagLeft, ($currentSpace+1));
$nextSpace = strpos($fromSpace, ' ');
$openQuotes = strpos($fromSpace, '"');
$closeQuotes = strpos(substr($fromSpace, ($openQuotes+1)), '"') + $openQuotes + 1;
// another equals exists
if (strpos($fromSpace, '=') !== false) {
// opening and closing quotes exists
if (($openQuotes !== false) && (strpos(substr($fromSpace, ($openQuotes+1)), '"') !== false)) {
$attr = substr($fromSpace, 0, ($closeQuotes+1));
} else {
// one or neither exist
$attr = substr($fromSpace, 0, $nextSpace);
}
// no more equals exist
} else {
$attr = substr($fromSpace, 0, $nextSpace);
}
// last attr pair
if (!$attr) {
$attr = $fromSpace;
}
// add to attribute pairs array
$attrSet[] = $attr;
// next inc
$tagLeft = substr($fromSpace, strlen($attr));
$currentSpace = strpos($tagLeft, ' ');
}
// appears in array specified by user
$tagFound = in_array(strtolower($tagName), $this->tagsArray);
// remove this tag on condition
if ((!$tagFound && $this->tagsMethod) || ($tagFound && !$this->tagsMethod)) {
// reconstruct tag with allowed attributes
if (!$isCloseTag) {
$attrSet = $this->filterAttr($attrSet);
$preTag .= '<' . $tagName;
for ($i = 0; $i < count($attrSet); $i++) {
$preTag .= ' ' . $attrSet[$i];
}
// reformat single tags to XHTML
if (strpos($fromTagOpen, "</" . $tagName)) {
$preTag .= '>';
} else {
$preTag .= ' />';
}
// just the tagname
} else {
$preTag .= '</' . $tagName . '>';
}
}
// find next tag's start
$postTag = substr($postTag, ($tagLength + 2));
$tagOpen_start = strpos($postTag, '<');
}
// append any code after end of tags
$preTag .= $postTag;
return $preTag;
}
/**
* Internal method to strip a tag of certain attributes
* @access protected
* @param Array $attrSet
* @return Array $newSet
*/
public function filterAttr($attrSet)
{
$newSet = array();
// process attributes
for ($i = 0; $i <count($attrSet); $i++) {
// skip blank spaces in tag
if (!$attrSet[$i]) {
continue;
}
// split into attr name and value
$attrSubSet = explode('=', trim($attrSet[$i]));
list($attrSubSet[0]) = explode(' ', $attrSubSet[0]);
// removes all "non-regular" attr names AND also attr blacklisted
if ((!eregi("^[a-z]*$",$attrSubSet[0])) || (($this->xssAuto) && ((in_array(strtolower($attrSubSet[0]), $this->attrBlacklist)) || (substr($attrSubSet[0], 0, 2) == 'on')))) {
continue;
}
// xss attr value filtering
if ($attrSubSet[1]) {
// strips unicode, hex, etc
$attrSubSet[1] = str_replace('&#', '', $attrSubSet[1]);
// strip normal newline within attr value
$attrSubSet[1] = preg_replace('/\s+/', '', $attrSubSet[1]);
// strip double quotes
$attrSubSet[1] = str_replace('"', '', $attrSubSet[1]);
// [requested feature] convert single quotes from either side to doubles (Single quotes shouldn't be used to pad attr value)
if ((substr($attrSubSet[1], 0, 1) == "'") && (substr($attrSubSet[1], (strlen($attrSubSet[1]) - 1), 1) == "'")) {
$attrSubSet[1] = substr($attrSubSet[1], 1, (strlen($attrSubSet[1]) - 2));
}
// strip slashes
$attrSubSet[1] = stripslashes($attrSubSet[1]);
}
// auto strip attr's with "javascript:
if (((strpos(strtolower($attrSubSet[1]), 'expression') !== false) &&(strtolower($attrSubSet[0]) == 'style')) ||
(strpos(strtolower($attrSubSet[1]), 'javascript:') !== false) ||
(strpos(strtolower($attrSubSet[1]), 'behaviour:') !== false) ||
(strpos(strtolower($attrSubSet[1]), 'vbscript:') !== false) ||
(strpos(strtolower($attrSubSet[1]), 'mocha:') !== false) ||
(strpos(strtolower($attrSubSet[1]), 'livescript:') !== false)
) {
continue;
}
// if matches user defined array
$attrFound = in_array(strtolower($attrSubSet[0]), $this->attrArray);
// keep this attr on condition
if ((!$attrFound && $this->attrMethod) || ($attrFound && !$this->attrMethod)) {
// attr has value
if ($attrSubSet[1]) {
$newSet[] = $attrSubSet[0] . '="' . $attrSubSet[1] . '"';
} elseif ($attrSubSet[1] == "0") {
// attr has decimal zero as value
$newSet[] = $attrSubSet[0] . '="0"';
} else {
// reformat single attributes to XHTML
$newSet[] = $attrSubSet[0] . '="' . $attrSubSet[0] . '"';
}
}
}
return $newSet;
}
/**
* Try to convert to plaintext
* @access protected
* @param String $source
* @return String $source
*/
public function decode($source)
{
// url decode
$source = html_entity_decode($source, ENT_QUOTES, "ISO-8859-1");
// convert decimal
$source = preg_replace('/&#(\d+);/me',"chr(\\1)", $source);// decimal notation
// convert hex
$source = preg_replace('/&#x([a-f0-9]+);/mei',"chr(0x\\1)", $source);// hex notation
return $source;
}
/**
* Method to be called by another php script. Processes for SQL injection
* @access public
* @param Mixed $source - input string/array-of-string to be 'cleaned'
* @param Buffer $connection - An open MySQL connection
* @return String $source - 'cleaned' version of input parameter
*/
public function safeSQL($source, &$connection)
{
// clean all elements in this array
if (is_array($source)) {
foreach ($source as $key => $value) {
// filter element for SQL injection
if (is_string($value)) {
$source[$key] = $this->quoteSmart($this->decode($value), $connection);
}
}
return $source;
// clean this string
} elseif (is_string($source)) {
// filter source for SQL injection
if (is_string($source)) {
return $this->quoteSmart($this->decode($source), $connection);
}
// return parameter as given
} else {
return $source;
}
}
/**
* @author Chris Tobin
* @author Daniel Morris
* @access protected
* @param String $source
* @param Resource $connection - An open MySQL connection
* @return String $source
*/
public function quoteSmart($source, &$connection)
{
// strip slashes
if (get_magic_quotes_gpc()) {
$source = stripslashes($source);
}
// quote both numeric and text
$source = $this->escapeString($source, $connection);
return $source;
}
/**
* @author Chris Tobin
* @author Daniel Morris
* @access protected
* @param String $source
* @param Resource $connection - An open MySQL connection
* @return String $source
*/
public function escapeString($string, &$connection)
{
// depreciated function
if (version_compare(phpversion(),"4.3.0", "<")) {
mysql_escape_string($string);
} else {
// current function
mysql_real_escape_string($string);
}
return $string;
}
}

View File

@@ -155,7 +155,7 @@ class Dashboard extends Controller
if ($data->DAS_INS_UID == '') { if ($data->DAS_INS_UID == '') {
throw new Exception( 'Parameter "DAS_INS_UID" is empty.' ); throw new Exception( 'Parameter "DAS_INS_UID" is empty.' );
} }
$this->pmDashlet->setup( $data->DAS_INS_UID ); $this->pmDashlet->setup( G::sanitizeInput($data->DAS_INS_UID) );
if (! isset( $_REQUEST['w'] )) { if (! isset( $_REQUEST['w'] )) {
$width = 300; $width = 300;

View File

@@ -1,5 +1,7 @@
<?php <?php
$action = isset( $_GET['action'] ) ? $_GET['action'] : 'default';
$action = isset( $_GET['action'] ) ? G::sanitizeInput($_GET['action']) : 'default';
G::LoadClass( 'case' ); G::LoadClass( 'case' );
G::LoadClass( 'configuration' ); G::LoadClass( 'configuration' );
$userId = isset( $_SESSION['USER_LOGGED'] ) ? $_SESSION['USER_LOGGED'] : '00000000000000000000000000000000'; $userId = isset( $_SESSION['USER_LOGGED'] ) ? $_SESSION['USER_LOGGED'] : '00000000000000000000000000000000';

View File

@@ -240,14 +240,14 @@ try {
if (strpos($_SERVER['HTTP_REFERER'], 'processes/processes_Map?PRO_UID=') !== false) { if (strpos($_SERVER['HTTP_REFERER'], 'processes/processes_Map?PRO_UID=') !== false) {
$sLocation = $_SERVER['HTTP_REFERER']; $sLocation = $_SERVER['HTTP_REFERER'];
} else { } else {
$sLocation = $_REQUEST['form']['URL']; $sLocation = G::sanitizeInput($_REQUEST['form']['URL']);
} }
} else { } else {
$sLocation = $_REQUEST['form']['URL']; $sLocation = G::sanitizeInput($_REQUEST['form']['URL']);
} }
} else { } else {
if (isset($_REQUEST['u']) && $_REQUEST['u'] != '') { if (isset($_REQUEST['u']) && $_REQUEST['u'] != '') {
$sLocation = $_REQUEST['u']; $sLocation = G::sanitizeInput($_REQUEST['u']);
} else { } else {
$sLocation = $oUserProperty->redirectTo($_SESSION['USER_LOGGED'], $lang); $sLocation = $oUserProperty->redirectTo($_SESSION['USER_LOGGED'], $lang);
} }

View File

@@ -1,7 +1,7 @@
<?php <?php
ob_start(); ob_start();
$request = isset( $_POST['request'] ) ? $_POST['request'] : (isset( $_GET['request'] ) ? $_GET['request'] : null); $request = isset( $_POST['request'] ) ? G::sanitizeInput($_POST['request']) : (isset( $_GET['request'] ) ? G::sanitizeInput($_GET['request']) : null);
switch ($request) { switch ($request) {
case 'loadMenu': case 'loadMenu':