For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Persist On Last JSESSIONID in HTTP Parameter

Problem this snippet solves:

This iRule was written with the goal to persist on only the last jsessionid that is present when multiple jsessionid HTTP Paremeters are present..

How to use this snippet:

I ran into a particular challenge where a customer was receiving a request where a jsessionid was expected to be set in an HTTP Request Parameter.
  • For those of you who are not familiar, see where the parameters lye below:

    <scheme>://<username>:<password>@<host>:<port>/<path>;<parameters>?<query>#<fragment>
    

REF: http://www.skorks.com/2010/05/what-every-developer-should-know-about-urls/

Here is an example of a full request:
http://www.example.com/my/resource.html;jsessionid=0123456789abcdef;jsessionid=0123456789abcdef?alice=mouse
In the above example, there are two jsessionid parameters, both of which are the same value.
This is what was being used to Persist
"*jsessionid*" {
   #Parse the URI and look for jsessionid. Skip 11 characters and match up to the next "?"
   set session_id [findstr [HTTP::uri] jsessionid 11 "?"]
}

Code :

when CLIENT_ACCEPTED {
set debug 1
}
when HTTP_REQUEST {
set logTuple "[IP::client_addr]:[TCP::client_port] - [IP::local_addr]:[TCP::local_port]"
set parameters [findstr [HTTP::path] ";" 1]
set session_id ""

foreach parameter [split $parameters ";"] {
scan $parameter {%[^=]=%s} name value
if {$debug}{log local0.debug "$logTuple :: Multiple JsessionID in: [HTTP::host][HTTP::uri]"}
if {$name equals "jsessionid"} {set session_id $value}
}
if {$session_id ne ""}{
#Persist on the parsed session ID for X seconds
if {$debug}{log local0.debug "$logTuple :: Single JsessionID in: [HTTP::host][HTTP::uri]"}
persist uie $session_id 86400
}
}
Updated Jun 06, 2023
Version 2.0

3 Comments

  • Hi,

     

    you can do it with a simpler code:

     

    when HTTP_REQUEST {
        set parameters [findstr [HTTP::path] ";" 1]
        foreach parameter [split $parameters ";"] {
            scan $parameter {%[^=]=%s} name value
            if {$name equals "jsessionid"} {set session_id $value}
        }
        if {$session_id ne ""}{
                Persist on the parsed session ID for X seconds
                if {$debug}{log local0.debug "$logTuple :: Single JsessionID in: [HTTP::host][HTTP::uri]"}
                persist uie $session_id 86400
        }
    }
    
  • Thank you Stanislas.

     

    I have updated the main code to represent your example.

     

  • more efficient code:

     

    when CLIENT_ACCEPTED {
        set debug 1
    }
    when HTTP_REQUEST {
        set path [HTTP::path]
        set logTuple "[IP::client_addr]:[TCP::client_port] - [IP::local_addr]:[TCP::local_port]"
        if {[set last_jsessionid_pos [string last "jsessionid=" $path]] ne -1} {
            if {[set semicolon_pos [string first ";" $path $last_jsessionid_pos]] ne -1} {
                set session_id [string range $path [expr {$last_jsessionid_pos + 11}] [expr {$semicolon_pos -1}]]
            } else {
                set session_id [string range $path [expr {$last_jsessionid_pos + 11}] end]
            }
            Persist on the parsed session ID for X seconds
            if {$debug}{log local0.debug "$logTuple :: Single JsessionID in: [HTTP::host][HTTP::uri]"}
            persist uie $session_id 86400        
        }
    }