Forum Discussion
Wizdem_38762
Nimbostratus
Dec 29, 2011iRule to log for Microsoft Security Advisory (2659883) Vulnerability in ASP.NET Could Allow Denial of Service?
Hi,
Based on Microsoft's snort signature:
http://blogs.technet.com/b/srd/archive/2011/12/27/more-information-about-the-december-2011-asp-net-vulnerability.aspx
Please comment on or verify the following iRule:
This irule checks for HTTP POST, that contains "application/x-www-form-urlencoded"
Then it collects the HTTP payload data and tries to matches it with Microsoft's snort signature
Logs the local.alert , client IP and Port and HTTP uri
when HTTP_REQUEST {
if { [HTTP::method] equals "POST" }{
set clength 0
if {[HTTP::header exists "Content-Length"] && [HTTP::header Content-Length] 0 && [HTTP::header Content-Type] contains "application/x-www-form-urlencoded"}{
set clength [HTTP::header Content-Length] }
else {
set clength 1048576
}
if { [info exists clength] && $clength > 0} { HTTP::collect $clength }
}
}
when HTTP_REQUEST_DATA {
if {[HTTP::payload] matches_regex "/(\w*(&|=)){1000,}/smi"} {
log local0.alert "Microsoft Security Advisory (2659883) IP Address [IP::client_addr]:[TCP::client_port] \ requested [HTTP::uri]" }
}
Thanks,
Peter
12 Replies
- hoolio
Cirrostratus
Hi Peter,
I'm not sure you can use the {1000,} count syntax with TCL or iRules. Regardless, a string pattern should be more efficient than a regex. Here's an untested example:when RULE_INIT { We want to check the payload for 500 or more parameter=value pairs set static::pattern "[string repeat *& 500]*" } when HTTP_REQUEST { Collect up to 1Mb of POST data if { [HTTP::method] equals "POST"}{ set clength 0 if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576 }{ set clength [HTTP::header Content-Length] } else { set clength 1048576 } if { $clength > 0} { HTTP::collect $clength } } } when HTTP_REQUEST_DATA { Check if the collected payload matches the pattern if {[HTTP::payload] matches_glob $static::pattern} { log local0.alert "Microsoft Security Advisory (2659883)\ IP Address [IP::client_addr]:[TCP::client_port] requested [HTTP::uri]" Drop the request drop } }
Aaron - JRahm
Admin
You could be a little more dynamic in finding the occurrences of "&":% set x [string repeat {&23456} 5] &23456&23456&23456&23456&23456 % puts [expr [llength [split $x "&"]] -1] 5 - JRahm
Admin
Edited for clarity - hoolio
Cirrostratus
I like that... I'm guessing it's more efficient and it's definitely more elegant. Also, I think most web apps don't normally use more than a 100 parameters for a single page. So basically you could do something like this:when HTTP_REQUEST { Collect up to 1Mb of POST data if { [HTTP::method] equals "POST"}{ set clength 0 if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576 }{ set clength [HTTP::header Content-Length] } else { set clength 1048576 } if { $clength > 0} { HTTP::collect $clength } } } when HTTP_REQUEST_DATA { Check if the collected payload contains more than 100 parameters if { [llength [split [HTTP::payload] &]] > 100 } { log local0.alert "Microsoft Security Advisory (2659883)\ IP Address [IP::client_addr]:[TCP::client_port] requested [HTTP::uri]" Drop the request drop } }
Aaron - Wizdem_38762
Nimbostratus
Thank you Aaron & Jason for your tweaks and great suggestions!
Very Much Appreciated!
Peter - hoolio
Cirrostratus
Here's another update which checks the query string for more than X parameters:when HTTP_REQUEST { Check if the query string contains more than 100 parameters if { [llength [split [HTTP::query] &]] > 100 } { log local0.alert "Microsoft Security Advisory (2659883)\ IP Address [IP::client_addr]:[TCP::client_port] requested [HTTP::uri]" Drop the request drop return } Collect up to 1Mb of POST data if { [HTTP::method] equals "POST"}{ set clength 0 if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048576 }{ set clength [HTTP::header Content-Length] } else { set clength 1048576 } if { $clength > 0} { HTTP::collect $clength } } } when HTTP_REQUEST_DATA { Check if the collected payload contains more than 100 parameters if { [llength [split [HTTP::payload] &]] > 100 } { log local0.alert "Microsoft Security Advisory (2659883)\ IP Address [IP::client_addr]:[TCP::client_port] requested [HTTP::uri]" Drop the request drop } }
Aaron - Colin_Walker_12Historic F5 AccountVery slick. Tagging for later proliferation.
Colin - Colin_Walker_12Historic F5 AccountI liked it too! I used this one as part of this week's 20 Lines or Less : Click Here. Thanks for the awesome example folks. ;)
Colin - Beinhard_8950
Nimbostratus
One curios question. Let´s say that the site that you want to secure and that with a maximum of 50 parameters.
But one URi is using more then 50, can the Irule be rewritten to change that limit for that specific URi?
Has anyone done any perfomance test with the Irule?, gain of CPU and so on.
/Beinhard - Beinhard_8950
Nimbostratus
Is the best way to use class match.?
Below i did a simple that pretty much is that if the URi:s in the group Uri_Parameters_Allowed, skip checking
when HTTP_REQUEST {
Check if the query string contains more than 100 parameters
if { ![class match [HTTP::uri]equals "Uri_Parameters_Allowed"] } {
if { [llength [split [HTTP::query] &]] > 100 } {
log local0.alert "Microsoft Security Advisory (2659883)\
IP Address [IP::client_addr]:[TCP::client_port] requested [HTTP::uri]"
Drop the request
drop
return
}
......................
But if you want to be alittle bit more specific, so that 1 datagroup is allowed to have 2000 parameters and the rest <50 and so on.
/Beinhard
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