Some failed logins not triggering the "login failed" event.

HugoFirst
Kilo Sage

Our security team is requesting a history of login attempts to our production instance.   They want both the successful and failed login attempts.

Since the event log only goes back a week or so, this is not suitable for their purpose.   So I created a custom table to record the attempts and then I created 2 script actions to capture both 'login' and 'login failed' events. They mostly work, but I found that the 'login failed' event does not fire if the userid entered in the login form doesn't match a userid in sys_user.   Is there a system property that I can set to capture ALL login attempts?   Or is there any other approach I should consider?

1 ACCEPTED SOLUTION

HugoFirst
Kilo Sage

FYI: I worked with Orlando Michaud of ServiceNow and now have solved the issue.



Here is his solution:



Try this solutjon in a development instance before attempt in production.


1. Locate the installation exit named 'Login' and open it. Observe that the loginFunciton looks like this:



loginFailed : function() {


      if (GlideController.exists("glide.ldap.error.connection")) {


        var ldapConnError = GlideController.getGlobal("glide.ldap.error.connection");


        if ( GlideStringUtil.notNil(ldapConnError) )


                GlideSession.get().addErrorMessage(ldapConnError);


      } else {


                          var message = GlideSysMessage.format("login_invalid");


                          GlideSession.get().addErrorMessage(message);


      }



2. Modify the code for function 'loginFailed'   to include the following 3 lines of code at the end of the 'else' statement:


                            var userName = request.getParameter("user_name");


                          var t = GlideTransaction.get();


                          GlideEventManager.queue("login.failed", "", userName, t == null ? null : t.getRemoteAddr());



Then the loginFailed function modified will looks like this:



loginFailed : function() {


      if (GlideController.exists("glide.ldap.error.connection")) {


        var ldapConnError = GlideController.getGlobal("glide.ldap.error.connection");


        if ( GlideStringUtil.notNil(ldapConnError) )


                GlideSession.get().addErrorMessage(ldapConnError);


      } else {


                          var message = GlideSysMessage.format("login_invalid");


                          GlideSession.get().addErrorMessage(message);


  var userName = request.getParameter("user_name");


                          var t = GlideTransaction.get();


                          GlideEventManager.queue("login.failed", "", userName, t == null ? null : t.getRemoteAddr());


      }


3. Save the changes.



That is sufficient to create an event also when the   login user name does not exist in the sys_user table.


I tested it and it works correctly. Long term solution is to create a PRB so the code will be included in some of the next releases.



Let me know if you have any doubt.



Best regards,


Orlando Michaud


View solution in original post

3 REPLIES 3

HugoFirst
Kilo Sage

FYI: I worked with Orlando Michaud of ServiceNow and now have solved the issue.



Here is his solution:



Try this solutjon in a development instance before attempt in production.


1. Locate the installation exit named 'Login' and open it. Observe that the loginFunciton looks like this:



loginFailed : function() {


      if (GlideController.exists("glide.ldap.error.connection")) {


        var ldapConnError = GlideController.getGlobal("glide.ldap.error.connection");


        if ( GlideStringUtil.notNil(ldapConnError) )


                GlideSession.get().addErrorMessage(ldapConnError);


      } else {


                          var message = GlideSysMessage.format("login_invalid");


                          GlideSession.get().addErrorMessage(message);


      }



2. Modify the code for function 'loginFailed'   to include the following 3 lines of code at the end of the 'else' statement:


                            var userName = request.getParameter("user_name");


                          var t = GlideTransaction.get();


                          GlideEventManager.queue("login.failed", "", userName, t == null ? null : t.getRemoteAddr());



Then the loginFailed function modified will looks like this:



loginFailed : function() {


      if (GlideController.exists("glide.ldap.error.connection")) {


        var ldapConnError = GlideController.getGlobal("glide.ldap.error.connection");


        if ( GlideStringUtil.notNil(ldapConnError) )


                GlideSession.get().addErrorMessage(ldapConnError);


      } else {


                          var message = GlideSysMessage.format("login_invalid");


                          GlideSession.get().addErrorMessage(message);


  var userName = request.getParameter("user_name");


                          var t = GlideTransaction.get();


                          GlideEventManager.queue("login.failed", "", userName, t == null ? null : t.getRemoteAddr());


      }


3. Save the changes.



That is sufficient to create an event also when the   login user name does not exist in the sys_user table.


I tested it and it works correctly. Long term solution is to create a PRB so the code will be included in some of the next releases.



Let me know if you have any doubt.



Best regards,


Orlando Michaud


Will this work if you use Multiprovider SSO? Our login is now handled through Azure AD.

gsh1
Tera Contributor

However if you have SSO enabled then you have to make same changes in

MultiSSOLogin script as it overrides the login script.