/** * Returns an instance of StringValidationRule constructed with a regex * pattern for validating Credit Card Numbers obtained from the ESAPI * SecurityConfiguration. * * @return object object of type StringValidationRule. */ private function _getCCRule() { global $ESAPI; $config = ESAPI::getSecurityConfiguration(); $pattern = $config->getValidationPattern(self::CREDIT_CARD_VALIDATOR_KEY); $ccr = new StringValidationRule('CreditCardValidator', $this->encoder, $pattern); $ccr->setMaximumLength(19); $ccr->setAllowNull(false); return $ccr; }
/** * Creates a new instance of EnterpriseSecurityException that includes a * root cause. * * @param string $userMessage The message displayed to the user * @param string $logMessage the message logged */ public function __construct($userMessage = '', $logMessage = '') { $cause = 0; if (empty($userMessage)) { $userMessage = null; } parent::__construct($userMessage); $this->logMessage = $logMessage; $this->logger = ESAPI::getAuditor("EnterpriseSecurityException"); if (!ESAPI::getSecurityConfiguration()->getDisableIntrusionDetection()) { ESAPI::getIntrusionDetector()->addException($this); } }
<?php /** * OWASP Enterprise Security API (ESAPI) * * This file is part of the Open Web Application Security Project (OWASP) * Enterprise Security API (ESAPI) project. * * PHP version 5.2 * * LICENSE: This source file is subject to the New BSD license. You should read * and accept the LICENSE before you use, modify, and/or redistribute this * software. * * @category OWASP * @package ESAPI * @author Andrew van der Stock <*****@*****.**> * @author Mike Boberski <*****@*****.**> * @copyright 2009-2011 The OWASP Foundation * @license http://www.opensource.org/licenses/bsd-license.php New BSD license * @version SVN: $Id$ * @link http://www.owasp.org/index.php/ESAPI */ error_reporting(E_ALL | ~E_STRICT); require_once __DIR__ . '/../src/ESAPI.php'; ESAPI::getSecurityConfiguration(__DIR__ . '/testresources/ESAPI.xml'); session_start(); // For HTTPUtilities;
/** * Implements corresponding isValidXX logic. * * @param string $context Please see corresponding isValidXX description. * @param string $input Please see corresponding isValidXX description. * @param int $maxBytes Please see corresponding isValidXX description. * @param bool $allowNull Please see corresponding isValidXX description. * * @return does not return a value. * @throws ValidationException thrown if input is invalid. * @throws IntrusionException thrown if intrusion is detected. */ private function _assertValidFileContent($context, $input, $maxBytes, $allowNull) { if (!is_string($context)) { $context = 'Validate File Content'; } if (!is_string($input) && $input !== null) { throw new ValidationException("{$context}: Input required", "Input was not a string or NULL: context={$context}", $context); } if (!is_numeric($maxBytes) || $maxBytes < 0) { $this->_auditor->warning(ESAPILogger::SECURITY, false, 'assertValidFileContent expected $maxBytes as positive integer.' . ' Falling back to AllowedFileUploadSize.'); $maxBytes = null; } if ($input === null || $input == '') { if ($this->allowNull) { return null; } throw new ValidationException("{$context}: Input required", "Input required: context={$context}", $context); } $config = ESAPI::getSecurityConfiguration(); $esapiMaxBytes = $config->getAllowedFileUploadSize(); $charEnc = mb_detect_encoding($input); $inputLen = mb_strlen($input, $charEnc); if ($inputLen > $esapiMaxBytes) { throw new ValidationException("{$context}: Invalid file content. Size must not exceed " . "{$esapiMaxBytes} bytes.", "Invalid file content. Input ({$inputLen} bytes) exceeds " . "AllowedFileUploadSize ({$esapiMaxBytes} bytes.)", $context); } if ($maxBytes !== null && $inputLen > $maxBytes) { throw new ValidationException("{$context}: Invalid file content. Size must not exceed " . "{$maxBytes} bytes.", "Invalid file content. Input ({$inputLen} bytes) exceeds " . "maximum of ({$esapiMaxBytes} bytes.)", $context); } return null; }
/** * Private constructor ensures CodecDebug can only be instantiated privately. * Stores boolean true in $_enabled if SepcialDebugging is enabled. This object * will only produce output if $_enabled is true. * * @return null */ private function __construct() { $this->_enabled = ESAPI::getSecurityConfiguration()->getSpecialDebugging(); }
/** * Helper function. * * Configures Apache's Log4PHP RootLogger based on values obtained from the * ESAPI properties file. All instances of Log4PHP Logger will inherit the * configuration. * * @return does not return a value. */ private static function _initialise() { self::$_initialised = true; $secConfig = ESAPI::getSecurityConfiguration(); $logLevel = $secConfig->getLogLevel(); // Patterns representing the format of Log entries // d date, p priority (level), m message, n newline $dateFormat = $secConfig->getLogFileDateFormat(); $logfileLayoutPattern = "%d{{$dateFormat}} %m %n"; // LogFile properties. $logFileName = $secConfig->getLogFileName(); $maxLogFileSize = $secConfig->getMaxLogFileSize(); $maxLogFileBackups = $secConfig->getMaxLogFileBackups(); // LogFile layout $logfileLayout = new LoggerLayoutPattern(); $logfileLayout->setConversionPattern($logfileLayoutPattern); // LogFile RollingFile Appender $appenderLogfile = new LoggerAppenderRollingFile('ESAPI LogFile'); $appenderLogfile->setFile($logFileName, true); $appenderLogfile->setMaxFileSize($maxLogFileSize); $appenderLogfile->setMaxBackupIndex($maxLogFileBackups); $appenderLogfile->setLayout($logfileLayout); if ($logLevel !== 'OFF') { $appenderLogfile->activateOptions(); } // Get the RootLogger and reset it, before adding our Appenders and // setting our Loglevel $rootLogger = Logger::getRootLogger(); $rootLogger->removeAllAppenders(); $rootLogger->addAppender($appenderLogfile); $rootLogger->setLevel(self::_convertESAPILeveltoLoggerLevel($logLevel)); }
/** * Helper method uses the supplied parameters to construct a pattern for * preg_match and which attempts to model log entries. It is important to * note that if changes are made to the format of log entries {@see * DefaultLogger::log()} then this method will need to be modified * accordingly. * * @param $level string uppercase log level. * @param $type string uppercase log entry type. * @param $success boolean true for a success log event, false otherwise. * @param $msg string log message as passed to the DefaultLogger method. * @param $exceptionClassName string optional class name of an exception * passed to DefaultLogger methods. * * @return string pattern (incl. terminators) for preg_match(). */ private function getExpected($level, $type, $success, $msg, $exceptionClassName = null) { $date = '[0-9-]{10,10} [0-9:]{8,8} [+-][0-9:]{5,5}'; $success = $success ? '-SUCCESS' : '-FAILURE'; $appName = ESAPI::getSecurityConfiguration()->getLogApplicationName() === true ? ' ' . ESAPI::getSecurityConfiguration()->getApplicationName() : ''; $name = __CLASS__; $serverName = '((?:(?:[0-9a-zA-Z][0-9a-zA-Z\\-]{0,61}[0-9a-zA-Z])\\.)*[a-zA-Z]{2,4}|[0-9a-zA-Z][0-9a-zA-Z\\-]{0,61}[0-9a-zA-Z]|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))'; $localSocket = "{$serverName}:[0-9]{1,5}"; $username = '******'; $remoteAddr = '([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|UnknownRemoteHost)'; $sessionID = '([0-9]{1,7}|SessionUnknown)'; if ($exceptionClassName !== null) { $msg .= " exception '{$exceptionClassName}'"; } return "{$date} {$level}{$appName} {$name} {$type}{$success} {$localSocket} {$username}{$remoteAddr}\\[ID:{$sessionID}\\] {$msg}"; }
/** * Adds a security event. These events are used to check that the user has * not reached the security thresholds set in the properties file. If a PHP * session has been started the events are stored there, otherwise they are * merely stored as an instance property. This means that if a session has * not been started prior to calling this function then events will not be * tracked across requests. * * @param string $eventName The name of the event that occurred. * * @return null */ private function _addSecurityEvent($eventName) { // if there is a threshold, then track this event $threshold = ESAPI::getSecurityConfiguration()->getQuota($eventName); if ($threshold === null) { return; } // determine the storage for events if (isset($_SESSION)) { if (!array_key_exists('ESAPI', $_SESSION)) { $_SESSION['ESAPI'] = array(); } if (!array_key_exists('IntrusionDetector', $_SESSION['ESAPI'])) { $_SESSION['ESAPI']['IntrusionDetector'] = array(); } if (!array_key_exists('UserEvents', $_SESSION['ESAPI']['IntrusionDetector'])) { $_SESSION['ESAPI']['IntrusionDetector']['UserEvents'] = array(); } // If a session was started after events existed then ensure those // events are added to the session store if (is_array($this->_userEvents) && $this->_userEvents !== $_SESSION['ESAPI']['IntrusionDetector']['UserEvents']) { $_SESSION['ESAPI']['IntrusionDetector']['UserEvents'] = $this->_userEvents; } // Assign a reference to the session store $this->_userEvents =& $_SESSION['ESAPI']['IntrusionDetector']['UserEvents']; } else { if (!isset($this->_userEvents)) { $this->_userEvents = array(); } } $event = null; if (array_key_exists($eventName, $this->_userEvents)) { $event = $this->_userEvents[$eventName]; } if ($event == null) { $this->_userEvents[$eventName] = new Event($eventName); $event = $this->_userEvents[$eventName]; } if ($threshold->count > 0) { $event->increment($threshold->count, $threshold->interval); } }
/** * Add a hash to a User's hashed password list. This method is used to store a user's old password hashes * to be sure that any new passwords are not too similar to old passwords. * * @param user * the user to associate with the new hash * @param hash * the hash to store in the user's password hash list */ private function setHashedPassword($user, $hash) { $hashes = $this->getAllHashedPasswords($user, true); $hashes[0] = $hash; if (count($hashes) > ESAPI::getSecurityConfiguration()->getMaxOldPasswordHashes()) { //TODO: Verify array_pop($hashes); } $this->logger->info(ESAPILogger::SECURITY, TRUE, "New hashed password stored for " . $user->getAccountName()); }
/** * Executor constructor. * * @return does not return a value. */ public function __construct() { $this->_auditor = ESAPI::getAuditor('Executor'); $this->_config = ESAPI::getSecurityConfiguration(); }
public function __construct($accountName) { $this->setAccountName($accountName); //TODO: Not the best way IMHO. I'd rather call the method via factory object each time. Needs discussion.. $this->IDLE_TIMEOUT_LENGTH = ESAPI::getSecurityConfiguration()->getSessionIdleTimeoutLength(); $this->ABSOLUTE_TIMEOUT_LENGTH = ESAPI::getSecurityConfiguration()->getSessionAbsoluteTimeoutLength(); do { $id = ESAPI::getRandomizer()->getRandomLong(); if (ESAPI::getAuthenticator()->getUserById($id) == null && $id != 0) { $this->setAccountID($id); } } while ($this->getAccountID() == 0); }
/** * Helper returns the ESAPILogger log file absolute path. * * @return string|bool RealPath for the ESAPI Auditor log file or * false. */ function getLogFileLoc() { $filename = ESAPI::getSecurityConfiguration()->getLogFileName(); return realpath($filename); }
/** * Test constructor of class SafeFile with Invalid path. * * @return bool True on Pass. */ function testSafeFileLowByteInFileName() { $config = ESAPI::getSecurityConfiguration(); $file = $config->getResourceDirectory() . "/ESAPI" . chr(8) . ".xml"; $this->setExpectedException('EnterpriseSecurityException'); $sf = new SafeFile($file); }
/** * This test will trigger IDS at a point which demonstrates the calculation * of event intervals. Using a threshold that triggers after 5 events * within 5 seconds, four events will occur at 1 second intervals, then a * pause of 3 seconds and then 3 more events in quick succession. IDS * should not trigger until the 7th event. * * * * e e e e eee * |-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-| * 0 1 2 3 4 5 6 7 8 * |___________________| * 5 second interval * * @return bool True on Pass. */ public function testSlidingInterval() { if ($this->_logFileLoc === false) { $this->fail('Cannot perform this test because the log file cannot be found.'); } $eventName = 'SlidingIntervalTestEvent'; $threshold = ESAPI::getSecurityConfiguration()->getQuota($eventName); $date = new DateTime(); $find = "User exceeded quota of {$threshold->count} " . "per {$threshold->interval} seconds for event {$eventName}." . sprintf(' Taking the following %d action%s - ', count($threshold->actions), count($threshold->actions) > 1 ? 's' : '') . implode(', ', $threshold->actions) . '.'; $m = 'Test attempts to detect IntrusionDetector' . ' action log message in logfile - %s'; // Generate 4 events at 1 sec intervals for ($i = 0; $i < 4; $i++) { ESAPI::getIntrusionDetector()->addEvent($eventName, 'This is a Test Event for IntrusionDetectorTest.'); usleep(1000000); } // Sleep for a further 2 secs (for a total of 3 secs between this and // the next event. usleep(2000000); // The following two events should not trigger... ESAPI::getIntrusionDetector()->addEvent($eventName, 'This is a Test Event for IntrusionDetectorTest.'); $this->assertFalse(fileContainsExpected($this->_logFileLoc, $find, $date, 10, $this->_logDateFormat), $m); ESAPI::getIntrusionDetector()->addEvent($eventName, 'This is a Test Event for IntrusionDetectorTest.'); $this->assertFalse(fileContainsExpected($this->_logFileLoc, $find, $date, 10, $this->_logDateFormat), $m); // OK this event SHOULD trigger! ESAPI::getIntrusionDetector()->addEvent($eventName, 'This is a Test Event for IntrusionDetectorTest.'); $this->assertTrue(fileContainsExpected($this->_logFileLoc, $find, $date, 10, $this->_logDateFormat), $m); }
/** * Test supplying constructor with an instance of a validator */ function testCCVR_constructValidator() { $config = ESAPI::getSecurityConfiguration(); $pattern = $config->getValidationPattern('CreditCard'); $ccr = new StringValidationRule('CreditCardValidator', null, $pattern); $ccr->setMaximumLength(16); // 19 in the default validator $ccvr = new CreditCardValidationRule('CreditCardValidatorLuhn', null, $ccr); $this->assertTrue($ccvr->isValid('testCCVR_constructValidator', '0000000000000000')); $this->assertFalse($ccvr->isValid('testCCVR_constructValidator', '0000-0000-0000-0000')); }