|
security
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
FTP maximum password attemptssatisfactory answer besides a few expensive add-on packages. I'm hoping someone has some ideas. Basically, I'm getting brute forced to death on my IIS FTP sites. They haven't found their way in yet, but, this weekend, I had 11 different ip addresses(one in the US, several in Korea, one in Argentena, several in China, etc) hitting my two different servers(on two different networks) at a rate of about 25 password attempts per second. I came in on saturday, blocked(via ip security policy) the 4 addresses that where busy, then came in this morning(monday) and blocked the remaining. This sitting around watching log files and blocking addresses doesn't solve the underlying problem in that I need to be able to just block an ip after so many attempts. I used to use a 3rd party FTP server back on NT/2000 because I read at how horrible IIS was, but as soon as I got Server 2003, I switched to IIS's FTP. But good lord, this isn't what I call secure when its just a matter of time before they hit the right combination, no matter how long/complex I've made my users passwords(which, they've already complained about). If any of the IIS team are reading this, give us a "Maximum Password Tries" and a "Block for how many minutes" capability. Reset the list when IIS is restarted if you want, but, give us some simple to configure tools to help curb this problem. Simple? Don't use FTP. That's the only real solution that is also simple.
It _is_ only a matter of time. And if you leave the users up to change their passwords they'll get in in seconds or minutes. A couple of suggestions; If you have no business need to have the pacific rim access your site via FTP, block all their class As at the firewall. You can find lists of these addresses at a lot of anti-spam sites. Don't mess around with single IPs, they are compromised machines and will probably never come back. They'll just go on to a different target and set up a new zombie to try your server. With 10,000s of these machines in each country over there... you will get tired of it long before they do. Typically, FTP is a "webmaster" tool, not an end user tool. So you can do this and offer any downloads you need to them via HTTP. Better yet, find out the WAN IP addresses of the authorized users, and block ALL access to FTP except for those. (Use entire C blocks for dynamic users.) If you don't have access to a real firewall, you can use IIS "security settings" to sort of do it there. It won't stop the traffic, but it will keep them from guessing a password. Additional use, is doing that causes the FTP log in attempt to log the password they are trying. <nx-2***@winvoice.com> wrote in message Show quoteHide quote news:1159194370.931660.227810@m7g2000cwm.googlegroups.com... > I've done quite a bit of searching on this and I haven't found a > satisfactory answer besides a few expensive add-on packages. I'm > hoping someone has some ideas. > > Basically, I'm getting brute forced to death on my IIS FTP sites. They > haven't found their way in yet, but, this weekend, I had 11 different > ip addresses(one in the US, several in Korea, one in Argentena, several > in China, etc) hitting my two different servers(on two different > networks) at a rate of about 25 password attempts per second. I came > in on saturday, blocked(via ip security policy) the 4 addresses that > where busy, then came in this morning(monday) and blocked the > remaining. This sitting around watching log files and blocking > addresses doesn't solve the underlying problem in that I need to be > able to just block an ip after so many attempts. > > I used to use a 3rd party FTP server back on NT/2000 because I read at > how horrible IIS was, but as soon as I got Server 2003, I switched to > IIS's FTP. But good lord, this isn't what I call secure when its just > a matter of time before they hit the right combination, no matter how > long/complex I've made my users passwords(which, they've already > complained about). > > If any of the IIS team are reading this, give us a "Maximum Password > Tries" and a "Block for how many minutes" capability. Reset the list > when IIS is restarted if you want, but, give us some simple to > configure tools to help curb this problem. > > Simple? Don't use FTP. That's the only real solution that is also simple. Not very simple if you have old softwares that sending trackinginformation via FTP up to the server that where written back in 1996 and do not lend themselves to be upgraded. Combined with several web sites that we host that have various companies updating their sites. We do have some of our demos available for FTP download, I could certainly close down that FTP site, but it still leaves several others that really have to stay online without deticating a huge amount of resources to rewriting applications and retraining people that have been happy and healthy for 10 years now. This is indeed a need without a defined response capability in Windows
(and not just for FTP auth attempts). Some form of host based IPS (intrusion prevention) within Windows would be welcome. However, I am concerned in that your post seemed to indicate a worry that one of these may find the right password, which in turn implies you are seeing attempts using valid account names. I deal with runs of auth attempts, but they are dumb (even attempting login with built-in group names!!) and mostly just bandwidth and cpu cycle pests. If you must have the exposures the pests probe, and you have no form of IPS that can detect and block, then you live with it. If however you are seeing valid account names attempted you do definitely need to examine all aspects of your exposure to the network. Roger <nx-2***@winvoice.com> wrote in message Show quoteHide quote news:1159194370.931660.227810@m7g2000cwm.googlegroups.com... > I've done quite a bit of searching on this and I haven't found a > satisfactory answer besides a few expensive add-on packages. I'm > hoping someone has some ideas. > > Basically, I'm getting brute forced to death on my IIS FTP sites. They > haven't found their way in yet, but, this weekend, I had 11 different > ip addresses(one in the US, several in Korea, one in Argentena, several > in China, etc) hitting my two different servers(on two different > networks) at a rate of about 25 password attempts per second. I came > in on saturday, blocked(via ip security policy) the 4 addresses that > where busy, then came in this morning(monday) and blocked the > remaining. This sitting around watching log files and blocking > addresses doesn't solve the underlying problem in that I need to be > able to just block an ip after so many attempts. > > I used to use a 3rd party FTP server back on NT/2000 because I read at > how horrible IIS was, but as soon as I got Server 2003, I switched to > IIS's FTP. But good lord, this isn't what I call secure when its just > a matter of time before they hit the right combination, no matter how > long/complex I've made my users passwords(which, they've already > complained about). > > If any of the IIS team are reading this, give us a "Maximum Password > Tries" and a "Block for how many minutes" capability. Reset the list > when IIS is restarted if you want, but, give us some simple to > configure tools to help curb this problem. > Upon leaving for the day, I checked logs and promptly shut down another
attack, then, before I could leave, another ip address took over, and another and another for about 20 addresses. So, now, a couple of frustrating hours later, I'd like to share the source code of what I pieced together from various code chunks around the net. I've got the IISBlockFTPAttempts class used in another app that runs on a schedule anyway but used this test console app when I was debugging which someone could set up in scheduler or adapt it to anything else. It simply runs through each of the FTP sites, checks for bad password entries in the logs for the day, counts them up, if the number of attempts from an ip address exceeds a given number, then it adds that ip address to the denied addresses for all the FTP sites. using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Reflection; using System.Threading; using System.Xml; using System.DirectoryServices; using System.IO; namespace IISBlock { /// <summary> /// Summary description for Class1. /// </summary> class Class1 { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { Console.WriteLine("Starting"); IISBlockFTPAttempts ftpb=new IISBlockFTPAttempts("WEBSERVER1","MyAdmin","MyAdminPass",30); ftpb.GetBlockList(); ftpb.FTPBlock(); //ftpb.Remove.Add("10.10.10.8"); //ftpb.FTPRemove(); //ftpb.Blocked.Add("10.10.10.8"); //ftpb.FTPBlock(); Console.WriteLine("Finished"); } } public class IISBlockFTPAttempts { private string ServerName; private string ServerUserName; private string ServerPassword; private int AttemptsBeforeKill; public ArrayList Blocked=new ArrayList(); public ArrayList Remove=new ArrayList(); public IISBlockFTPAttempts(string ServerName,string ServerUserName,string ServerPassword,int AttemptsBeforeKill) { this.ServerName=ServerName; this.ServerUserName=ServerUserName; this.ServerPassword=ServerPassword; this.AttemptsBeforeKill=AttemptsBeforeKill; } public void GetBlockList() { SortedList ht=new SortedList(); DateTime dt=DateTime.Now; string FileName="ex"+(dt.Year-2000).ToString("00")+dt.Month.ToString("00")+dt.Day.ToString("00")+".log"; DirectoryEntry root = new DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC",ServerUserName,ServerPassword); foreach (DirectoryEntry IIS in root.Children) { if (IIS.SchemaClassName == "IIsFtpServer") { Console.WriteLine(IIS.Name); string LogFilePath = System.IO.Path.Combine( IIS.Properties["LogFileDirectory"].Value.ToString(), "MSFTPSVC"+IIS.Name); string LogFileName=LogFilePath+"\\"+FileName; Console.WriteLine(LogFileName); if(File.Exists(LogFileName)) { FileStream fs=new FileStream(LogFileName,FileMode.Open,FileAccess.ReadWrite); StreamReader sr=new StreamReader(fs); string s; while((s=sr.ReadLine())!=null) { if(s.IndexOf("PASS - 530")!=-1) { string[] fields=s.Split(' '); if(fields.Length>1) { string ip=fields[1].Trim(); if(ht.ContainsKey(ip)) ht[ip]=((int)ht[ip])+1; else ht.Add(ip,(int)1); } } } sr.Close(); fs.Close(); } IIS.Close(); //IIS.Dispose(); } } root.Close(); //root.Dispose(); for(int i=0;i<ht.Count;i++) { string ip=(string)ht.GetKey(i); if((int)ht[ip]>AttemptsBeforeKill) Blocked.Add(ip); } } public void FTPBlock() { DirectoryEntry root = new DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC",ServerUserName,ServerPassword); foreach (DirectoryEntry site in root.Children) { if (site.SchemaClassName == "IIsFtpServer") { Console.WriteLine(site.Name); DirectoryEntry IIS = new DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC/"+site.Name+"/root",ServerUserName,ServerPassword); Type typ = IIS.Properties["IPSecurity"][0].GetType(); object IPSecurity = IIS.Properties["IPSecurity"][0]; Array origIPDenyList = (Array) typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null); Array.Sort(origIPDenyList); ArrayList ToAdd=new ArrayList(); for(int i=0;i<Blocked.Count;i++) { string block=Blocked[i]+", 255.255.255.255"; bool bAlreadyDone=false; foreach(string s in origIPDenyList) { if(s==block) { Console.WriteLine(s+" = "+block); bAlreadyDone=true; } } if(bAlreadyDone==false) { ToAdd.Add(block); Console.WriteLine("Adding "+block); } } if(ToAdd.Count>0) { bool bGrantByDefault = (bool) typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null); if(!bGrantByDefault) { typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] {true}); } object[] newIPDenyList = new object[origIPDenyList.Length+ToAdd.Count]; int i=0; foreach(string s in origIPDenyList) { newIPDenyList[i]=s; i++; } for(int x=0;x<ToAdd.Count;x++) { newIPDenyList[i]=(string)ToAdd[x]; i++; } Array.Sort(newIPDenyList); typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] {newIPDenyList}); IIS.Properties["IPSecurity"][0] = IPSecurity; // commit the changes IIS.CommitChanges(); //IIS.RefreshCache(); IIS.Close(); //IIS.Dispose(); Console.WriteLine("Added"); } else Console.WriteLine("None to add"); } } root.CommitChanges(); root.Close(); //root.Dispose(); } public void FTPRemove() { DirectoryEntry root = new DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC",ServerUserName,ServerPassword); foreach (DirectoryEntry site in root.Children) { if (site.SchemaClassName == "IIsFtpServer") { Console.WriteLine(site.Name); DirectoryEntry IIS = new DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC/"+site.Name+"/root",ServerUserName,ServerPassword); Type typ = IIS.Properties["IPSecurity"][0].GetType(); object IPSecurity = IIS.Properties["IPSecurity"][0]; Array origIPDenyList = (Array) typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null); Array.Sort(origIPDenyList); ArrayList ToRemove=new ArrayList(); for(int i=0;i<Remove.Count;i++) { string block=Remove[i]+", 255.255.255.255"; bool bAlreadyDone=false; foreach(string s in origIPDenyList) { if(s==block) { Console.WriteLine(s+" = "+block); bAlreadyDone=true; } Console.WriteLine("* "+s); } if(bAlreadyDone==true) { ToRemove.Add(block); Console.WriteLine("Removing "+block); } } if(ToRemove.Count>0) { bool bGrantByDefault = (bool) typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null); if(!bGrantByDefault) { typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] {true}); } object[] newIPDenyList = new object[origIPDenyList.Length-ToRemove.Count]; int i=0; foreach(string s in origIPDenyList) { if(!ToRemove.Contains(s)) { newIPDenyList[i]=s; i++; } } Array.Sort(newIPDenyList); typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] {newIPDenyList}); IIS.Properties["IPSecurity"][0] = IPSecurity; // commit the changes IIS.CommitChanges(); //IIS.RefreshCache(); IIS.Close(); //IIS.Dispose(); Console.WriteLine("Removed"); } else Console.WriteLine("None to remove"); } } root.CommitChanges(); root.Close(); //root.Dispose(); } } } Nice. You now have me thinking of extending this in two ways.
Reading other logs (security and IIS http), and adding address to a "block pest" IPsec filter. Thanks for sharing. Roger <nx-2***@winvoice.com> wrote in message Show quoteHide quote news:1160712937.173534.177240@i3g2000cwc.googlegroups.com... > Upon leaving for the day, I checked logs and promptly shut down another > attack, then, before I could leave, another ip address took over, and > another and another for about 20 addresses. > > So, now, a couple of frustrating hours later, I'd like to share the > source code of what I pieced together from various code chunks around > the net. I've got the IISBlockFTPAttempts class used in another app > that runs on a schedule anyway but used this test console app when I > was debugging which someone could set up in scheduler or adapt it to > anything else. It simply runs through each of the FTP sites, checks > for bad password entries in the logs for the day, counts them up, if > the number of attempts from an ip address exceeds a given number, then > it adds that ip address to the denied addresses for all the FTP sites. > > using System; > using System.Collections; > using System.Collections.Specialized; > using System.ComponentModel; > using System.Data; > using System.Diagnostics; > using System.Reflection; > using System.Threading; > using System.Xml; > using System.DirectoryServices; > using System.IO; > > namespace IISBlock > { > /// <summary> > /// Summary description for Class1. > /// </summary> > class Class1 > { > /// <summary> > /// The main entry point for the application. > /// </summary> > [STAThread] > static void Main(string[] args) > { > Console.WriteLine("Starting"); > IISBlockFTPAttempts ftpb=new > IISBlockFTPAttempts("WEBSERVER1","MyAdmin","MyAdminPass",30); > > ftpb.GetBlockList(); > ftpb.FTPBlock(); > > //ftpb.Remove.Add("10.10.10.8"); > //ftpb.FTPRemove(); > > //ftpb.Blocked.Add("10.10.10.8"); > //ftpb.FTPBlock(); > > Console.WriteLine("Finished"); > } > } > public class IISBlockFTPAttempts > { > private string ServerName; > private string ServerUserName; > private string ServerPassword; > private int AttemptsBeforeKill; > public ArrayList Blocked=new ArrayList(); > public ArrayList Remove=new ArrayList(); > > public IISBlockFTPAttempts(string ServerName,string > ServerUserName,string ServerPassword,int AttemptsBeforeKill) > { > this.ServerName=ServerName; > this.ServerUserName=ServerUserName; > this.ServerPassword=ServerPassword; > this.AttemptsBeforeKill=AttemptsBeforeKill; > } > public void GetBlockList() > { > SortedList ht=new SortedList(); > DateTime dt=DateTime.Now; > string > FileName="ex"+(dt.Year-2000).ToString("00")+dt.Month.ToString("00")+dt.Day.ToString("00")+".log"; > DirectoryEntry root = new > DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC",ServerUserName,ServerPassword); > foreach (DirectoryEntry IIS in root.Children) > { > if (IIS.SchemaClassName == "IIsFtpServer") > { > Console.WriteLine(IIS.Name); > string LogFilePath = System.IO.Path.Combine( > IIS.Properties["LogFileDirectory"].Value.ToString(), > "MSFTPSVC"+IIS.Name); > string LogFileName=LogFilePath+"\\"+FileName; > Console.WriteLine(LogFileName); > if(File.Exists(LogFileName)) > { > FileStream fs=new > FileStream(LogFileName,FileMode.Open,FileAccess.ReadWrite); > StreamReader sr=new StreamReader(fs); > string s; > while((s=sr.ReadLine())!=null) > { > if(s.IndexOf("PASS - 530")!=-1) > { > string[] fields=s.Split(' '); > if(fields.Length>1) > { > string ip=fields[1].Trim(); > if(ht.ContainsKey(ip)) > ht[ip]=((int)ht[ip])+1; > else > ht.Add(ip,(int)1); > } > } > } > sr.Close(); > fs.Close(); > } > IIS.Close(); > //IIS.Dispose(); > } > } > root.Close(); > //root.Dispose(); > for(int i=0;i<ht.Count;i++) > { > string ip=(string)ht.GetKey(i); > if((int)ht[ip]>AttemptsBeforeKill) > Blocked.Add(ip); > } > } > public void FTPBlock() > { > DirectoryEntry root = new > DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC",ServerUserName,ServerPassword); > foreach (DirectoryEntry site in root.Children) > { > if (site.SchemaClassName == "IIsFtpServer") > { > Console.WriteLine(site.Name); > DirectoryEntry IIS = new > DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC/"+site.Name+"/root",ServerUserName,ServerPassword); > Type typ = IIS.Properties["IPSecurity"][0].GetType(); > object IPSecurity = IIS.Properties["IPSecurity"][0]; > > Array origIPDenyList = (Array) typ.InvokeMember("IPDeny", > BindingFlags.DeclaredOnly | > BindingFlags.Public | BindingFlags.NonPublic | > BindingFlags.Instance | BindingFlags.GetProperty, > null, IPSecurity, null); > > Array.Sort(origIPDenyList); > > ArrayList ToAdd=new ArrayList(); > for(int i=0;i<Blocked.Count;i++) > { > string block=Blocked[i]+", 255.255.255.255"; > bool bAlreadyDone=false; > foreach(string s in origIPDenyList) > { > if(s==block) > { > Console.WriteLine(s+" = "+block); > bAlreadyDone=true; > } > } > if(bAlreadyDone==false) > { > ToAdd.Add(block); > Console.WriteLine("Adding "+block); > } > } > if(ToAdd.Count>0) > { > bool bGrantByDefault = (bool) typ.InvokeMember("GrantByDefault", > BindingFlags.DeclaredOnly | > BindingFlags.Public | BindingFlags.NonPublic | > BindingFlags.Instance | BindingFlags.GetProperty, > null, IPSecurity, null); > > if(!bGrantByDefault) > { > typ.InvokeMember("GrantByDefault", > BindingFlags.DeclaredOnly | > BindingFlags.Public | BindingFlags.NonPublic | > BindingFlags.Instance | BindingFlags.SetProperty, > null, IPSecurity, new object[] {true}); > } > > object[] newIPDenyList = new > object[origIPDenyList.Length+ToAdd.Count]; > int i=0; > foreach(string s in origIPDenyList) > { > newIPDenyList[i]=s; > i++; > } > for(int x=0;x<ToAdd.Count;x++) > { > newIPDenyList[i]=(string)ToAdd[x]; > i++; > } > Array.Sort(newIPDenyList); > > typ.InvokeMember("IPDeny", > BindingFlags.DeclaredOnly | > BindingFlags.Public | BindingFlags.NonPublic | > BindingFlags.Instance | BindingFlags.SetProperty, > null, IPSecurity, new object[] {newIPDenyList}); > > IIS.Properties["IPSecurity"][0] = IPSecurity; > > // commit the changes > IIS.CommitChanges(); > //IIS.RefreshCache(); > IIS.Close(); > //IIS.Dispose(); > Console.WriteLine("Added"); > } > else > Console.WriteLine("None to add"); > } > } > root.CommitChanges(); > root.Close(); > //root.Dispose(); > } > public void FTPRemove() > { > DirectoryEntry root = new > DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC",ServerUserName,ServerPassword); > foreach (DirectoryEntry site in root.Children) > { > if (site.SchemaClassName == "IIsFtpServer") > { > Console.WriteLine(site.Name); > DirectoryEntry IIS = new > DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC/"+site.Name+"/root",ServerUserName,ServerPassword); > > Type typ = IIS.Properties["IPSecurity"][0].GetType(); > object IPSecurity = IIS.Properties["IPSecurity"][0]; > > Array origIPDenyList = (Array) typ.InvokeMember("IPDeny", > BindingFlags.DeclaredOnly | > BindingFlags.Public | BindingFlags.NonPublic | > BindingFlags.Instance | BindingFlags.GetProperty, > null, IPSecurity, null); > > Array.Sort(origIPDenyList); > ArrayList ToRemove=new ArrayList(); > for(int i=0;i<Remove.Count;i++) > { > string block=Remove[i]+", 255.255.255.255"; > bool bAlreadyDone=false; > foreach(string s in origIPDenyList) > { > if(s==block) > { > Console.WriteLine(s+" = "+block); > bAlreadyDone=true; > } > Console.WriteLine("* "+s); > } > if(bAlreadyDone==true) > { > ToRemove.Add(block); > Console.WriteLine("Removing "+block); > } > } > if(ToRemove.Count>0) > { > bool bGrantByDefault = (bool) typ.InvokeMember("GrantByDefault", > BindingFlags.DeclaredOnly | > BindingFlags.Public | BindingFlags.NonPublic | > BindingFlags.Instance | BindingFlags.GetProperty, > null, IPSecurity, null); > > if(!bGrantByDefault) > { > typ.InvokeMember("GrantByDefault", > BindingFlags.DeclaredOnly | > BindingFlags.Public | BindingFlags.NonPublic | > BindingFlags.Instance | BindingFlags.SetProperty, > null, IPSecurity, new object[] {true}); > } > > object[] newIPDenyList = new > object[origIPDenyList.Length-ToRemove.Count]; > int i=0; > > foreach(string s in origIPDenyList) > { > if(!ToRemove.Contains(s)) > { > newIPDenyList[i]=s; > i++; > } > } > Array.Sort(newIPDenyList); > > typ.InvokeMember("IPDeny", > BindingFlags.DeclaredOnly | > BindingFlags.Public | BindingFlags.NonPublic | > BindingFlags.Instance | BindingFlags.SetProperty, > null, IPSecurity, new object[] {newIPDenyList}); > > IIS.Properties["IPSecurity"][0] = IPSecurity; > > // commit the changes > IIS.CommitChanges(); > //IIS.RefreshCache(); > IIS.Close(); > //IIS.Dispose(); > Console.WriteLine("Removed"); > } > else > Console.WriteLine("None to remove"); > } > } > root.CommitChanges(); > root.Close(); > //root.Dispose(); > } > } > } > > Nice. You now have me thinking of extending this in two ways. I did the IPSec stuff last week due to a new string of attacks...> Reading other logs (security and IIS http), and adding address > to a "block pest" IPsec filter. using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Reflection; using System.Threading; using System.Xml; using System.DirectoryServices; using System.IO; using System.Text; using IISLog; namespace IISBlock { class Class1 { [STAThread] static void Main(string[] args) { Console.WriteLine("Starting"); FTPBlock ftpb=new FTPBlock("MyWebServer","MyAdmin","MyPassword"); ftpb.GetBlock(DateTime.Now,10); ftpb.Block(); IPSecBlock ipsb=new IPSecBlock("MyIPSecRule"); ipsb.GetBlock(DateTime.Now,10); ipsb.Block(); Console.WriteLine("Finished"); } } public class IPSecBlock { private string FilterList; public ArrayList Blocked=new ArrayList(); public ArrayList Removed=new ArrayList(); public ArrayList Errors=new ArrayList(); public IPSecBlock(string FilterList) { this.FilterList=FilterList; } public void Block() { if(Blocked.Count==0) return; for(int i=0;i<Blocked.Count;i++) AddFilter(FilterList,(string)Blocked[i]); } private void AddFilter(string FilterList,string ip) { ProcessStartInfo pi = new ProcessStartInfo("netsh"); pi.Arguments = "ipsec static add filter filterlist="+FilterList+" \"description="+ip+" on "+DateTime.Now.ToShortDateString()+"\" srcaddr="+ip+" dstaddr=Me protocol=any mirrored=yes"; pi.WindowStyle = ProcessWindowStyle.Hidden; Console.WriteLine("netsh "+pi.Arguments); System.Diagnostics.Process.Start(pi); } public void GetBlock(DateTime dt,int AttemptsBeforeKill) { SortedList ht=new SortedList(); EventLog el=new EventLog("Security"); for(int i=0;i<el.Entries.Count;i++) { EventLogEntry en=el.Entries[i]; if(en.EventID==529 && en.TimeGenerated>=dt.AddMinutes(-15)) { int g=en.Message.IndexOf("Source Network Address:"); if(g!=-1) { string ip=en.Message.Substring(g); ip=ip.Replace("Source Network Address:",""); g=ip.IndexOf("\n"); if(g!=-1) ip=ip.Substring(0,g); g=ip.IndexOf("\r"); if(g!=-1) ip=ip.Substring(0,g); ip=ip.Trim(); if(ip.Length>0 && ip.IndexOf("10.")!=0) // filter out my internal addresses { if(ht.ContainsKey(ip)) ht[ip]=((int)ht[ip])+1; else ht.Add(ip,(int)1); } } } } for(int i=0;i<ht.Count;i++) { string ip=(string)ht.GetKey(i); if((int)ht[ip]>AttemptsBeforeKill) Blocked.Add(ip); } } } public class FTPBlock { private string ServerName; private string ServerUserName; private string ServerPassword; public ArrayList Blocked=new ArrayList(); public ArrayList Removed=new ArrayList(); public ArrayList Errors=new ArrayList(); public FTPBlock(string ServerName,string ServerUserName,string ServerPassword) { this.ServerName=ServerName; this.ServerUserName=ServerUserName; this.ServerPassword=ServerPassword; } public void GetBlock(DateTime dt,int AttemptsBeforeKill) { SortedList ht=new SortedList(); string FileName="ex"+(dt.Year-2000).ToString("00")+dt.Month.ToString("00")+dt.Day.ToString("00")+".log"; DirectoryEntry root = new DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC",ServerUserName,ServerPassword); foreach (DirectoryEntry IIS in root.Children) { if (IIS.SchemaClassName == "IIsFtpServer") { string LogFilePath = System.IO.Path.Combine( IIS.Properties["LogFileDirectory"].Value.ToString(), "MSFTPSVC"+IIS.Name); string LogFileName=LogFilePath+"\\"+FileName; if(File.Exists(LogFileName)) { try { IISLog.LogScriptingClass l=new IISLog.LogScriptingClass(); l.OpenLogFile(LogFileName,IOMode.ForReading,"MSFTPSVC",1,"0"); while(!l.AtEndOfLog()) { l.ReadLogRecord(); if(l.ProtocolStatus!=null) { if(l.ProtocolStatus.ToString()=="530") { string ip=l.ClientIP.ToString(); if(ht.ContainsKey(ip)) ht[ip]=((int)ht[ip])+1; else ht.Add(ip,(int)1); } } } l.CloseLogFiles(IOMode.AllOpenFiles); } catch(Exception ex) { Errors.Add(ex.Message.ToString()); } /* try { FileStream fs=new FileStream(LogFileName,FileMode.Open,FileAccess.Read,FileShare.ReadWrite); StreamReader sr=new StreamReader(fs); string s; while((s=sr.ReadLine())!=null) { if(s.IndexOf("PASS - 530")!=-1) { string[] fields=s.Split(' '); if(fields.Length>1) { string ip=fields[1].Trim(); if(ht.ContainsKey(ip)) ht[ip]=((int)ht[ip])+1; else ht.Add(ip,(int)1); } } } sr.Close(); fs.Close(); } catch(Exception ex) { Errors.Add("Can't open "+LogFileName"+ex.Message.ToString()); } */ } IIS.Close(); //IIS.Dispose(); } } root.Close(); //root.Dispose(); for(int i=0;i<ht.Count;i++) { string ip=(string)ht.GetKey(i); if((int)ht[ip]>AttemptsBeforeKill) Blocked.Add(ip); } } public void Block() { bool bDidOne=false; if(Blocked.Count==0) return; DirectoryEntry root = new DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC",ServerUserName,ServerPassword); foreach (DirectoryEntry site in root.Children) { if (site.SchemaClassName == "IIsFtpServer") { DirectoryEntry IIS = new DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC/"+site.Name+"/root",ServerUserName,ServerPassword); Type typ = IIS.Properties["IPSecurity"][0].GetType(); object IPSecurity = IIS.Properties["IPSecurity"][0]; Array origIPDenyList = (Array) typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null); Array.Sort(origIPDenyList); ArrayList ToAdd=new ArrayList(); for(int i=0;i<Blocked.Count;i++) { string block=Blocked[i]+", 255.255.255.255"; bool bAlreadyDone=false; foreach(string s in origIPDenyList) { if(s==block) bAlreadyDone=true; } if(bAlreadyDone==false) ToAdd.Add(block); } if(ToAdd.Count>0) { bool bGrantByDefault = (bool) typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null); if(!bGrantByDefault) { typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] {true}); } object[] newIPDenyList = new object[origIPDenyList.Length+ToAdd.Count]; int i=0; foreach(string s in origIPDenyList) { newIPDenyList[i]=s; i++; } for(int x=0;x<ToAdd.Count;x++) { newIPDenyList[i]=(string)ToAdd[x]; i++; } Array.Sort(newIPDenyList); typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] {newIPDenyList}); IIS.Properties["IPSecurity"][0] = IPSecurity; // commit the changes IIS.CommitChanges(); //IIS.RefreshCache(); IIS.Close(); //IIS.Dispose(); StopSite(site.Name); StartSite(site.Name); bDidOne=true; } } } root.CommitChanges(); root.Close(); //root.Dispose(); if(bDidOne==true) { StopSite(""); StartSite(""); } } public void Remove() { bool bDidOne=false; if(Removed.Count==0) return; DirectoryEntry root = new DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC",ServerUserName,ServerPassword); foreach (DirectoryEntry site in root.Children) { if (site.SchemaClassName == "IIsFtpServer") { DirectoryEntry IIS = new DirectoryEntry("IIS://"+ServerName+"/MSFTPSVC/"+site.Name+"/root",ServerUserName,ServerPassword); Type typ = IIS.Properties["IPSecurity"][0].GetType(); object IPSecurity = IIS.Properties["IPSecurity"][0]; Array origIPDenyList = (Array) typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null); Array.Sort(origIPDenyList); ArrayList ToRemove=new ArrayList(); for(int i=0;i<Removed.Count;i++) { string block=Removed[i]+", 255.255.255.255"; bool bAlreadyDone=false; foreach(string s in origIPDenyList) { if(s==block) bAlreadyDone=true; } if(bAlreadyDone==true) ToRemove.Add(block); } if(ToRemove.Count>0) { bool bGrantByDefault = (bool) typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null); if(!bGrantByDefault) { typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] {true}); } object[] newIPDenyList = new object[origIPDenyList.Length-ToRemove.Count]; int i=0; foreach(string s in origIPDenyList) { if(!ToRemove.Contains(s)) { newIPDenyList[i]=s; i++; } } Array.Sort(newIPDenyList); typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] {newIPDenyList}); IIS.Properties["IPSecurity"][0] = IPSecurity; // commit the changes IIS.CommitChanges(); //IIS.RefreshCache(); IIS.Close(); //IIS.Dispose(); StopSite(site.Name); StartSite(site.Name); bDidOne=true; } } } root.CommitChanges(); root.Close(); //root.Dispose(); if(bDidOne==true) { StopSite(""); StartSite(""); } } public void StartSite(string siteName) { try { string site="IIS://"+ServerName+"/MSFTPSVC/"+siteName; if(siteName.Length==0) site="IIS://"+ServerName+"/MSFTPSVC"; Console.WriteLine("Starting "+site); DirectoryEntry siteEntry = new DirectoryEntry(site,ServerUserName,ServerPassword); siteEntry.Invoke("Start", new object[] {}); siteEntry.CommitChanges(); siteEntry.Close(); Console.WriteLine("Started "+site); } catch(Exception ex) { Console.WriteLine(ex.Message.ToString()); } } public void StopSite(string siteName) { try { string site="IIS://"+ServerName+"/MSFTPSVC/"+siteName; if(siteName.Length==0) site="IIS://"+ServerName+"/MSFTPSVC"; Console.WriteLine("Stopping "+site); DirectoryEntry siteEntry = new DirectoryEntry(site,ServerUserName,ServerPassword); siteEntry.Invoke("Stop", new object[] {}); siteEntry.CommitChanges(); siteEntry.Close(); Console.WriteLine("Stopped "+site); } catch(Exception ex) { Console.WriteLine(ex.Message.ToString()); } } } }
Implications of a SSL site as a virtual directory rather than a root website?
error message SPN for SSL over common name Can't save password if Integrated Authentication is used Accessing a web application anonymously Internet Access on an SBS 2003 Install Allow anonymous access between times Certificate Service Button SSL on a different IP Configuring SSL Host Headers in IIS 6 W2K3 SP1 |
|||||||||||||||||||||||