How to protect webapp -- fail2ban



  • Hello,
    has anybody tried to protect z-push and webapplogin with the help of fail2ban to prevent password guessing?

    I tried to build a regex to react to webapp login errors.

    Logfileentry:

    [Wed Mar 08 20:03:24.725781 2017] [:error] [pid 12297] [client aaa.bbb.ccc.ddd:4453] Kopano WebApp user: ysdxfsa: authentication failure at MAPI, referer: https://my.server.at/webapp/?logon
    

    Unfortunatly I cannot handle regex very well…
    Would be great, if someone has some tips.

    Thanks!


  • Kopano

    There are some examples in the z-push wiki. I hope this helps. Feel free to extend later when you got it working ;)

    https://wiki.z-hub.io/display/ZP/Fail2Ban+support



  • @Sebastian
    Hey, I know the link you mentioned already. ;-)

    This is a nice description, but did not work in my case (different logentry.)

    If I am able to find a solution I will post it!


  • Kopano

    @mcdaniels ah, ok… ;)

    try something like (untested)

    failregex = client <HOST>:4453] Kopano WebApp user: *.? authentication failure at MAPI
    


  • @Sebastian
    as the whole thing is apache-related I included “before = apache.common.conf” in the filter

    After some fiddeling around with regex (never used it before) I got the following “solution”:

    1.) in /etc/fail2ban/filter.d/kopano-webapp-login.conf

    # FILE : /etc/fail2ban/filter.d/kopano-webapp-login.conf
    # Fail2Ban configuration file
    [INCLUDES]
    before = apache-common.conf
    
    [Definition]
    # Option:  failregex
    # Notes.:  regex to match the password failures messages in the logfile. The
    #          host must be matched by a group named "host". The tag "<HOST>" can
    #          be used for standard IP/hostname matching and is only an alias for
    #          (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
    # Values:  TEXT
    #
    
    failregex =  ^%(_apache_error_client)s Kopano WebApp user: .+?(?=:): authentication failure at MAPI
    
    ignoreregex =
    

    Hint:.+?(?=:) reads all characters until the next :** which covers any kind of “username given” in the log.

    2.) /etc/fail2ban/jail.local

    [kopano-webapp]
    enabled = true
    port = https
    filter = kopano-webapp-login
    logpath = /var/log/apache2/kopano_ssl_error.log
    
    

    Finally…

    
    2017-03-09 19:20:56,586 fail2ban.actions[26156]: WARNING [kopano-webapp] Ban xx.119.yyy.141
    

    :-)

    This side was a great help: http://regexr.com/



  • @Sebastian
    These examples rely on z-push logging IP/host-information to z-push-error.log.

    With config (on Z-Push 2.3.6beta0+3)

    define('LOGLEVEL', LOGLEVEL_WARN);
    define('LOGAUTHFAIL', true);
    

    no IP-information reaches the logs - a single unauthorized authentification attempt produces the following lines:

    # cat /var/log/z-push/z-push-error.log
    10/03/2017 10:32:04 [18885] [FATAL] [unknown] Exception: (AuthenticationRequiredException) - Access denied. Please send authorisation information
    10/03/2017 10:32:04 [18885] [FATAL] [unknown] Exception: (AuthenticationRequiredException) - Access denied. Please send authorisation information
    10/03/2017 10:32:17 [17858] [ERROR] [haderlump] KopanoBackend->Logon(): login failed with error code: 0xFFFFFFFF80040111
    10/03/2017 10:32:17 [17858] [ERROR] [haderlump] KopanoBackend->Logon(): login failed with error code: 0xFFFFFFFF80040111
    10/03/2017 10:32:17 [17858] [FATAL] [haderlump] Exception: (AuthenticationRequiredException) - Access denied. Username or password incorrect
    10/03/2017 10:32:17 [17858] [FATAL] [haderlump] Exception: (AuthenticationRequiredException) - Access denied. Username or password incorrect
    

    Is there any other switch to have orginating IPs pushed to the logs?

    thanks,
    umgfoin.


  • Kopano

    @umgfoin Did you look at https://wiki.z-hub.io/display/ZP/Fail2Ban+support?

    You have to enable LOGAUTHFAIL to get this in the log.



  • Hi Sebastian,
    it is enabled - the above is my log-output with define('LOGAUTHFAIL', true);.


  • Kopano

    @umgfoin I just tested that because I couldn’t believe it and (of course) you are right.

    The log message is logged only to the default log file, but not to the error logfile.
    This is because it’s logged at WARN level and these are not (anymore?) written to the error log.

     [WARN] [test] IP: 192.168.42.1 failed to authenticate user 'test'
    

    I created a ticket for this https://jira.z-hub.io/browse/ZP-1182.
    There were several changes to the logging for 2.3.x and I thought we did also write warns to the error log before, but I might remember wrong.

    For now, you could just use the standard z-push.log for fail2ban or change the loglevel of that log statement in index.php, around line 194 to LOGLEVEL_ERROR.



  • By the way, I think a even better way is to use this. Just tested. It is not relying on the :

    failregex =  ^%(_apache_error_client)s Kopano WebApp user:.* authentication failure at MAPI


  • No worries - dev’s everyday life…

    and I thought we did also write warns to the error log before, but I might remember wrong.

    I’m relatively sure, too, it once was logged to z-push-error.
    And, just verified - IP is logged to standard z-push.log.

    If working on this - do you see any chance to have HTTP_X_REAL_IP logged, if set?

    e.g. lib/request/request.php

      if(isset($_SERVER["REQUEST_METHOD"]))
                self::$method = self::filterEvilInput($_SERVER["REQUEST_METHOD"], self::LETTERS_ONLY);
            // TODO check IPv6 addresses
            if(isset($_SERVER["HTTP_X_REAL_IP"]))
                self::$remoteAddr = self::filterEvilInput($_SERVER["HTTP_X_REAL_IP"], self::NUMBERSDOT_ONLY);
            elseif(isset($_SERVER["REMOTE_ADDR"]))
                self::$remoteAddr = self::filterEvilInput($_SERVER["REMOTE_ADDR"], self::NUMBERSDOT_ONLY);
    

    and autodiscover/autodicover.php

     if (defined('LOGAUTHFAIL') && LOGAUTHFAIL != false){
         if(isset($_SERVER["HTTP_X_REAL_IP"]))
             $remoteAddrProp = "HTTP_X_REAL_IP";
         else
             $remoteAddrProp = "REMOTE_ADDR";
    
         ZLog::Write(LOGLEVEL_WARN, sprintf("Unable to complete autodiscover because login failed for user with email '%s' from IP %s.", $incomingXml->Request->EMailAddress, $remoteAddrProp));
     }
    

    This would be great for nginx/php-fpm setups, where you otherwise see only localhost’s ip in the logs or z-push-top.

    I tried define('USE_X_FORWARDED_FOR_HEADER', true); but this seems not to help in this respect.

    ++umgfoin.


  • Kopano

    I created a ticket for the usage of HTTP_X_REAL_IP: https://jira.z-hub.io/browse/ZP-1183



  • @Sebastian
    Great - thank you!


Log in to reply
 

Looks like your connection to Kopano Community Forum was lost, please wait while we try to reconnect.