I am calling on the collective mind of the stackoverflow community to help this novice programmer fix a major issue.
I have a multipart form written in Classic ASP that is based on the code below. I use stored procedures and parameters to write to the sql DB, I use Server.HTMLEncode before it is submitted also. I have javascript based validation (jquery validation plugin) as well as server side ASP validation for all the fields. I am not worried about injection but the page is vulnerable to XSS code listed below.
My question is: How do I prevent this type of cross site scripting on a classic ASP page like the one below?
Basically, all the data is collected then on the last "page" after submit is hit I run it through the server side validation. But I need to know how to prevent XSS before the user gets to the submission point.
Thanks very very much in advance for any thorough advice and tips!
XSS CODE:
';alert(String.fromCharCode(88,83,83))//\';alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//\";alert(String.fromCharCode(88,83,83))//--></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
CODE:
<%
Const NUMBER_OF_PAGES = 3
Dim intPreviousPage
Dim intCurrentPage
Dim strItem
' What page did we come from?
intPreviousPage = Request.Form("page")
' What page are we on?
Select Case Request.Form("navigate")
Case "< Back"
intCurrentPage = intPreviousPage - 1
Case "Next >"
intCurrentPage = intPreviousPage + 1
Case Else
' Either it's our first run of the page and we're on page 1 or
' the form is complete and pages are unimportant because we're
' about to process our data!
intCurrentPage = 1
End Select
' If we're not finished then display the form.
If Request.Form("navigate") <> "Finish" Then %>
<form action="<%= Request.ServerVariables("URL") %>" method="post">
<input type="hidden" name="page" value="<%= intCurrentPage %>">
<%
' Take data and store it in hidden form fields. All our fields are
' prefixed with numbers so that we know what page it belongs to.
For Each strItem In Request.Form
' Ignore the "page" and "navigate" button form fields.
If strItem <> "page" And strItem <> "navigate" Then
' If the data is from the current page we don't need
' the hidden field since the data will show in the visible
' form fields.
If CInt(Left(strItem, 1)) <> intCurrentPage Then
Response.Write("<input type=""hidden"" name=""" & strItem & """" _
& " value=""" & Request.Form(strItem) & """>" & vbCrLf)
End If
End If
Next
' Display current page fields. The fields are all named with
' numerical prefix that tells us which page they belong to.
' We need a Case for each page.
Select Case intCurrentPage
Case 1
%>
<table>
<tr>
<td><strong>Name:</strong></td>
<td><input type="text" name="1_name" value="<%= Request.Form("1_name") %>"></td>
</tr><tr>
<td><strong>Email:</strong></td>
<td><input type="text" name="1_email" value="<%= Request.Form("1_email") %>"></td>
</tr>
</table>
<%
Case 2
%>
<table>
<tr>
<td><strong>Address:</strong></td>
<td><input type="text" name="2_address" value="<%= Request.Form("2_address") %>"></td>
</tr><tr>
<td><strong>City:</strong></td>
<td><input type="text" name="2_city" value="<%= Request.Form("2_city") %>"></td>
</tr><tr>
<td><strong>State:</strong></td>
<td><input type="text" name="2_state" value="<%= Request.Form("2_state") %>"></td>
</tr><tr>
<td><strong>Zip:</strong></td>
<td><input type="text" name="2_zip" value="<%= Request.Form("2_zip") %>"></td>
</tr>
</table>
<%
Case 3
' Notice that you can do other types of form fields too.
%>
<table>
<tr>
<td><strong>Sex:</strong></td>
<td>
<input type="radio" name="3_sex" value="male" <% If Request.Form("3_sex") = "male" Then Response.Write("checked=""checked""") %>>Male
<input type="radio" name="3_sex" value="female" <% If Request.Form("3_sex") = "female" Then Response.Write("checked=""checked""") %>>Female
</td>
</tr><tr>
<td><strong>Age:</strong></td>
<td>
<select name="3_age">
<option></option>
<option<% If Request.Form("3_age") = "< 20" Then Response.Write(" selected=""selected""") %>>< 20</option>
<option<% If Request.Form("3_age") = "20 - 29" Then Response.Write(" selected=""selected""") %>>20 - 29</option>
<option<% If Request.Form("3_age") = "30 - 39" Then Response.Write(" selected=""selected""") %>>30 - 39</option>
<option<% If Request.Form("3_age") = "40 - 49" Then Response.Write(" selected=""selected""") %>>40 - 49</option>
<option<% If Request.Form("3_age") = "50 - 59" Then Response.Write(" selected=""selected""") %>>50 - 59</option>
<option<% If Request.Form("3_age") = "60 - 69" Then Response.Write(" selected=""selected""") %>>60 - 69</option>
<option<% If Request.Form("3_age") = "70 - 79" Then Response.Write(" selected=""selected""") %>>70 - 79</option>
<option<% If Request.Form("3_age") = "80 +" Then Response.Write(" selected=""selected""") %>>80 +</option>
</select>
</td>
</tr>
</table>
<%
Case Else
' You shouldn't see this error unless something goes wrong.
Response.Write("Error: Bad Page Number!")
End Select
%>
<br />
<!-- Display form navigation buttons. -->
<% If intCurrentPage > 1 Then %>
<input type="submit" name="navigate" value="< Back">
<% End If %>
<% If intCurrentPage < NUMBER_OF_PAGES Then %>
<input type="submit" name="navigate" value="Next >">
<% Else %>
<input type="submit" name="navigate" value="Finish">
<% End If %>
</form>
<%
Else
' This is where we process our data when the user submits the final page.
' I just display the data, but you're free to store the data in a
' database, send it via email, or do whatever you want with it.
'For Each strItem In Request.Form
' Response.Write(strItem & ": " & Request.Form(strItem) & "<br />" & vbCrLf)
'Next
%>
<p><strong>
Here's what you entered:
</strong></p>
<pre>
<strong>Name:</strong> <%= Request.Form("1_name") %>
<strong>Email:</strong> <%= Request.Form("1_email") %>
<strong>Address:</strong> <%= Request.Form("2_address") %>
<strong>City:</strong> <%= Request.Form("2_city") %>
<strong>State:</strong> <%= Request.Form("2_state") %>
<strong>Zip:</strong> <%= Request.Form("2_zip") %>
<strong>Sex:</strong> <%= Request.Form("3_sex") %>
<strong>Age:</strong> <%= Request.Form("3_age") %>
</pre>
<p>
<a href="<%= Request.ServerVariables("URL") %>">Start Again</a>
</p>
<%
End If
%>