* @license http://www.contenido.org/license/LIZENZ.txt * @link http://www.4fb.de * @link http://www.contenido.org * @since file available since contenido release <= 4.6 * * @TODO: Some features are the same as in Contenido_Security (see contenido/classes/class.security.php), * merge them... * * {@internal * created 2008-02-06 * modified 2008-06-10, I. van Peeren, initially set $this->bLog as $bLog in config file * modified 2008-07-02, Frederic Schneider, add security fix * * $Id$: * }} * */ if(!defined('CON_FRAMEWORK')) { die('Illegal call'); } #### FORMAT CONSTANTS #### define('CON_CHECK_INTEGER', '/^[0-9]*$/'); // integer value define('CON_CHECK_PRIMITIVESTRING', '/^[a-zA-Z0-9 -_]*$/'); // simple string define('CON_CHECK_STRING', '/^[\w0-9 -_]*$/'); // more complex string define('CON_CHECK_HASH32', '/^[a-zA-Z0-9]{32}$/'); // 32-character hash /** * This class is the extended version of excelent * code made by kummer. * * @version 1.0.1 * @see http://contenido.org/forum/viewtopic.php?p=113492#113492 */ class HttpInputValidator { /** * Associative array with available POST parameter name as * key and flag whether this parameter is "clean" or not. * * @var array */ var $aPostVariables = array(); /** * Path and filename of logfile * * @var string */ var $sLogPath = ''; /** * Flag whether to write log or not. * * @var boolean */ var $bLog = false; /** * Path to config file. * * @var string */ var $sConfigPath = ''; /** * Array with all possible parameters and parameter formats. * Structure has to be: * * * $check['GET']['param1'] = VALIDATE_FORMAT; * $check['POST']['param2'] = VALIDATE_FORMAT; * * * Possible formats are defined as constants in top of these class file. * * @var array */ var $aCheck = array(); /** * Contains first invalid parameter name. * * @var string */ var $sFailure = ''; /** * Current mode * * @var string */ var $sMode = 'training'; /** * Constructor * * Configuration path $sConfigPath is mandatory and has to contain the complete * path to configuration file with defined parameters. * * The class provides two modes: training and arcade. * Training mode only logs violations - if log path is given into log file otherwise * as comment into HTML output. Arcade mode is made for killing - every violation will * cause an hard exit! * * @param string $sConfigPath * @return HttpInputValidator */ function __construct($sConfigPath) { // check config and logging path if (!empty($sConfigPath) && file_exists($sConfigPath)) { $this->sConfigPath = realpath($sConfigPath); } else { die ('Could not load HttpInputValidator configuration! (invalid path)'); } // include configuration require ($this->sConfigPath); // if custom config exists, include it also here if (file_exists(dirname($this->sConfigPath) . '/config.http_check.local.php')) { require (dirname($this->sConfigPath) . '/config.http_check.local.php'); } $this->bLog = $bLog; if ($this->bLog === true) { if (!empty($sLogPath) && is_writable(dirname($sLogPath))) { $this->sLogPath = realpath($sLogPath); } else { die ('Could not log into not existing or empty log path!'); } } $this->aCheck = $aCheck; // run GET check if ($this->checkGetParams()) { // logging is needed in both modes, training and arcade $this->logHackTrial(); // stops here in case of arcade mode if ($sMode == 'arcade') { ob_end_clean(); die ('Parameter check failed! (' . $this->sFailure . ')'); } } // check POST params for further processings $this->checkPostParams(); } /** * Checks all GET params and returns true in case of a violation, otherwise false. * * @return bool */ function checkGetParams () { $bResult = false; foreach ($_GET as $sKey => $mValue) { if (!$this->checkParameter('GET', $sKey, $mValue)) { $this->sFailure = $sKey; $bResult = true; break; } } return $bResult; } /** * Fills status-array $aPostVariables. Is POST-param known and valid mapped value is true. * */ function checkPostParams () { foreach ($_POST as $sKey => $mValue) { $this->aPostVariables[$sKey] = ($this->checkParameter('POST', $sKey, $mValue)) ? (true) : (false); } } /** * This method checks parameter of type $sType (currently GET and POST * are supported) and name $sKey has valid value $mValue. In this case or * in case of unknown but empty params, the method will also return true. * * @param string $sType * @param string $sKey * @param mixed $mValue * @return bool */ function checkParameter ($sType, $sKey, $mValue) { $bResult = false; if (in_array(strtoupper($sType), array('GET', 'POST'))) { if (!isset($this->aCheck[$sType][$sKey]) && (is_null($mValue) || empty($mValue))) { // if unknown but empty the value is unaesthetic but ok $bResult = true; } elseif (isset($this->aCheck[$sType][$sKey])) { // parameter is known, check it... $bResult = preg_match($this->aCheck[$sType][$sKey], $mValue); } } return $bResult; } /** * Tries to log date, remote ip and the requested URI into log file. */ function logHackTrial() { if ($this->bLog === true && !empty($this->sLogPath)) { if (($rLogFile = @fopen($this->sLogPath, 'a')) !== false) { fwrite($rLogFile, date('Y-m-d H:i:s')); fwrite($rLogFile, ' '); fwrite($rLogFile, $_SERVER['REMOTE_ADDR'] . str_repeat(' ', 17 - strlen($_SERVER['REMOTE_ADDR']))); fwrite($rLogFile, $_SERVER['QUERY_STRING']); fwrite($rLogFile, "\n"); fclose($rLogFile); } } elseif ($this->sMode == 'training') { echo "\n
VIOLATION: URL contains invalid or undefined paramaters! URL: '" . clHtmlEntities($_SERVER['QUERY_STRING']) . "'
\n"; } } /** * Print html comment or returns (depending on flag $bReturn) all POST params. * * @return string */ function showPosts($bReturn = false) { $sResult = ''; foreach ($_POST as $sKey => $sValue) { $sResult .= $key . ": "; if (is_null($this->isRegularPost($sKey))) { $sResult .= "not defined"; } else if ($this->isRegularPost($key) === false) { $sResult .= "iregular"; } else { $sResult .= "ok"; } $sResult .= "\n"; } if ($bReturn === false) { $sResult = "\n\n\n\n"; echo $sResult; } else { return $sResult; } } /** * Checks POST param $sKey is unknown (result is null), known but invalid (result is false) * or it is known and valid (result is true). * * @param string $sKey * @return mixed */ function isRegularPost($sKey) { $mResult = null; if (isset ($this->postVariable[$sKey])) { $mResult = $this->postVariable[$sKey]; } return $mResult; } } ?>