Return to HomePage



Encoding Output within a DataTable (VB.NET)


Applies To

* ASP.NET 2.0
* VB.NET


Summary

This code demonstrates how to implement security output encoding when using the .NET DataTable object to display application data. Output encoding mitigates against client-side script vulnerabilities by representing output data using escape character equivalents for values that might otherwise be interpreted by the browser, such as those characters used in the formatting of HTML pages (<,>,&,",').

Objectives

* Protect application users from client-side scripting attacks
* Ensure that malicious data that may pre-date input validation routines or have been missed through poor validation does not render as application output

Scenarios

* Database-backed web application that uses data tables to present output
* Application that uses data tables to present input from an untrusted source

Solution Example


'Solution Example #1: Looping through the DataTable
The following code illustrates the use of output encoding accomplished
by looping through the DataRow object and calling Server.HtmlEncode for
each output value we wish to encode.

Public Sub LoadEncodedPeopleTableEvent(ByVal adapter As SqlDataAdapter)
		    		' Build a Data Grid to house our data and add to the set of page controls
		    		Dim dataGrid As [DataGrid] =  New [DataGrid()] 
		    		Me.Controls.Add(dataGrid)
	

		    		' Create a new data table and fill our that table with names from the adapter 
		    		Dim names As [DataTable] =  New [DataTable()] 
		    		adapter.Fill(names)
	

		   		' Manually register the event-handling method for the
		    		' [ItemDataBound] event of the [DataGrid] control.
		    		[AddHandler] [dataGrid.ItemDataBound,] [AddressOf] dataGrid_EncodeItem
	

		    		' Present the data to the user in the previously created Data Grid
		    		[dataGrid.DataSource] = names
		    		[dataGrid.DataBind()]
	
End Sub

Private Sub dataGrid_EncodeItem(ByVal sender As Object, ByVal e As DataGridItemEventArgs)
		    		' Encode each actual data row presented within the Data Grid
		    		If [e.Item.ItemType.Equals(ListItemType.Item)] Or [e.Item.ItemType.Equals]				[(ListItemType.AlternatingItem)] Then
		        			e.Item.Cells(0).Text = [Server.HtmlEncode(e.Item.Cells(0).Text)]
		    		End If
	
End Sub


This approach is flexible and can be used in a variety of different data presentation settings. For the example data above, the row containing malicious Javascript will be encoded and presented as escaped HTML output.


The following code illustrates the use of output encoding accomplished by associating a custom encoding handler within the ItemDataBound event support by the DataGrid in use for rendering the application output.

Public Sub LoadEncodedPeopleTableLoop(ByVal adapter As SqlDataAdapter)
		    		' Build a Data Grid to house our data and add to the set of page controls
		    		Dim dataGrid As [DataGrid] =  New [DataGrid()] 
		    		Me.Controls.Add(dataGrid)
	

		    		' Create a new data table and fill our that table with names from the adapter 
		    		Dim names As [DataTable] =  New [DataTable()] 
		    		adapter.Fill(names)
	

		    		Dim row As [DataRow]
		   		For Each row In names.Rows
		        			row("Name") = Server.HtmlEncode(CType(row("Name"), String))
		        			[row.EndEdit()]
		    		Next
	

		    		' Present the data to the user in the previously created Data Grid
		    		[dataGrid.DataSource] = names
		    		[dataGrid.DataBind()]
	
End Sub

This solution takes advantage of the event-driven architecture of .NET and eliminates the requirement to loop through the DataTable in order to access individual data items. Where presentation of data makes use of an object such as a DataGrid that supports data binding events, we recommend this approach for reasons of performance and architectural consistency.


Problem Example

The following example demonstrates the use of a DataTable to query data without the use of any output encoding:

' Build a datagrid to house our data and add to the set of page controls
Dim dataGrid As DataGrid = New DataGrid()
Me.Controls.Add(dataGrid)

' Create a new database connection using Integrated Security and open that connection
Dim connectionString As String = "Initial Catalog=snippets;Data Source=vm-win2003\sqlexpress;Integrated Security=SSPI;"
Dim cn As SqlConnection = New SqlConnection(connectionString)
cn.Open()

' Create a new SQL Command object with a query to execute the stored procedure
Dim cmd As SqlCommand = New SqlCommand("exec spFullNames",cn)
Dim adapter As SqlDataAdapter = New SqlDataAdapter(cmd)

' Create a new data table and fill our that table with names from the adapter
Dim names As DataTable = New DataTable()
adapter.Fill(names)

' Present the data to the user in the previously created Data Grid
dataGrid.DataSource = names
dataGrid.DataBind()

* Any HTML data present within the database query output will be rendered as part of the application HTML output
* Any Javascript data present within the database query output will be rendered as part of the application HTML output
* Code is vulnerable to client-side script attacks such as cross-site scripting (XSS)

Test Case

The following classes must be included in any project making use of the sample code provided above:

Imports System.Data
Imports System.Data.SqlClient
Imports System.Web

Create a new VB ASP.NET application and use the following Page_Load method to test the provided example methods (adjust database code for your example):

Protected Sub Page_Load(ByVal Source As Object, ByVal E As EventArgs) Handles MyBase.Load
		    		If Not [Page.IsPostBack] Then
		        		' Create a new database connection using Integrated Security and open that connection
		        		Dim connectionString As String =  "Initial Catalog=snippets;Data Source=vm-win2003\\sqlexpress;Integrated Security=SSPI;" 
		        		Dim cn As [SqlConnection] =  New [SqlConnection(connectionString)] 
		        		cn.Open()
	

		        		' Create a new SQL Command object with a query to execute the stored procedure
		        		Dim cmd As [SqlCommand] =  New SqlCommand("exec spFullNames",cn) 
		        		Dim adapter As [SqlDataAdapter] =  New [SqlDataAdapter(cmd)] 
	

		        		[LoadEncodedPeopleTableEvent(adapter)]
		    		End If
	
End Sub


Expected Result

<table cellspacing="0" rules="all" border="1" style="border-collapse:collapse;">
<tr><td>Name</td></tr>
<tr><td>Elvin Jones</td></tr>
<tr><td>Gene Krupa</td></tr>
<tr><td>Tony Williams</td></tr>
<tr><td><script>alert('XSS!');</script> XSS</td></tr>
</table>

More Information

* In addition to output validation, developers should always validate any input that originates from untrusted sources, such as application users or external feeds.


Additional Resources

* Preventing Cross-Site Scripting Attacks (.NET): http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/paght000001.asp
* Anti-Cross Site Scripting Library (.NET): http://www.microsoft.com/downloads/details.aspx?familyid=9A2B9C92-7AD9-496C-9A89-AF08DE2E5982&displaylang=en


Attributes

* Applies To: .NET Framework 2.0, VB
* Category: Data Validation
* Author: Jonathan Bailey





Return to HomePage
Microsoft Communities