Forum Discussion
ukstin
Nimbostratus
Jan 29, 2009encrypt/decrypt URI
Hi,
I´m trying to do an Irule to encrypt and decrypt the URI with a cookie value as key. But it´s not working as expected, somebody as any opinion about these irule?
when HTTP_REQUEST {
set uri [HTTP::uri]
set host [HTTP::host]
if { [HTTP::cookie exists "JSESSIONID"] } {
if {not ([catch { AES::decrypt [HTTP::cookie value "JSESSIONID"] [b64decode $uri] } decrypted])}{
log local0. "session: $IDkey uri $uri decriptada: $decrypted"
HTTP::uri $decrypted
set uri $decrypted
}
}
}
when HTTP_RESPONSE {
if { [HTTP::cookie exists "JSESSIONID"] } {
set encrypted [b64encode [AES::encrypt [HTTP::cookie value "JSESSIONID"] $uri]]
log local0. "session: $IDkey uri: $uri encriptada: $encrypted"
HTTP::header replace Location "$encrypted"
}
}11 Replies
- Colin_Walker_12Historic F5 AccountFirst, it's always helpful if you give us more info to go off of than that something just isn't working as expected. Including details on HOW it's misbehaving, error log entries, etc. is very helpful.
That being said, it doesn't look like you're setting the value of decrypted anywhere. This would make it pretty hard to use that to update the uri later. Try changing the HTTP_REQUEST section to something like:when HTTP_REQUEST { set uri [HTTP::uri] set host [HTTP::host] if { [HTTP::cookie exists "JSESSIONID"] } { set decrypted [AES::decrypt [HTTP::cookie value "JSESSIONID"] [b64decode $uri]] if { [string length $decrypted] > 1 } { log local0. "session: $IDkey uri $uri decriptada: $decrypted" HTTP::uri $decrypted set uri $decrypted } } }
I think that'll get you closer to the result you're looking for. That's a pretty interesting use of a cookie as a key. I'd love to hear how it works out for you once you get it up and running.
Colin - ukstin
Nimbostratus
sorry for my mistake Colin,
the main problem is with the decrypt part in http_request, the response encryption i think is working, but I´m in trouble to identify when a uri was previously encrypted or not, if the URI wasn´t encrypted before, there´s no reason for me to decrypt it. If I undertand well if the string wasn´t encrypted the decripted variable will be empty. Is that right?
other question,
on the decryption line i´m getting the errorJan 29 15:23:44 tmm tmm[3789]: 01220001:3: TCL error: Rule irule_encrypt_uri - conversion error invoked from within "b64decode $uri"
it´s happening because the uri wasn´t previously encrypted or this function wasn´t supported this way, the line that invoke this error is this:set decrypted [AES::decrypt [HTTP::cookie value "JSESSIONID"] [b64decode $uri]]
I think if I can put a control to define when a uri is encrypted I can solve the problem easily. - ukstin
Nimbostratus
sorry for my mistake Colin,
the main problem is with the decrypt part in http_request, the response encryption i think is working, but I´m in trouble to identify when a uri was previously encrypted or not, if the URI wasn´t encrypted before, there´s no reason for me to decrypt it. If I undertand well if the string wasn´t encrypted the decripted variable will be empty. Is that right?
other question,
on the decryption line i´m getting the errorJan 29 15:23:44 tmm tmm[3789]: 01220001:3: TCL error: Rule irule_encrypt_uri - conversion error invoked from within "b64decode $uri"
it´s happening because the uri wasn´t previously encrypted or this function wasn´t supported this way, the line that invoke this error is this:set decrypted [AES::decrypt [HTTP::cookie value "JSESSIONID"] [b64decode $uri]]
I think if I can put a control to define when a uri is encrypted I can solve the problem easily. - Colin_Walker_12Historic F5 AccountCouldn't you just uncomment the line that checks for the JSESSIONID cookie? Wouldn't every incoming connection that's had that cookie set by the server have the encrypted URI?
Colin - hoolio
Cirrostratus
So far, you've tried to encrypt the Location field in 302 redirects. This doesn't handle the links in the response content. I'm not sure why you'd only want to encrypt the redirect links but not the response content links. Trying to encrypt the response content links wouldn't be so easy. You could try doing this using a regular expression to identify links. You could configure this regex as a STREAM::expression and encrypt the links in the STREAM_MATCHED event. You would not want to encrypt links to URI's that users could legitimately start accessing the application at. In requests, you could check the requested URI against the defined start pages. If it's not a defined start page, then you try to decrypt the path.
You can check the stream related pages for examples on using a stream profile to rewrite response content (Click here).
Aaron - ukstin
Nimbostratus
Hoolio, firstly I would like to just encrypt the Header Location, links inside the page will be the next step.
Colin, I´ve uncommented the verification of cookie, but I´m still getting error with the funcition b64decode, anybody as idea why the conversion trigger an error? - hoolio
Cirrostratus
RFC2616 states the Location value should be a fully qualified URL. Some apps use a local reference (just the URI). I've seen absolute URIs and relative URIs. Here are a few examples of the different forms and how the browser typically handles it:
http://example.com/new_location - browser doesn't do any normalisation of this
/new_location - most browsers assume the same protocol and host, and then append the new URI to form the new request
new_location - most browsers assume the same protocol and host, and then append the new URI portion to the previously requested protocol, host and path to form the new request
If your app uses the fully qualified URL, you would need to parse the URI. You would then need to encrypt it, base64 encode it, URI encode it and finally prepend a forward slash to the new path. Similarly, for an absolute URI, you would need to encrypt it, base64 encode it, URI encode it and then prepend a leading forward slash. For a local URI, you would need to save the requested path, append the new location token, encrypt it, base64 encode it, URI encode it and then prepend a forward slash.
URI encoding is necessary as the base64 encoded value can contain characters outside the normal ASCII set allowed in HTTP headers.
To differentiate between a URI which was encrypted and one that wasn't, I'd suggest inserting some arbitrary characters like enc_. The command would look something like this:
set encrypted_location_path "/enc_[URI::encode [b64encode [AES::encrypt $::my_aes_key $string_to_encrypt]]]"
To decyrpt this on the request, you'd want to first check if the requested path started with /_enc. If not, it wasn't encrypted. You would want to use catch (Click here) to handle any errors in decoding/decrypting the request.
You would want to strip off the prepended forward slash, URI decode, base64 decode and the decrypt the string.Before trying to decrypt the path, check if the session cookie has a length and that the path starts with the encrypted string prefix if {[string length $session_cookie_value] and $path starts_with "/$::encrypted_string_prefix"}{ URI decode the path. Need to take off the leading forward slash and string "enc_" we added in the response. Use 'catch' to catch any errors that occur when trying to decode the path value. Save the output to path_uri_decoded. if {not ([catch {URI::decode [string range [HTTP::path] [expr {$::encrypted_string_prefix_length + 1}] end]} path_uri_decoded]) \ and [string length $path_uri_decoded]}{ Log that the path was URI decoded if {$::path_encrypt_debug > 2}{log local0. "[IP::client_addr]:[TCP::client_port]: \$path_uri_decoded was set successfully: $path_uri_decoded"}
If you see failures in the decoding and/or decrypting, try logging the values you're setting in the response and comparing them to the value the client sends in the request.
When I did this last, I ended up encrypting the paths (not the full query string) and just parameters that the application set. If you try to encrypt all parameters, you can potentially run into a problem handling the client-set parameters.
Aaron
Aaron - ukstin
Nimbostratus
thanks hoolio, your suggestions are pretty valuable, now the rule is almost working as expected, the only problem is that the decrypted variable is always returning empty, there is no error message or something like that, it just return empty when I decrypt, decode e b64decode.when RULE_INIT { set ::prefix "enc_" set ::sessao "JSESSIONID" } when HTTP_REQUEST { if { ([HTTP::uri] starts_with "/$::prefix") and ([HTTP::cookie exists $::sessao]) }{ set decrypted [AES::decrypt [HTTP::cookie value $::sessao] [b64decode [URI::decode [string range [HTTP::uri] [expr {[string length $::prefix] + 1} ] end]]]] log local0. "uri [HTTP::uri] decrypted: $decrypted" HTTP::uri $decrypted set uri $decrypted } else { set uri [HTTP::uri] } if { [string tolower $uri] contains "abc" } { pool pool_abc } elseif { [string tolower $uri] contains "def" } { pool pool_def } } when HTTP_RESPONSE { if { [HTTP::header value Content-Type] starts_with "text" } { set encrypted "/$::prefix[URI::encode [b64encode [AES::encrypt [HTTP::cookie value $::sessao] $uri]]]" log local0. "uri: $uri encrypted: $encrypted" HTTP::header replace Location "$encrypted" } } - ukstin
Nimbostratus
just to update, the decryption is returing empty value, because of the key, when I created an AES::key it worked, i´m looking for a way to convert the cookie value into a AES valid key. - hoolio
Cirrostratus
I think the AES key must be hex characters. If the jsessionid isn't made up of only hex characters, you could convert it to hex:Save a test string set key_string "a b . *^&E^ d asdfasdfasdf " Convert the test string to hex binary scan $key_string H* key_hex log local0. "\$key_hex: $key_hex" Encrypt another test string with the key in hex set encrypted [AES::encrypt $key_hex "test123"] Log the decrypted value log local0. "decrypted: [AES::decrypt $key_hex $encrypted]"
Or you could use a single key to encrypt the content for all users.
Aaron
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects
