如何在经典ASP多部分表单中防止XSS?

时间:2010-08-03 22:17:56

标签: validation asp-classic xss multipartform-data

我有一个用Classic ASP编写的多部分表单,它基于下面的代码。我使用存储过程和参数写入sql DB,我在提交之前使用Server.HTMLEncode。我有基于javascript的验证(jquery验证插件)以及所有字段的服务器端ASP验证。我不担心注入,但页面容易受到下面列出的XSS代码的影响。

我的问题是:如何在如下所示的传统ASP页面上阻止此类跨网站脚本?

基本上,在提交命中之后,所有数据都会收集到最后一个“页面”上。我通过服务器端验证运行它。但我需要知道如何在用户到达提交点之前阻止XSS。

XSS代码:

';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
%>

1 个答案:

答案 0 :(得分:2)

在将用户输入写入页面之前,应该使用Server.HTMLEncode,而不是在写入数据库之前。实际上,最好将非编码值存储在DB中以避免双重编码。

固定代码:

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>
<%

另外,请确保Request.Form("page")是一个数字

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

我的内部功能

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