Forum Discussion
- abhinayNimbostratus
I am trying the below after collecting the payload but it is not working. For form-data do we have to use something else to match? FYI the below works for form-urlencoded?
when HTTP_REQUEST_DATA {
if { [HTTP::method] equals "POST" }{
set http_request_body "?[HTTP::payload]"
if { [URI::query $http_request_body func] contains "qds." } {
HTTP::respond 403 content "Forbidden" "Content-Type" "text/html"
} }
} - JRahmAdmin
Hi abhinay, this solution might be helpful to craft to your unique scenario.
- abhinayNimbostratus
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
}
}
}
Hello abhinay , I've scripted the irule, now testing it in my lab.
Will update you shortly
- abhinayNimbostratus
Hi JRahm, I was able to achieve this using findstr with below iRule.
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") 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
}
}
}
- xuwenCumulonimbus
deal with json data, the best way is to use iRulesLX
- xuwenCumulonimbus
It would be pretty impractical to use iRules TCL to perform the translation POST JSON data. However, this task is trivial for iRules LX because of the power of Node.js
rules>>json_post
when HTTP_REQUEST { # Collect POST data if { [HTTP::method] eq "POST" }{ set cl [HTTP::header "Content-Length"] HTTP::collect $cl } } when HTTP_REQUEST_DATA { # Send data to Node.js set handle [ILX::init "ilxlab2_plugin" "ilxlab2_ext"] if {[catch {ILX::call $handle jsonPost [HTTP::payload]} result]} { # Error handling log local0.error "Client - [IP::client_addr], ILX failure: $result" HTTP::respond 400 content "<html>There has been an error.</html>" return } log local0. "result is $result" # Replace Content-Type header and POST payload # HTTP::header replace "Content-Type" "application/json" # HTTP::payload replace 0 $cl $result if { [lindex $result 0] > 0 } { HTTP::respond 400 content "<html>The following error occured: Invalid JSON</html>" } else { if { [lindex $result 1] contains "qds" } { HTTP::respond 403 content "Forbidden Access!" } else { HTTP::respond 400 content "value is [lindex $result 1]" } } }
ilxlab2_ext>>index.js
'use strict' // Just for best practices // Import modules here var f5 = require('f5-nodejs'); // var qs = require('querystring'); // Used for parsing the POST data querystring // Create an ILX server instance var ilx = new f5.ILXServer(); // This method will transform POST data into JSON ilx.addMethod('jsonPost', function (req, res) { // Get POST data from TCL and parse to JS object //var postData = qs.parse(req.params()[0]); var postData = req.params()[0]; try { var jsonData = JSON.parse(postData); } catch (err) { console.log('Error with JSON.parse: ' + err.message); return res.reply(1); } if ( jsonData.formdata[0].key == "func" ) { console.log(jsonData.formdata[0].value); var qds_value = jsonData.formdata[0].value; return res.reply([0, qds_value]) } else { return res.reply([0, "no"]) } // Turn postData object into JSON and return to TCL // res.reply(JSON.stringify(postData)); }); //Start the ILX server ilx.listen();
curl test command is:
curl -kv http://10.10.10.177 -X POST -H "Content-Type: application/json" -d '{"mode":"formdata","formdata":[{"key":"func","value":"qds.ObjAction","type":"default"}]}'
result is:
[root@f5:LICENSE EXPIRES IN 4 DAYS:Active:Standalone] config # curl -kv http://10.10.10.177 -X POST -H "Content-Type: application/json" -d '{"mode":"formdata","formdata":[{"key":"func","value":"qds.ObjAction","type":"default"}]}' Note: Unnecessary use of -X or --request, POST is already inferred. * Rebuilt URL to: http://10.10.10.177/ * Trying 10.10.10.177... * Connected to 10.10.10.177 (10.10.10.177) port 80 (#0) > POST / HTTP/1.1 > Host: 10.10.10.177 > User-Agent: curl/7.47.1 > Accept: */* > Content-Type: application/json > Content-Length: 88 > * upload completely sent off: 88 out of 88 bytes * HTTP 1.0, assume close after body < HTTP/1.0 403 Forbidden < Server: BigIP * HTTP/1.0 connection set to keep alive! < Connection: Keep-Alive < Content-Length: 17 < * Connection #0 to host 10.10.10.177 left intact Forbidden Access![root@f5:LICENSE EXPIRES IN 4 DAYS:Active:Standalone] config #
tail -f /var/log/ltm
Dec 30 15:20:48 f5 info tmm[10644]: Rule /Common/ilxlab2_plugin/json_post <HTTP_REQUEST_DATA>: result is 0 qds.ObjAction Dec 30 15:20:48 f5.bigip-gtm110.com info sdmd[5171]: 018e0017:6: pid[20389] plugin[/Common/ilxlab2_plugin.ilxlab2_ext] qds.ObjAction