fix: [remote_ip] respect MISP.log_client_ip_header everywhere fixes #8781

pull/8796/head
Christophe Vandeplas 2022-11-28 14:08:11 +01:00
parent 6236cca38a
commit 192ed311b9
9 changed files with 33 additions and 38 deletions

View File

@ -1058,7 +1058,7 @@ class AppController extends Controller
$headerNamespace = '';
}
if (isset($server[$headerNamespace . $header]) && !empty($server[$headerNamespace . $header])) {
if (Configure::read('Plugin.CustomAuth_only_allow_source') && Configure::read('Plugin.CustomAuth_only_allow_source') !== $server['REMOTE_ADDR']) {
if (Configure::read('Plugin.CustomAuth_only_allow_source') && Configure::read('Plugin.CustomAuth_only_allow_source') !== $this->_remoteIp()) {
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$log = array(
@ -1067,7 +1067,7 @@ class AppController extends Controller
'model_id' => 0,
'email' => 'SYSTEM',
'action' => 'auth_fail',
'title' => 'Failed authentication using external key (' . trim($server[$headerNamespace . $header]) . ') - the user has not arrived from the expected address. Instead the request came from: ' . $server['REMOTE_ADDR'],
'title' => 'Failed authentication using external key (' . trim($server[$headerNamespace . $header]) . ') - the user has not arrived from the expected address. Instead the request came from: ' . $this->_remoteIp(),
'change' => null,
);
$this->Log->save($log);
@ -1373,9 +1373,10 @@ class AppController extends Controller
protected function _remoteIp()
{
$ipHeader = Configure::read('MISP.log_client_ip_header') ?: 'REMOTE_ADDR';
return isset($_SERVER[$ipHeader]) ? trim($_SERVER[$ipHeader]) : null;
return isset($_SERVER[$ipHeader]) ? trim($_SERVER[$ipHeader]) : $_SERVER['REMOTE_ADDR'];
}
/**
* @param string $key
* @return bool Returns true if the same log defined by $key was not stored in last hour

View File

@ -1167,7 +1167,7 @@ class UsersController extends AppController
if ($this->request->is(['post', 'put'])) {
$this->Bruteforce = ClassRegistry::init('Bruteforce');
if (!empty($this->request->data['User']['email'])) {
if ($this->Bruteforce->isBlocklisted($_SERVER['REMOTE_ADDR'], $this->request->data['User']['email'])) {
if ($this->Bruteforce->isBlocklisted($this->request->data['User']['email'])) {
$expire = Configure::check('SecureAuth.expire') ? Configure::read('SecureAuth.expire') : 300;
throw new ForbiddenException('You have reached the maximum number of login attempts. Please wait ' . $expire . ' seconds and try again.');
}
@ -1213,7 +1213,7 @@ class UsersController extends AppController
if ($this->request->is('post') || $this->request->is('put')) {
$this->Flash->error(__('Invalid username or password, try again'));
if (isset($this->request->data['User']['email'])) {
$this->Bruteforce->insert($_SERVER['REMOTE_ADDR'], $this->request->data['User']['email']);
$this->Bruteforce->insert($this->request->data['User']['email']);
}
}
// populate the DB with the first role (site admin) if it's empty
@ -1784,7 +1784,7 @@ class UsersController extends AppController
$body = $this->__replaceEmailVariables($body);
$body = str_replace('$validity', $validity, $body);
$body = str_replace('$otp', $otp, $body);
$body = str_replace('$ip', $this->__getClientIP(), $body);
$body = str_replace('$ip', $this->_remoteIp(), $body);
$body = str_replace('$username', $user['email'], $body);
// Fetch user that contains also PGP or S/MIME keys for e-mail encryption
@ -1800,22 +1800,6 @@ class UsersController extends AppController
}
}
/**
* Helper function to determine the IP of a client (proxy aware)
*/
private function __getClientIP() {
$x_forwarded = filter_input(INPUT_SERVER, 'HTTP_X_FORWARDED_FOR', FILTER_SANITIZE_STRING);
$client_ip = filter_input(INPUT_SERVER, 'HTTP_CLIENT_IP', FILTER_SANITIZE_STRING);
if (!empty($x_forwarded)) {
$x_forwarded = explode(",", $x_forwarded);
return $x_forwarded[0];
} elseif(!empty($client_ip)){
return $client_ip;
} else {
return filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_SANITIZE_STRING);
}
}
// shows some statistics about the instance
public function statistics($page = 'data')
{

View File

@ -28,7 +28,7 @@ class WhoamiWidget
array('title' => 'Email', 'value' => $user['email']),
array('title' => 'Role', 'value' => $user['Role']['name']),
array('title' => 'Organisation', 'value' => $user['Organisation']['name']),
array('title' => 'IP', 'value' => empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['REMOTE_ADDR'] : $_SERVER['HTTP_X_FORWARDED_FOR']),
array('title' => 'IP', 'value' => $this->Log->_remoteIp()),
array('title' => 'Last logins', 'value' => $entries)
);
}

View File

@ -138,7 +138,7 @@ class SecurityAudit
if (!Configure::read('MISP.log_new_audit')) {
$output['Logging'][] = [
'hint',
__('New audit log stores more information, like used authkey ID or request ID that can help when analysing or correlating audit logs.'),
__('New audit log stores more information, like used authkey ID or request ID that can help when analysing or correlating audit logs. Set `MISP.log_new_audit` to `true` to enable.'),
];
}

View File

@ -3906,4 +3906,14 @@ class AppModel extends Model
}
return null;
}
/**
* @return string|null
*/
public function _remoteIp()
{
$ipHeader = Configure::read('MISP.log_client_ip_header') ?: 'REMOTE_ADDR';
return isset($_SERVER[$ipHeader]) ? trim($_SERVER[$ipHeader]) : $_SERVER['REMOTE_ADDR'];
}
}

View File

@ -25,7 +25,11 @@ class AuditLog extends AppModel
ACTION_REMOVE_GALAXY = 'remove_galaxy',
ACTION_REMOVE_GALAXY_LOCAL = 'remove_local_galaxy',
ACTION_PUBLISH = 'publish',
ACTION_PUBLISH_SIGHTINGS = 'publish_sightings';
ACTION_PUBLISH_SIGHTINGS = 'publish_sightings',
ACTION_LOGIN = 'login',
ACTION_PASSWDCHANGE = 'password_change',
ACTION_LOGOUT = 'logout',
ACTION_LOGIN_FAILED = 'login_failed';
const REQUEST_TYPE_DEFAULT = 0,
REQUEST_TYPE_API = 1,
@ -194,10 +198,7 @@ class AuditLog extends AppModel
{
$auditLog = &$this->data['AuditLog'];
if (!isset($auditLog['ip']) && $this->logClientIp) {
$ipHeader = Configure::read('MISP.log_client_ip_header') ?: 'REMOTE_ADDR';
if (isset($_SERVER[$ipHeader])) {
$auditLog['ip'] = $_SERVER[$ipHeader];
}
$auditLog['ip'] = $this->_remoteIp();
}
if (!isset($auditLog['user_id'])) {

View File

@ -5,10 +5,11 @@ App::uses('Sanitize', 'Utility');
class Bruteforce extends AppModel
{
public function insert($ip, $username)
public function insert($username)
{
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$ip = $this->_remoteIp();
$expire = Configure::check('SecureAuth.expire') ? Configure::read('SecureAuth.expire') : 300;
$amount = Configure::check('SecureAuth.amount') ? Configure::read('SecureAuth.amount') : 5;
$expire = time() + $expire;
@ -19,8 +20,8 @@ class Bruteforce extends AppModel
'expire' => $expire
);
$this->save($bruteforceEntry);
$title = 'Failed login attempt using username ' . $username . ' from IP: ' . $_SERVER['REMOTE_ADDR'] . '.';
if ($this->isBlocklisted($ip, $username)) {
$title = 'Failed login attempt using username ' . $username . ' from IP: ' . $ip . '.';
if ($this->isBlocklisted($username)) {
$title .= 'This has tripped the bruteforce protection after ' . $amount . ' failed attempts. The user is now blocklisted for ' . $expire . ' seconds.';
}
$log = array(
@ -45,11 +46,12 @@ class Bruteforce extends AppModel
$this->query($sql);
}
public function isBlocklisted($ip, $username)
public function isBlocklisted($username)
{
// first remove old expired rows
$this->clean();
// count
$ip = $this->_remoteIp();
$params = array(
'conditions' => array(
'Bruteforce.ip' => $ip,

View File

@ -18,7 +18,7 @@ class Inbox extends AppModel
parent::beforeValidate();
$this->data['Inbox']['uuid'] = CakeText::uuid();
$this->data['Inbox']['timestamp'] = time();
$this->data['Inbox']['ip'] = $_SERVER['REMOTE_ADDR'];
$this->data['Inbox']['ip'] = $this->_remoteIp();
$this->data['Inbox']['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
$this->data['Inbox']['user_agent_sha256'] = hash('sha256', $_SERVER['HTTP_USER_AGENT']);
return true;

View File

@ -123,10 +123,7 @@ class Log extends AppModel
return false;
}
if (Configure::read('MISP.log_client_ip')) {
$ipHeader = Configure::read('MISP.log_client_ip_header') ?: 'REMOTE_ADDR';
if (isset($_SERVER[$ipHeader])) {
$this->data['Log']['ip'] = $_SERVER[$ipHeader];
}
$this->data['Log']['ip'] = $this->_remoteIp();
}
$setEmpty = array('title' => '', 'model' => '', 'model_id' => 0, 'action' => '', 'user_id' => 0, 'change' => '', 'email' => '', 'org' => '', 'description' => '', 'ip' => '');
foreach ($setEmpty as $field => $empty) {