Sustained SMTP AUTH LOGIN Brute Force

Use this forum if you have problems with a hMailServer script, such as hMailServer WebAdmin or code in an event handler.
Post Reply
User avatar
DragonDesign
Normal user
Normal user
Posts: 38
Joined: 2008-08-03 17:20
Location: UK
Contact:

Sustained SMTP AUTH LOGIN Brute Force

Post by DragonDesign » 2020-08-19 22:33

Hi All,

My Server has one 'big' client and is under a sustained attack from a botnet, as an example:

Code: Select all

"SMTPD"	3832	40146	"2020-08-19 20:27:08.662"	"182.160.104.22"	"SENT: 220 inetc930.inetc.net"
"SMTPD"	3856	40146	"2020-08-19 20:27:08.870"	"182.160.104.22"	"RECEIVED: HELO [116.212.109.195]"
"SMTPD"	3856	40146	"2020-08-19 20:27:08.871"	"182.160.104.22"	"SENT: 250 Hello."
"SMTPD"	3832	40146	"2020-08-19 20:27:09.078"	"182.160.104.22"	"RECEIVED: AUTH LOGIN"
"SMTPD"	3832	40146	"2020-08-19 20:27:09.079"	"182.160.104.22"	"SENT: 334 VXNlcm5hbWU6"
"SMTPD"	3856	40146	"2020-08-19 20:27:09.691"	"182.160.104.22"	"RECEIVED: ZGF2aWRmaXNoZXJAZ2VvcmdlYnJvd25zLmNvLnVr"
"SMTPD"	3856	40146	"2020-08-19 20:27:09.691"	"182.160.104.22"	"SENT: 334 UGFzc3dvcmQ6"
"SMTPD"	3856	40146	"2020-08-19 20:27:10.301"	"182.160.104.22"	"RECEIVED: ***"
"SMTPD"	3856	40146	"2020-08-19 20:27:10.310"	"182.160.104.22"	"SENT: 535 Authentication failed. Too many invalid logon attempts."
'Too many login attempts' is because I have had to reduce the Auto Ban (Failed Logins) to 1 due to the size of the botnet and the lack of regular repeating IP addresses.

I've looked at blanket blocking countries at the firewall but the server is old, so Powershell is not useful, to use this : https://www.gregsitservices.com/blog/20 ... -firewall/ and, to be honest, the IPs are coming from all around the world so 'by region' firewalling is not useful here and my client has many overseas clients, so the risk of cutting off their clients is not acceptable.

Most of these attempted logins are not providing a scriptable EHLO ("RECEIVED: HELO [116.212.109.195]"), this seems the same as an email client (Desktop Outlook etc.).

I have used this to test for the HELO as, from the log, there isn't a proper EHLO but the 'SMTPD' RECEIVED: HELO [116.212.109.195].

I can't get this string from oCLient or other VBS means, have tried this as a test :

Code: Select all

Sub OnClientConnect(oClient)   
	EventLog.Write( "CONNECT" ) 
	EventLog.Write( oClient.IPAddress )	
End Sub
Sub OnSMTPData(oClient, oMessage)
	EventLog.Write( "SMTP START" )
	EventLog.Write( oClient.HELO )
	EventLog.Write( oClient.IPAddress )
End Sub
Results:

Code: Select all

3952	"2020-08-19 21:15:41.178"	"CONNECT"
3952	"2020-08-19 21:15:41.179"	"82.31.168.38"
3856	"2020-08-19 21:15:41.184"	"CONNECT"
3856	"2020-08-19 21:15:41.184"	"82.31.168.38"
3952	"2020-08-19 21:15:58.405"	"CONNECT"
3952	"2020-08-19 21:15:58.408"	"177.22.86.79"
3952	"2020-08-19 21:16:02.726"	"CONNECT"
3952	"2020-08-19 21:16:02.727"	"62.193.129.232"
3952	"2020-08-19 21:16:25.765"	"CONNECT"
3952	"2020-08-19 21:16:25.765"	"192.35.168.193"
3856	"2020-08-19 21:16:36.711"	"CONNECT"
3856	"2020-08-19 21:16:36.712"	"86.13.173.48"
3856	"2020-08-19 21:16:40.687"	"CONNECT"
3856	"2020-08-19 21:16:40.687"	"86.13.173.48"
3952	"2020-08-19 21:16:40.886"	"CONNECT"
3952	"2020-08-19 21:16:40.886"	"192.35.168.193"
3952	"2020-08-19 21:16:42.000"	"CONNECT"
3952	"2020-08-19 21:16:42.001"	"192.35.168.193"
3952	"2020-08-19 21:16:42.657"	"CONNECT"
3952	"2020-08-19 21:16:42.657"	"192.35.168.193"
3952	"2020-08-19 21:17:03.827"	"CONNECT"
3952	"2020-08-19 21:17:03.827"	"90.197.184.250"
3952	"2020-08-19 21:17:07.527"	"CONNECT"
3952	"2020-08-19 21:17:07.528"	"86.13.173.48"
3832	"2020-08-19 21:17:58.706"	"CONNECT"
3832	"2020-08-19 21:17:58.706"	"109.151.246.143"
3712	"2020-08-19 21:18:01.402"	"CONNECT"
3712	"2020-08-19 21:18:01.403"	"38.89.254.163"
3952	"2020-08-19 21:18:06.843"	"CONNECT"
3952	"2020-08-19 21:18:06.843"	"38.89.254.163"
3952	"2020-08-19 21:18:06.935"	"CONNECT"
3952	"2020-08-19 21:18:06.935"	"86.13.173.48"
3952	"2020-08-19 21:18:07.920"	"SMTP START"
3952	"2020-08-19 21:18:07.921"	"mx127.antispamcloud.com"
3952	"2020-08-19 21:18:07.921"	"38.89.254.163"
3952	"2020-08-19 21:18:29.805"	"CONNECT"
3952	"2020-08-19 21:18:29.805"	"37.120.198.229"
3952	"2020-08-19 21:18:42.191"	"CONNECT"
3952	"2020-08-19 21:18:42.192"	"86.13.173.48"
3952	"2020-08-19 21:18:59.324"	"CONNECT"
3952	"2020-08-19 21:18:59.324"	"46.165.223.16"
3632	"2020-08-19 21:18:59.877"	"SMTP START"
3632	"2020-08-19 21:18:59.878"	"out8.antispamcloud.com"
3632	"2020-08-19 21:18:59.878"	"46.165.223.16"
3632	"2020-08-19 21:19:53.554"	"CONNECT"
3632	"2020-08-19 21:19:53.554"	"190.147.133.202"
3856	"2020-08-19 21:20:01.922"	"CONNECT"
3856	"2020-08-19 21:20:01.923"	"82.8.194.220"
3856	"2020-08-19 21:20:06.400"	"CONNECT"
3856	"2020-08-19 21:20:06.400"	"82.8.194.220"
3632	"2020-08-19 21:20:06.641"	"CONNECT"
3632	"2020-08-19 21:20:06.641"	"196.216.92.79"
3632	"2020-08-19 21:20:06.709"	"CONNECT"
3632	"2020-08-19 21:20:06.710"	"82.8.194.220"
3632	"2020-08-19 21:20:06.757"	"CONNECT"
3632	"2020-08-19 21:20:06.758"	"82.8.194.220"
3632	"2020-08-19 21:20:07.675"	"CONNECT"
3632	"2020-08-19 21:20:07.675"	"82.8.194.220"
3632	"2020-08-19 21:20:07.953"	"CONNECT"
3632	"2020-08-19 21:20:07.953"	"82.8.194.220"
3856	"2020-08-19 21:20:08.236"	"CONNECT"
3856	"2020-08-19 21:20:08.236"	"82.8.194.220"
3856	"2020-08-19 21:20:08.270"	"CONNECT"
3856	"2020-08-19 21:20:08.270"	"82.8.194.220"
3952	"2020-08-19 21:20:10.043"	"SMTP START"
3952	"2020-08-19 21:20:10.043"	"217.21.124.194.liquidtelecom.net"
3952	"2020-08-19 21:20:10.044"	"196.216.92.79"
3632	"2020-08-19 21:20:10.746"	"CONNECT"
3632	"2020-08-19 21:20:10.747"	"77.37.208.119"
3856	"2020-08-19 21:20:14.759"	"CONNECT"
3856	"2020-08-19 21:20:14.759"	"82.8.194.220"
During testing, I can't see a way to distinguish between a legit email client HELO and the spammer HELO.

The domain has behind a Spam Wall service for over two years but, due to it's age, the historical MX records are clearly still out there and I still get direct SMTP spammers, bypassing the now official MX records of the spamwall. I can't restrict the 'incoming relays', to the spamwall only, as there are other clients and services being provided, e.g. an invoicing system, scanners / printers etc. and a couple of other smaller clients.

Am up to nearly 5000 banned IPs and have spent the last two days trying to fathom a way to block these dickheads.

Is there a limit in HMS for the banned IP list ? Am currently only showing a medium critical status on the number in Status -> Server.

If it is ok I'll just let the list grow and see if HMS can handle more banned IPs than they can afford botnet IPs..?

Am really looking for ideas on how to identify between a spammer and a legit client SMTP connection in code. The API is great but doesn't go into enough detail.

User avatar
SorenR
Senior user
Senior user
Posts: 4169
Joined: 2006-08-21 15:38
Location: Denmark

Re: Sustained SMTP AUTH LOGIN Brute Force

Post by SorenR » 2020-08-19 22:58

Code: Select all

Function Lookup(strRegEx, strMatch) : Lookup = False
    If strRegEx = "" Then Exit Function
    With CreateObject("VBScript.RegExp")
        .Pattern = strRegEx
        .Global = False
        .MultiLine = True
        .IgnoreCase = True
        If .Test(strMatch) Then Lookup = True
    End With
End Function

Sub OnSMTPData(oClient, oMessage)

    '
    '   Validate HELO/EHLO greeting
    '
    Dim strRegEx
    Const strFQDN = "^(?=^.{1,254}$)(^(?:(?!\.|-)([a-z0-9\-\*]{1,63}|([a-z0-9\-]{1,62}[a-z0-9]))\.)+(?:[a-z]{2,})$)$"
    Const strIPv4 = "^\[(?:[0-9]{1,3}\.){3}[0-9]{1,3}\]$"
    Const strIPv6 = "^\[(IPv6)((?:[0-9A-Fa-f]{0,4}:){1,7}(?:(?:(>25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|[0-9A-Fa-f]{1,4}))\]$"
    strRegEx = strFQDN & "|" & strIPv4 & "|" & strIPv6
    If Not Lookup(strRegEx, oClient.HELO) Then
        Result.Message = "5.3.0 [BAD HELO] Your access to this mail system has been rejected due to the sending MTA's poor reputation. If you believe that this failure is in error, please contact the intended recipient via alternate means."
        Result.Value = 2
        Exit Sub
    End If

End Sub
SørenR.

Algorithm (noun.)
Word used by programmers when they do not want to explain what they did.

User avatar
SorenR
Senior user
Senior user
Posts: 4169
Joined: 2006-08-21 15:38
Location: Denmark

Re: Sustained SMTP AUTH LOGIN Brute Force

Post by SorenR » 2020-08-19 23:26

Eh... Actually... RvdH made a custom edition of 5.6.8 with the "Sub OnHELO" trigger... I run a modified version of it.

https://www.hmailserver.com/forum/viewt ... 51#p220551
Just a note... All these modifications are carried forward into the official 5.7 64bit Alpha...

My previous code sample would then look like this:

Code: Select all

Function Lookup(strRegEx, strMatch) : Lookup = False
    If strRegEx = "" Then Exit Function
    With CreateObject("VBScript.RegExp")
        .Pattern = strRegEx
        .Global = False
        .MultiLine = True
        .IgnoreCase = True
        If .Test(strMatch) Then Lookup = True
    End With
End Function

Sub OnHELO(oClient)

    '
    '   Validate HELO/EHLO greeting
    '
    Dim strRegEx
    Const strFQDN = "^(?=^.{1,254}$)(^(?:(?!\.|-)([a-z0-9\-\*]{1,63}|([a-z0-9\-]{1,62}[a-z0-9]))\.)+(?:[a-z]{2,})$)$"
    Const strIPv4 = "^\[(?:[0-9]{1,3}\.){3}[0-9]{1,3}\]$"
    Const strIPv6 = "^\[(IPv6)((?:[0-9A-Fa-f]{0,4}:){1,7}(?:(?:(>25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|[0-9A-Fa-f]{1,4}))\]$"
    strRegEx = strFQDN & "|" & strIPv4 & "|" & strIPv6
    If Not Lookup(strRegEx, oClient.HELO) Then
        Result.Message = "5.3.0 [BAD HELO] Your access to this mail system has been rejected due to the sending MTA's poor reputation. If you believe that this failure is in error, please contact the intended recipient via alternate means."
        Result.Value = 2
        Exit Sub
    End If

End Sub
Another thing you can do is remove AUTH on port 25. Server will send and receive on port 25 as usual - only authentication is disabled. You will need to open SMTP port 465 (SSL) or 587 (TLS) for your clients to authenticate to send.

hmailserver.ini

Code: Select all

[Settings]
DisableAUTHList=25
SørenR.

Algorithm (noun.)
Word used by programmers when they do not want to explain what they did.

palinka
Senior user
Senior user
Posts: 2450
Joined: 2017-09-12 17:57

Re: Sustained SMTP AUTH LOGIN Brute Force

Post by palinka » 2020-08-20 00:26

DragonDesign wrote:
2020-08-19 22:33

Am up to nearly 5000 banned IPs and have spent the last two days trying to fathom a way to block these dickheads.

Is there a limit in HMS for the banned IP list ? Am currently only showing a medium critical status on the number in Status -> Server.

If it is ok I'll just let the list grow and see if HMS can handle more banned IPs than they can afford botnet IPs..?

Am really looking for ideas on how to identify between a spammer and a legit client SMTP connection in code. The API is great but doesn't go into enough detail.
First of all, I don't think there is any limit to the number of autobans. The only limit is your hardware.

Secondly, I created a firewall ban project for hmailserver. It works great, but in your use case, I'd probably say you don't need it. One of the things that I get out of the project is a nice log for banned connections and what I've found is that these botnet IPs never return. 60% of the IPs I've banned have never returned once - I know because I have a database that scrapes windows firewall logs and counts the number of drops for each IP.

Soren's helo validation is great, but in the year I've been using my firewall ban, only 546 out of 30,228 (mail) IPs banned were for invalid helo using Soren's (RvdH's) helo validation code. So 1.8% of the total. Not a lot, but its lightweight code, so its definitely worthy of implementation. Also, you can

Also, like Soren said, disabling AUTH on port 25 is very effective.

My advice is to delete all your autobans. They're probably not coming back to attack you anyway. Then, reduce the time limit to max 1 hour so you keep system resources down. Also, its safe to put back 2 or 3 failed attempts before autobanning. Again - these password guessing botnets rarely return using the same IP and if they do, it will be a long time in the future.

The most important thing is making sure your users have strong passwords.

Another thing you can do is check helo and ptr for dynamic-looking records and for no ptr record. I get a few more hits from these, totaling 1,874, or 6.2%. Getting better. Every little thing counts. This can ONLY be tested on port 25 because, as you mentioned, valid clients use dynamic IPs also.

Code: Select all

Function Lookup(strRegEx, strMatch) : Lookup = False
   With CreateObject("VBScript.RegExp")
      .Pattern = strRegEx
      .Global = False
      .MultiLine = True
      .IgnoreCase = True
      If .Test(strMatch) Then Lookup = True
   End With
End Function

REM - Function requires RvdH's DNS Resolver - https://d-fault.nl/files/DNSResolverComponent_1.3.exe.zip
Function PTRLookup(strIP)
	Dim strLookup, strPTR
	With CreateObject("DNSLibrary.DNSResolver")
		strLookup = .PTR(strIP)
	End With
	If strLookup = Empty Then strPTR = "No.PTR.Record" Else strPTR = strLookup End If
	PTRLookup = strPTR
End Function

Sub OnClientConnect(oClient)

	Dim PTR_Record
	Dim strRegEx, Match, Matches
	Dim a, i 


	REM	- Exclude local LAN & Backup from test after recording connection
	If (Left(oClient.IPAddress, 11) = "192.168.1.") Then Exit Sub
	If oClient.IPAddress = "127.0.0.1" Then Exit Sub
	If (Left(oClient.IPAddress, 12) = "184.105.182.") Then Exit Sub

	REM	- Grab PTR-Record
	PTR_Record = PTRLookup(oClient.IPAddress)

	REM	- Reject on No-PTR
	If (oClient.Port = 25) Then
		If PTR_Record = "No.PTR.Record" Then
			Result.Value = 2
			Result.Message = ". 03 Your access to this mail system has been rejected due to the sending MTA's poor reputation. If you believe that this failure is in error, please contact the intended recipient via alternate means."
			Exit Sub
		End If
	End If

	REM	- Filter connections on dynamic looking records
	REM	- First, split the IPAddress
	a = Split(oClient.IPAddress, ".")
	For i = 0 to 3
	Next
	REM	- Search for dynamic looking PTR
	REM	- Search for dynamic looking PTR
	strRegEx = 	"(.*(((?:[0]{0,2})" & a(0) & "|(?:[0]{0,2})" & a(1) & "|(?:[0]{0,2})" & a(2) & "|(?:[0]{0,2})" & a(3) & ")(?:.+)){3}" &_
				"((?:[0]{0,2})" & a(0) & "|(?:[0]{0,2})" & a(1) & "|(?:[0]{0,2})" & a(2) & "|(?:[0]{0,2})" & a(3) & ").+)$"
	If (oClient.Port = 25) Then
		If Lookup(strRegEx, PTR_Record) Then
			Result.Value = 2
			Result.Message = ". 18 Your access to this mail system has been rejected due to the sending MTA's poor reputation. If you believe that this failure is in error, please contact the intended recipient via alternate means."
			Exit Sub
		End If
	End If
	REM	- Search for dynamic looking HELO
	strRegEx = 	"(.*(((?:[0]{0,2})" & a(0) & "|(?:[0]{0,2})" & a(1) & "|(?:[0]{0,2})" & a(2) & "|(?:[0]{0,2})" & a(3) & ")(?:.+)){3}" &_
				"((?:[0]{0,2})" & a(0) & "|(?:[0]{0,2})" & a(1) & "|(?:[0]{0,2})" & a(2) & "|(?:[0]{0,2})" & a(3) & ").+)$"
	If (oClient.Port = 25) Then
		If Lookup(strRegEx, oClient.HELO) Then
			Result.Value = 2
			Result.Message = ". 05 Your access to this mail system has been rejected due to the sending MTA's poor reputation. If you believe that this failure is in error, please contact the intended recipient via alternate means."
			Exit Sub
		End If
	End If

End Sub

Post Reply