Forum Discussion

Imran_Abid's avatar
Icon for Altocumulus rankAltocumulus
Jul 30, 2019

Device Fingerprinting for mobile devices

We have published Microsoft Exchange server behind ASM+APM policies.


I am using BotDefense to generate Device IDs for the connecting clients and then inserting the value of "device_id" variable into HTTP header and then passing it to APM.


APM extracts the "device_id" value from HTTP header and sets it as an APM variable:


ACCESS::session data set "session.custom.device_id" "$device_id"


This APM session variable is then called in APM iRules to perform the required logic.


So far, the logic and traffic flow is working as expected.


Now, here comes the problem part:


If the client is not a web browser, the whole logic fails because BotDefense is generating Device IDs based on JavaScript challenge.


In case of Microsoft Exchange, the client could be a mobile device using the native email app of the phone (not mobile browser) like the mail app of Andriod or iOS devices. How can we perform device fingerprinting and generate Device IDs in such case?


All mobile devices use the standard Exchange protocol "Microsoft ActiveSync" which is based on HTTPS.


When traffic hits my virtual server from a mobile client, BIG-IP can detect it and differentiate it from other web browser traffic because all requests coming from mobile devices have this particular URI string in the HTTP Request: "/Microsoft-Server-ActiveSync". But because it is not a web browser, the JavaScript challenge is not performed and no Device ID generated.


My question is:


How can we perform fingerprinting and generate Device IDs for mobile devices (not mobile browsers)?


Here is my ASM iRule which is handling the Device IDs and fingerprinting:




when RULE_INIT {

  set static::TPS_Value 1

  set static::debug 1

  # set as 1 - send request logs set 0 if no request logs should be sent. 

  set static::PBD_debug 1

  # list of botdefense actions you want to get request log on

  set static::Logged_PBD_actions "tcp_rst browser_challenge internal_bigip_response captcha_challenge"

  set static::host_header "Host:"



set hsl [HSL::open -proto TCP -pool ASM_Log_Pool2]

set http_request [HTTP::request]

#HSL::send $hsl $http_request




  #for demo purpose, make the challange valid from the first request - make sure you go to the default

  if {[HTTP::uri] equals "/"} {

    BOTDEFENSE::cs_allowed true


  #Mandate the device_id attribute extraction

  BOTDEFENSE::cs_attribute device_id enable




  set device_id [BOTDEFENSE::device_id]

  if {$static::debug > 0} {log "reason is, [BOTDEFENSE::reason], action is [BOTDEFENSE::action], botdefense device_id is: $device_id"}

  if {$static::Logged_PBD_actions contains [BOTDEFENSE::action]} {

    set botdefense_action [BOTDEFENSE::action]

    set botdefense_reason [BOTDEFENSE::reason]

    set PBD_header [concat Host:\r\nPbd_Action: $botdefense_action\r\nPbd_reason: $botdefense_reason]

    set asm_http_requet_log [string map -nocase [list $static::host_header $PBD_header] $http_request]

    if {($static::PBD_debug > 0) && ([info exists asm_http_requet_log])} {

      HSL::send $hsl $asm_http_requet_log 



  log "action is [BOTDEFENSE::action], reason is: [BOTDEFENSE::reason] cs_allowed is: [BOTDEFENSE::cs_allowed]"

  if {([BOTDEFENSE::action] eq "tcp_rst") && [BOTDEFENSE::cs_allowed] eq 0} {

    set res [BOTDEFENSE::action custom_response {


      i am blocking you, try to restart the session

    } 200]

    if {$res eq "ok"} {

      set botdefense_responded 1




#  if {[BOTDEFENSE::action] eq "captcha_challenge"} {

#    set res [BOTDEFENSE::action allow]

#    log "captcha challange with res $res"

#    if {$res eq "ok"} {

#      log "bypass allow"

#    }

#  }



  if {$static::debug > 0} {log "http uri is [HTTP::uri]"}

  virtual Hackazone_APM_virt



  clientside {

  # Need to force the host header replacement and HTTP:: commands into the clientside context

  # as the HTTP_REQUEST_SEND event is in the serverside context

   if {$static::debug > 0} {log "device id is: $device_id"}

   HTTP::header insert "device_id" "$device_id"

#   if { $suspicious_browser eq "1" } {

#   HTTP::header insert "suspicious_browser" "1"

#   log "sending suspicious_browser header"

#  }

  # log "after the change [HTTP::request]"





  if {[info exists botdefense_responded]} {

    HTTP::header insert "X-TS-BP-Action" "2"





Many thanks.

1 Reply

  • mhamdy's avatar
    Icon for Nimbostratus rankNimbostratus

    The same question  with other scenario we have ?  We need to enable session tracking to block based on the device-id  but again the endpoints are mobile applications not browser . 

    I believe F5 should have a soltuion for that scenario except to go with appdome and sdk soltuions