CVE-2020-8416 (published 2020-01-29T17:15Z)

IKTeam BearFTP before 0.2.0 allows remote attackers to achieve denial of service via a large volume of connections to the PASV mode port.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-770
cwe_name: Allocation of Resources Without Limits or Throttling
description: The product allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on the size or number of resources that can be allocated, in violation of the intended security policy for that actor.
extended_description: Code frequently has to work with limited resources, so programmers must be careful to ensure that resources are not consumed too quickly, or too easily.  Without use of quotas, resource limits, or other protection mechanisms, it can be easy for an attacker to consume many resources by rapidly making many requests, or causing larger resources to be used than is needed. When too many resources are allocated, or if a single resource is too large, then it can prevent the code from working correctly, possibly leading to a denial of service.
         

Fix information:
repo_url: https://github.com/kolya5544/BearFTP
commit_details: repo_url: https://github.com/kolya5544/BearFTP
author: kolya5544
author_date: 2020-01-29 18:41:40+03:00
msg: CVE-2020-8416 DoS fix and antispam system improvement. Official v0.2.0
repository: repo_url: https://github.com/kolya5544/BearFTP
repo_name: kolya5544/BearFTP
description: Honeypot FTP server written in .NET Core (C#) for both Linux and Windows.
repo_language: C#
owner: kolya5544
file_changes: filename: Active.cs
change_type: ModificationType.ADD
diff: @@ -0,0 +1,53 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BearFTP
+{
+    class Active
+    {
+        public string hostname = "";
+        public int connected = 0;
+
+        public Active(string hostname, int connected)
+        {
+            this.hostname = hostname;
+            this.connected = connected;
+        }
+
+        public static bool CheckExists(string hostname, List<Active> list)
+        {
+            foreach (Active act in list)
+            {
+                if (act.hostname == hostname)
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public static int GetConnections(string hostname, List<Active> list)
+        {
+            foreach (Active act in list)
+            {
+                if (act.hostname == hostname)
+                {
+                    return act.connected;
+                }
+            }
+            return -1;
+        }
+
+        public static void SetConnections(string hostname, List<Active> list, int connections)
+        {
+            foreach (Active act in list)
+            {
+                if (act.hostname == hostname)
+                {
+                    act.connected = connections;
+                }
+            }
+        }
+    }
+}

programming_language: C#
filename: Program.cs
change_type: ModificationType.MODIFY
diff: @@ -42,7 +42,7 @@ namespace BearFTP
         public static Directory root = new Directory();
 
         //Current version
-        public static string _VERSION = "v0.1.0 BETA";
+        public static string _VERSION = "v0.2.0 BETA";
 
         //Default log.
         public static StreamWriter logfile = new StreamWriter("log.txt", true);
@@ -50,6 +50,14 @@ namespace BearFTP
         //Dictionary of passvie clients (clients with PASV mode. Used to communicate directly later.)
         public static Dictionary<Client, Connectivity> passives = new Dictionary<Client, Connectivity>();
 
+        //List of connections per second from hostname
+        public static List<Active> per_second = new List<Active>();
+        //List of overall connections from hostname
+        public static List<Active> actives = new List<Active>();
+
+        //List of overall connections to PASV
+        public static List<Active> pasv_actives = new List<Active>();
+
         /// <summary>
         /// Reports an IP
         /// </summary>
@@ -296,6 +304,23 @@ namespace BearFTP
                     }
                 }
             })).Start();
+            //Connections per seconds (antibot) handling
+            new Thread(new ThreadStart(() => {
+                Thread.CurrentThread.IsBackground = true;
+
+                while (true)
+                {
+                    Thread.Sleep(1000);
+                    for (int i = 0; i < per_second.Count; i++)
+                    {
+                        if (per_second[i].connected > 0)
+                        {
+                            per_second[i].connected -= 1;
+                        }
+                    }
+                 //   Console.WriteLine("[DBG] Iterated per_second!");
+                }
+            })).Start();
             ftp.Start();
             pasv.Start();
             new Thread(() =>
@@ -312,6 +337,53 @@ namespace BearFTP
                     StreamWriter sw = new StreamWriter(ns);
 
                     sw.AutoFlush = true;
+                    string hostname = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();
+                    if (Active.CheckExists(hostname, actives))
+                    {
+                        if (Active.GetConnections(hostname, actives) >= 5)
+                        {
+                            client.Close();
+                            if (Ban)
+                            {
+                                var aaa = new Ban();
+                                aaa.hostname = hostname;
+                                aaa.time = 3600;
+                                bans.Add(aaa);
+                            }
+                        }
+                        else
+                        {
+                            Active.SetConnections(hostname, actives, Active.GetConnections(hostname, actives) + 1);
+                        }
+                    }
+                    else
+                    {
+                        actives.Add(new Active(hostname, 1));
+                    }
+
+                    if (Active.CheckExists(hostname, per_second))
+                    {
+                        if (Active.GetConnections(hostname, per_second) >= 5)
+                        {
+                            client.Close();
+                            if (Ban)
+                            {
+                                var aaa = new Ban();
+                                aaa.hostname = hostname;
+                                aaa.time = 3600;
+                                bans.Add(aaa);
+                            }
+                        }
+                        else
+                        {
+                            Active.SetConnections(hostname, per_second, Active.GetConnections(hostname, per_second) + 1);
+                        }
+                    }
+                    else
+                    {
+                        per_second.Add(new Active(hostname, 1));
+                       
+                    }
 
                     new Thread(new ThreadStart(() =>
                     {
@@ -325,9 +397,9 @@ namespace BearFTP
                         string directory = "/";
                         bool Authed = false;
                         bool passive = false;
-                        int error = 10;
-                        string hostname = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();
+                        int error = 5;
                         
+
                         //AbuseDBIP.com API
                         bool hacking = false;
                         bool bruteforce = false;
@@ -343,25 +415,26 @@ namespace BearFTP
                                 client.Close();
                             }
                         }
-                        catch { 
+                        catch
+                        {
 
                         }
 
-
+                        
 
                         try
                         {
                             Thread.Sleep(100);
                             Log("Connected - " + hostname, "in", true, hostname);
-                            LogWrite("220 "+config.Banner.Replace("%host%", Hostname)+"\r\n", sw, hostname);
-                            
+                            LogWrite("220 " + config.Banner.Replace("%host%", Hostname) + "\r\n", sw, hostname);
+
                             while (client.Connected)
                             {
                                 Thread.Sleep(100);
                                 //Receiving handler START
                                 string answ = "";
                                 bool flag = true;
-                                
+
                                 while (flag)
                                 {
                                     int a = sr.Read();
@@ -379,7 +452,7 @@ namespace BearFTP
                                 //Receiving handler END
 
                                 //Command processing.
-                                if (answ.Length > 3) //We dont want dummies to spam/DDoS.
+                                if (answ.Length >= 3) //We dont want dummies to spam/DDoS.
                                 {
                                     Log(answ, "in", true, hostname);
                                 }
@@ -393,12 +466,12 @@ namespace BearFTP
                                         bans.Add(aaa);
                                         client.Close();
                                     }
-                                    var a = ReportAsync(hostname, "["+DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") + "] " + "System scanning (Proxy judging) using CONNECT or GET requests", false, false, true, true, false);
+                                    var a = ReportAsync(hostname, "[" + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") + "] " + "System scanning (Proxy judging) using CONNECT or GET requests", false, false, true, true, false);
                                     a.Start();
-                                    
-                                    
+
+
                                 }
-                                if (answ.Length > 64)
+                                if (answ.Length > 128)
                                 {
                                     client.Close();
                                 }
@@ -549,7 +622,7 @@ namespace BearFTP
                                             LogWrite("150 Ok to send data.\r\n", sw, hostname);
                                             Thread.Sleep(100);
                                             //       byte[] file = aaaa.content;
-                                           //Encoding.ASCII.GetChars(file);
+                                            //Encoding.ASCII.GetChars(file);
                                             //      connn.sw.Write(chars, 0, file.Length);
                                             //      connn.tcp.Close();
                                             SendFile(aaaa, connn.sw);
@@ -678,10 +751,14 @@ namespace BearFTP
                                 }
                                 else
                                 {
-                                    error--;
-                                    if (error <= 0)
+                                    if (answ.Length >= 3)
                                     {
-                                        client.Close();
+                                        error--;
+                                        if (error <= 0)
+                                        {
+                                            client.Close();
+                                        }
+
                                     }
                                 }
                                 if (answ.Contains("php") && triggered)
@@ -700,20 +777,22 @@ namespace BearFTP
                                         bans.Add(aaa);
                                         client.Close();
                                     }
-                                    var a = ReportAsync(hostname, "["+DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") + "] " + "RCE Attempt at 21 port using ProFTPd exploit", true, false, false, false, false);
+                                    var a = ReportAsync(hostname, "[" + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") + "] " + "RCE Attempt at 21 port using ProFTPd exploit", true, false, false, false, false);
                                     a.Start();
-                                    
-                                    
+
+
 
                                 }
 
                             }
+
                         }
                         catch (Exception e)
                         {
                             client.Close();
                             c.Connected = false;
                         }
+                        Active.SetConnections(hostname, actives, Active.GetConnections(hostname, actives) - 1);
                     }
                     )).Start();
                 }
@@ -742,33 +821,89 @@ namespace BearFTP
                     StreamWriter sw = new StreamWriter(ns);
 
                     sw.AutoFlush = true;
-                    string hostname = "";
+                    string hostname = ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString();
+
+                    try
+                    {
+                        if (bans.Any(ban => ban.hostname == hostname))
+                        {
+                            client.Close();
+                        }
+                    }
+                    catch
+                    {
+
+                    }
+
+                    if (Active.CheckExists(hostname, pasv_actives))
+                    {
+                        if (Active.GetConnections(hostname, pasv_actives) >= 3)
+                        {
+                            client.Close();
+                            if (Ban)
+                            {
+                                var aaa = new Ban();
+                                aaa.hostname = hostname;
+                                aaa.time = 3600;
+                                bans.Add(aaa);
+                            }
+                        }
+                        else
+                        {
+                            Active.SetConnections(hostname, pasv_actives, Active.GetConnections(hostname, pasv_actives) + 1);
+                        }
+                    }
+                    else
+                    {
+                        pasv_actives.Add(new Active(hostname, 1));
+                    }
                     Thread user = new Thread(new ThreadStart(() =>
                     {
                         Thread.CurrentThread.IsBackground = true;
 
                         Client c = new Client("1", "2", "3");
 
+                        
+
                         try
                         {
+                            bool ispresent = false;
                             foreach (Client cl in connected)
                             {
-                                if (cl.hostname == ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString() && cl.Connected)
+                                if (cl.hostname == hostname && cl.Connected)
                                 {
                                     c = cl;
+                                    ispresent = true;
                                 }
                             }
-                            Connectivity ca = new Connectivity();
-                            ca.sr = sr;
-                            ca.sw = sw;
-                            ca.tcp = client;
-                            passives.Add(c, ca);
-                            while (client.Connected)
+                            if (!ispresent)
                             {
-                                Thread.Sleep(3000);
+                                client.Close();
+
+                            }
+                            else
+                            {
+                                Connectivity ca = new Connectivity();
+                                ca.sr = sr;
+                                ca.sw = sw;
+                                ca.tcp = client;
+                                passives.Add(c, ca);
+                                /*  while (client.Connected)
+                                  {
+                                      Thread.Sleep(3000);
+                                  }*/
+                                for (int i = 0; client.Connected; i++)
+                                {
+                                    Thread.Sleep(1000);
+                                    if (i >= 120)
+                                    {
+                                        client.Close();
+                                        passives.Remove(c);
+                                    }
+                                }
+                                client.Close();
+                                passives.Remove(c);
                             }
-                            client.Close();
-                            passives.Remove(c);
                         }
                         catch (Exception e)
                         {
@@ -778,7 +913,9 @@ namespace BearFTP
                                 passives.Remove(c);
                             }
                         }
+                        Active.SetConnections(hostname, pasv_actives, Active.GetConnections(hostname, pasv_actives) - 1);
                     }
+
                     ));
                     user.Start();
 

programming_language: C#
filename: CHANGELOG.txt
change_type: ModificationType.MODIFY
diff: @@ -1,8 +1,10 @@
 --> IT ONLY CONTAINS THE MOST RECENT CHANGES!
 
-v0.1.0:
-- Ability to RECV files more than 2 kbs in size
-- Ability to add byte[] contents to files (a.k.a you can now send .exes over FTP)
-- JSON format fixed
-- Possible fix of unique characters breaking encoding of logs.
-- Download speed limited to 40 kbit/sec.
\ No newline at end of file
+v0.2.0:
+- Fixed "errors" handling, designed to prevent users spamming invalid FTP commands
+- Fixed PWN not being logged due to its size
+- Added "connections per second" and "total connections" antispam for default port
+- Added "total connections" antispam for PASV port
+- Fixed PASV mode handler not checking for default port connection, as well as fixed handling of non-active users (CVE-2020-8416 fix)
+- Passive mode now autodisconnects AFK persons after 120 seconds of inactivity (Beware when sending big files!)
+- Minor bugfixes
\ No newline at end of file

programming_language: Markdown
filename: README.md
change_type: ModificationType.MODIFY
diff: @@ -83,7 +83,6 @@ Here's our CURRENT todo list:
 - Administrator commands (adding files right through FTP!)
 - Local command handler (execute FTP commands in your console, ban spamming IPs and such)
 - Implement directories
-- Implement support of files with size more than 2 kbs
 - Add more features (Active mode, more advanced ban system)
 
 

programming_language: Markdown