Brute Force Protection
Combodo's customers only
- Brute Force Protection
- Securing the login process
- ITSM Designer
- PHP 8.0
Basically this extension watch every login tentative and on some conditions:
If the login comes from some IP ranges
If the login fails (invalid login or invalid password)
If a captcha image was used to login and returns a high score
If a recaptcha returns a low score
It can triggers brut force countermeasures, which can be any of those:
slowdown: user has to wait between login trials.
recaptcha: recaptcha is activated on the login page
captcha: a captcha image is added to the login page
login invalid: Could be used to deny iTop access from a given IP range for eg.
login invalid for a limited duration: applies to a specific
no answer: do not reply to login request, should be limited to some conditions
no answer for a limited duration: applied to a particular
Conditions and countermeasures are explained in further details below.
|2022-08-31||1.0.7||* Fix wrong calls to ResetCurrentCmdbChange()
* Fix PHP notices in Strategy manager and Captcha handler
|2021-12-17||1.0.6||* Removed gregwar/captcha demo files|
|2021-06-03||1.0.5||New 'enabled' module config parameter|
|2020-12-04||1.0.4||* Fix crash when login with a admin user in admin
* Fix REST comment field not working anymore
|2020-10-27||1.0.3||Fix some DE translations|
|2020-08-27||1.0.2||Fix error when iTop is readonly|
|2020-06-04||1.0.1||Fix bug : PHP Notice “Undefined index:
Requires at least PHP 7.1.3
|2020-02-05||1.0.0||First public version|
The scripts called using CLI may not be secured by this extension.
login_modeform is the only one that can interact with captcha and recaptcha.
By default this extension does not perform any securement, until you configure it.
iTop 2.7 or above
Use the Standard installation process
You'll find below a series of configuration examples, they vary in complexity.
Disable this extension
You can use this minimal configuration, which slowdown after 3 failed logins:
'itop-fence' => array ( // Associate countermeasure with checkers, // optionnaly filtering them with levels and login_mode. 'checker_to_countermeasure' => array ( //The most basic configuration : if the login fail three times, slowdown the auth process array ( 'checker' => 'Combodo\\iTop\\Fence\\Checker\\LoginFailedListener', 'countermeasure' => 'Combodo\\iTop\\Fence\\Countermeasure\\Slowdown', 'min_level' => 3, ), ), ),
This configuration, with lock a login for one hour after 3 failed logins:
If you want to always display a captcha:
Captcha in IP range example
In this example we want to:
Let users with IP in a trusted range, login without captcha,
Ask users to fill a captcha if their IP is not trusted and they use the “form”
Do not answer in other situation
'itop-fence' => array ( // Define trusted IPs 'trusted_ip_list' => array ( 0 => '::1', // An IP mask 1 => '127.0.0.1', // A single IP 2 => '192.168.55.0/24', // A subnet ), 'malicious_ip_list' => array ( ), 'checker_to_countermeasure' => array ( // If login_mode = 'form' and IP in trusted list // => Ask for a captcha image to be filled 0 => array ( 'checker' => 'Combodo\\iTop\\Fence\\Checker\\IpRangeChecker', 'countermeasure' => 'Combodo\\iTop\\Fence\\Hybrid\\Captcha', 'max_level' => 1, 'login_mode_included' => ['form'] ), // Else if login_mode other than 'form' and IP in trusted list // => No answer 1 => array ( 'checker' => 'Combodo\\iTop\\Fence\\Checker\\IpRangeChecker', 'countermeasure' => 'Combodo\\iTop\\Fence\\Countermeasure\\NoAnswer', 'max_level' => 1, 'login_mode_excluded' => ['form'] ), // Else IP NOT in trusted list // => No Answer 2 => array ( 'checker' => 'Combodo\\iTop\\Fence\\Checker\\IpRangeChecker', 'countermeasure' => 'Combodo\\iTop\\Fence\\Countermeasure\\NoAnswer', 'min_level' => 2, ), ), ),
Configuration - full example
Here is a complex example of configuration:
'itop-fence' => array ( // if false, iTop Fence will be entirely disabled 'enabled' => true, //recaptcha will not be activable until both two keys are configured // if you have no key, remove following entry from your configuration 'recaptcha_public_key' => NULL, 'recaptcha_private_key' => NULL, // IpRangeChecker base configuration. // NB: You can use ipv4 and ipv6, you can also use subnets 'trusted_ip_list' => array('::1', '127.0.0.1'), 'malicious_ip_list' => array(), //you can use ipv4 and ipv6, you can also use subnets // Associate countermeasure with checkers, // optionally filter them with levels and login_mode. 'checker_to_countermeasure' => array ( //The most basic configuration : if the login fail three times, slowdown the auth process array ( 'checker' => 'Combodo\\iTop\\Fence\\Checker\\LoginFailedListener', 'countermeasure' => 'Combodo\\iTop\\Fence\\Countermeasure\\Slowdown', 'min_level' => 3, ), // Recaptcha is meant to be used only with the login_mode "form" // 0.4 is a really bad score, below let's consider the user as a BOT // and lie him by saying that the password is invalid array ( 'checker' => 'Combodo\\iTop\\Fence\\Hybrid\\Recaptcha', 'countermeasure' => 'Combodo\\iTop\\Fence\\Countermeasure\\LoginInvalid', 'max_level' => 0.4, 'login_mode_included' => ['form'], ), // Better score but still suspicious, let's add an image captcha in order to check array ( 'checker' => 'Combodo\\iTop\\Fence\\Hybrid\\Recaptcha', 'countermeasure' => 'Combodo\\iTop\\Fence\\Hybrid\\Captcha', 'min_level' => 0.4, 'max_level' => 0.6, 'login_mode_included' => ['form'], ), // IpRangeChecker: // if the ip is not from the trusted list and the login mode is form, let's add a captcha array ( 'checker' => 'Combodo\\iTop\\Fence\\Checker\\IpRangeChecker', 'countermeasure' => 'Combodo\\iTop\\Fence\\Hybrid\\Captcha', 'max_level' => 1, 'login_mode_included' => ['form'], ), // IpRangeChecker: // if the ip is not trusted and the login mode is NOT form, let's refuse to answer // this require you to list every and each non interactive client's IP to iTop // generally, you'll need to provide a VPN for mobile users as their IP may vary otherwise array ( 'checker' => 'Combodo\\iTop\\Fence\\Checker\\IpRangeChecker', 'countermeasure' => 'Combodo\\iTop\\Fence\\Countermeasure\\NoAnswerUntil', 'max_level' => 1, 'login_mode_excluded' => ['form'], ), // IpRangeChecker: // if the ip is from the malicious list, we don't even bother to answer. // note: you should use the malicious list as an emergency tool, // Firewall rules offer better performance to handle thousand of rules array ( 'checker' => 'Combodo\\iTop\\Fence\\Checker\\IpRangeChecker', 'countermeasure' => 'Combodo\\iTop\\Fence\\Countermeasure\\NoAnswerUntil', 'min_level' => 2, ), ), ),
Here is the details of each possible parameter for this extension:
|activation||enabled||to inactivate the extension, in case of issue with it|
|ip range||trusted_ip_list||An array of IPs, masks and subnets, which are trusted|
|malicious_ip_list||An array of IPs, masks and subnets, which are suspicious|
|recaptcha||recaptcha_public_key||Those keys need to be negotiated with Google. They are required for the recaptcha to be activated by iTop|
|recaptcha_minimum_score||Used in countermeasure only, its a float between 0 and 1, below which we don't trust the requester to be a human, by default it's set to 0.4|
|slowdown||slowdown_initial_duration||Duration in micro seconds of the first sleep period|
|slowdown_duration_incrementation||Number of micro seconds added to previous sleep period|
|slowdown_duration_max||When the sleep period reach this number of micro seconds, it stops increasing|
|login invalid||login_always_invalid_duration||number of seconds during which a login will be flagged as invalid|
|no answer||no_answer_duration||number of seconds during which for a login no reply will be provided|
|no_answer_http_response_code||the http response code to use (429 by default)|
Checkers & Countermeasure
The main work is to associate checkers with countermeasure inside the configuration's checker_to_countermeasure entry, using optionally these filters:
max_level: When you set a max level, the returned level must be below or equal to
max_levelto apply the countermeasure
min_level: When you set a min level, the returned level must be above or equal to
min_levelto apply the countermeasure
login_mode_included - if not specified, all login_modes are included
login_mode_excluded - if not specified, none are excluded
If a login_mode is included and excluded at the same time, I can't predict the behavior, just change your configuration
Each security checker returns a
level of risk.
Depending on the level reached, iTop activates countermeasures.
level depends on the security checker:
What is returned by the Checker:
login failed: the number of successive fails
level 1: the IP is not in the trusted list (
level 2: the IP is in the malicious list (
recaptcha: a float between 0 and 1, it's the confidence about the user being a human (1 : max trust)
captcha image: the number of miss-typed characters
|login failed||It returns the number of successive fails for a
|ip range||This security checkers is enabled only if
|Captcha image||As a security checker: it does
always enforce the display of a captcha in the login form (It
has no impact on other login_modes). The returned
|Recaptcha||It is enabled only if both
As a security checker: it does always enforce the use of the google's recaptcha service.
If the user's score is below
Question: If a
trusted_ip_list and a
malicious_ip_list are set and the IP is not in the
first one but is in the second, the level returned? Answer: The
returned level is 2.
Value to use in the configuration file
login failed: Combodo\\iTop\\Fence\\Checker\\LoginFailedListener
ip range: Combodo\\iTop\\Fence\\Checker\\IpRangeChecker
captcha: Combodo\\iTop\\Fence\\Hybrid\\Captcha |
recaptcha: Combodo\\iTop\\Fence\\Hybrid\\Recaptcha |
|Slowdown||This countermeasure is maybe the most efficient:
if enabled, iTop fence will sleep during
|Captcha image||If the user type a wrong captcha at this stage, the credentials will be considered as “wrong” and the user invited to enter them again.|
|Recaptcha||It is usable only if both
If the user's score is below
|LoginInvalid||This one is somehow extremist: if enabled, even if the credentials are valid, the response will be “invalid”. Apart from denying access to iTop from outside an IP range, not sure you will need this.|
|LoginInvalidUntil||The same as LoginInvalid but limited in time: once it expires, it let on attempt to login before being re-enabled. Each cycle start with an allowed attempt. When this countermeasure is applied, it stores in the iTopFenceLogin object (labelled “Login audit” in english), the date-time until which an invalid answer will be provided if this login is used.|
|NoAnswer||If enabled, the login attempt will be stopped.|
|NoAnswerUntil||Same as NoAnswer but limited in time: once it expires, the login can be used again. When this countermeasure is applied, it stores in the iTopFenceLogin object (labelled “Login audit” in english), the date-time until which no answer will be provided if this login is used.|
Note: there is possibility for the NoAnswer and NoAnswerUntil,
to display an error message, also this is rather incoherent with
the purpose of NoAnswer. For this just define this dictionary
Value to use in the configuration file:
Captcha image: Combodo\\iTop\\Fence\\Hybrid\\Captcha
There is a global parameter in iTop which allow to configure how talkative a log should be for a given module
log_level_min: You can filter/disable the logs
by adding an entry into
Info: (default) use this value in production
Debug: if you are trying to configure itop fence, you should switch to this level
Trace: This level enable more logs than Debug, most of the time you don't need this.
The above example give you a hint at how to properly use iTop fence : you define countermeasure that are called when checker trigger
optionally filtering them to a specific level and/or to specific login_mode.
checker_to_countermeasureis empty (this is the case by default), then no rules are applied at all!
Question: Which countermeasure is applied, when two or more are
triggered by a different checker?
NoAnswer and NoAnswerUntil, take over all other countermeasures, which are not applied.
Then LoginInvalid and LoginInvalidUntil, will take precedence, on the remaining countermeasures
Then, the 3 others work in parallel
iTop Fence is written as an plugin system: so you can write your own checkers and countermeasures.
Writing your own checkers and countermeasures require very few
code. This is made possible because they have no dependencies with
each other (the
StrategyManager is the glue bringing
them together based on the
Writing your own checker
IpRangeChecker. And then read those explanations
Writing your own checker is extremely easy, you just have to
plug yourself in the login process of iTop, the easiest way is to
AbstractLoginFSMExtension (see https://wiki.combodo.com/doku.php?id=latest:customization:authentication#extending_the_authentication_process
for a full list of possibilities).
Once you've done this, you'll just have to call
$yourOwnLevelSystem); when relevant. please note that this
call must take place:
before the standard login procedure
ListSupportedLoginModes()must at least return 'before'
startand during the
return true only if the checker if configured for the current
Appending content to the login form
Captcha::GetLoginData(). And then read those explanations.
This is easily feasible by defining a
method. Please note that this probably mean that you checker is not
compatible with other login mode than form, thus, every time a
configuration reference this checker, it should filter using
'login_mode_included' ⇒ ['form']. This also mean that
another checker should cover the case of
'login_mode_excluded' ⇒ ['form'],.
Please refer to https://wiki.combodo.com/doku.php?id=latest:customization:authentication#screen_customization
in order to discover how to write the
Writing your own countermeasure
LoginInvalid. And then read those explanations.
In order to create your own countermeasure, you just have to
AbstractCountermeasure and write your own
if you want to let the login process continue, return
if you want to stop the login process
set to a relevant error code (ie
$iErrorCode = LoginWebPage::EXIT_CODE_WRONGCREDENTIALS)
$this→IsEnabled() return true only if you have
been activated has a countermeasure.
Writing Hybrid classes that are both checker and countermeasure
This is the case of captcha and recaptcha, so, you know the idea
: you should take a look at
Captcha. And then read
those explanations ;)
You have to call
$iLevel) when you detect a suspicious activity, and alway
return a relavant value for the statemachine (ie
LoginWebPage::LOGIN_FSM_ERROR in the
Finally, checker and countermeasure are always called by the
login FSM, so if you want to perform code only if you are legit,
you should do this check