From: <gem...@li...> - 2011-11-21 11:22:21
|
Revision: 251 http://gemstracker.svn.sourceforge.net/gemstracker/?rev=251&view=rev Author: michieltcs Date: 2011-11-21 11:22:10 +0000 (Mon, 21 Nov 2011) Log Message: ----------- Refs #454 - introduce throttling in AskAction Modified Paths: -------------- trunk/library/classes/Gems/Default/AskAction.php trunk/library/classes/Gems/Project/ProjectSettings.php Modified: trunk/library/classes/Gems/Default/AskAction.php =================================================================== --- trunk/library/classes/Gems/Default/AskAction.php 2011-11-21 10:58:55 UTC (rev 250) +++ trunk/library/classes/Gems/Default/AskAction.php 2011-11-21 11:22:10 UTC (rev 251) @@ -215,9 +215,35 @@ $form->addElement($element); if ($this->_request->isPost()) { - if ($form->isValid($_POST)) { + $throttleSettings = $this->project->getAskThrottleSettings(); + + // Prune the database for (very) old attempts + $this->db->query("DELETE FROM gems__token_attempts WHERE gta_datetime < DATE_SUB(NOW(), INTERVAL ? second)", + $throttleSettings['period'] * 20); + + // Retrieve the number of failed attempts that occurred within the specified window + $attemptData = $this->db->fetchRow("SELECT COUNT(1) AS attempts, UNIX_TIMESTAMP(MAX(gta_datetime)) AS last " . + "FROM gems__token_attempts WHERE gta_datetime > DATE_SUB(NOW(), INTERVAL ? second)", $throttleSettings['period']); + + $remainingDelay = ($attemptData['last'] + $throttleSettings['delay']) - time(); + + if ($attemptData['attempts'] > $throttleSettings['threshold'] && $remainingDelay > 0) { + $this->escort->logger->log("Possible token brute force attack, throttling for $remainingDelay seconds", Zend_Log::ERR); + + $this->addMessage($this->_('The server is currently busy, please wait a while and try again.')); + } else if ($form->isValid($_POST)) { $this->_forward('forward'); return; + } else { + if (isset($_POST[MUtil_Model::REQUEST_ID])) { + $this->db->insert( + 'gems__token_attempts', + array( + 'gta_id_token' => $_POST[MUtil_Model::REQUEST_ID], + 'gta_ip_address' => $this->getRequest()->getClientIp() + ) + ); + } } } elseif ($id = $this->_getParam(MUtil_Model::REQUEST_ID)) { $form->populate(array(MUtil_Model::REQUEST_ID => $id)); Modified: trunk/library/classes/Gems/Project/ProjectSettings.php =================================================================== --- trunk/library/classes/Gems/Project/ProjectSettings.php 2011-11-21 10:58:55 UTC (rev 250) +++ trunk/library/classes/Gems/Project/ProjectSettings.php 2011-11-21 11:22:10 UTC (rev 251) @@ -236,6 +236,30 @@ return $this->defaultSessionTimeout; } } + + /** + * Returns an array with throttling settings for the ask + * controller + * + * @return array + */ + public function getAskThrottleSettings() + { + // Check for the 'askThrottle' config section + if (!empty($this->askThrottle)) { + return $this->askThrottle; + } else { + // Set some sensible defaults + // Detection window: 15 minutes + // Threshold: 20 requests per minute + // Delay: 10 seconds + $throttleSettings = array( + 'period' => 15 * 60, + 'threshold' => 15 * 20, + 'delay' => 10 + ); + } + } /** * Returns the super admin name, if any This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |