在经典ASP中过滤编码的XSS

时间:2011-09-29 14:24:13

标签: unicode vbscript asp-classic xss

确定。我正在处理在VBScript上编写的经典ASP应用程序。我试图过滤可能来自编码查询字符串的可能的XSS。

我有一个简单的XSS消除函数[getUserInput]。这会寻找像<等特殊字符。 > /'....并用空格替换它们。这非常有效。

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

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

Repro步骤:

<%
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是一篇很好的文章,但是当我处理Classic ASP时,它对我的​​场景并不安静。

感谢。

3 个答案:

答案 0 :(得分:8)

  

我正在尝试过滤可能的XSS

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

这种XSS是一个输出阶段的问题,是因为将数据插入HTML而不是HTML转义它。

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

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

这样您就不必担心<的编码版本,因为当您将它们放在页面上时,您将对它们进行解码,并且可以应用正确的编码形式,即HTML转义。

这与Unicode无关。非ASCII字符可以包含在页面中而不会出现任何问题;它只是<&,并且在属性值中,引号字符被用作分隔符,在注入HTML时会出现任何危险。

过去的UTF-8序列曾经存在问题,其中<可以在无效的顶级位设置字节序列中走私,这些字节将通过HTML编码保持不变。然后IE(和Opera)将其视为真正的<。虽然如果你使用具有本机字节字符串而不是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中,有一个方便的<%:快捷方式可以为您执行<%= Server.HTMLEncode;不幸的是,在经典ASP中没有这样做。)

答案 1 :(得分:1)

您应该使用Unescape

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

答案 2 :(得分:1)

当您在xml构建器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注入的方法。从表格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