Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering Encoded XSS in Classic ASP

ok. I am dealing with a Classic ASP app written on VBScript. I am trying to filter possible XSS that might come via encoded Query string.

I have a simple XSS elimination function in place [getUserInput]. This looks for special charactors like < > / ' .... and replaces them with blank space. That works pretty well.

But, when I input something that is encoded via Server.URLEncode (VBScript) or escape (Javascript), obviously my above filter does not work.

I want to know the recommended solutions that are in place to prevent this Unicode converted input that makes my page vulnerable to XSS.

Repro steps:

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

I am required to host the app on IIS 7.5/Win 2008 R2. Simple/elegant advices please?

How To: Prevent Cross-Site Scripting in ASP.NET is a good article, but it does not quiet to my scenario as I am dealing with Classic ASP.

Thanks.

like image 597
gmaran23 Avatar asked Dec 28 '22 13:12

gmaran23


2 Answers

I am trying to filter possible XSS

This is largely a waste of time.

This breed of XSS is an output-stage issue, caused by inserting data into HTML without HTML-escaping it.

Despite the many efforts of deeply misguided “anti-XSS” tools and function, this problem simply cannot be handled by filtering at the input phase. At input time it is not known where data will end up, which data will need to be HTML-escaped (as opposed to injected into other text contexts like SQL or JavaScript), and what processing will be done to that data before it ends up on the page—in your example's case you're demonstrating this with URL-decoding, but it could be anything.

To correct problems caused by < and &, you need to remember to call Server.HTMLEncode on every string you inject into your output page, so that they'll be converted into &lt; and &amp; respectively. This is safe and will also allow users to use any character at will without some of them disappearing. (Imagine trying to post this message to SO with all the <s removed!)

That way you don't need to worry about encoded versions of <, because by the time you come to put them on the page you will have decoded them, and can apply the correct form of encoding, namely HTML-escaping.

This is not really anything to do with Unicode. Non-ASCII characters can be included in a page without any issues; it is only <, &, and in attribute values the quote character being used as a delimiter, that present any danger when injected into HTML.

There used to be a problem with over-long UTF-8 sequences, where a < could be smuggled in an invalid sequence of top-bit-set bytes that would get through HTML-encoding unchanged. Then IE (and Opera) would treat it as a real <. Whilst it's still a good idea to filter overlongs if you are working with UTF-8 in a language that has native byte strings rather than Unicode, it's not the necessity it once was as all current major browsers treat overlongs correctly, as non-functional invalid sequences.

Using correct HTML-escaping, your example might look like this (omitted the unchanged URLDecode2 function):

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

(In ASP.NET 4.0 there is a handy <%: shortcut to do <%= Server.HTMLEncode for you; unfortunately not so in Classic ASP.)

like image 191
bobince Avatar answered Dec 30 '22 09:12

bobince


You should use Unescape.

Function getUserInput(input)
dim newString
'***********************
newString=Unescape(input)
'***********************
newString    = replace(newString,"--","")
'etc ...
'etc ...
'etc ...
End Function
like image 39
Kul-Tigin Avatar answered Dec 30 '22 10:12

Kul-Tigin