Tutorial :How to prevent XSS in a Classic ASP multipart form?



Question:

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.

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""") %>>&lt; 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="&lt; Back">      <% End If %>      <% If intCurrentPage < NUMBER_OF_PAGES Then %>          <input type="submit" name="navigate" value="Next &gt;">      <% 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  %>  


Solution:1

You should use Server.HTMLEncode before writing the user input to the page, not before writing to the DB. In fact, it's better to store non encoded values in the DB to avoid double encoding.

Fixed code:

Case 1  %>  <table>    <tr>      <td><strong>Name:</strong></td>      <td><input type="text"                  name="1_name"                  value="<%= Server.HTMLEncode(Request.Form("1_name")) %>"></td>    </tr>    <tr>      <td><strong>Email:</strong></td>      <td><input type="text"                  name="1_email"                  value="<%= Server.HTMLEncode(Request.Form("1_email")) %>"></td>    </tr>  </table>  <%  

Also, make sure that Request.Form("page") is a number

intPreviousPage = TryCLng(Request.Form("page"))  

Internal function of mine

function TryCLng( NumeroEnTexto )      if isNumeric( NumeroEnTexto ) then          TryCLng = clng(NumeroEnTexto)      else          TryCLng = 0      end if  end function  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »