Two-Factor Authentication using YubiKey, YubiCloud and APM
Introduction What is a YubiKey? The YubiKey is an innovative USB-key that simplifies the process of logging in with strong two factor authentication. With a simple touch on the device, it generates a One-Time Password (OTP) on any computer and platform without any client software needed. How it YubiKey works By touching the integrated button, the YubiKey sends a time-variant, secure login code as if it was typed in from a keyboard. The unique passcode is verified by a YubiKey compliant web service or software application, in our case APM. For more details see: http://www.yubico.com/yubikey What is YubiCloud? The YubiCloud is a free cloud based YubiKey (OTP) validation service, for easy integration of strong two-factor authentication with your web site or online service. i.e APM For more details see: http://www.yubico.com/yubicloud YubiKey 2-Factor Authentication Process with APM The authentication process can be broken down into a few simple steps which is illustrated below and explained in more detail. Step 1 – The user is presented with a login page. The login page in my example asks for a Username, Password and YubiKey OTP. After entering your username and password, you simply plug in the YubiKey to the USB port and press the button. The YubiKey will generate the unique OTP followed by the enter key. Step 2 & 3 – The Username and Password is verified by Active Directory. On success move to Step 4. Step 4 & 5 – Check to make sure the user has been assigned a YubiKey. I store the 8-digit YubiKey serial number to an Active Directory attribute: “employeeID”. Obviously you can use any attribute field you like or a data group. Step 6 – Make sure the OTP generated matches the YubiKey serial number for that user. YubiKey OTP uses Modified Hexadecimal output, known as MODHEX. The MODHEX alphabet is explained on the Yubico forum: http://forum.yubico.com/viewtopic.php?f=6&t=96. I created an iRule which takes a number (YubiKey Serial) and converts it to MODHEX and saves this to an APM session variable. Next compare the OTP value from step 1 to the MODHEX serial number, if the string exists, then we are good to go. Step 7, 8 & 9 – Send the YubiKey OTP to the YubiCloud validation service. If the YubiCloud API returns “Status=OK” then we can allow the user to access to the resource. An explanation of the validation protocol can be found here: http://code.google.com/p/yubikey-val-server-php/wiki/ValidationProtocolV20. In my example setup, I’m not signing or validating the response, this could be done with an iRule, something for my next post. BIG-IP APM Configuration The APM configuration is straight forward and assumes: You have an existing directory server with users configured and you can add the YubiKey serial number to an LDAP/AD attribute. Your YubiKey is registered with the YubiCloud service. You have obtained an Auth ID and API key from: https://upgrade.yubico.com/getapikey/ to validate the YubiKey. You have use a BIG-IP before and have suitable LTM knowledge. This configuration was created using BIG-IP v11.2.0. Lets get into the APM configuration. Authentication Servers Active Directory Access Policy >> AAA Servers >> Active Directory >> “Create” Supply the following: Name: dc1.test.lab (something sensible) Domain Name: test.lab (Domain Name) Domain Controller: <FQDN> or (AD server) Admin Name and Password Select “Finished" to save. YubiCloud API The HTTP AAA Server object doesn’t support HTTPS connections, so we need to create a Virtual Server to proxy the traffic from the BIG-IP to the YubiCloud API. The Virtual Server will listen on HTTP, but we will apply a Server SSL profile creating a HTTP –> HTTPS proxy. Local Traffic >> Nodes >> Node List >> “Create” Supply the following: Name: api.yubico.com Address: api.yubico.com Health Monitor Select “Finished" to save. Local Traffic >> Pools >> Pool List >> “Create” Supply the following: Name: pool_yubicloud Description: YubiCloud Proxy Pool (optional) Health Monitor (optional) Address: api.yubico.com Service Port: HTTPS Select “Finished" to save. Local Traffic >> Virtual Servers >> Virtual Server List >> “Create” Supply the following: Name: vs_yubicloud Description: YubiCloud Proxy VS (optional) Destination: <IP Address> Service Port: HTTP HTTP Profile: http SSL Profile (Server): clientssl SNAT Pool: Auto Map Default Pool: pool_yubicloud Select “Finished" to save. Access Policy >> AAA Servers >> HTTP Supply the following: Name: aaa_yubicloud Form Method: GET Form Action: http://IP_address_of_vs_yubicloud/wsapi/verify Form Parameter For User Name: id Form Parameter For Password: otp Successful Logon Detection Match Type: By Specific String in Response Successful Logon Detection Match Value: status=OK The Form Action uses the Virtual Server IP configured above instead of the YubiCloud server FQDN. You need to supply at least the id and otp parameters for an unsigned response. The id parameter is your Auth ID for the YubiCloud service and otp is the token code generated by the YubiKey. Select “Finished" to save. MODHEX Encode iRule Local Traffic >> iRules >> iRules List >> “Create” Copy and paste the following iRule which will convert the YubiKey serial number to Modified Hexadecimal (MODHEX) format. In my example, I’m retrieving the YubiKey serial associated with the user from Active Directory using the “employeeID” attribute. This iRule will need to be modified if the serial number has been stored in alternate source, such as a data group or a custom LDAP/AD attribute. when ACCESS_POLICY_AGENT_EVENT { if { [ACCESS::policy agent_id] eq "irule_apm_yubikey_modhex_encode" } { # yubikey serial number set yubikey_serial [ACCESS::session data get session.ad.last.attr.employeeID] # modhex alphabet array set modhex_alphabet { 0 c 1 b 2 d 3 e 4 f 5 g 6 h 7 i 8 j 9 k A l B n C r D t E u F v } # remove leading zeros from serial number set yubikey_serial [string trimleft $yubikey_serial 0] # convert serial to hex and pad with zeros set yubikey_serial [format %012X $yubikey_serial] # split the string set yubikey_serial [split $yubikey_serial ""] # for each HEX change to MODHEX using alphabet set yubikey_modhex "" foreach index $yubikey_serial { append yubikey_modhex $modhex_alphabet($index) } ACCESS::session data set session.custom.yubikey.modhex $yubikey_modhex } } Access Profile & Policy Access Policy >> Access Profiles >> Access Profiles List >> “Create” Supply the following: Name: profile_yubicloud Language: English (en) Use the default settings for all other settings. Select “Finished" to save. Access Policy >> Access Profiles >> Access Profiles List >> “Edit” On the “fallback” branch after the “Start” object, add a “Logon Page” object. Add a third field: Type: text Post Variable Name: yubiotp Session Variable Name: yubiotp Read Only: No In the “Customization” section further down the page, set the “Form Header Text” to what ever you like and change “Logon Page Input Field #3” to something meaningful, see my example below for inspiration. Leave the “Branch Rules” as the default. Don’t forget to “Save”. On the “fallback” branch after the “Logon Page” object, add an “AD Auth” object. This step verifies the username and password is correct against Active Directory. Supply the following Properties: Name: AD Auth AAA Server: /Common/dc1.test.lab (select your AD Server) Leave the “Branch Rules” as the default. Select “Save” when your done. On the “Successful” branch after the “AD Auth” object, add an “AD Query” object. This step checks if the user has a YubiKey provisioned in their Active Directory account. I’ve added the serial number of the YubiKey to the “employeeID” attribute in Active Directory for each user. I used the “employeeID” attribute for simplicity, but I would recommend creating a custom AD attribute for the YubiKey serial number. Supply the following Properties: Name: YubiKey Provisioned SearchFilter: sAMAccountName=%{session.logon.last.username} Under “Branch Rules”, delete the default and add a new one, by selecting “Add Branch Rule”. Update the Branch Rule settings: Name: Yes Expression (Advanced): expr { [mcget {session.ad.last.attr.employeeID}] != "" } Select “Finished”, then “Save” when your done. On the “Yes” branch after the “YubiKey Provisioned” object, add an “iRule Event” object. This step passes “session.ad.last.attr.employeeID” (YubiKey serial) from the successful AD Query to the iRule called “irule_apm_yubikey_modhex_encode”. The iRule returns a Modified Hexadecimal (MODHEX) encoded string and stores this to “session.custom.yubikey.modhex”. We need the YubiKey serial in the MODHEX format so we can compare this to the original YubiKey OTP entered on the Logon Page. To learn more about how/why Yubico uses this format, visit the Yubico Forum: http://forum.yubico.com/viewtopic.php?f=6&t=96 Supply the following Properties: Name: YubiKey MODHEX Encode ID: irule_apm_yubikey_modhex_encode Now we compare the MODHEX formatted YubiKey serial to the YubiKey OTP entered on the Logon Page. This step verifies the user is using their YubiKey and not someone else's. The first 12 characters of the YubiKey OTP is the serial of that YubiKey, this makes is very easy to verify using the “string first” TCL command. Under “Branch Rules” add a new one, by selecting “Add Branch Rule”. Update the Branch Rule settings: Name: YubiKey Serial Match Expression (Advanced): expr { [string first [mcget {session.custom.yubikey.modhex}] [mcget {session.logon.last.yubiotp}]] == 0 } Select “Finished”, then “Save” when your done. On the “YubiKey Serial Match” branch after the “YubiKey MODHEX Encode” object, add a “Variable Assign” object. This step assigns your YubiCloud Auth ID to to “session.logon.last.username” and the YubiKey OTP entered on the Logon Page to “session.logon.last.password”. These session variables are then assigned to the id and otp HTTP parameters used in the HTTP Auth AAA object “aaa_yubicloud” created earlier. If you don’t quite follow how this works, just believe me and just do it! Supply the following Properties: Name: Assign YubiCloud Variables Add the Variable assignments by selecting “Add new entry” >> “change”. Variable Assign 1: Custom Variable (Unsecure): session.logon.last.username Custom Expression: expr {"1111"} (change “1111” to your YubiCloud Auth ID) Variable Assign 2: Custom Variable (Secure): session.logon.last.password Custom Expression: expr { [mcget {session.logon.last.yubiotp}] } Select “Finished”, then “Save” when your done.Leave the “Branch Rules” as the default. On the “fallback” branch after the “Assign YubiCloud Variables” object, add a “HTTP Auth” object. This step sends a HTTP Get to the YubiCloud API (https://api.yubico.com/wsapi/verify) to verify the YubiKey OTP entered on the Logon Page. Supply the following Properties: Name: YubiCloud Auth AAA Server: /Common/aaa_yubicloud Leave the “Branch Rules” as the default. Select “Save” when you’re done. This competes the Access Policy. It should resemble something similar to this: Next attached the “Access Profile” and “iRule” to a Virtual Server to test. Conclusion This is another great example how you can easily add a 2nd factor of authentication to any application using the power of Access Policy Manager (APM). F5 provides a 10 Concurrent User trial version of APM with every BIG-IP licensed with LTM. APM is one of my favourite pieces of technology, it amazes me every day what I can create with this flexible tool. Why not give it a try today.1.8KViews0likes4CommentsPost of the Week: Two-Factor Auth and SSO with BIG-IP
In this Lightboard Post of the Week, I answer a question about 2FA and SSO with AD/RSA on BIG-IP by creating a SSO Credential Mapping policy agent in the Visual Policy Editor, that takes the username and password from the logon page, and maps them to variables to be used for SSO services. Special thanks to senthil147for the question and a new 2018 MVP, MrPlastic (Lee Sutcliffe, which I flubbed) for the great answer. Posted Question on DevCentral: 2FA Authentication with SSO on APM ps1.2KViews0likes1CommentAPM Cookbook: Two-Factor Authentication using YubiKey OTP with iRulesLX.
Introduction It’s been a number of years since I penned my first DC article: Two-Factor Authentication using YubiKey, YubiCloud and APM. A lot has changed over the years, BIG-IP versions and features, new YubiKey models and the YubiCloud Validation API has changed significantly rendering my older article obsolete. This article is a rewrite of the original with a number of improvements, such as: No need for HTTP Auth agent No need to Reverse Proxy the HTTP connection to the YubiCloud API “yub” NPM package used with iRulesLX. This does all the hard work for us, such as signing the message, validating the response and decoding the YubiKey serial. HMAC-SHA1 signed message Signed response validation VPE improvements to protect AD Account Lockouts YubiKey 2-Factor Authentication Process with APM The authentication process can be broken down into a few simple steps which is illustrated below and explained in more detail. Step 1 – The user is presented with a login page. The login page in my example asks for a Username, Password and YubiKey OTP. After entering your username and password, you simply plug in the YubiKey to the USB port and press the button. The YubiKey will generate the unique OTP followed by the enter key. Step 2 & 3 – APM sends the YubiKey OTP to the YubiCloud validation service. If the YubiCloud API returns “Status=OK”, the signature and the nonce is verified, then we know the YubiKey OTP is valid. This is performed by the “yub” NPM package using iRulesLX. Step 4 & 5 – Check to make sure the user has been provisioned a YubiKey and the Serial number assigned to that user matches. I store the 8-digit YubiKey serial number to an Active Directory attribute: “employeeID”. Obviously you can use any attribute field you like or you can modify the policy to query a data group. Step 6 & 7 – The Username and Password is verified by Active Directory/LDAP or what ever is your preference. Step 8 - On success, grant the user access to the resource. An explanation of the validation protocol can be found here: https://developers.yubico.com/yubikey-val/Validation_Protocol_V2.0.html. The “yub” NPM module uses this API and simplifies the validation and signing process. Before we get started I have a pre-configured Active Directory 2012 R2 server which I will be using as my LDAP server with an IP address of 10.1.30.101. My BIG-IP is running TMOS 12.1.2 and the iRules Language eXtension has been licensed and provisioned. Make sure your BIG-IP has internet access to download the required Node.JS packages. This guide also assumes you have a basic level of understanding and troubleshooting at a Local Traffic Manager (LTM) level and your BIG-IP Self IP, VLANs, Routes, etc.. are all configured and working as expected. You have obtained a Client ID and API Key from: https://upgrade.yubico.com/getapikey/ to validate the YubiKey OTP. Step 1 – iRule and iRuleLX Configuration 1.1 Create a new iRulesLX workspace Local Traffic >> iRules >> LX Workspaces >> “Create” Supply the following: Name: yubikey_auth_workspace Select “Finished" to save. You will now have any empty workspace, ready to cut/paste the TCL iRule and Node.JS code. 1.2 Add the iRule Select “Add iRule” and supply the following: Name: yubikey_auth_apm_event_irulelx Select OK Cut / Paste the following iRule into the workspace editor on the right hand side. Select “Save File” to save. # Author: Brett Smith @f5 when RULE_INIT { # Debug logging control. # 0 = debug logging off, 1 = debug logging on. set static::yubikey_debug 0 } when ACCESS_POLICY_AGENT_EVENT { if { [ACCESS::policy agent_id] eq "yubikey_auth" } { # Get the YubiKey OTP from APM session data set yubiotp [ACCESS::session data get session.logon.last.yubiotp] if { $static::yubikey_debug == 1 }{ log local0. "YubiKey OTP: $yubiotp" } # Basic error handling - don't execute Node.JS if session.logon.last.yubiotp is null if { ([string trim $yubiotp] eq "") } { # The YubiKey OTP is not valid ACCESS::session data set session.yubikey.valid 0 if { $static::yubikey_debug == 1 }{ log local0. "YubiKey OTP is not valid!" } } else { # Initialise the iRulesLX extension set rpc_handle [ILX::init yubikey_auth_extension] # Need to change the default RPC timeout from 3 sec to 30 sec to # allow for the HTTPS request to the Yubico API set timeout 30000 # Pass the YubiKey OTP to Node.JS and save the iRulesLX response set rpc_response [ILX::call $rpc_handle -timeout $timeout yubikey_auth $yubiotp] if { $static::yubikey_debug == 1 }{ log local0. "rpc_response: $rpc_response" } # Loop through each key/value pair returned from "yub.verify" foreach {key value} $rpc_response { # Assign the key/value pair to an APM session variable so it # can be referenced in the Access Policy ACCESS::session data set session.yubikey.$key $value if { $static::yubikey_debug == 1 }{ log local0. "$key $value" } } } } } 1.3 Add the Extension Select “Add extenstion” and supply the following: Name: yubikey_auth_extension Select OK Cut / Paste the following Node.JS and replace the default index.js. Select “Save File” to save. Update the “client_id” and “secret_key” variables with your Yubico Client ID and API Key. // Author: Brett Smith @f5 // index.js for yubikey_auth_apm_event_lx // Includes var f5 = require('f5-nodejs'); var yub = require('yub'); // Create a new rpc server for listening to TCL iRule calls. var ilx = new f5.ILXServer(); // Start listening for ILX::call and ILX::notify events. ilx.listen(); // YubiKey Auth ilx.addMethod('yubikey_auth', function(yubiotp, response) { // Get a Yubico Client ID and API Key from here: https://upgrade.yubico.com/getapikey/ var client_id = 'XXXX'; var secret_key = 'XXXXXXXXXXXXXXX'; // Initialise the yub library yub.init(client_id, secret_key); // Attempt to verify the OTP yub.verify(yubiotp.params()[0], function(err,data) { if (err) { console.log('Error: YubiKey OTP Verify Failed!'); response.reply('valid 0'); } else { response.reply(data); } }); }); 1.4 Install the “yub” package SSH to the BIG-IP as root cd /var/ilx/workspaces/Common/yubikey_auth_workspace/extensions/yubikey_auth_extension npm install yub -save You should expect the following output from the above command: [root@big-ip1:Active:Standalone] ldap_modify_extension # npm install yub -save yub@0.11.1 node_modules/yub 1.5 Create a the iRulesLX plugin Local Traffic >> iRules >> LX Plugin >> “Create” Supply the following: Name: yubikey_auth_plugin From Workspace: yubikey_auth_workspace Select “Finished" to save. If you look in /var/log/ltm, you will see the extension start a process per TMM for the iRuleLX plugin. big-ip1 info sdmd[16339]: 018e000b:6: Extension /Common/yubikey_auth_plugin:yubikey_auth_extension started, pid:975 big-ip1 info sdmd[16339]: 018e000b:6: Extension /Common/yubikey_auth_plugin:yubikey_auth_extension started, pid:976 big-ip1 info sdmd[16339]: 018e000b:6: Extension /Common/yubikey_auth_plugin:yubikey_auth_extension started, pid:977 big-ip1 info sdmd[16339]: 018e000b:6: Extension /Common/yubikey_auth_plugin:yubikey_auth_extension started, pid:978 Step 2 – APM Configuration 2.1 Create a new Authentication Server or reuse an existing server 2.1.1 Access Policy >> AAA Servers >> Active Directory >> “Create” Supply the following: Name: f5.demo_ad_aaa (something sensible) Domain Name: f5.demo (Domain Name) Server Connection: Direct or Use Pool depending on your setup. Domain Controller: <FQDN> or (AD server) or leave blank and APM will use DNS. Admin Name and Password Select “Finished" to save. 2.2 Create an Access Profile and Policy 2.2.1 Access Policy >> Access Profiles >> Access Profiles List >> “Create” Supply the following: Name: yubikey_otp_2fa_iruleslx_ap Profile Type: All Profile Scope: Profile Languages: English (en) Use the default settings for all other settings. Select “Finished" to save. 2.2.2 Access Policy >> Access Profiles >> Access Profiles List >> “Edit” On the “fallback” branch after the “Start” object, add a “Logon Page” object. Add a third field: Type: text Post Variable Name: yubiotp Session Variable Name: yubiotp Read Only: No In the “Customization” section further down the page, set the “Form Header Text” to what ever you like and change “Logon Page Input Field #3” to something meaningful, see my example below for inspiration. Leave the “Branch Rules” as the default. Don’t forget to “Save”. 2.2.3 On the “fallback” branch after the “Logon Page” object, add an “iRule Event” object. This step verifies the YubiKey OTP by passing “session.logon.last.yubiotp” from the ”Logon Page” to the iRuleLX created in Step 1. Supply the following Properties: Name: YubiKey Auth ID: yubikey_auth 2.2.3.1 Under “Branch Rules”, add a new one, by selecting “Add Branch Rule”. Update the Branch Rule settings: Name: YubiKey OTP Valid Expression (Advanced): expr { [mcget {session.yubikey.valid}] == "1" } Select “Finished”, then “Save” when your done. 2.2.4 On the “YubiKey OTP Valid” branch after the “YubiKey Auth” object, add an “AD Query” object. This step checks if the user has a YubiKey provisioned in their Active Directory account and the Serial number assigned to that user matches. I’ve added the serial number of the YubiKey to the “employeeID” attribute in Active Directory for each user. I used the “employeeID” attribute for simplicity, but I would recommend creating a custom AD attribute for the YubiKey serial number. Supply the following Properties: Name: YubiKey Serial Match Server: /Common/f5.demo_ad_aaa (select your AD Server) SearchFilter: sAMAccountName=%{session.logon.last.username} Required Attributes: employeeID 2.2.4.1 Under “Branch Rules”, delete the default and add a new one, by selecting “Add Branch Rule”. Update the Branch Rule settings: Name: Not Provisioned Expression (Advanced): expr { [mcget {session.ad.last.attr.employeeID}] == "" } Select “Finished. 2.2.4.2 Add another Branch Rule by selecting “Add Branch Rule”. Update the Branch Rule settings: Name: Match Found Expression (Advanced): expr { [mcget {session.yubikey.serial}] eq [string trim [mcget {session.ad.last.attr.employeeID}] 0] } Select “Finished”, then “Save” when your done. 2.2.5 On the “Match Found” branch after the “YubiKey Serial Match” object, add an “AD Auth” object. This step verifies the username and password is correct against Active Directory. Supply the following Properties: Name: AD Auth AAA Server: /Common/f5.demo_ad_aaa (select your AD Server) Leave the “Branch Rules” as the default. Select “Save” when your done. 2.2.6 On the “Successful” branch after the “AD Auth” object, change the branch end from “ Deny” to “Allow”. This competes the Access Policy. It should resemble something similar to this: Step 3 – Virtual Server Configuration Attach the Access Policy (yubikey_otp_2fa_iruleslx_apldap_modify_ap) to a HTTPS virtual server. Attach the iRuleLX (yubikey_auth_apm_event_irulelx) under the Resources section. Conclusion This is another great example how you can easily add a 2nd factor of authentication to any application using the power of Access Policy Manager (APM). F5 provides a 10 Concurrent User trial version of APM with every BIG-IP licensed with LTM. APM is one of my favourite pieces of technology, it amazes me every day what I can create with this flexible tool. Why not give it a try today.2.7KViews0likes6CommentsF5 SOC Malware Summary Report: Neverquest
#F5SOC #malware #2FA #infosec The good news is that compromising #2FA requires twice the work. The bad news? Malware can do it. That malware is a serious problem, particularly for organizations that deal with money, is no surprise. Malware is one of the primary tools used by fraudsters to commit, well, fraud. In 2013, the number of cyberattacks involving malware designed to steal financial data rose by 27.6% to reach 28.4 million according to noted security experts at Kaspersky. Organizations felt the result; 36% of financial institutions admit to experiencing ACH/wire fraud (2013 Faces of Fraud Survey). To protect against automated transactions originating from infected devices, organizations often employ two-factor authentication (2FA) that leverages OTP (one time passwords) or TAN (transaction authorization numbers) via a secondary channel such as SMS to (more) confidently verify identity. 2FA systems that use a secondary channel (a device separate from the system on which the transaction is initiated) are more secure, naturally, than those that transmit the second factor over a channel that can be used from the initiating system, a la an e-mail. While 2FA that use two disparate systems are, in fact, more secure, they are not foolproof, as malware like Neverquest has shown. Neverquest activity has been seen actively in the wild, meaning despite the need to compromise two client devices - usually a PC/laptop and a smartphone - it has been successful at manipulating victims into doing so. The primary infection occurs via the PC, which is a lot less difficult these days thanks to the prevalence of infected sites. But the secondary infection requires the victim to knowingly install an app on their phone, which means convincing them they should do so. This is where script injection comes in handy. Malware of this ilk modify the web app by injecting a script that changes the behavior and/or look of the page. Even the most savvy browsers are unlikely to be aware of such changes as they occur "under the hood" at the real, official site. Nothing about the URI or host changes, which means all appears as normal. The only way to detect such injections is to have prior knowledge of what the page should look like - down to the code level. The trust a victim has for the banking site is later exploited with a popup indicating they should provide their phone number and download an app. As it appears to be a valid request coming from their financial institution, victims may very well be tricked into doing so. And then Neverquest has what it needs - access to SMS messages over which OTP and/or TAN are transmitted. The attacker can then initiate automated transactions and confirm them by intercepting the SMS messages. Voila. Fraud complete. We (as in the corporate We) rely on our F5 SOC (Security Operations Center) team to analyze malware to understand how they compromise systems and enable miscreants to carry out their fraudulent goals. In July, the F5 SOC completed its analysis of Neverquest and has made its detailed results available. You can download the full technical analysis here on DevCentral. We've also made available a summary analysis that provides an overview of the malware, how it works, and how its risk can be mitigated. You can get that summary here on DevCentral as well. The F5 SOC will continue to diligently research, analyze and document malware in support of our security efforts and as a service to the broader community. We hope you find it useful and informative, and look forward to sharing more analysis in the future. You can get the summary analysis here, and the full technical analysis here. Additional Resources: F5 SOC on DevCentral F5 WebSafe Service F5 Web Fraud Protection Reference Architecture317Views0likes0Comments