CVE-2018-12649: Improper Restriction of Excessive Authentication Attempts (CWE-307)
value: An issue was discovered in app/Controller/UsersController.php in MISP 2.4.92. An adversary can bypass the brute-force protection by using a PUT HTTP method instead of a POST HTTP method in the login part, because this protection was only covering POST requests.
CWE description: The product does not implement sufficient measures to prevent multiple failed authentication attempts within a short time frame, making it more susceptible to brute force attacks.
CVSS v3 base score: 9.8
Published: 2018-06-22T14:29Z
Repository: https://github.com/MISP/MISP
Language: PHP
Files changed: app/Controller/UsersController.php
Commit date: 2018-06-21 15:48:32 +0200
Commit message: fix: [security] Brute force protection can be bypased with a PUT request

- fixes an issue where brute forcing the login would work by using PUT requests
- as reported by Silver Saks from CCDCOE

Diff: diff --git a/app/Controller/UsersController.php b/app/Controller/UsersController.php
index 9926c329f6..a272436ba5 100644
--- a/app/Controller/UsersController.php
+++ b/app/Controller/UsersController.php
@@ -854,17 +854,17 @@ class UsersController extends AppController {
 		$this->Auth->login($user);
 		$this->redirect(array('Controller' => 'User', 'action' => 'dashboard'));
 	}
 
 	public function login() {
-		$this->Bruteforce = ClassRegistry::init('Bruteforce');
-		if ($this->request->is('post') && isset($this->request->data['User']['email'])) {
-			if ($this->Bruteforce->isBlacklisted($_SERVER['REMOTE_ADDR'], $this->request->data['User']['email'])) {
-				throw new ForbiddenException('You have reached the maximum number of login attempts. Please wait ' . Configure::read('SecureAuth.expire') . ' seconds and try again.');
-			}
-		}
 		if ($this->request->is('post') || $this->request->is('put')) {
+			$this->Bruteforce = ClassRegistry::init('Bruteforce');
+			if (!empty($this->request->data['User']['email'])) {
+				if ($this->Bruteforce->isBlacklisted($_SERVER['REMOTE_ADDR'], $this->request->data['User']['email'])) {
+					throw new ForbiddenException('You have reached the maximum number of login attempts. Please wait ' . Configure::read('SecureAuth.expire') . ' seconds and try again.');
+				}
+			}
 			// Check the length of the user's authkey
 			$userPass = $this->User->find('first', array(
 				'conditions' => array('User.email' => $this->request->data['User']['email']),
 				'fields' => array('User.password'),
 				'recursive' => -1

Vulnerable code: 		$this->Bruteforce = ClassRegistry::init('Bruteforce');
		if ($this->request->is('post') && isset($this->request->data['User']['email'])) {
			if ($this->Bruteforce->isBlacklisted($_SERVER['REMOTE_ADDR'], $this->request->data['User']['email'])) {
				throw new ForbiddenException('You have reached the maximum number of login attempts. Please wait ' . Configure::read('SecureAuth.expire') . ' seconds and try again.');
			}
		}
Fixed code: 			$this->Bruteforce = ClassRegistry::init('Bruteforce');
			if (!empty($this->request->data['User']['email'])) {
				if ($this->Bruteforce->isBlacklisted($_SERVER['REMOTE_ADDR'], $this->request->data['User']['email'])) {
					throw new ForbiddenException('You have reached the maximum number of login attempts. Please wait ' . Configure::read('SecureAuth.expire') . ' seconds and try again.');
				}
			}