Forum Discussion

James_Quinby_46's avatar
James_Quinby_46
Historic F5 Account
Apr 07, 2011

Question re: HTTP::retry

I have an embedded webserver on a device in my network and am working on a rule to basically by-pass the login screen.

The trick with the login process is that it collects a username and a password, but also seeds the page with a randomly generated 8-character string. These three strings are concatenated together, MD5 hashed via some javascript, and POSTed to the form action location.

I've got the salt-grabbing and md5-hashing hex digest stuff worked out, but am getting hung up on the retry. I've looked in pcaps but don't see the POST ever leaving the LTM. Here's the rule. The POST request has been pared down a bit to eliminate some of the client request headers for the sake of readability.

when HTTP_RESPONSE {

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

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

} else {

set content_length 1000000

}

if { $content_length > 0 } {

HTTP::collect $content_length

}

}

when HTTP_RESPONSE_DATA {

get the salt off the page

set salt_value [lindex [regexp -all -inline {(ge\" VALUE=\")(.{8})} [HTTP::payload]] 2]

log local0. "salt -> $salt_value"

set response "adminpassword123$salt_value"

log local0. "salted response -> $response"

binary scan [ md5 $response ] H* hexhash

log local0. "md5(hex) of $response -> $hexhash"

Here goes

HTTP::retry "POST /tgi/login.tgi HTTP/1.1\r\n

Host: 10.10.10.10\r\nContent-Type: application/x-www-form-urlencoded\r\n

Content-Length: 77\r\n\r\nUsername=admin&Password=&Challenge=&Response=$hexhash"

}

  • James_Quinby_46's avatar
    James_Quinby_46
    Historic F5 Account
    ...and sorry for the heinous formatting. I"ve been trying for the last 20 minutes to make this all neat and pretty. Every time I edit, things get uglier. Quitting here.
  • Is the problem that the POST request isn't being sent? Can you try reposting your code in [ code ] [/ code ] blocks in a new reply to this thread?

     

     

    Can you add logging to the iRule to make sure it's hitting the retry?

     

     

    Aaron
  • James_Quinby_46's avatar
    James_Quinby_46
    Historic F5 Account

    Correct. The POST doesn't get sent at all. That last logging statement gets printed out correctly, so I know the rule is proceeding that far. Just not seeing anything actually leave the box.

     

     

    (edit: ugly code block redacted)

     

     

  • Three questions:

     

     

    1. What version are you running?

     

    2. It's hard to tell here, but is the original response for which you're scanning through the payload for a result of a GET or a POST to the same server?

     

    3. What's the result of running this iRule towards the server? Do you get any server response back at all? The orignal page? Or "Bad Request"?

     

     

    I've been doing quite a bit of work with HTTP::retry lately. It's handy, but a little hard to navigate in server response.
  • James_Quinby_46's avatar
    James_Quinby_46
    Historic F5 Account
    Joel -

     

     

    Running this on 10.2.1 HF2. The original response coming from the server is from a GET. I want to scrape a bit of text off the page and POST it directly to the form action on the page. The response back from the server ends up being a RST. I've looked at pcaps from the LTM to the app but never see the POST happening.

     

     

  • One more: Is the response payload from the server that you're initially plucking off coming through with "Content-Encoding: gzip"? That is to say, is it compressed when the LTM gets ahold of it?
  • Y'know what? Disregard the above. If you're logging the right input values, you're not compressed coming from the pool member.

    Try something like this:

    when CLIENT_ACCEPTED {
       set trypost 0
       set collected 0
       set retried 0
    }
    
    when HTTP_REQUEST {
      if { (! $retried) && ([HTTP::method] equals "GET") && ([string tolower [HTTP::uri]] equals "/tgi/login.tgi") } {
    set trypost 1
    HTTP::header sanitize "Accept-Encoding Connection Keep-Alive"
    HTTP::header insert Connection "close"
      } 
    }
    
    when HTTP_RESPONSE {
      if {($trypost) && (! $collected) && (! $retrying) }{
        if {[HTTP::header exists Content-Length] && ([HTTP::header Content-Length] < 100000)} {
           set clength [HTTP::header Content-Length]
        } else {
           set clength 100000
        }
        HTTP::collect $clength
    set collected 1
      }
    }
    
    when HTTP_RESPONSE_DATA {
      if { ($trypost) && ($collected) && (! $retried) } {
    set salt_value [lindex [regexp -all -inline {(ge\" VALUE=\")(.{8})} [HTTP::payload]] 2]
    log local0. "salt -> $salt_value"
    
    set response "adminpassword123$salt_value"
    log local0. "salted response -> $response"
    
    binary scan [ md5 $response ] H* hexhash
    log local0. "md5(hex) of $response -> $hexhash"
    
    HTTP::payload replace 0 [HTTP::payload length] ""
    HTTP::retry "POST /tgi/login.tgi HTTP/1.1\r\n Host: 10.10.10.10\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 77\r\n\r\nUsername=admin&Password=&Challenge=&Response=$hexhash"
    
    set trypost 0
    set collected 0
    set retried 1
      } 
    }

    Yeah, it doesn't look like some of the other stuff you've seen on HTTP::retry, but most of those are not re-hitting the same pool member, they're going to some other pool or node entirely. What I'm doing here is essentially forcing a close from the browser when a GET request to the login page occurs, then in HTTP_RESPONSE, I'm taking steps to throw away the payload that's been collected before attempting the HTTP::retry.
  • Forum strikes again, and I'm not going to go back and re-edit (you know how that works :) )... Replace all the & with a plain 'ol ampersand, please.
  • James_Quinby_46's avatar
    James_Quinby_46
    Historic F5 Account
    I may be up against a badly written TCP stack and/or HTTP server. I've come across some other threads out there regarding this embedded device and there are some fairly uniform complaints about things Just Not Working. For sanity checking, I've wrapped my POST request in a shell script with nc and am still not making much in the way of progress. Real work calls again soon, so I'll need to putz around with this as I have time. This thread: Click Here

     

     

    ...describes someone struggling with a Dell-branded version of the same firmware. He's working with what looks like a slightly more recent version of the code. His error and POST string are different than mine, but the back-end looks to be pretty similar.

     

     

    Anyway, it just goes to show you: there's still plenty of wacky stuff out there. If nothing else, this exercise has renewed my passing interest in embedded systems and The Internet of Things. (Click Here)