Forum Discussion
Hi abhinay, this solution might be helpful to craft to your unique scenario.
mihaicand CA_Valli, Sorry for tagging you here. Both your solutions worked for me in my previous post and was looking for your help in combining two POST methods.
The second requirement is {Method is POST - (URI contains "/cs" OR "llisapi.dll") AND (body contains Key "func" which contains Value "qds.") AND (body contains "_REQUEST" which contains Value "SYNDICATION_REQUEST" )} for which I am using below iRule and combined it with (body contains Key "_fInArgs=" which contains Value "=#").
From this iRule I am observing that whatever is the second "if statement" it is returning Forbidden, but the first "if statement" is returning "Could not get response". Tried interchanging the if statements but same issue, the second works and first doesnt.
Any help will be appreciated.
when HTTP_REQUEST {
if {[HTTP::method] eq "POST"}{
# Trigger collection for up to 1MB of data
if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576}{
set content_length [HTTP::header "Content-Length"]
} else {
set content_length 1048576
}
# Check if $content_length is not set to 0
if { $content_length > 0} {
HTTP::collect $content_length
}
}
}
when HTTP_REQUEST_DATA {
if { [HTTP::method] equals "POST" }{
# Extract the entire HTTP request body and escape it to become a HTTP::uri string (for easier parsings)
set http_request_body "?[HTTP::payload]"
log local0. "http payload: $http_request_body"
# Try to parse type value from the HTTP request body.
if { [URI::query $http_request_body _fInArgs%3D] contains "%3D%23" } {
HTTP::respond 403 content "You don't have authorization to view this page. Access Denied" noserver Content-Type text/html Connection Close Cache-Control no-cache
} }
if { ([HTTP::method] equals "POST") and ([HTTP::uri] contains "/cs" or [HTTP::uri] contains "llisapi.dll" )}{
# Extract the entire HTTP request body and escape it to become a HTTP::uri string (for easier parsings)
set varB [findstr [HTTP::payload] "func"]
set varC [findstr [HTTP::payload] "_REQUEST"]
if { ($varB contains "qds.") and ($varC contains "SYNDICATION_REQUEST")} {
HTTP::respond 403 content "You don't have authorization to view this page. Access Denied" noserver Content-Type text/html Connection Close Cache-Control no-cache
}
}
}
- CA_ValliDec 28, 2022MVP
Hello abhinay , I've scripted the irule, now testing it in my lab.
Will update you shortly- CA_ValliDec 28, 2022MVP
abhinay I've achieved something, this seems to work but might be heavy on performance.
proc key2value {list key} { set element [split $list ,] set kv_pair0 [split [lindex $element 0] :] if {$key equals [string trim [lindex $kv_pair0 1] "\"{ }" ] }{ set kv_pair1 [split [lindex $element 1] :] return [string trim [lindex $kv_pair1 1] "\"{ }" ] } } when HTTP_REQUEST { # if you need fInArgs code to match on GET's too, you can paste lines #4-10 (excluding "else \{" syntax on line #10) of my other script here, they shoudn't conflict # setting HTTP::collect triggers -- notice that POST method is mantadory now if { [HTTP::method] eq "POST" && ([HTTP::uri] contains "/cs" || [HTTP::uri] contains "llisapi.dll") }{ if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576}{ set content_length [HTTP::header "Content-Length"] } else { set content_length 1048576 } if { $content_length > 0} { HTTP::collect $content_length } } } when HTTP_REQUEST_DATA { set cleanpl [URI::decode [HTTP::payload]] # json format in payload is already formatted as a list - lindex is used to parse every element for {set i 0} {$i < [llength $cleanpl]} {incr i}{ if { [findstr [lindex $cleanpl $i] func] ne "" }{ set func [call key2value [lindex $cleanpl $i] "func"] ; log local0. "func value is $func" } if { [findstr [lindex $cleanpl $i] _REQUEST] ne "" }{ set req [call key2value [lindex $cleanpl $i] "_REQUEST"] ; log local0. "_REQUEST value is $req" } } if { $func contains "qds." && $req contains "SYNDICATION_REQUEST" }{ log local0. "violation detected, restricting access" HTTP::respond 403 content "Forbidden" } # if you also need fInArgs code, you can paste lines #24-28 of my other script here as they shoudn't conflict }
I was only able to test it with this command
curl -v http://10.163.191.11/cs -X POST --header "Content-Type: application/json" -d $'{ "key" : "func",\n"value" : "qds.ObjAction"}\n{ "key" : "_REQUEST",\n"value" : "SYNDICATION_REQUEST"}'
Parameters are recognized and request is blocked
Dec 28 14:16:40 bigip info tmm3[11336]: Rule /Common/iRule_DC <HTTP_REQUEST_DATA>: func value is qds.ObjAction Dec 28 14:16:40 bigip info tmm3[11336]: Rule /Common/iRule_DC <HTTP_REQUEST_DATA>: _REQUEST value is SYNDICATION_REQUEST Dec 28 14:16:40 bigip info tmm3[11336]: Rule /Common/iRule_DC <HTTP_REQUEST_DATA>: violation detected, restricting access
I feel like code can be improved a lot, but might be a starting point.
- abhinayDec 29, 2022Nimbostratus
CA_Valli, Thanks for your efforts. I was able to achieve this with single if statement and combine both the requirements.
However I want to know if anyone pads with larger payload over 1MB, in that case the iRule will get bypassed right as we are collecting data only upto 1MB. Also we dont want to collect huge data on each POST request. Any idea how we can mitigate this?