Compare commits
3 Commits
95537fb60e
...
dc9d7abe14
Author | SHA1 | Date | |
---|---|---|---|
dc9d7abe14
|
|||
729a964d0c
|
|||
7120b5dc74
|
@ -9,7 +9,6 @@ declare(strict_types = 1);
|
|||||||
* functions.
|
* functions.
|
||||||
*/
|
*/
|
||||||
final class MD_STD {
|
final class MD_STD {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around file_get_contents, that provides catches errors on it and returns
|
* Wrapper around file_get_contents, that provides catches errors on it and returns
|
||||||
* with type safety.
|
* with type safety.
|
||||||
@ -211,7 +210,7 @@ final class MD_STD {
|
|||||||
* Function lang_getfrombrowser gets the browser language based on HTTP headers.
|
* Function lang_getfrombrowser gets the browser language based on HTTP headers.
|
||||||
*
|
*
|
||||||
* @param array<string> $allowed_languages Array containing all the languages for which
|
* @param array<string> $allowed_languages Array containing all the languages for which
|
||||||
* there are translations.
|
* there are translations.
|
||||||
* @param string $default_language Default language of the instance of MD.
|
* @param string $default_language Default language of the instance of MD.
|
||||||
* @param string $lang_variable Currently set language variable. Optional.
|
* @param string $lang_variable Currently set language variable. Optional.
|
||||||
* @param boolean $strict_mode Whether to demand "de-de" (true) or "de" (false) Optional.
|
* @param boolean $strict_mode Whether to demand "de-de" (true) or "de" (false) Optional.
|
||||||
@ -431,5 +430,4 @@ final class MD_STD {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ declare(strict_types = 1);
|
|||||||
* Class providing static functions with basic security operations.
|
* Class providing static functions with basic security operations.
|
||||||
*/
|
*/
|
||||||
final class MD_STD_SEC {
|
final class MD_STD_SEC {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for retrieving the anti-csrf token or generating it if need be.
|
* Function for retrieving the anti-csrf token or generating it if need be.
|
||||||
*
|
*
|
||||||
@ -45,4 +44,82 @@ final class MD_STD_SEC {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BRUTE_FORCE_DELAY_DEFAULT = 2000; // 2000 microseconds = 2 milliseconds
|
||||||
|
const BRUTE_FORCE_DELAY_MULTIPLIER_COMMON = 1.08;
|
||||||
|
const BRUTE_FORCE_DELAY_MULTIPLIER_PER_USER = 3;
|
||||||
|
const BRUTE_FORCE_DELAY_MULTIPLIER_PER_IP = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent brute force attacks by delaying the login .
|
||||||
|
*
|
||||||
|
* @param string $tool_name Identifier of the login.
|
||||||
|
* @param string $username Username to look for.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function preventBruteForce(string $tool_name, string $username):bool {
|
||||||
|
|
||||||
|
// Unstable but working way to get the user's IP. If the IP is falsified,
|
||||||
|
// this can't be found out anyway and security is established by _common.
|
||||||
|
$ip = \strval($_SERVER['REMOTE_ADDR'] ?: ($_SERVER['HTTP_X_FORWARDED_FOR'] ?: $_SERVER['HTTP_CLIENT_IP']));
|
||||||
|
|
||||||
|
// Set name of log file
|
||||||
|
$logfile_common = \sys_get_temp_dir() . "/logins_{$tool_name}.json";
|
||||||
|
|
||||||
|
// Ensure the log files exist
|
||||||
|
if (!\file_exists($logfile_common)) \file_put_contents($logfile_common, "[]");
|
||||||
|
|
||||||
|
// Hash entered username and IP to prevent malicious strings from
|
||||||
|
// entering the system.
|
||||||
|
$hash_user = \md5($username);
|
||||||
|
$hash_ip = \md5($ip);
|
||||||
|
|
||||||
|
// Delete the log files if they are too old
|
||||||
|
$loginLog = \json_decode(MD_STD::file_get_contents($logfile_common), \true) ?: [];
|
||||||
|
|
||||||
|
// Ensure the counters exist and aren't old than 600 seconds / 10 minutes
|
||||||
|
if (empty($loginLog['common']) || \time() - $loginLog['common']['time'] > 600) {
|
||||||
|
$loginLog['common'] = ["count" => 0, "time" => \time()];
|
||||||
|
}
|
||||||
|
if (empty($loginLog['usr'][$hash_user]) || \time() - $loginLog['usr'][$hash_user]['time'] > 600) {
|
||||||
|
$loginLog['usr'][$hash_user] = ["count" => 0, "time" => \time()];
|
||||||
|
}
|
||||||
|
if (empty($loginLog['ip'][$hash_ip]) || \time() - $loginLog['ip'][$hash_ip]['time'] > 600) {
|
||||||
|
$loginLog['ip'][$hash_ip] = ["count" => 0, "time" => \time()];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increase counters and update timers
|
||||||
|
$loginLog['common']['count']++;
|
||||||
|
$loginLog['common']['time'] = \time();
|
||||||
|
$loginLog['usr'][$hash_user]['count']++;
|
||||||
|
$loginLog['usr'][$hash_user]['time'] = \time();
|
||||||
|
$loginLog['ip'][$hash_ip]['count']++;
|
||||||
|
$loginLog['ip'][$hash_ip]['time'] = \time();
|
||||||
|
|
||||||
|
// Update the log file
|
||||||
|
\file_put_contents($logfile_common, \json_encode($loginLog));
|
||||||
|
|
||||||
|
// Translate counters into delay multipliers
|
||||||
|
$delay_multiplier_common = $loginLog['common']['count'];
|
||||||
|
$delay_multiplier_per_user = $loginLog['usr'][$hash_user]['count'];
|
||||||
|
$delay_multiplier_per_ip = $loginLog['usr'][$hash_ip]['count'];
|
||||||
|
|
||||||
|
// Calculate delay
|
||||||
|
$delay_micoseconds = \intval(self::BRUTE_FORCE_DELAY_DEFAULT *
|
||||||
|
(self::BRUTE_FORCE_DELAY_MULTIPLIER_COMMON ** $delay_multiplier_common) *
|
||||||
|
(self::BRUTE_FORCE_DELAY_MULTIPLIER_PER_USER ** $delay_multiplier_per_user) *
|
||||||
|
(self::BRUTE_FORCE_DELAY_MULTIPLIER_PER_IP ** $delay_multiplier_per_ip));
|
||||||
|
|
||||||
|
$max_execution_microseconds = \abs((int)\ini_get("max_execution_time")) * 1000000;
|
||||||
|
|
||||||
|
// Sleep
|
||||||
|
\usleep(min($delay_micoseconds, \abs($max_execution_microseconds - 1000000)));
|
||||||
|
|
||||||
|
if ($delay_micoseconds > \abs($max_execution_microseconds - 1000000)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user