Click here to Skip to main content
15,880,651 members
Articles / Programming Languages / C#
Article

How to Programmatically add IP Addresses to IIS's Deny Access List using C# and WMI

Rate me:
Please Sign up or sign in to vote.
4.80/5 (5 votes)
31 Jul 20033 min read 159.5K   1.3K   51   25
An article that shows the basic steps to programmatically adding an IP address to the IIS deny access list.

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:

  1. only the "kid" hackers using daddy's computer will get caught because they don't spoof their IP addresses
  2. the prevalence of dynamic IPs foils the blocking of reported IPs attempting to be malicious
  3. This does nothing for new types of attacks since this solution is dependant on what URLScan knows.
  4. 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 Code

C#
using System;
using System.IO;
using System.Collections;
using System.DirectoryServices;
using System.Reflection;


namespace soccerwrek
{
 class IISWMI
 {      

  [STAThread]
  static void Main(string[] args) 
      {
         try
         {
            // retrieve the directory entry for the root of the IIS server

            System.DirectoryServices.DirectoryEntry IIS = 
               new System.DirectoryServices.DirectoryEntry(
               "IIS://localhost/w3svc/1/root");

            // retrieve the list of currently denied IPs

            Console.WriteLine(
                "Retrieving the list of currently denied IPs.");

            // get the IPSecurity property

            Type typ = IIS.Properties["IPSecurity"][0].GetType();
            object IPSecurity = IIS.Properties["IPSecurity"][0];

            // retrieve the IPDeny list from the IPSecurity object
            Array origIPDenyList = (Array) typ.InvokeMember("IPDeny", 
                       BindingFlags.DeclaredOnly | 
                       BindingFlags.Public | BindingFlags.NonPublic | 
                       BindingFlags.Instance | BindingFlags.GetProperty, 
                       null, IPSecurity, null);

            // display what was being denied
            foreach(string s in origIPDenyList)
               Console.WriteLine("Before: " + s);

            // check GrantByDefault.  This has to be set to true, 
            // or what we are doing will not work.
            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});
            }

            // update the list of denied IPs.  This is a 
            // complete replace.  If you want to maintain what
            // was already being denied, you need to make sure 
            // those IPs are in here as well.  This area
            // will be where you will most likely modify to
            // your needs as this is just an example.
            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");

            // add the updated list back to the IPSecurity object
            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.");

            // commit the changes
            IIS.CommitChanges();
            IIS.RefreshCache();

            // check to see if the update took
            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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Currently a manager at a healthcare IT company, I've spent the last 7 years managing a variety of projects that range from web based kiosk applications to larger transaction based applications. Previously, I spent 8 years as a software engineer developing messaging, image editing, web based applications, and mainframe applications.

Comments and Discussions

 
GeneralLong Live IIS 7 Pin
_PolyGram_1-Mar-10 1:49
_PolyGram_1-Mar-10 1:49 
GeneralIPDeny doesn't work Pin
afterburn24-Jul-09 14:23
afterburn24-Jul-09 14:23 
GeneralRe: IPDeny doesn't work Pin
David Wyn Evans10-Feb-10 13:35
David Wyn Evans10-Feb-10 13:35 
QuestionWhere? Pin
GotzBoost31-Jan-07 8:11
GotzBoost31-Jan-07 8:11 
GeneralThere is a simpler way to this Pin
hmehanna2-Nov-06 11:22
hmehanna2-Nov-06 11:22 
Generalcreate new site Pin
horhen2-Nov-06 10:51
horhen2-Nov-06 10:51 
QuestionHow can i doo Pin
flashwebb27-Sep-06 23:42
flashwebb27-Sep-06 23:42 
AnswerRe: How can i doo Pin
Scott Burgett28-Sep-06 2:41
Scott Burgett28-Sep-06 2:41 
GeneralRe: How can i doo Pin
flashwebb28-Sep-06 3:36
flashwebb28-Sep-06 3:36 
GeneralNew site Pin
sja215-Feb-06 11:25
sja215-Feb-06 11:25 
GeneralRe: New site Pin
Scott Burgett10-Jun-06 4:38
Scott Burgett10-Jun-06 4:38 
GeneralDocumentation Pin
perlmunger17-Dec-04 11:47
perlmunger17-Dec-04 11:47 
GeneralRe: Documentation Pin
Scott Burgett31-Dec-04 7:46
Scott Burgett31-Dec-04 7:46 
GeneralWMI on remote machine !!! Pin
dharani23-Jun-04 6:10
dharani23-Jun-04 6:10 
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
GeneralIIS MIME table. Pin
Seth.8-Jun-04 15:39
sussSeth.8-Jun-04 15:39 
GeneralRe: IIS MIME table. Pin
selat28-Jan-05 1:50
selat28-Jan-05 1:50 
GeneralThanks! Pin
Xanadu200023-Mar-04 10:46
Xanadu200023-Mar-04 10:46 
GeneralRe: Thanks! Pin
Scott Burgett23-Mar-04 11:26
Scott Burgett23-Mar-04 11:26 
GeneralSpecified cast is not valid Pin
Ben Merrills15-Oct-03 6:16
Ben Merrills15-Oct-03 6:16 
GeneralRe: Specified cast is not valid Pin
Scott Burgett15-Oct-03 6:22
Scott Burgett15-Oct-03 6:22 
GeneralRe: Specified cast is not valid Pin
Ben Merrills15-Oct-03 6:28
Ben Merrills15-Oct-03 6:28 
GeneralFYI - Your example is ADSI, not WMI Pin
Anonymous9-Sep-03 16:35
Anonymous9-Sep-03 16:35 
GeneralRe: FYI - Your example is ADSI, not WMI Pin
Scott Burgett2-Oct-03 3:26
Scott Burgett2-Oct-03 3:26 
GeneralRe: FYI - Your example is ADSI, not WMI [modified] Pin
abutun31-Mar-06 3:18
abutun31-Mar-06 3:18 
General"kid hackers" Pin
Anonymous5-Aug-03 4:16
Anonymous5-Aug-03 4:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.