/**
  * 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);
     }
 }
 /**
  * The errorAction handles errors and exceptions.
  *
  * @return null
  */
 public function errorAction()
 {
     $this->getResponse()->clearBody();
     $errors = $this->_getParam('error_handler');
     switch ($errors->type) {
         case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
         case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
         case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
             // 404 error -- controller or action not found
             $this->getResponse()->setHttpResponseCode(404);
             $this->view->message = 'The page requested was not found.';
             break;
         default:
             // Log exceptions. EnterpriseSecurityException were automagically logged
             // so they are not logged here.
             if ($errors->exception instanceof EnterpriseSecurityException === false) {
                 ESAPI::getIntrusionDetector()->addException($errors->exception);
             }
             // application error - if display_errors is off then the client
             // is redirected to the index controller error action where a
             // generic error message will be rendered.
             $bootstrap = $this->getInvokeArg('bootstrap');
             if ($bootstrap->hasOption('phpsettings')) {
                 $o = $bootstrap->getOption('phpsettings');
                 if (array_key_exists('display_errors', $o) && $o['display_errors'] !== '1') {
                     if (Zend_Session::sessionExists()) {
                         $ns = new Zend_Session_Namespace('Contact');
                         $ns->error = true;
                     }
                     $this->_helper->getHelper('redirector')->setCode(303)->gotoSimple('error', 'index', null, $this->_request->getParams());
                     return;
                 }
             }
             $this->getResponse()->setHttpResponseCode(500);
             $this->view->message = 'Application error';
     }
     // conditionally display exceptions
     if ($this->getInvokeArg('displayExceptions') == true) {
         $this->view->exception = $errors->exception;
     }
     $this->view->request = $errors->request;
 }
 /**
  * The send action is the target for form submission.  If the request does
  * not contain POST data then the response will be a redirect to the index
  * action where the form will be displayed.
  * POST data is validated and if successful an email will be sent before
  * redirecting the client away from the send action (to a success message).
  * If validation fails, the form is persisted in the session and the client
  * is redirected away from the send action to display the form with error
  * messages.
  * Whether or not the form is successfully validated, a user session will be
  * started so that the client can be tracked and certain thresholds enforced.
  *
  * @return null
  */
 public function sendAction()
 {
     if (!$this->_request->isPost()) {
         $this->_helper->getHelper('redirector')->setCode(303)->gotoSimple('index', null, null, $this->_request->getParams());
     }
     $ns = new Zend_Session_Namespace('Contact');
     $ids = ESAPI::getIntrusionDetector();
     // Is the form submission a valid one?
     $valid = $this->_form->isValid($this->_request->getPost());
     // Check whether a csrf token is being re-used.  This should not happen
     // often due to the POST-Redirect-GET design of this application.
     // If the token is being reused then throw an Intrusion Exception.
     if (isset($ns->history->token) && in_array($this->_form->token->getValue(), $ns->history->token)) {
         throw new IntrusionException('Form resubmission is not permitted.', 'Submitted token is one contained in the history of the current session.');
     }
     if ($valid !== true) {
         // Add a formValidationErrors event to the client session.
         $ids->addEvent('ValidationErrorEvent', 'Form submission contained inputs that caused Validation errors.');
         // There are certain validation errors that require an exception to
         // be thrown becuase errors for these elements is assumed to be
         // evidence of tampering. Throw IntrusionException if there are
         // errors in CSRFToken or recipientsMap.
         if ($this->_form->detectedTamper()) {
             throw new IntrusionException('The submitted form contained invalid information.', 'Form submission contained evidence of tampering!');
         }
         // Log a warning about failed validation and include the error
         // messages.
         $validationErrMsgs = $this->_form->getMessages(null, true);
         $vmsgs = '';
         foreach ($validationErrMsgs as $elem => $messageArray) {
             $vmsgs .= "[{$elem}:";
             foreach ($messageArray as $validator => $message) {
                 $vmsgs .= "{$validator}={$message};";
             }
             $vmsgs .= "] ";
         }
         ESAPI::getAuditor('IndexController')->warning(Auditor::SECURITY, false, 'Validation failure messages: ' . $vmsgs);
         // Store the form in the session so that we can perform a redirect
         // away from the send action. // TODO expire it soon!
         $ns->submission = false;
         $ns->form = $this->_form;
         $this->_helper->getHelper('redirector')->setCode(303)->gotoSimple('index', null, null, $this->_request->getParams());
         return;
     }
     // We have a valid form!!
     // Kill the CSRF cookie.
     setcookie(Form_Contact::CSRFCOOKIE, 'expired', 1, '/');
     // Add token to map of submitted tokens
     if (is_array($ns->history->token)) {
         array_unshift($ns->history->token, $this->_form->token->getValue());
     } else {
         $ns->history->token = array($this->_form->token->getValue());
     }
     // extract the valid values from the form and send a mail
     $validValues = array();
     $elements = $this->_form->getElements();
     foreach ($elements as $key => $elem) {
         $validValues[$key] = $elem->getValue();
     }
     // attempt to send a mail
     $successfulDelivery = $this->_helper->sendMail($validValues, $this->_recipientsConfig);
     // If mail delivery was not successful show a
     if ($successfulDelivery !== true) {
         ESAPI::getAuditor('IndexController')->warning(Auditor::SECURITY, false, 'Sending of mail failed - ' . $this->_helper->sendMail->getResponse());
         $ids->addEvent('MailNotDeliveredEvent', 'successfully submitted valid contact form but mail was NOT sent.');
         // TODO an encrypted logfile with failed email messages?
         // View helpful error message.
         throw new Exception('Successful form submission failed to be sent.');
     } else {
         $ns->submission = true;
         $this->_helper->getHelper('redirector')->setCode(303)->gotoSimple('index', null, null, $this->_request->getParams());
         return;
     }
 }
Exemplo n.º 4
0
 /**
  * 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);
 }
 /**
  * Request the delivery of emial via the mail transport defined in the mail
  * configuration file.
  *
  * @param array $values An array of name value pairs obtained from the
  *                      submitted form. {@see _compose}
  *
  * @return bool True if the request to the mail transport resulted in
  *              successful delivery or False otherwise.
  */
 public function request($values)
 {
     $this->_rawVals = $values;
     $defaultTransport = null;
     // get the bootstrap, need to retrieve configs
     $front = Zend_Controller_Front::getInstance();
     $bs = $front->getParam('bootstrap');
     // get mail configuration
     $mailConfigLoc = $bs->getOption('mailconfigloc');
     $mailConfig = null;
     if (!empty($mailConfigLoc)) {
         $mailConfig = new Zend_Config_Ini($mailConfigLoc, APPLICATION_ENV, true);
     }
     if ($mailConfig instanceof Zend_Config === false) {
         $mailConfig = new Zend_config(array(), true);
         $this->Auditor->warning(Auditor::SECURITY, false, 'SendMail.request() cannot find mail configuration. Using defaults!');
     }
     $transportType = 'sendmail';
     $transportOpts = null;
     if (isset($mailConfig->transport->type)) {
         $transportType = $mailConfig->transport->type;
         unset($mailConfig->transport->type);
         $transportOpts = $mailConfig->transport;
         unset($mailConfig->transport);
     }
     $mailResource = new Zend_Application_Resource_Mail($mailConfig);
     if ($transportType == 'smtp') {
         $defaultTransport = new Zend_Mail_Transport_Smtp($transportOpts->host, $transportOpts->toArray());
     } else {
         if (ini_get('safe_mode')) {
             $defaultTransport = new Zend_Mail_Transport_Sendmail();
         } else {
             $defaultTransport = new Zend_Mail_Transport_Sendmail($transportOpts);
         }
     }
     Zend_Mail::setDefaultTransport($defaultTransport);
     // get recipients configuration
     $recipientConfigLoc = $bs->getOption('recipientsconfigloc');
     $recipientConfig = null;
     if (!empty($recipientConfigLoc)) {
         $recipientConfig = new Zend_Config_Ini($recipientConfigLoc, APPLICATION_ENV, false);
     }
     if ($recipientConfig instanceof Zend_Config) {
         $this->_recipientConfig = $recipientConfig;
     } else {
         $this->_auditor->warning(Auditor::SECURITY, false, 'SendMail.request() cannot find any recipient data. Not sending mail!');
     }
     // Compose Mail
     $mail = $this->_compose($mailConfig);
     // Make sure there's at least one recipient and bail if not.
     if ($this->_recipientConfig === null || sizeof($this->_recipientConfig) == 0) {
         $this->_response = 'No recipients of mail found!';
         $m = $mail->getBodyText()->getContent();
         $this->_auditor->info(Auditor::SECURITY, false, "No recipients of mail found. What do you want me to do with this: {$m}");
         return false;
     }
     $cfg = null;
     if (sizeof($this->_recipientConfig) == 1) {
         $cfg = $this->_recipientConfig->current();
     } else {
         $i = 0;
         $limit = $this->_recipientConfig->count();
         while (++$i <= $limit) {
             $foo = $this->_recipientConfig->current()->display;
             if ($this->_rawVals['recipientMap'] === $this->_recipientConfig->current()->display) {
                 break;
             }
             $this->_recipientConfig->next();
         }
         $cfg = $this->_recipientConfig->current();
     }
     foreach ($cfg as $_ => $rcpt) {
         if ($_ == 'display') {
             continue;
         }
         $mail->addTo($rcpt->address, $rcpt->name);
     }
     try {
         $mail->send();
     } catch (Exception $e) {
         ESAPI::getIntrusionDetector()->addException($e);
         $this->_response = 'Call to mail.send threw an Exception: ' . $e->getMessage . '.';
         return false;
     }
     if ($transportType == 'sendmail') {
         $this->_response = 'mail.send did NOT throw and exception using sendmail transport.';
         $this->_auditor->info(Auditor::SECURITY, true, $this->_response);
         return true;
     } else {
         // get response and determine whether it represents success or failure.
         $connection = $defaultTransport->getConnection();
         $response = $connection->getResponse();
         $success = false;
         foreach ($response as $messageEntry) {
             $success = $this->_isSuccessMessage($messageEntry);
             $this->_auditor->info(Auditor::SECURITY, $success, "SMTP connection response: {$messageEntry}");
         }
         if (sizeof($response, false) === 0) {
             // send got no reply...
             $this->_response = 'No Reply!';
             $this->_auditor->info(Auditor::SECURITY, false, 'SMTP connection failed! No response.');
             return $success;
         } else {
             if (sizeof($response, false) === 1) {
                 // got one response. good.
                 $this->_response = array_shift($response);
                 return $success;
             } else {
                 $this->_auditor->info(Auditor::SECURITY, false, 'SMTP connection returned multiple responses!');
                 $this->_response = 'Multiple SMTP responses, don\'t know what\'s happening...';
                 return false;
             }
         }
     }
     // unreached
 }