【问题标题】:Filtering Encoded XSS in Classic ASP在经典 ASP 中过滤编码的 XSS
【发布时间】:2011-09-29 14:24:13
【问题描述】:

好的。我正在处理一个用 VBScript 编写的经典 ASP 应用程序。我正在尝试过滤可能通过编码查询字符串出现的 XSS。

我有一个简单的 XSS 消除功能 [getUserInput]。这会寻找特殊字符,如 / ' .... 并用空格替换它们。效果很好。

但是,当我输入通过 Server.URLEncode (VBScript) 或转义 (Javascript) 编码的内容时,显然我上面的过滤器不起作用。

我想知道推荐的解决方案,以防止这种 Unicode 转换的输入使我的页面易受 XSS 攻击。

复制步骤:

<%
Response.Write getUserInput(Request("txt1")) + "<br/>"
Response.Write Server.URLEncode(getUserInput(Request("txt1"))) + "<br/>"
'the below line is where I am trying to decode and echo the input
Response.Write URLDecode2((getUserInput(Request("txt1")))) + "<br/>"
Response.Write "<br/>"
%>

<html>
Try any of the below two encoded strings in the input box and hit the button. </br></br>
alert('hi') </br>
%3Cscript%3Ealert%28%27hi%27%29%3C%2Fscript%3E  <br/>
alert(document.cookie) </br>
%3Cscript%3Ealert%28document.cookie%29%3C%2Fscript%3E <br/> 
</br>
<form method="get" name="form1" id="form1" action="#" onSubmit="CallOnLoad()">
    <input type='text' name='txt1' id='txt1' />
    <button name='btn' type='submit' id='btn'>Hitme</button>
</form>
</html>

<%
function getUserInput(input)

dim newString
newString=input  
newString    = replace(newString,"--","")
newString    = replace(newString,";","")          
  newString    = replace(newString,chr(34),"'") 
  newString    = replace(newString,"'","") 
  newString    = replace(newString,"=","=") 
  newString    = replace(newString,"(","[") 
  newString    = replace(newString,")","]")
  newString = replace(newString,"'","''")
  newString = replace(newString,"<","[")
  newString = replace(newString,">","]")  
  newString = replace(newString,"/*","/") 
  newString = replace(newString,"*/","/")
  getUserInput = newString

end function
%>
<%
'URLDecode2 - source code from http://www.motobit.com/tips/detpg_URLDecode/ 
Function URLDecode2(ByVal What)

  Dim Pos, pPos
  What = Replace(What, "+", " ")
  on error resume Next
  Dim Stream: Set Stream = CreateObject("ADODB.Stream")
  If err = 0 Then 
    on error goto 0
    Stream.Type = 2 'String
    Stream.Open
    Pos = InStr(1, What, "%")
    pPos = 1
    Do While Pos > 0
      Stream.WriteText Mid(What, pPos, Pos - pPos) + _
        Chr(CLng("&H" & Mid(What, Pos + 1, 2)))
      pPos = Pos + 3
      Pos = InStr(pPos, What, "%")
    Loop
    Stream.WriteText Mid(What, pPos)
    Stream.Position = 0
    URLDecode2 = Stream.ReadText
    Stream.Close
  Else 'URL decode using string concentation
    on error goto 0
    Pos = InStr(1, What, "%")
    Do While Pos>0 
      What = Left(What, Pos-1) + _
        Chr(Clng("&H" & Mid(What, Pos+1, 2))) + _
        Mid(What, Pos+3)
      Pos = InStr(Pos+1, What, "%")
    Loop
    URLDecode2 = What
  End If
End Function
%>

我需要在 IIS 7.5/Win 2008 R2 上托管应用程序。 请简单/优雅的建议?

How To: Prevent Cross-Site Scripting in ASP.NET 是一篇好文章,但它对我的场景并不安静,因为我正在处理经典 ASP。

谢谢。

【问题讨论】:

    标签: unicode vbscript asp-classic xss


    【解决方案1】:

    我正在尝试过滤可能的 XSS

    这在很大程度上是浪费时间。

    这种类型的 XSS 是一个输出阶段的问题,是由于将数据插入 HTML 而没有对其进行 HTML 转义而引起的。

    尽管对严重误导的“反 XSS”工具和功能做出了许多努力,但这个问题根本无法通过在输入阶段进行过滤来解决。在输入时,不知道数据将在哪里结束,哪些数据需要进行 HTML 转义(而不是注入到 SQL 或 JavaScript 等其他文本上下文中),以及在该数据结束之前将对其进行什么处理在页面上 - 在您的示例中,您使用 URL 解码来演示这一点,但它可以是任何东西。

    要纠正由&amp;lt;&amp;amp; 引起的问题,您需要记住在您注入输出页面的每个 字符串上调用Server.HTMLEncode,以便将它们转换为&amp;lt;&amp;amp; 分别。这是安全的,并且还允许用户随意使用任何角色,而其中一些角色不会消失。 (想象一下,在删除所有 &amp;lt;s 的情况下尝试将此消息发布给 SO!)

    这样您就不必担心&amp;lt; 的编码版本,因为当您将它们放到页面上时,您已经对其进行了解码,并且可以应用正确的编码形式,即 HTML-逃跑。

    这实际上与 Unicode 无关。非 ASCII 字符可以毫无问题地包含在页面中;只有&amp;lt;&amp;amp; 和在属性值中用作分隔符的引号字符在注入 HTML 时会带来任何危险。

    过去存在过长 UTF-8 序列的问题,其中 &amp;lt; 可能被偷运到无效的最高位集字节序列中,这些字节将通过 HTML 编码保持不变。然后 IE(和 Opera)会将其视为真正的&amp;lt;。如果您在使用具有本机字节字符串而不是 Unicode 的语言使用 UTF-8 时,过滤超长仍然是一个好主意,但这不是以前的必要性,因为所有当前主要浏览器都正确地将超长视为非功能性无效序列。

    使用正确的 HTML 转义,您的示例可能如下所示(省略未更改的 URLDecode2 函数):

    <p>
        <%= Server.HTMLEncode( Request("txt1") ) %> <br/>
        <%= Server.HTMLEncode( URLDecode2(Request("txt1")) ) %>
    </p>
    <p>
        Try any of the below two encoded strings in the input box and hit the button.
    </p>
    <ul>
        <li>&lt;script>alert('hi')&lt;/script></li>
        <li>%3Cscript%3Ealert%28%27hi%27%29%3C%2Fscript%3E</li>
        <li>&lt;script>alert(document.cookie)&lt;/script></li>
        <li>%3Cscript%3Ealert%28document.cookie%29%3C%2Fscript%3E<li>
    </ul>
    <form method="get" action="this.asp">
        <input type="text" name="txt1" value="<%= Server.HTMLEncode( Request("txt1") ) %>"/>
        <input type="submit" value="Hitme"/>
    </form>
    

    (在 ASP.NET 4.0 中,有一个方便的 &lt;%: 快捷方式可以为您执行 &lt;%= Server.HTMLEncode;不幸的是,在经典 ASP 中不是这样。)

    【讨论】:

    • 漂亮!解释清楚:) 我试图展示的例子是指我同意的输出阶段问题。我应该选择更好的复制品。但实际上,我的目标是从查询字符串输入中过滤脚本标签(如果有人尝试通过查询字符串进行注入),我不担心输出阶段,而是我在收到输入后所做的处理。感谢您提供的整洁示例:)格式比我的要好。
    • 如果(由于输出级转义)尝试的攻击永远不会成功,为什么要从输入字符串中过滤字符串"&lt;script&gt;" 或其他任何内容?输入过滤实际上从来没有解决 XSS 攻击,它只会混淆它们,而您使用 URL 解码作为处理步骤的示例就是一个完美的证明。
    • 有道理!
    • 确保根据上下文使用正确的转义。对于 html 属性,转义实际上与标签之间不同。见owasp.org/index.php/…
    • 对 HTML 中的文本内容具有不同转义规则的唯一标签(然后,只有 HTML 而不是 XHTML)是 CDATA 元素:&lt;script&gt;&lt;style&gt;。但是随后将内容注入 JavaScript 和 CSS 字符串文字需要一组不同的规则来完全转义......
    【解决方案2】:

    你应该使用Unescape

    Function getUserInput(input)
    dim newString
    '***********************
    newString=Unescape(input)
    '***********************
    newString    = replace(newString,"--","")
    'etc ...
    'etc ...
    'etc ...
    End Function
    

    【讨论】:

    • 嗯。那很整洁。我不知道 VBscript 中存在 Unescape。我想我无论如何都不需要 URLDecode2 函数。所以,我要试试这个解决方案。除非有人不同意,否则这对我来说似乎很简洁和可取。
    • 不客气。此外,我建议您阅读 Mike 的回答。
    • 迈克的回答?还是bobince的回答?
    【解决方案3】:

    当您在 xml builder asp 中有要解析的字符串时。你可以像这样创建它:

    <description><![CDATA[ "& descriptionString &"]]></description>
    

    您可以使用 HTML 剥离功能来剥离不需要的 html 或转义 html 标签:

    Function stripHTML(strHTML)
    Dim objRegExp, strOutput
    Set objRegExp = New RegExp
        with objRegExp
            .Pattern = "<(.|\n)+?>"
            .IgnoreCase = True
            .Global = True
        end with
    
    'Replace all HTML tag matches with the empty string
    strOutput = objRegExp.Replace(strHTML, "")
    Set objRegExp = Nothing
    
    'Replace all < and > with &lt; and &gt;
    strOutput = Replace(strOutput, "<", "&lt;")
    strOutput = Replace(strOutput, ">", "&gt;")
    stripHTML = strOutput   
     'Return the value of strOutput
    End Function
    

    另一个用于防止 SQL 注入的。例如从 Form get/post 解析 requests.querystrings。

    function SQLInject(strWords)
     dim badChars, newChars, tmpChars, regEx, i
     badChars = array( _
     "select(.*)(from|with|by){1}", "insert(.*)(into|values){1}", "update(.*)set", "delete(.*)(from|with){1}", _
    "drop(.*)(from|aggre|role|assem|key|cert|cont|credential|data|endpoint|event|f ulltext|function|index|login|type|schema|procedure|que|remote|role|route|sign| stat|syno|table|trigger|user|view|xml){1}", _
    "alter(.*)(application|assem|key|author|cert|credential|data|endpoint|fulltext |function|index|login|type|schema|procedure|que|remote|role|route|serv|table|u ser|view|xml){1}", _
    "xp_", "sp_", "restore\s", "grant\s", "revoke\s", _
    "dbcc", "dump", "use\s", "set\s", "truncate\s", "backup\s", _
    "load\s", "save\s", "shutdown", "cast(.*)\(", "convert(.*)\(", "execute\s", _
    "updatetext", "writetext", "reconfigure", _
    "/\*", "\*/", ";", "\-\-", "\[", "\]", "char(.*)\(", "nchar(.*)\(")  
    
     newChars = strWords
     for i = 0 to uBound(badChars)
         Set regEx = New RegExp
         regEx.Pattern = badChars(i)
         regEx.IgnoreCase = True
         regEx.Global = True
         newChars = regEx.Replace(newChars, "")
         Set regEx = nothing
     next
     newChars = replace(newChars, "'", "''")
     SqlInject = newChars
    end function
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多