|
Introduction
Over the course of a few days, I've been spending a lot of time trying to secure my personal web server. I have used the IISLockDown tool and installed the latest URLScan. Since that time, I've been looking through my IIS logs and have found entries where people have been attempting to get into my system, either intentionally or because they've fallen victim to a "worm" or virus. It's annoying to see so many entries in my logs of where attacks have occurred.
So, one day as I was browsing other sites similar to CodeProject, I came across a snippet of code someone wrote to automatically report abuse to the ISP that owns the IP address of where the attack originated from. So, after modifying the code quite a bit to fit my needs, I got it up and running. Of course, the next thing I wanted to do was to ban these reported IP addresses from my site, hence this article.
Before I go any further, let me state that there are a few downsides with the approach I'm taking here to add additional "security" to my personal web server:
- only the "kid" hackers using daddy's computer will get caught because they don't spoof their IP addresses
- the prevalence of dynamic IPs foils the blocking of reported IPs attempting to be malicious
- This does nothing for new types of attacks since this solution is dependant on what URLScan knows.
- It's a reactive response to an attack that has already occurred.
With that said, it was still an interesting exercise.
The Catch
In order to gain access to the IIS server for my project, you have to use Windows Management Instrumentation (WMI) and Active Directory Service Interfaces (ADSI). For a general overview of these two items, refer to the MSDN website.
Since I've never worked with WMI, the first thing I did was look for examples. I found a few, but what I found were in VBScript. I'm not sure why, other than administrators wanting to write a few quick scripts to get something done or maybe it has something to do with the fact that you have to use late binding. I've had to work with objects that were late bound in ATL, and it was not fun. VB/VBScript makes it quite easy to do (which may be why I saw so many examples in VB). Anyway, I've never really had to do anything with late binding in C#, so it took me a few minutes to get acquainted with it. For those of you not familiar with early vs late binding, check here for an explanation:
http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q245/1/15.ASP&NoWebContent=1
Parameter passing and method execution are lots of fun if you're not used to it if late binding is involved.
The Codeusing System;
using System.IO;
using System.Collections;
using System.DirectoryServices;
using System.Reflection;
namespace soccerwrek
{
class IISWMI
{
[STAThread]
static void Main(string[] args)
{
try
{
System.DirectoryServices.DirectoryEntry IIS =
new System.DirectoryServices.DirectoryEntry(
"IIS://localhost/w3svc/1/root");
Console.WriteLine(
"Retrieving the list of currently denied IPs.");
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);
foreach(string s in origIPDenyList)
Console.WriteLine("Before: " + s);
bool bGrantByDefault = (bool) typ.InvokeMember("GrantByDefault",
BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.GetProperty,
null, IPSecurity, null);
Console.WriteLine("GrantByDefault = " + bGrantByDefault);
if(!bGrantByDefault)
{
typ.InvokeMember("GrantByDefault",
BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.SetProperty,
null, IPSecurity, new object[] {true});
}
Console.WriteLine("Updating the list of denied IPs.");
object[] newIPDenyList = new object[4];
newIPDenyList[0] = "192.168.1.1, 255.255.255.255";
newIPDenyList[1] = "192.168.1.2, 255.255.255.255";
newIPDenyList[2] = "192.168.1.3, 255.255.255.255";
newIPDenyList[3] = "192.168.1.4, 255.255.255.255";
Console.WriteLine("Calling SetProperty");
typ.InvokeMember("IPDeny",
BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.SetProperty,
null, IPSecurity, new object[] {newIPDenyList});
IIS.Properties["IPSecurity"][0] = IPSecurity;
Console.WriteLine("Commiting the changes.");
IIS.CommitChanges();
IIS.RefreshCache();
Console.WriteLine("Checking to see if the update took.");
IPSecurity = IIS.Properties["IPSecurity"][0];
Array y = (Array) typ.InvokeMember("IPDeny",
BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.GetProperty,
null, IPSecurity, null);
foreach(string s in y)
Console.WriteLine("After: " + s);
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.ToString());
}
}
}
}
In Closing
As you can see it's not terribly difficult or complicated. The hardest part of this exercise is just looking up what you need to know and putting it all together.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 22 of 22 (Total in Forum: 22) (Refresh) | FirstPrevNext |
|
|
 |
|
|
Where is this other article that you found? 
"automatically report abuse to the ISP that owns the IP address of where the attack originated from."
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, Great code thanks, but I think there is a simpler way to this. If you add a COM reference in your project to "Active DS IIS Namespace Provider" you can get the late binding stuff done for you by VS consuming the type library in the dll you just referenced. The code to view the IP Grant list could be simplified to :
DirectoryEntry IISAdmin = new DirectoryEntry(metabasePath); IISOle.IISIPSecurity iisipsec = (IISOle.IISIPSecurity)IISAdmin.Properties["IPSecurity"].Value; if (!iisipsec.GrantByDefault) { Array IPGrantList = (Array)iisipsec.IPGrant; foreach (string IP in IPGrantList) { //do what you want with the IP } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
could you please give all the code how to create new stie withouth going to iis console window and also how to start and stop the site.
best appreciate.
boa_sovann
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi
i have this spider-trap (php code) to get the bad spider ip-number and all the bad spider ipnumber is store in blacklist.txt...so now i wonder how i can use this deny script to look into the blacklist.txt and take all the ipnumber and put into the deny list in IIS...or do i have to manualy put the all the ipnumber in this line newIPDenyList[0] = "192.168.1.1, 255.255.255.255";
Peter
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Well, if you've written some PHP code to dump the bad IP addresses to a text file, then you just need to modify the code above to read in that file you've created. As you iterate through each line of the file, grabbing the bad IP address, you would then add the IP address to the newIPDenyList array (incrementing the index with each new IP address).
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi I did not write that php-code...i found it on internet about hot to trap bad robot spider...
Sooo..is there anyone who can modify the above code so it can take the bad ip adress from the text file blacklist.and put it on a new newIPDenyList array?? peter
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
On IIS, i have created a new site instead of using the default website. What changes would i need to make inorder to make the application work. Thanks for your response.
If i run the code as is, it gives an exception with "path cannot be found"
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
System.DirectoryServices.DirectoryEntry IIS = new System.DirectoryServices.DirectoryEntry( "IIS://localhost/w3svc/1/root");
Where the 1 is, you would change that to a 2 or a 3 or a 4, depending on which site you just created.
sorry it took SO long to respond. I don't ever think I got the email stating that a comment was posted here.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Are you aware of any documentation listing all of the members and properties you can invoke using this method for IIS?
Thanks.
-Matt
------------------------------------------
The 3 great virtues of a programmer: Laziness, Impatience, and Hubris. --Larry Wall
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I would start here: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iissdk/iis/ref_prog_iaoref.asp
Unfortunately, I don't think it's going to be as easy as "here is the documentation for the method/property and here's the exact code snippet to use to call it." That's what made this article a little tricky to work on in the first place.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
HI auther Thanks for this article . I have a WMI sample in VC++ which enumerates local services ( using //./root/cimv2 input) . But when I try to connect to remote machine the pWbemLocater-->ConnectServer() fails . I am using XP machine and the remote machine is also XP. So I have a user name Dharani and password xxxxx with administrator rights . The same way I set up another user account with the same USer name and password in the remote machine ( Is it necessary to have the same USer name /passwrod at the remote machine ? ) But still the remote connection is not happening . How to solve it ? What r the real previleges needed at the target system ?? could u point it out ?? PS : When I try to connect to a system in my IP group - thats if my IP is 210.210.124.xxx and remote machine's IP is 210.210.124.xxy it fails in milliseconds and returns but in case if the remote machine's IP is differing to another layer like 210.210.12x.xfg then the pWbemLocator-->ConnectServer() takes a big 8-9 seconds to return to say it failed !!!! I hope this will be a terrible effect on my C/S design to query WMI machines . any ideas pls ??
regards and thanks in advance dharani babu
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi there,
Thank you for you article. I need to add values to IIS MIME table programmatically. Any ideas ?
Cheers,
Seth.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Adding and deleting coudl look like this
Public Class IISAdministration Public Sub AddMIMEType(ByVal DirectoryName, ByVal MIMEExtension, ByVal MIMEType) Dim MMItem, MimeMapObj, aMimeMap, MMType, MMExtension, i, aMimeMapNew() Const ADS_PROPERTY_UPDATE = 2 'Get the mimemap object. Try MimeMapObj = GetObject("IIS://LocalHost/W3SVC/1/ROOT/" & DirectoryName) Catch ex As Exception Exit Sub End Try
'Get the mappings from the MimeMap property. aMimeMap = MimeMapObj.GetEx("MimeMap")
For Each MMItem In aMimeMap If MMItem.Extension = MIMEExtension Then Exit Sub End If Next
i = UBound(aMimeMap) + 1 ReDim Preserve aMimeMap(i) aMimeMap(i) = CreateObject("MimeMap") aMimeMap(i).Extension = MIMEExtension aMimeMap(i).MimeType = MIMEType MimeMapObj.PutEx(ADS_PROPERTY_UPDATE, "MimeMap", aMimeMap) MimeMapObj.SetInfo() End Sub Public Sub DeleteMIMEType(ByVal DirectoryName, ByVal MIMEExtension) Dim MMItem, MimeMapObj, aMimeMap, MMType, MMExtension, i, aMimeMapNew() Const ADS_PROPERTY_CLEAR = 1 Const ADS_PROPERTY_UPDATE = 2 'Get the mimemap object. Try MimeMapObj = GetObject("IIS://LocalHost/W3SVC/1/ROOT/" & DirectoryName) Catch ex As Exception Exit Sub End Try
'Get the mappings from the MimeMap property. aMimeMap = MimeMapObj.GetEx("MimeMap") i = 0 Dim found = False For Each MMItem In aMimeMap If MMItem.Extension <> MIMEExtension Then found = True ReDim Preserve aMimeMapNew(i) aMimeMapNew(i) = CreateObject("MimeMap") aMimeMapNew(i).Extension = MMItem.Extension aMimeMapNew(i).MimeType = MMItem.MimeType i = i + 1 End If Next If found Then MimeMapObj.PutEx(ADS_PROPERTY_UPDATE, "MimeMap", aMimeMapNew) MimeMapObj.SetInfo() Else MimeMapObj.PutEx(ADS_PROPERTY_CLEAR, "MimeMap", Nothing) MimeMapObj.SetInfo() End If
End Sub End Class
Piotr Szczytowski
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I spent my day looking at many websites about WMI and ADSI, probably the same you initially went to, trying to figure out VBScript (which I know nothing of), finding your site and deleting all my attempts at .vbs files for going back to C#... this was exactly what I was looking for, and it works great. Thanks a lot.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Nice to hear that it helped you out. Yea, it was a real struggle to find what I was looking for to put this app and article together. At the time I wrote this article, there were a few VBS scripts out there (I think I stumbled on two examples in my search) and zero C#.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, wondering if you can help, but i seem to get the following error when using some of the code, specified in this article. When i attempt to get the type of the IPSecurity object from the Properties object, it returns a cast exception.
--- Error: System.InvalidCastException: Specified cast is not valid. at System.DirectoryServices.PropertyValueCollection.PopulateList() at System.DirectoryServices.PropertyCollection.get_Item(String propertyName) at Griffin.IISWMI.UpdateIPSecurity(String host, String webname) ---
Where UpdateIPSecurity is my Method for adding the new IPs to the Grant list.
If anyone could shed some light on this, please get in touch.
Kind Regards,
Ben Merrills
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
An exception is being thrown on your system when this line is called?
Type typ = IIS.Properties["IPSecurity"][0].GetType();
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
It would seem so, yes. It doesn't get any further into the code. If i put a Console.Write statement before it, that gets fired, but nothing after it, and then of course, the exception is thrown.
I'm just ripping my hair out trying to figure out what i'm doing wrong. If you need any more information, you can email me. (ben at griffin dot net dot uk).
Thanks,
Ben Merrills
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Just thought you might want to know that you're using ADSI and not WMI. If you were using WMI, you would be using system.management instead of system.directoryservices.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
yea, I got in a hurry when writing that article. I was reading up on ADSI and WMI at the same time trying to figure out how to do this. After I posted the article, I realized that I hadn't even used WMI. LOL
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
you'd be pretty surprised at how few people spoof their ip when attacking iis (its rarely come up in all the security work I've done for corporations) Why? Because they want to achieve something "interactive" with their attempt at iis. They may be able to send off a spoofed "GET" request using a known vulnerability, but their real ip address will be revealed at some point. In addition they want to know the response. This adds quite a bit of complexity, so Id have to disagree about the part with the kids using "daddy's" computer.
|
| Sign In·View Thread·PermaLink | 1.20/5 (2 votes) |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|