Modeling user behavior using OpenAM and Guardian Analytics

Guardian’s FraudMAP Access

A brief overview of Guardian’s flagship analytics engine is in order. A range of methods from malware to social engineering to phishing schemes plus combinations of these can be used by cyber criminals to defeat authentication and illegally access accounts. FraudMAP Access is able to detect the fraudster’s unexpected or suspicious activity when it occurs, as compared to the victim’s typical login behavior. FraudMAP Access models the normal behavior of every user or account holder, building and continually updating individual profiles against which all subsequent activity is compared to look for unusual activity. Powered by Guardian Analytics’ Dynamic Account Modeling™ technology, FraudMAP Access continually monitors the following parameters:

  1. Location from which the account is being accessed
  2. The device being used to access the account
  3. IP address
  4. Day of week and time of day
  5. Frequency patterns

From a regulatory standpoint, FraudMAP Access helps credit unions and banks conform to FFIEC guidance by meeting minimum expectation for anomaly detection at login (for banks and credit unions).

We are interested in the Login, Logout and DeviceRegistered events. The Login event can be used to signal both login success and failure events. The Login event can also be used to send device signature creating a signal of user behavior that FraudMAP tracks on a per user and per session basis. The DeviceRegistered event is used to register a new device, using the uuid and signature created by OpenAM’s DevicePrint module.

Event Data

OpenAM is required to send the following bits of information to the FraudMAP SOAP endpoint:

BrowserPlugins Cookie CookiesEnabled DeviceID FontList HTTPAccept HTTPAcceptCharsets HTTPAcceptEncoding HTTPAcceptLanguage HTTPClientIP HTTPCookie HTTPForwarded HTTPForwardedFor HTTPHost HTTPLocation HTTPProxy HTTPReferer HTTPRequestURI HTTPVia HTTPXClusterClientIP HTTPXForwarded HTTPXForwardedFor HTTPXTrusteerRapport ImmutableUserID IPAddress IPv6Address JavaEnabled LanguageBrowser LanguageSystem LanguageUser Latitude Longitude OSPlatform ScreenResolution SessionID SignOnID TimeZoneOffset UserAgentString UserAgentStringDOM UTCTimestamp

The ImmutableUserID is the key in this mapping process, and is defaulted to the SignOnID, which is the username used to login into OpenAM. Due to privacy concerns, the immutable user id or the sign on id are not sent in the clear, but are SHA1 hashed before being included in the SOAP payload.

OpenAM Configuration Overview

External User Repository

Create a new realm in OpenAM, call it “deviceid” for example. Associate a datastore such as an OpenDJ instance. Check the “Load schema when saved” checkbox. This will ensure the device fingerprint schema is added to the data store. We need this schema because the integration relies on the Device Save module.

Device (Id) Match and Save modules

For this integration the Device Id Match and Save modules in OpenAM can be used as-is. No customizations are necessary. Just ensure the OpenAM schema is loaded into the external user repository you configured into the “deviceid” realm.

Post Authentication Plugin

The HttpServletRequest object is passed into the PaP in the case of a login success and login failure. It contains the following sample data:

Header Name: host-> Header Value: http://<openam-server-hostname>:8080
Header Name: content-type-> Header Value: application/x-www-form-urlencoded
Header Name: origin-> Header Value: http://<openam-server-hostname>:8080
Header Name: cookie-> Header Value: JSESSIONID=496706A47350E1294B0B207E1D9A35B3; AMAuthCookie=AQIC5wM2LY4Sfcz8NstUlg1Chv-_gRP2s-Fj2ZHkPQDYTug.*AAJTSQACMDEAAlNLABMxMDY3MTM1NTMyODY1NTQyNjg4*; amlbcookie=01
Header Name: content-length-> Header Value: 979
Header Name: connection-> Header Value: keep-alive
Header Name: accept-> Header Value: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Header Name: user-agent-> Header Value: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14
Header Name: referer-> Header Value:  http://<openam-server-hostname>:8080/openam/UI/Login
Header Name: accept-language-> Header Value: en-us
Header Name: accept-encoding-> Header Value: gzip, deflate

The user-agent string could be used to detect the type of device used to login.

The value of IDToken0 is also passed into the post authentication module in a Map variable in the case of a login success and failure. A sample value would be:

{"screenWidth":1440,"screenHeight":900,"screenColourDepth":24,"timezone":420,"installedPlugins":"CitrixOnlineWebDeploymentPlugin.plugin;WebEx64.plugin;Default Browser.plugin;Flash Player.plugin;googletalkbrowserplugin.plugin;JavaAppletPlugin.plugin;o1dbrowserplugin.plugin;QuickTime Plugin.plugin;SharePointBrowserPlugin.plugin;;","installedFonts":"cursive;monospace;serif;sans-serif;fantasy;Arial;Arial Black;Arial Narrow;Arial Rounded MT Bold;Bookman Old Style;Century;Century Gothic;Comic Sans MS;Courier;Courier New;Georgia;Impact;Lucida Console;Monotype Corsiva;Papyrus;Tahoma;Times;Times New Roman;Trebuchet MS;Verdana;"}

The timezone offset is the offset in minutes with sign reversed. We simply massage this value in the post authentication module, reverse the sign to get an offset in hours.

In summary, we are able to send most of the information FraudMAP requires using the HttpServletRequest object and the IDToken0 value.

onLoginSuccess()

In the case of a successful login, we read the HttpServletRequest object, and use a JSON parser to parse the IDToken0 value to extract device signature.

onLoginFailure()

The logic here is very similar to onLoginSuccess() with one difference. OpenAM does not send the accountState usually, however, the AMLoginContext class in OpenAM-Core can be customized to include the accountState- active, inactive or locked out- in the Map variable passed into this method. This is not necessary to achieve a successful integration but I decided to do it to take advantage of the “LockedOut” and “UserAccessRestricted” events that FraudMAP accepts among the reasons for login failure.

onLogout()

We reused the logic from onLoginSuccess() to read the HttpServletRequest object but also checked if the logout was user initiated or was the result of a timeout. FraudMAP cares about the difference and it helps to build a more accurate model of user behavior.

Performance Note

OpenAM synchronously calls the PaP and therefore it is paramount we keep delays in creating and sending events to FraudMAP to a minimum. I created a new PostAuthHandler thread to create and fire the event inside each of the login, logout and login failed methods in the PaP. The PostAuthHandler creates the SOAP message and uses org.apache.commons.httpclient.HTTPClient to post the message to FraudMAP’s endpoint.

OpenAM Configuration

Create a new realm

Log into the console as “amadmin”. On the dashboard under the “Access Control” tab

  • Click on the “New..” button
  • Specify the Name as “deviceid”
  • Click OK

Configure the DataStore

  • Click on the deviceid realm, and then click on the “DataStore” tab
  • Delete the existing datastore, and click “New..”
  • Enter the name “DJ” and check the radio button for “OpenDJ”, hit Next
  • Setup the directory configuration details for your OpenDJ
  • Make sure to check “Load schema when saved” check box
  • Click on Save

Create and Configure the Module Instances and Authentication Chain

  • Click on the Authentication tab (OpenAM 12), or the Menu Item (OpenAM 13)
  • Click on “Module Instances”, and click “New” (OpenAM 12), or “Add Module” (OpenAM 13)
  • Create the match and save modules by selecting Device Id (Match) once and Device Id (Save) next

Module instances

  • Click on the match module instance and select the client-side and server-side scripts:

match

  • Specify “hotp” as the Name and select “HOTP” as type, Click OK
  • Click on the “hotp” module instance to edit its properties

hotp

  • Enter a valid gmail account in “Mail Server Authentication Username”
  • Enter a valid “Mail Server Authentication Password”, confirm it
  • Enter a valid “Email From Address”
  • Leave everything else as-is, and click “Save”
  • Chain the HOTP and Device module instances together as shown

Screen Shot 2016-02-02 at 10.03.56 AM

Note that configuring the “match” module instance in Sufficient mode ensures that if an existing device fingerprint were found on the user profile, HOTP will not be triggered since an acceptable device fingerprint was previously registered by the user.
Configure a new Post Authentication Class

  • Click on the Authentication tab
  • Click on “All Core Settings…”, and scroll down to “Post Authentication Processing”
  • Scroll down to “Authentication Post Processing Classes”
  • Add the full name of your PaP class, including the package prefix
  • Click on “Save” and click on “Back to Authentication”
  • Click on “Save” and click on “Back to Access Control”

Ensure users are loaded from DataStore

  • Click on the “deviceid” realm
  • Click on “Subjects”
  • You should see a list of users in your directory

Change test user’s phone number and email

  • Click on the test user, say user.1
  • Edit the phone number to your phone number
  • Edit the email address to your email address
  • This will ensure the SMS sent by the HOTP module arrives at your phone

 

Testing

Login to the realm

  • Browse to the url https://<openam-server.domain>/openam/XUI/#login/&realm=deviceid
  • Enter username and password, and login
  • You should see the following page, click on “Request OTP Code”

hotp1

  • You will receive an SMS on your phone, enter it here and click “Submit OTP Code”

Confirm profile save

  • The Device Save module will ask you to confirm to add the device profile to list of trusted devices

register

  • Select “Yes” and click on “Log In”

Login to view your profile

At this point you will be taken to your user profile page, where you can manage all previously registered devices.

dashboard

Under the hood

Device Registered

In this case, I logged in from a linux virtual machine.

<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Body><addEvent xmlns="http://com.ga.collector.service/xsd"><requireRiskscore>false</requireRiskscore><serviceId>210057</serviceId><platformId>13</platformId><channel>OLBRetail</channel><payLoad><![CDATA[<?xml version="1.0" encoding="UTF-8"?><GAE:GAEvent xmlns:GAE="http://www.guardiananalytics.com/APIEvents" xmlns:GAET="http://www.guardiananalytics.com/APIEventTypes" xmlns:GAT="http://www.guardiananalytics.com/APIDataTypes"><GAE:DeviceRegistered><GAT:Common><GAT:SchemaVersion>2.00</GAT:SchemaVersion><GAT:TenantID>210057</GAT:TenantID><GAT:Channel>OLBRetail</GAT:Channel><GAT:ProviderEventName>DeviceRegistered</GAT:ProviderEventName></GAT:Common><GAT:RetailSession><GAT:ImmutableUserID>8FC62C1442CC32DAA50D5302E5C997080FB9D747</GAT:ImmutableUserID><GAT:SignOnID>8FC62C1442CC32DAA50D5302E5C997080FB9D747</GAT:SignOnID><GAT:UTCTimestamp>1399562334911</GAT:UTCTimestamp><GAT:IPAddress>127.0.0.1</GAT:IPAddress><GAT:UserAgentString>Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20131029 Firefox/17.0</GAT:UserAgentString><GAT:BrowserHeader><GAT:HTTPAcceptLanguage>en-US,en;q=0.5</GAT:HTTPAcceptLanguage><GAT:HTTPAcceptEncoding>gzip, deflate</GAT:HTTPAcceptEncoding><GAT:HTTPReferer>http://<openam-server.domain>:8080/openam/UI/Login</GAT:HTTPReferer><GAT:HTTPAccept>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</GAT:HTTPAccept></GAT:BrowserHeader></GAT:RetailSession><GAET:DeviceID>790498b4-0f32-4311-960a-629c70ab4424</GAET:DeviceID><GAET:DeviceType>computer</GAET:DeviceType></GAE:DeviceRegistered></GAE:GAEvent>]]></payLoad><key>8d9d0e4c11a19df474c24da34bc6d3c9fd2368ee</key></addEvent></env:Body></env:Envelope>

User Login

I logged in from a mac using a different test user which is the reason the hash of ImmutableUserID is different from the previous example.

LoginStatus: Successful

<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Body><addEvent xmlns="http://com.ga.collector.service/xsd"><requireRiskscore>false</requireRiskscore><serviceId>210057</serviceId><platformId>13</platformId><channel>OLBRetail</channel><payLoad><![CDATA[<?xml version="1.0" encoding="UTF-8"?><GAE:GAEvent xmlns:GAE="http://www.guardiananalytics.com/APIEvents" xmlns:GAET="http://www.guardiananalytics.com/APIEventTypes" xmlns:GAT="http://www.guardiananalytics.com/APIDataTypes"><GAE:Login><GAT:Common><GAT:SchemaVersion>2.00</GAT:SchemaVersion><GAT:TenantID>xxxxxx</GAT:TenantID><GAT:Channel>OLBRetail</GAT:Channel><GAT:ProviderEventName>Login Attempt</GAT:ProviderEventName></GAT:Common><GAT:RetailSession><GAT:ImmutableUserID>B093FEED33DB091084355C1A464290EE6339A109</GAT:ImmutableUserID><GAT:SignOnID>B093FEED33DB091084355C1A464290EE6339A109</GAT:SignOnID><GAT:UTCTimestamp>1399392974892</GAT:UTCTimestamp><GAT:IPAddress>x.y.z.w</GAT:IPAddress><GAT:UserAgentString>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14</GAT:UserAgentString><GAT:BrowserHeader><GAT:HTTPAcceptLanguage>en-us</GAT:HTTPAcceptLanguage><GAT:HTTPAcceptEncoding>gzip, deflate</GAT:HTTPAcceptEncoding><GAT:HTTPReferer>http://<openam-server.domain>:8080/openam/UI/Login</GAT:HTTPReferer><GAT:HTTPAccept>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</GAT:HTTPAccept></GAT:BrowserHeader><GAT:DeviceAttribute><GAT:FontList>cursive| monospace| serif| sans-serif| fantasy| Arial| Arial Black| Arial Narrow| Arial Rounded MT Bold| Bookman Old Style| Century| Century Gothic| Comic Sans MS| Courier| Courier New| Georgia| Impact| Lucida Console| Monotype Corsiva| Papyrus| Tahoma| Times| Times New Roman| Trebuchet MS| Verdana| </GAT:FontList><GAT:BrowserPlugins>CitrixOnlineWebDeploymentPlugin.plugin| WebEx64.plugin| Default Browser.plugin| Flash Player.plugin| googletalkbrowserplugin.plugin| JavaAppletPlugin.plugin| o1dbrowserplugin.plugin| QuickTime Plugin.plugin| SharePointBrowserPlugin.plugin </GAT:BrowserPlugins><GAT:TimeZoneOffset>-7</GAT:TimeZoneOffset><GAT:ScreenResolution>24|900|1440</GAT:ScreenResolution></GAT:DeviceAttribute></GAT:RetailSession><GAET:LoginStatus>Successful</GAET:LoginStatus></GAE:Login></GAE:GAEvent>]]></payLoad><key>65d67a6d0e87d771d5b843f148d9812d2ec95e10</key></addEvent></env:Body></env:Envelope>

LoginStatus: LockedOut

<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Body><addEvent xmlns="http://com.ga.collector.service/xsd"><requireRiskscore>false</requireRiskscore><serviceId>210057</serviceId><platformId>13</platformId><channel>OLBRetail</channel><payLoad><![CDATA[<?xml version="1.0" encoding="UTF-8"?><GAE:GAEvent xmlns:GAE="http://www.guardiananalytics.com/APIEvents" xmlns:GAET="http://www.guardiananalytics.com/APIEventTypes" xmlns:GAT="http://www.guardiananalytics.com/APIDataTypes"><GAE:Login><GAT:Common><GAT:SchemaVersion>2.00</GAT:SchemaVersion><GAT:TenantID>xxxxxx</GAT:TenantID><GAT:Channel>OLBRetail</GAT:Channel><GAT:ProviderEventName>Login Attempt</GAT:ProviderEventName></GAT:Common><GAT:RetailSession><GAT:ImmutableUserID>B093FEED33DB091084355C1A464290EE6339A109</GAT:ImmutableUserID><GAT:SignOnID>B093FEED33DB091084355C1A464290EE6339A109</GAT:SignOnID><GAT:UTCTimestamp>1399392974892</GAT:UTCTimestamp><GAT:IPAddress>x.y.z.w</GAT:IPAddress><GAT:UserAgentString>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14</GAT:UserAgentString><GAT:BrowserHeader><GAT:HTTPAcceptLanguage>en-us</GAT:HTTPAcceptLanguage><GAT:HTTPAcceptEncoding>gzip, deflate</GAT:HTTPAcceptEncoding><GAT:HTTPReferer>http://<openam-server.domain>:8080/openam/UI/Login</GAT:HTTPReferer><GAT:HTTPAccept>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</GAT:HTTPAccept></GAT:BrowserHeader><GAT:DeviceAttribute><GAT:FontList>cursive| monospace| serif| sans-serif| fantasy| Arial| Arial Black| Arial Narrow| Arial Rounded MT Bold| Bookman Old Style| Century| Century Gothic| Comic Sans MS| Courier| Courier New| Georgia| Impact| Lucida Console| Monotype Corsiva| Papyrus| Tahoma| Times| Times New Roman| Trebuchet MS| Verdana| </GAT:FontList><GAT:BrowserPlugins>CitrixOnlineWebDeploymentPlugin.plugin| WebEx64.plugin| Default Browser.plugin| Flash Player.plugin| googletalkbrowserplugin.plugin| JavaAppletPlugin.plugin| o1dbrowserplugin.plugin| QuickTime Plugin.plugin| SharePointBrowserPlugin.plugin </GAT:BrowserPlugins><GAT:TimeZoneOffset>-7</GAT:TimeZoneOffset><GAT:ScreenResolution>24|900|1440</GAT:ScreenResolution></GAT:DeviceAttribute></GAT:RetailSession><GAET:LoginStatus>LockedOut</GAET:LoginStatus></GAE:Login></GAE:GAEvent>]]></payLoad><key>65d67a6d0e87d771d5b843f148d9812d2ec95e10</key></addEvent></env:Body></env:Envelope>
Note that this article was first published in the OpenAM Wiki Confluence site for OpenAM 11: OpenAM and Guardian Analytics using Device module  The technical content has been adapted for OpenAM 13. Please let us know if we can improve it in anyway.

Google+ Social Login Risk Profiling using ZeroFOX

Introduction

ZeroFOX Enterprise evaluates and records the risk associated with social media users and organizations. This evaluation is conducted through the ZeroFOX Enterprise security analysis engine which analyzes the full social graph for a targeted user to include their associated people, organizations and interactions.

The ZeroFOX Social Risk Score API allows OpenAM to query the ZeroFOX Enterprise Platform RESTful API for risk attributes associated with a given social media asset- social media user or organization. If ZF does not have recent ZeroFOX data on the requested asset, it is immediately submitted for analysis and can be queried again at a later time.

For purposes of this demo with Google Plus, I created a custom OpenAM 13 build that enables chaining the Scripted Authentication Module to the OAuth module. The custom build also enables passing an Authorization header into the httpClient POST API in the server-side script. On every login attempt from a Social Login platform, the Scripted Authentication Module invokes the ZF api with an Authorization header to assess the risk associated with the login.

The following risk attributes can be flagged on a social account and each one of these can be detected from within the Scripted Authentication Module in OpenAM via the ZeroFOX Social Login Risk Score API.

Configuration

From Common Tasks, under the “Configure Social Authentication” menu, select and configure ‘Configure Google Authentication’.

Create a Scripted Authentication Module instance in OpenAM. Add code in the server side script to invoke the ZF API:

httpClient.post("https://api.zerofox.com/1.0/sra/", "{"network":"google+", "user_id":"+userId +"}", {cookies:[], headers:[{"field": "Content-type","value":"application/json"},{"field": "Authorization","value": "forgerock:*******"}]});

Chain the Scripted Authentication Module instance to the GoogleSocialAuthentication instance created in the previous step:

In Google Plus, open a test account and post a phishing link. At this point you should kick off the scan by invoking the ZF API from Postman or using curl. If you do not do it now, the scan is started when you attempt to login into OpenAM using this malicious account, except of course, the Social Login Score is not ready just yet and authentication passes.

Demo

From the OpenAM login page, click on the Google Plus icon to login:

Login as the malicious user and you should immediately see an Authentication denied error. The Scripted Authentication Module checks for high threat indicators and denies login if one or more are found.

Using Postman, invoking the ZF Social Login Score API confirms that phishing links were found on the account and threat level is too high to allow login into OpenAM.

{
  • "phishing": "2015-04-24 17:13:24 UTC",
  • "drugs_and_alcohol": "2015-04-24 17:09:24 UTC",
  • "malware": "2015-04-24 17:13:24 UTC"
}