DoS and NTLM Brute force protection for SIP traffic
Problem this snippet solves:
This snippet has been designed to mainly protect against NTLM's downgrade attacks present in a widely used Instant Messaging solution. This solution authenticate users on the SIP/TLS protocol. This irule block brute forced users and source IP address.
How to use this snippet:
This snippet should be applied on the Virtual Server that handle SIP/TLS traffic. SSL bridging is required to make this irule work properly. Moreover, Skype for Business may require that you change your cipher suite to a weak one.
The internal domain should be define in "
email_domain" and "user_domain" variables. The script will focus on those domains.
The max attempts before blocking is defined in the "
max_failures" variable. This setting should be under the max attempts allowed on the Active Directory.
The blocking duration is configured in the "
block_duration" variable. (in seconds)
The "
fail_memory" variable define the window that we increase the attempt counter. After reaching the end of this duration, the entry is removed until a new invalid attempt occurs.
External links
Github : github.com/e-XpertSolutions/f5
Related Articles
Code :
when RULE_INIT {
array set NTLMFlags {
unicode 0x00000001
oem 0x00000002
req_target 0x00000004
unknown1 0x00000008
sign 0x00000010
seal 0x00000020
datagram 0x00000040
lmkey 0x00000080
netware 0x00000100
ntlm 0x00000200
unknown2 0x00000400
unknown3 0x00000800
ntlm_domain 0x00001000
ntlm_server 0x00002000
ntlm_share 0x00004000
NTLM2 0x00008000
targetinfo 0x00800000
128bit 0x20000000
keyexch 0x40000000
56bit 0x80000000
}
set static::email_domain "domain.org"
set static::user_domain "DOMAIN"
set static::log_pri "local0."
set static::fail_tab "NTLMfails"
set static::blacklist_tab "NTLMblackhole"
set static::userfail_tab "NTLMUserfails"
set static::userblacklist_tab "NTLMUserblackhole"
set static::max_failures 5
set static::fail_memory 300
set static::block_duration 300
}
when CLIENT_ACCEPTED {
if {[table lookup -subtable $static::blacklist_tab [IP::client_addr]] == 1} {
log $static::log_pri "[virtual] - BLACKHOLED IPADDR [IP::client_addr]:[TCP::client_port] (Reputation=[IP::reputation [IP::client_addr]])"
reject
return
}
}
when CLIENTSSL_HANDSHAKE {
SSL::collect
}
when CLIENTSSL_DATA {
set payload [SSL::payload]
if { ($payload contains "3 REGISTER") } {
regexp -nocase {gssapi-data=\"([A-Za-z0-9+\/=]*)\",} $payload match gssapi garbage
if { [info exists match] } {
unset match
unset garbage
if { $gssapi != "" } {
set ntlm_msg [ b64decode [string trim $gssapi]]
binary scan $ntlm_msg a7ci protocol zero type
if { $type eq 3} {
binary scan $ntlm_msg @12ssissississississii \
lmlen lmlen2 lmoff \
ntlen ntlen2 ntoff \
dlen dlen2 doff \
ulen ulen2 uoff \
hlen hlen2 hoff \
slen slen2 soff \
flags
set ntlm_domain {}; binary scan $ntlm_msg @${doff}a${dlen} ntlm_domain
set ntlm_user {}; binary scan $ntlm_msg @${uoff}a${ulen} ntlm_user
set ntlm_host {}; binary scan $ntlm_msg @${hoff}a${hlen} ntlm_host
set unicode [expr {$flags & 0x00000001}]
if {$unicode} {
set ntlm_domain_convert ""
foreach i [ split $ntlm_domain ""] {
scan $i %c c
if {$c>1} {
append ntlm_domain_convert $i
} elseif {$c<128} {
set ntlm_domain_convert $ntlm_domain_convert
} else {
append ntlm_domain_convert \\u[format %04.4X $c]
}
}
set ntlm_domain $ntlm_domain_convert
set ntlm_user_convert ""
foreach i [ split $ntlm_user ""] {
scan $i %c c
if {$c>1} {
append ntlm_user_convert $i
} elseif {$c<128} {
set ntlm_user_convert $ntlm_user_convert
} else {
append ntlm_user_convert \\u[format %04.4X $c]
}
}
set ntlm_user $ntlm_user_convert
set ntlm_host_convert ""
foreach i [ split $ntlm_host ""] {
scan $i %c c
if {$c>1} {
append ntlm_host_convert $i
} elseif {$c<128} {
set ntlm_host_convert $ntlm_host_convert
} else {
append ntlm_host_convert \\u[format %04.4X $c]
}
}
set ntlm_host $ntlm_host_convert
}
binary scan $ntlm_msg @${ntoff}a${ntlen} ntdata
binary scan $ntlm_msg @${lmoff}a${lmlen} lmdata
binary scan $ntdata H* ntdata_h
binary scan $lmdata H* lmdata_h
set interesting 1
if { ($ntlm_domain equals $static::user_domain or $ntlm_user ends_with $static::email_domain) } {
set attack 1
if {[table lookup -subtable $static::userblacklist_tab $ntlm_user] == 1} {
log $static::log_pri "[virtual] - BLACKHOLED $ntlm_domain\\$ntlm_user from $ntlm_host at [IP::client_addr]:[TCP::client_port] (Reputation=[IP::reputation [IP::client_addr]])"
reject
return
} else {
log $static::log_pri "[virtual] - Login attempt by $ntlm_domain\\$ntlm_user from $ntlm_host for SIP."
}
} else {
set attack 0
log $static::log_pri "[virtual] - Not a valid user - Login attempt by $ntlm_domain\\$ntlm_user from $ntlm_host for SIP."
}
}
}
}
}
# Release the payload
SSL::release
SSL::collect
}
when SERVERSSL_HANDSHAKE {
SSL::collect
SSL::release 0
}
when SERVERSSL_DATA {
set payload [SSL::payload]
if {[info exists interesting] && $interesting == 1} {
set client [IP::client_addr]:[TCP::client_port]
set node [IP::server_addr]:[TCP::server_port]
if { $payload contains "401 Unauthorized ms-user-logon-data" and ([info exists attack] and $attack == 1) } {
table set -subtable $static::fail_tab -notouch -excl [IP::client_addr] 0 indef $static::fail_memory
table incr -subtable $static::fail_tab [IP::client_addr]
set now [clock seconds]
set now_date [split [clock format $now -format {%X %x}] " "]
set later [expr {$now + $static::block_duration}]
set later_date [split [clock format $later -format {%X %x}] " "]
if {[info exists ntlm_user]} {
table set -subtable $static::userfail_tab -notouch -excl $ntlm_user 0 indef $static::fail_memory
table incr -subtable $static::userfail_tab $ntlm_user
if {[table lookup -subtable $static::userfail_tab $ntlm_user] >= $static::max_failures} {
log $static::log_pri "[virtual] - BLACKHOLING USER - $ntlm_user at $now_date until $later_date"
table set -subtable $static::userblacklist_tab -excl $ntlm_user 1 indef $static::block_duration
}
}
if {[table lookup -subtable $static::fail_tab [IP::client_addr]] >= $static::max_failures} {
log $static::log_pri "[virtual] - BLACKHOLING IPADDR - [IP::client_addr] (Reputation=[IP::reputation [IP::client_addr]]) at $now_date until $later_date"
table set -subtable $static::blacklist_tab -excl [IP::client_addr] 1 indef $static::block_duration
}
}
}
SSL::release
SSL::collect
}Tested this on version:
11.5Updated Jun 06, 2023
Version 2.0Yann_Desmarest
Cirrus
Joined September 11, 2012
No CommentsBe the first to comment