Labels

Monday, June 28, 2010

Web Application Security

1. Cross-Site Scripting

Cross-site scripting (XSS) is a threat where the attacker can inject code into a Web
application which gets executed at the visitor’s site. This is possible whenever the
input of the user gets displayed on the Web site again, for example in guest books.
This attack form can be used to exploit browser bugs like buffer overflows and
ActiveX flaws or to steal cookies

1.1 Protection: Approach I
      Filter HTML Characters
The simplest approach to disable cross-site scripting is the filtering of HTML characters.
         > =  &gt
         < =  &lt
         ”  =  &quot
        & =  &amp
If you put this sanitized code in an HTML environment it should keep you save
from cross-site scripting bugs. But imagine this code:





This allows a lot of query strings that don’t include any “forbidden characters”.
For example this query string would redirect every visitor to my Web site:
str=Welcome!’);location.href=’http://www.patrice.ch/’;//
So always check if you really have replaced all characters that can be used to
escape the current environment. In the example above this would at least include
the single quote. You should also escape the backslash in JavaScript, as it might be
possible to abuse it.

<%
Function cHtml(str)
   s = str

  s = Replace(s, "&", "&")
  s = Replace(s, ">", "&qt;")
  s = Replace(s, "<", "<")
  s = Replace(s, """", """)

     cHtml = s
End Function

str = cHtml(Request("str"))
%>

<html>
     <head>
        <title>custom JavaScript</title>
             <script language="JavaScript">
                  function cmsg() {
                  alert('custom message: <%=str%>');
         }
</script>
</head>
      <body onload="cmsg()">
           This displays a custom message on page load.
</body>
</html>

1.2 Protection: Approach II
      Only Allow a Limited Character Set
The first approach works quite well if you want to disallow any HTML. But from a
security point of view it’s far from ideal, because it only forbids the characters that
are dangerous today. With the next great browser there might be some other way
to inject a script into the page. So it’s recommended to allow only a minimal set of
characters. For example only letters, numbers and newlines.
This code works fine to disable any character not included in the constant
allowed. It also allows newlines.
’ Replace all evil characters
  Function cHtml(ByVal s)
      Dim i
      Dim snew
Const allowed="abcdefghijklmnopqrstuvwxyz" & _
                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" & _
                        "0123456789.,!:;" & vbCrLf
snew=""
For i = 1 To Len(s)
       If Instr(1, allowed, Mid(s, i, 1))>0 Then
       snew = snew & Mid(s, i, 1)
   End If
Next

   cHtml = snew
End Function

I have implemented this approach with the function limitStr in appendix A.

1.3 Protection: Approach III
         Safely Allow Some Tags

If you really want to allow the user to insert HTML tags, the most secure way for
this is to first sanitize all data using approach I (see section 1.1) and then re-replace
all allowed tags. For example:

<%
Function cHtml(str)
  s = str

  s = Replace(s, "&", "&")
  s = Replace(s, ">", "&qt;")
  s = Replace(s, "<", "<")
  s = Replace(s, """", """)

  cHtml = s
End Function

Function htmlIze(str)
    Dim s

    s = cHtml(str)

'Allowed tags, b, i, u

      s = Replace(s, "<b>", "<b>", 1, -1, 1)
      s = Replace(s, "</b>", "</b>", 1, -1, 1)
      s = Replace(s, "<i>", "<i>", 1, -1, 1)
      s = Replace(s, "</i>", "</i>", 1, -1, 1)
      s = Replace(s, "<u>", "<u>", 1, -1, 1)
      s = Replace(s, "</u>", "</u>", 1, -1, 1)

   htmlIze = s
    End Function

 str = htmlIze(Request("str"))
 %>

<html>
    <head>
       <title>htmlIze</title>
            </head>
<body>
     This was your text:
     <p><%=str%></p>
</body>
</html>

1.4 Common Pitfalls
Case sensitivity If you replace strings, replace everything case insensitive. The
Replace function has a parameter for this. The last argument defines, whether
to compare the strings binary (0) or as text (1):

s = Replace(s, "<script>", "", 1, -1, 1)

Note: I don’t recommend to only replace some “hostile” tags, because this
approach is very risky and prone to changes in the browsers. Additionally
you will most probably miss a few tags or attributes. So if you really need to
allow the user to insert some tags, see section 1.3.

Newlines When you want to strip out single tags, make sure that you also replace
them over newlines. Assume this script:

s = Request("str")
s = Replace(s, "<script>", "", 1, -1, 1)
Response.Write str
The intention is to remove every occurrence of the tag “script”, it’s even case
insensitive. Now this can be circumvented with this query string:

str=%3Cscript%0D%0A%3Ealert(’testing’)%3C%2Fscript%3E
Or to make it more human readable:
str=alert(’testing’) There is now a newline (%0D%0A) right before the closing bracket. As HTML ignores this newline, the script will execute. To fix this vulnerability, this code can be used:
s = Request("str")
' replace newline combinations
s = Replace(s, "<" & vbCr, "<")
s = Replace(s, "<" & vbLf, "<")
s = Replace(s, vbLf & ">", ">")
s = Replace(s, vbCr & ">", ">")
s = Replace(s, "<script>", "", 1, -1, 1)
Response.Write str

Check all data Make sure that you really check all supplied data. A common
problem is, that the form data is cleansed before displaying on the page, but
the database data isn’t. The best approach to prevent that kind of problems
is to define for every table whether the data in it is sanitized or not. So the
developers know when they have to HTML-ize the data: either when putting
it into the table or when using it for HTML output.
I recommend you to protect all data against SQL injection directly when
getting the input from the client. If you follow this approach you can use the
checker script to check your code for bugs. See section 4.3 for information.
But when I use approach 1, I usually protect against XSS when displaying
the content. One reason for this is, that this way I can use the same data for
displaying on a HTML page and for sending in mails, etc.
 

No comments:

Post a Comment