To protect your website, use multiple layers of security rather than relying only on a list of blocked strings.
1. Identify suspicious requests in IIS logs
Watch for patterns such as:
SQL injection expressions, including
UNION SELECT, Boolean conditions, and database function calls.XSS payloads containing HTML tags, JavaScript URLs, and event handlers such as
onerror.Server-side script injection attempts containing
response.writeor<% ... %>syntax.Command injection attempts involving commands such as
nslookupandcurl.Automated scans targeting paths such as
/wp-admin,/wp-includes, and/wp-json.
These patterns indicate potentially malicious requests, but a matching log entry alone does not prove that an attack succeeded.
2. Configure custom deny-string rules
A custom deny-string list can help detect known malicious patterns. Example entries include:
<add string="union select" />
<add string="waitfor delay" />
<add string="information_schema" />
<add string="xp_cmdshell" />
<add string="dbms_pipe.receive_message" />
<add string="response.write(" />
<add string="<script" />
<add string="<iframe" />
<add string="<img" />
<add string="onerror=" />
<add string="onload=" />
<add string="javascript:" />
<add string="data:text/html" />
<add string="nslookup" />
<add string="invoke-webrequest" />These are examples, not a complete list of every possible attack. Your custom validation code must actually enforce these rules; adding them to an XML element alone does not automatically block requests in IIS.
<requestFiltering>
<!-- Increase the maximum allowed length for the query string and URL -->
<requestLimits
maxQueryString="116384"
maxUrl="132768" />
<!-- Block common SQL Injection patterns -->
<filteringRules>
<filteringRule
name="BlockSQLInjection"
scanUrl="false"
scanQueryString="true">
<appliesTo>
<clear />
<add fileExtension="." />
</appliesTo>
<denyStrings>
<clear />
<!-- =============================== -->
<!-- UNION-based SQL Injection -->
<!-- =============================== -->
<add string="union select" />
<add string="union all select" />
<add string="union distinct select" />
<!-- =============================== -->
<!-- SQL expressions / conditions -->
<!-- =============================== -->
<add string="convert(" />
<add string="cast(" />
<add string="case when" />
<add string="case" />
<add string="when" />
<add string="waitfor delay" />
<add string="waitfor time" />
<!-- =============================== -->
<!-- SQL comments -->
<!-- =============================== -->
<add string="--" />
<add string="/*" />
<add string="*/" />
<add string="#" />
<!-- =============================== -->
<!-- SQL execution -->
<!-- =============================== -->
<add string="declare" />
<add string="exec" />
<add string="execute" />
<!-- =============================== -->
<!-- SQL Server procedures/functions -->
<!-- =============================== -->
<add string="xp_cmdshell" />
<add string="xp_regread" />
<add string="xp_regwrite" />
<add string="xp_regdeletekey" />
<add string="xp_dirtree" />
<add string="xp_fileexist" />
<add string="sp_executesql" />
<add string="sp_oacreate" />
<add string="sp_oamethod" />
<add string="sp_oagetproperty" />
<add string="sp_oasetproperty" />
<!-- =============================== -->
<!-- External data access -->
<!-- =============================== -->
<add string="openrowset" />
<add string="opendatasource" />
<add string="openquery" />
<add string="openxml" />
<!-- =============================== -->
<!-- Database/table modification -->
<!-- =============================== -->
<add string="drop table" />
<add string="drop database" />
<add string="drop column" />
<add string="alter table" />
<add string="alter database" />
<add string="truncate table" />
<add string="insert into" />
<add string="delete from" />
<!-- =============================== -->
<!-- Database enumeration -->
<!-- =============================== -->
<add string="information_schema" />
<add string="sysobjects" />
<add string="syscolumns" />
<add string="sysdatabases" />
<add string="sys.tables" />
<add string="sys.columns" />
<add string="sys.objects" />
<add string="sysusers" />
<add string="systables" />
<!-- =============================== -->
<!-- Common boolean SQL injection -->
<!-- =============================== -->
<add string="' or '" />
<add string="' and '" />
<add string="') or ('" />
<add string="') and ('" />
<add string="') or 1=1" />
<add string="' or 1=1" />
<add string="' and 1=1" />
<add string="or 1=1" />
<add string="and 1=1" />
<add string="or 1=0" />
<add string="and 1=0" />
<!-- =============================== -->
<!-- Common SQL functions -->
<!-- =============================== -->
<add string="substring(" />
<add string="substring" />
<add string="charindex(" />
<add string="patindex(" />
<add string="ascii(" />
<add string="unicode(" />
<add string="len(" />
<add string="db_name(" />
<add string="user_name(" />
<add string="system_user" />
<add string="current_user" />
<add string="suser_name(" />
<add string="suser_sname(" />
<!-- =============================== -->
<!-- SQL Server version/database info -->
<!-- =============================== -->
<add string="@@version" />
<add string="@@servername" />
<add string="@@spid" />
<add string="@@language" />
<add string="@@servicename" />
<!-- =============================== -->
<!-- Common SQL operators/patterns -->
<!-- =============================== -->
<add string="like '%" />
<add string="having 1=1" />
<add string="group by" />
<add string="order by" />
<!-- PowerShell command execution -->
<add string="powershell" />
<add string="invoke-webrequest" />
<add string="invoke-restmethod" />
<add string="wp-admin" />
<add string="wp-includes" />
<add string="wordpress" />
<add string="wp-content" />
<add string="wp-json" />
</denyStrings>
</filteringRule>
</filteringRules>
</requestFiltering>
</security>
3. Do not rely on exact-string matching
Attackers can change numbers, capitalization, whitespace, quotation marks, comments, and URL encoding to bypass exact matches.
For example, blocking one mathematical expression such as 5*5=25 will not detect every variation. Use suitable pattern-based detection, normalize encoded input safely, and validate values according to the expected format of each parameter.
Avoid broad deny strings that could reject legitimate customer input. Test new rules against normal website traffic before deploying them to production.
4. Validate input using allowlists
For an ASP.NET MVC application, validate every parameter according to its purpose.
Product and product type: Accept only supported product names and types.
Quantity: Require a positive integer within a reasonable business limit.
Platform: Accept only recognized platform values.
Download parameters: Accept only supported product and platform combinations.
Validation must happen on the server, even if the same fields are validated in JavaScript.
5. Use parameterized SQL queries
Parameterized queries are a primary defense against SQL injection. Never build SQL statements by concatenating untrusted request values.
For Entity Framework, prefer LINQ queries or properly parameterized database commands. Avoid executing dynamically constructed SQL from user input.
6. Prevent Cross-Site Scripting
Use context-aware output encoding when displaying user-controlled data. In ASP.NET MVC Razor views, prefer normal encoded expressions such as:
@Model.CustomerNameAvoid rendering untrusted input with Html.Raw() unless it has been safely sanitized for the intended HTML context.
7. Use IIS Request Filtering and a Web Application Firewall
IIS Request Filtering can reject malformed requests and restrict unwanted URL sequences, file extensions, and request sizes. A Web Application Firewall (WAF) can provide additional detection for common attack patterns.
These controls complement application-level validation; they do not replace secure coding practices.
8. Investigate HTTP status codes and application errors
A suspicious request returning HTTP 200 does not necessarily mean that the payload executed. Similarly, a 302 redirect does not prove that the request was blocked.
Review application logs and exception details for HTTP 500 responses, verify the behavior of affected endpoints, and check whether unexpected database operations or changes occurred.
Conclusion
Protecting an ASP.NET MVC website requires layered security: safe SQL access, strict server-side input validation, output encoding, appropriate IIS filtering, and monitoring of suspicious requests. Custom deny-string rules are useful as an additional layer, but they cannot guarantee protection against every attack variation.