Filtering for SQL Injection on IIS 7 and later

March 11th, 2010 amitmathur31 No comments

I hope that you all know about SQL Injection. But before staring on prevention of this major cause let us first understand  that in actual what is SQL injection.

Defination:
SQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution. Any procedure that constructs SQL statements should be reviewed for injection vulnerabilities because SQL Server will execute all syntactically valid queries that it receives. Even parameterized data can be manipulated by a skilled and determined attacker.

The primary form of SQL injection consists of direct insertion of code into user-input variables that are concatenated with SQL commands and executed. A less direct attack injects malicious code into strings that are destined for storage in a table or as metadata. When the stored strings are subsequently concatenated into a dynamic SQL command, the malicious code is executed.

The injection process works by prematurely terminating a text string and appending a new command. Because the inserted command may have additional strings appended to it before it is executed, the malefactor terminates the injected string with a comment mark "–". Subsequent text is ignored at execution time.

Now let us start learning on how to disable this web curse on IIS 7 and later web servers.

This article is specific to IIS 7 and later.  If you are using IIS 6.0 or earlier, please see this article.

Starting with version 7.0, IIS has a built-in feature that is able to filter HTTP requests.  If a request is found to have contents deemed unacceptable to the administrator, it will be blocked before it is processed by a web application.  This feature is useful as a mitigation tool in defense of SQL Injection vulnerabilities.

Note that any scheme that filters SQL Injection attempts is only a mitigation.  The complete solution to the problem requires fixing vulnerable web applications.  For more information about SQL Injection vulnerabilities and strategies for fixing them, here are some suggested links:

Definition of SQL Injection
SQL Server Injection Protection
Preventing SQL Injections in ASP
How To: Protect from SQL Injection in ASP.NET
Coding Techniques for protecting against SQL Injection in ASP.NET
Filtering SQL Injection from Classic ASP
Security Vulnerability Research & Defense Blog on SQL Injection Attack

Prerequisite

Before getting started, you should verify the specific version of IIS that you are using.  If you are using SP1 or earlier with IIS 7.0, you will need to install this update to the request filtering component before applying the following configuration.  If you are using IIS 7.0 with SP2, or any later version of IIS, you do not need to install any updates.

Configuring the Request Filter

To create a global filtering rule for SQL Injection:

  • Open the applicationhost.config file in the following path:

%systemroot%\system32\inetsrv\config\applicationhost.config

  • Search the applicationhost.config file for "<requestFiltering>" (without the quotes.)
  • Immediately under the <requestFiltering> tag, paste the following settings:

<filteringRules>
    <filteringRule name="SQLInjection" scanQueryString="true">
        <appliesTo>
            <add fileExtension=".asp" />
            <add fileExtension=".aspx" />
        </appliesTo>
        <denyStrings>
            <add string="–" />
            <add string=";" />
            <add string="/*" />
            <add string="@" />
            <add string="char" />
            <add string="alter" />
            <add string="begin" />
            <add string="cast" />
            <add string="create" />
            <add string="cursor" />
            <add string="declare" />
            <add string="delete" />
            <add string="drop" />
            <add string="end" />
            <add string="exec" />
            <add string="fetch" />
            <add string="insert" />
            <add string="kill" />
            <add string="open" />
            <add string="select" />
            <add string="sys" />
            <add string="table" />
            <add string="update" />
        </denyStrings>
    </filteringRule>
</filteringRules>

  • Save the changes to applicationhost.config.

What effect does this have on my server?

With the above configuration in place, IIS will look at each incoming request for pages with .asp or .aspx extensions to search for specific strings in the request’s query string.  If found, IIS will block the request and return a 404 Not Found page to the client.  If you want to change the file extensions, you can add or remove fileExtension tags in the <appliesTo> section.  The specific strings in the search are controlled by the <denyStrings> section.  If you want to change the strings, you can do so by adding or remove entries here.

It is worth noting that the above rule is fairly aggressive about blocking requests.  It is possible that this rule will block legitimate requests.  If this is an issue for your content, it is possible to use a web.config file to create a rule that applies only to content under that web.config.  Do do this, remove any overly restrictive strings from the above applicationhost.config rule.  Then, in the web.config file, include the following configuration with the more restrictive settings in the <system.webServer> section.  For example, if you have content on the server that requires "end" in the query string, remove the <add string="end" /> entry from applicationhost.config and then add the following into the web.config file where you want to restrict "end":

<security>
    <requestFiltering>
        <filteringRules>
            <filteringRule name="SQLInjection2" scanQueryString="true">
                <appliesTo>
                    <add fileExtension=".asp" />
                    <add fileExtension=".aspx" />
                </appliesTo>
                <denyStrings>
                    <add string="end" />
                </denyStrings>
            </filteringRule>
        </filteringRules>
    </requestFiltering>
</security>

Note that the name of the filteringRule tag must be unique and cannot conflict with a name in applicationhost.config or any other web.config files in the path.

Also note that if you want to skip request filtering for all but a specific directory or directories, it is possible to omit the filtering rules in applicationhost.config entirely and just use web.config files to constrain the paths to which filtering applies.

It is also possible to constrain the scope of filtering rules through the use of location tags.

How can I check my logs for SQL Injection attempts?

The request filter logs all of the requests that it blocks in the regular IIS W3SVC logs.  Rejections triggered by a filteringRule will have a status of 404 with a substatus 19.

You can check these logs periodically to see if you’ve been getting requests with SQL Injection attempts and also to see if your rule may be blocking legitimate requests.

In conclusion

This should be everything that you need to know to get a quick start in filtering SQL Injection attempts on your web server.  For more information about things the request filter can do, check out articles here and here.

VN:F [1.6.3_896]
Rating: 0.0/5 (0 votes cast)
Categories: ASP.Net Tags:

Filtering for SQL Injection on IIS 6 and earlier

March 11th, 2010 amitmathur31 No comments

I hope that you all know about SQL Injection. But before staring on prevention of this major cause let us first understand  that in actual what is SQL injection.

Defination:
SQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution. Any procedure that constructs SQL statements should be reviewed for injection vulnerabilities because SQL Server will execute all syntactically valid queries that it receives. Even parameterized data can be manipulated by a skilled and determined attacker.

The primary form of SQL injection consists of direct insertion of code into user-input variables that are concatenated with SQL commands and executed. A less direct attack injects malicious code into strings that are destined for storage in a table or as metadata. When the stored strings are subsequently concatenated into a dynamic SQL command, the malicious code is executed.

The injection process works by prematurely terminating a text string and appending a new command. Because the inserted command may have additional strings appended to it before it is executed, the malefactor terminates the injected string with a comment mark "–". Subsequent text is ignored at execution time.

Now let us start learning on how to disable this web curse on IIS 6 and earlier web servers.

This article is specific to IIS 6 and earlier.  If you are using IIS 7.0 or later, please see this article.

The IIS team has created an add-on tool for IIS called UrlScan that is able to filter HTTP requests.  If a request is found to have contents deemed unacceptable to the administrator, it will be blocked before it is processed by a web application.  This feature is useful as a mitigation tool in defense of SQL Injection vulnerabilities.

Note that any scheme that filters SQL Injection attempts is only a mitigation.  The complete solution to the problem requires fixing vulnerable web applications.  For more information about SQL Injection vulnerabilities and strategies for fixing them, here are some suggested links:

Definition of SQL Injection
SQL Server Injection Protection
Preventing SQL Injections in ASP
How To: Protect from SQL Injection in ASP.NET
Coding Techniques for protecting against SQL Injection in ASP.NET
Filtering SQL Injection from Classic ASP
Security Vulnerability Research & Defense Blog on SQL Injection Attack

 

Prerequisite

Before getting started, you will need the current version of UrlScan.  As of the date of this writing, it is version 3.1.  Most of the information here will also work with UrlScan 3.0, but there are a number of bug fixes in 3.1 and it is strongly encouraged that you upgrade if you are running an earlier version.  A free download of UrlScan 3.1 can be found here.

Configuring UrlScan

UrlScan is configured via the urlscan.ini file.

  • Open the urlscan.ini file in the following path:

%systemroot%\system32\inetsrv\urlscan\urlscan.ini

  • Search the urlscan.ini file for "RuleList=" (without the quotes.)
  • Add "SQLInjection" (without the quotes) to the end of the RuleList line.  If there is already an item or items in the RuleList, use a comma to separate them.
  • Create the following new sections at the end of the urlscan.ini file:

[SQLInjection]
AppliesTo=.asp,.aspx
DenyDataSection=SQLInjectionStrings
ScanURL=0
ScanAllRaw=0
ScanQueryString=1
ScanHeaders=

[SQLInjectionStrings]

%3b ; a semicolon
/*
@ ; also catches @@
char ; also catches nchar and varchar
alter
begin
cast
create
cursor
declare
delete
drop
end
exec ; also catches execute
fetch
insert
kill
open
select
sys ; also catches sysobjects and syscolumns
table
update

  • Save the changes to urlscan.ini.

What effect does this have on my server?

With the above configuration in place, IIS will look at each incoming request for pages with .asp or .aspx extensions to search for specific strings in the request’s query string.  If found, IIS will block the request and return a 404 Not Found page to the client.  If you want to change the file extensions, you can add or remove file extensions on the AppliesTo line.  The specific strings in the search are controlled by the entries in the [SQLInjectionStrings] section.  If you want to change the strings, you can do so by adding or removing entries here.

It is worth noting that the above rule is fairly aggressive about blocking requests.  If this is an issue for your content, it is possible to make specific URLs exempt from UrlScan filtering.  To do this, search the urlscan.ini file for the [AlwaysAllowedUrls] section and add the exempt URLs (one per line.)  Note that URLs here should not include "http://hostname.com" or "https://hostname.com".  Follow the example in the urlscan.ini comments for this section.  Also note that the behavior of this section has changed with UrlScan 3.1.  If you are using UrlScan 3.0, you cannot bypass query string filtering in this manner.

Note that it is very important that you thoroughly check any URLs for SQL Injection vulnerabilities before adding them to the [AlwaysAllowedUrls] section!

How can I check my logs for SQL Injection attempts?

UrlScan logs all of the requests that it blocks in UrlScan log files.  The default location for these files is %systemroot%\system32\inetsrv\urlscan\logs.  Beginning with UrlScan version 3.1, these logs are in W3C compliant format.  Rejections triggered by the above SQL Injection rule will have "rule+SQLInjection+triggered" in the x-reason field.

You can check these logs periodically to see if you’ve been getting requests with SQL Injection attempts and also to see if your rule may be blocking legitimate requests.

In Conclusion

This should be everything you need to know to get a quick start in filtering SQL Injection attempts with UrlScan on your server.  For more information about things UrlScan can do, check out the articles here.

VN:F [1.6.3_896]
Rating: 0.0/5 (0 votes cast)
Categories: ASP.Net Tags:

Health Check of your ASP.NET 2.0 Web Application

March 8th, 2010 amitmathur31 No comments

One of the best, yet often overlooked, features of ASP.NET 2.0 is health monitoring. I believe it is absolutely essential to be notified of any problems with your web application, and this is where health monitoring comes in handy. Health Monitoring is a natural progression of that approach.

There are three pieces to this puzzle:

Events

You need to decide what you want to be notified about. ASP.NET 2.0 comes with a number of events pre-configured for you. I found just about the best diagram of what events are available out of the box in this how-to (follow the link or click the diagram below).

 

For example, if you want to know about all events, you’ll get bombarded. Every time your site starts up, shuts down, recompiles, etc, an event will be raised. If your method of delivery is email, your inbox will beg for mercy.

If you only want to know about errors (and you always should!), you will be notified about aborted requests, view state errors, unhandled exceptions, etc. In my opinion, you owe your users to monitor at least this much. On the diagram above, it’s everything next to WebErrorEvent and WebRequestErrorEvent.

You may want to zero in on a specific error. Scott Guthrie showed how to log shutdown events with some hacking. Health monitoring comes with a pre-defined event, ApplicationShutdown (#1002) which you can easily wire to achieve the same.

 

<eventMappings>
<add
  name="My site shutdown notifications"
  type="System.Web.Management.WebApplicationLifetimeEvent,
  System.Web, Version=2.0.0.0, Culture=neutral,
  PublicKeyToken=b03f5f7f11d50a3a"
  startEventCode="1002"
  endEventCode="1002" />
</eventMappings>

An event will list the shutdown reason along the following lines:

** Events **
---------------
Event code: 1002
Event message: Application is shutting down. Reason: Configuration
changed.
[...skipped...]

Last, but not least, you can write your own (custom) events. For example, Positive Lookahead raises a custom event every time a review is submitted and sends me an email with detailed information. Implementing and raising custom events is very easy.

Even though I’ve been talking about “defining events,” most likely you won’t need to define anything. Below are listed a handful of interesting events pre-configured for you in 2.0. Class names in parentheses are for your reference. You’ll be able to look them up on the above diagram.

  • “All events” (WebBaseEvent). Anything and everything that happens on your site.
  • “Application Lifetime Events” (WebApplicationLifetimeEvent). Application compilation, start-up and shutdown.
  • “All Errors” (WebBaseErrorEvent). Any and all errors on the site.
  • “Infrastructure Errors” (WebErrorEvent). Compilation, configuration, parse, etc, errors.
  • “Request Processing Errors” (WebRequestErrorEvent). View state and validation errors, as well as all unhandled exceptions.

 

    Providers

    Once you’ve decided what to monitor, you need to decide what to do with notifications. You can have them written to the system event log, sent to the trace (ASP.NET page tracing system), emailed, written to a database, or passed to the Windows Management Instrumentation (WMI). This is where providers come into picture.

    You may write your own provider, for example, to log events via a web service. Below is a diagram of pre-canned providers (click for a bigger image):

Health monitoring allows you to have the same event(s) handled by multiple providers. For example, all site errors can be emailed to you and handed over to a custom provider, should you write one.

If you host a site in a shared environment, you won’t have access to the system event log. This is where email providers, “simple” and “templated”, come to the rescue.

SimpleMailWebEventProvider sends insanely detailed logs. It’s fine as long as you need all that information. To tame the format and content, use TemplatedMailWebEventProvider which allows you to design a template and limit the amount of information that gets put in. Send E-mail for Health Monitoring Notifications shows how to use these two providers. Another extremely helpful how-to, Use Health Monitoring in ASP.NET 2.0, provides additional clues how to set email header, footer, separator, and so on.

 

Rules

Rules bring events and providers together. A rule spells out which events to monitor and how to deliver them.

For example, I’d like to have all errors from my site emailed to me. I’d add the following configuration section to web.config:

<system.web>
<healthMonitoring enabled="true">
<providers>
<add
  name="MailWebEventProvider"
  type="System.Web.Management.SimpleMailWebEventProvider"
  to="[an email here]"
  from="[an email here]"
  buffer="false"
  subjectPrefix="My site crapped its pants: "
  />
</providers>
<rules>
 <add
   name="All errors from my site"
   eventName="All Errors"
   provider="MailWebEventProvider"
   profile="Critical"
  />
</rules>
</healthMonitoring>
</system.web>

<system.net>
<mailSettings>
 <smtp deliveryMethod="Network">
  <network
     defaultCredentials="true"
     host="[your SMTP server]" />
 </smtp>
</mailSettings>
</system.net>

You’ll notice I don’t explicitly declare events here. As discussed before, “All errors” is pre-configured. You will find it here under <eventMappings>. The finer points of what each attribute means are well documented on MSDN. I only want to draw your attention to the profile attribute.

Out of the box, there are two profiles: default and critical.

<profiles>
 <add
  name="Default"
  minInstances="1"
  maxLimit="Infinite"
  minInterval="00:01:00"
  custom="" />
 <add
  name="Critical"
  minInstances="1"
  maxLimit="Infinite"
  minInterval="00:00:00"
  custom="" />
</profiles>

Under the default profile

  • The minimum number of times an event can occur before an event notification is sent is 1.
  • The maximum number of times an event can occur before notifications stop is 2147483647 (infinite).
  • The minimum time interval between two events is one minute.

The critical profile doesn’t throttle the flow of event notifications, so there’s no one-minute limitation, and notifications are dispatched right away. I’m deliberately not getting into a discussion about buffering to keep things simple.

Conclusion

I hope this post gives you enough information to get going with health monitoring. I wanted to keep it on a conceptual level, which is why there was no talk of implementation details.

VN:F [1.6.3_896]
Rating: 0.0/5 (0 votes cast)
Categories: ASP.Net Tags:

Dynamically write text on an image

March 8th, 2010 amitmathur31 No comments

This posts basically concentrates on dynamically writing some text content on image. This technique can be used in many of our development tasks like for developing captcha, printing of email addresses on websites which actually avoids spammers and many other purposes as per the development requirements.

Below given is the sample code to print sometext “Hey! this is me.” on an image.

Namespaces to be used:

using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Drawing.Text;

Text and Image load content:

Bitmap bitMapImage = new System.Drawing.Bitmap(Server.MapPath(”Amit.jpg”));
Graphics graphicImage = Graphics.FromImage(bitMapImage);
graphicImage.SmoothingMode = SmoothingMode.AntiAlias;
graphicImage.DrawString(”Hey! This is me.”, new Font(”Arial”, 12, FontStyle.Bold),SystemBrushes.WindowText, new Point(100, 250));
graphicImage.DrawArc(new Pen(Color.Red, 3), 90, 235, 150, 50, 0, 360);

Response.ContentType = “image/jpeg”;
//Save the new image to the response output stream.

bitMapImage.Save(Response.OutputStream, ImageFormat.Jpeg);

graphicImage.Dispose();
bitMapImage.Dispose();

VN:F [1.6.3_896]
Rating: 0.0/5 (0 votes cast)
Categories: ASP.Net, C Sharp Tags:

C# Forms Authentication using ticket and managing user roles in asp.net

February 16th, 2010 amitmathur31 No comments

In this article i am going to describe how to implement Forms authentication using tickets and managing roles based access in ASP.NET using C#

Solution Explorer

For implementing forms authentication without using formsauthentication ticket, read my previous article – Forms Authentication with C# and managing folder lavel access with multiple web.config files

Configuring web.config file in application root

<authentication mode=”Forms”>
<forms defaultUrl=”Default.aspx” loginUrl=”~/Login.aspx”
slidingExpiration=”true” timeout=”20″></forms>
</authentication>

Defining roles and accessibility in root web.config

<location path=”Admin”>
<system.web>
<authorization>
<allow roles=”admin”/>
<deny users=”*”/>
</authorization>
</system.web>
</location>

Defining roles settings for folders and aspx within those folders in web.config file in those folders

<system.web>
<authorization>
<allow roles=”user”/>
<deny users=”*”/>
</authorization>
</system.web>

settings for any logged in member

<system.web>
<authorization>
<deny users=”?”/>
</authorization>

Now after creating Login page we need to authenticate user

protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
string userName = Login1.UserName;
string password = Login1.Password;
bool rememberUserName = Login1.RememberMeSet;

//Fetch User login information fromthe xml file into Dataset

string xmlFilePath = Server.MapPath(”~/App_Data/LoginInfo.xml”);
DataSet objDs = new DataSet();
objDs.ReadXml(xmlFilePath);
DataRow[] dRow = objDs.Tables[0].Select(”UserName = ‘” + userName + “‘ and Password = ‘” + password + “‘”);
if (dRow.Length > 0)
{
//Fetch the role
string roles = dRow[0]["Roles"].ToString();

//Create Form Authentication ticket
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(20), rememberUserName, roles, FormsAuthentication.FormsCookiePath);

// In the above parameters 1 is ticket version, username is the username associated with this ticket
//time when ticket was issued , time when ticket will expire, remember username is user has chekced it
//roles associted with the user, and path of cookie if any

//For security reasons we may hash the cookies
string hashCookies = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hashCookies);

// add the cookie to user browser

Response.Cookies.Add(cookie);

// get the requested page

string returnUrl = Request.QueryString["ReturnUrl"];
if (returnUrl == null)
returnUrl = “~/Default.aspx”;
Response.Redirect(returnUrl);
}

Now to retrieve the authentication and roles information on every request we need to write this code in Global.asax file

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
// look if any security information exists for this request

if (HttpContext.Current.User != null)
{

// see if this user is authenticated, any authenticated cookie (ticket) exists for this user

if (HttpContext.Current.User.Identity.IsAuthenticated)
{

// see if the authentication is done using FormsAuthentication

if (HttpContext.Current.User.Identity is FormsIdentity)
{

// Get the roles stored for this request from the ticket

// get the identity of the user

FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity;

//Get the form authentication ticket of the user

FormsAuthenticationTicket ticket = identity.Ticket;

//Get the roles stored as UserData into ticket

string[] roles = ticket.UserData.Split(’,');

//Create general prrincipal and assign it to current request

HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(identity, roles);
}
}
}
}

To check whether user in in the role or not we need to write this code in every page which provide access on role basis
protected void Page_Load(object sender, EventArgs e)
{
if (HttpContext.Current.User.IsInRole(”admin”))
{
lblMessage.Text = “Welcome Administrator”;
}
}

VN:F [1.6.3_896]
Rating: 0.0/5 (0 votes cast)
Categories: ASP.Net Tags: