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.

Forum Discussion

JJ_Scott_44057's avatar
JJ_Scott_44057
Icon for Nimbostratus rankNimbostratus
Jul 03, 2013

Any way to use payload data in headers / cookies?

Never mind, answered my own question....

 

 

I have patterend data in the response of a web page that I need to capture and then modify ( I don't know the exact data, and it's unique per user session, I do know how to match the pattern), but also pass it to the client in a header / cookie for reuse on subsequent requests to the backend servers...

 

 

Example

 

 

href="./URIXXYYZZ/blah'

 

 

I need to capture /URIXXYYZZ/

 

 

Rewrite the content href='./GOODURI/blah'

 

 

Pass what was rewritten back to the client in a header or a cookie

 

 

HTTP::header insert ORIG_URL URIXXYYZZ

 

 

Then i'll check for the existence of the header for particular URI's and rewrite the request being sent to the backend server with the origional URI?

 

 

-------------------------------------------------------------------------------------------------------

 

In my case, there is only 1 issue of bad data, so the indicies can go away, and i'll only fix one thing.

 

 

But, there could be a case to have multiple headers / cookies to contain multiple fixed data elements from the page ( hope I don't have to do it )

 

------------------------------------------------------------------------------------

 

here is the ugly first hack at it - with barely any checks in palce

 

------------------------------------------------------------------------------------

 

when HTTP_REQUEST {

 

set scrub_content 1

 

set FIXEDURL ""

 

if { [HTTP::cookie exists "BIGIPFIXEDURL" ] } {

 

set FIXEDURL [HTTP::cookie "BIGIPFIXEDURL"]

 

if { [HTTP::uri] contains "THIS_IS_SCRUBBED_DATA" } {

 

set uri [HTTP::uri]

 

set find "THIS_IS_SCRUBBED_DATA"

 

set replace [HTTP::cookie "BIGIPFIXEDURL"]

 

set newuri [ regsub -all $find $uri $replace ]

 

HTTP::uri $newuri

 

}

 

}

 

}

 

 

when HTTP_RESPONSE {

 

if { $scrub_content } {

 

if { [HTTP::header exists "Content-Length"] } {

 

set content_length [HTTP::header "Content-Length"]

 

} else {

 

set content_length 4294967295

 

}

 

if { $content_length > 0 } {

 

HTTP::collect $content_length

 

}

 

set bad_data_indices [regexp -all -inline -indices {TestParamater=\d{7}} [HTTP::payload]]

 

foreach bad_dataidx $bad_data_indices {

 

set bad_datastart [lindex $bad_dataidx 0]

 

set bad_dataend [lindex $bad_dataidx 1]

 

set bad_datalen [expr {[lindex $bad_dataidx 1] - $bad_datastart + 1}]

 

set bad_datadata [string range [HTTP::payload] $bad_datastart $bad_dataend]

 

HTTP::cookie insert name BIGIPFIXEDURL value $bad_datadata

 

HTTP::payload replace $bad_datastart $bad_datalen "THIS_IS_SCRUBBED_DATA"

 

}

 

}

 

}

 

1 Reply

  • This was indeed a challenge, and maybe the following isn't exactly what you're looking for, but here goes:

    
    when RULE_INIT {
         User-defined: New URI value for replacement
        set static::GOODURI "GOODURI"
         User-defined: Old URI pattern to match (starts_with?)
        set static::URIPATTERN "uri"
    }
    when HTTP_RESPONSE {
        STREAM::disable
        if { [HTTP::header Content-Type] contains "text" } {
            HTTP::collect [HTTP::header Content-Length]
        }
    }
    when HTTP_RESPONSE_DATA {
         Find the HREF elements
        set indices [regexp -all -inline -indices -nocase {
                     Full URL
                    catch {
                        if { [scan $url {<%*s %*[^:]://%*[^/]/%[^/]} URI] } {
                             If scanned URI value matches the predefined pattern...
                            if { [string tolower $URI] starts_with $static::URIPATTERN } {
                                 Create a new URL with the replaced value
                                set new_url [string map "$URI $static::GOODURI" $url]
                                 Append the found/matched URI to the URILIST list
                                lappend URILIST $URI
                                 Append the old and new URLs to the STREAMLIST list
                                lappend STREAMLIST $url
                                lappend STREAMLIST $new_url
                            }
                        }
                    }
                } else {
                     Relative URL
                    catch {
                        if { [scan $url {<%*s %*[^/]/%[^/]} URI] } {
                             If scanned URI value matches the predefined pattern...
                            if { [string tolower $URI] starts_with $static::URIPATTERN } {
                                 Create a new URL with the replaced value
                                set new_url [string map "$URI $static::GOODURI" $url]
                                 Append the found/matched URI to the URILIST list
                                lappend URILIST $URI
                                 Append the old and new URLs to the STREAMLIST list
                                lappend STREAMLIST $url
                                lappend STREAMLIST $new_url
                            }
                        }
                    }
                }
            }
            
             If STREAMLIST is not empty (matched href values), generate a STREAM expression and replace the payload
            if { $STREAMLIST ne "" } {
                 Create a STREAM expression from the STREAMLIST list
                set STREAMTEXT ""
                for { set i 0 } { $i < [llength $STREAMLIST] } { incr i } {
                    if { [expr { $i %2 }] == 0 } {
                         first string (old)
                        append STREAMTEXT "@[lindex $STREAMLIST $i]"
                    } else {
                         second string (new)
                        append STREAMTEXT "@[lindex $STREAMLIST $i]@"
                    }
                }
                 Evaluate the STREAM expression to replace all of the payload content
                STREAM::expression "$STREAMTEXT"
                STREAM::enable
            }
            
             We created a list of found/matched URIs. This can be used to send headers/cookies to the client
            for { set x 0 } { $x < [llength $URILIST] } { incr x } {
                HTTP::cookie insert name ORG_URL_${x} value [lindex $URILIST $x]
            }
        }    
    }
    

    Here's how it works:

    1. Issue a collect statement in the HTTP_RESPONSE event

    2. In the HTTP_RESPONSE_DATA event perform a regexp command that builds a list of lists - a list of the start and end indexes for every "a href=..." string in the payload.

    3. If the list isn't empty, start a loop

    4. Use catch and scan commands to extract the first part of the URI from the anchor string (full and relative URLs).

    5. Once found, create a new URL by string mapping the predefined GOODURI over the matched old URI.

    6. Add the new and old URLs to a list (STREAMLIST).

    7. After the loop, if the STREAMLIST list isn't empty, create a STREAM expression from the list (@old url@new url@ @old url@new url@ @old url@new url@...) and evaluate the expression to replace all of the old content in the payload.

    8. During the loop, another list was created to store the matched URIs. After the STREAM expression, loop through this list to produce the values you need for cookies. This will create a different cookie for each matched URI (if more than one).

    A header won't be returned to the server, so a cookie is probably the better route. Not having enough information to know exactly how the application works, I had to assume that 1) there might be more than one offending URI in the payload, 2) you have a specific pattern that you're looking for, and 3) you'll need to devise a method to remap the incoming URI back to the original, which would be a bit more complicated if there was more than one replacement. It might actually make more sense to send the entire old URI in the cookie values, or perhaps even better to encode the original URI as a query string object at the end of each replaced URI.

    Example: a href="./GOODURI/blah/F5_URL=unnf89sdfnds98dsn32..."