Protecting Against Malicious Users


Unfortunately, malicious users are out there, ranging from the casual to the very serious. If your Ajax application involves credit card use or other sensitive data, that application may be open to abuse.

The problem with Ajax applications is that the way you deal with the server is by using JavaScript, and that JavaScript is visible to all. Even placing that JavaScript in a .js file on the server offers no relief-those .js files are easily downloaded. Even if you create the JavaScript on the fly, as with a PHP script, it’s still easily accessible by the user, who has only to view the page source.

That means you have to assume that, security-wise, users have access to your JavaScript, which means they can figure out how your application deals with the server. In simple terms, for example, you might access this URL on the server to record a user’s score:

 scorekeeper.cgi?score=21 

Not much is stopping users from figuring this out and uploading fictitious scores, like this:

 scorekeeper.cgi?score=2221

All of which means that you have to be very careful with the data sent to you from the browser-and never execute that data as code, which is one of the primary doors through which hackers enter.

Note 

Not even appending a checksum, uniquely generated by some algorithm based on the score you’ve come up with, will help:

 scorekeeper.cgi?score=2221;checksum=3949503

Appending a checksum doesn’t help because the code you use to generate that checksum is in your application’s JavaScript, in plain view, and easily copied and used.

The JavaScript in an Ajax application is always very public. For that reason, a primary rule of Ajax security is to keep the business rules code (that is, the in-depth, core code) on the server. You should never expose more code than necessary.

Tip 

You can also try to make your JavaScript unreadable, a process known as obfuscation, which replaces characters with character codes, and so on. There’s a limit to the obfuscation you can perform, of course, because the browser needs to read your JavaScript, but if you’re interested, take a look at www.semdesigns.com/Products/Obfuscators/ECMAScriptObfuscationExample.html.

JavaScript insertion

Another malicious technique is JavaScript insertion, where users insert JavaScript into their response, and when you display that response in the browser, that JavaScript executes. For example, Yahoo! Mail was hijacked by the Yamanner worm recently, which exploited the software’s ability to include JavaScript in e-mail.

Following is an example, comments.html, which accepts and displays user comments and displays. To work through the examples in this chapter you need access to a Web server, because security solutions are often implemented on the server. A good Web server for this purpose is the Apache Tomcat server because it handles security in both a very powerful and easily generalized way.

Note 

You can pick up a copy of Tomcat, which is a Java-based server, for free at http://tomcat.apache.org/.

Here’s what comments.html looks like; it’s just a straightforward Ajax application that reads and displays user comments:

 <html>    <head>      <title>Display your comments</title>      <script language = "javascript">       var XMLHttpRequestObject = false;        if (window.XMLHttpRequest) {         XMLHttpRequestObject = new XMLHttpRequest();       } else if (window.ActiveXObject) {         XMLHttpRequestObject = new          ActiveXObject("Microsoft.XMLHTTP");       }       function getData(dataSource, divID)        {          if(XMLHttpRequestObject) {           var obj = document.getElementById(divID);            XMLHttpRequestObject.open("GET", dataSource +              "?text=" + escape(document.getElementById               ("text").value));            XMLHttpRequestObject.onreadystatechange = function()            {              if (XMLHttpRequestObject.readyState == 4 &&                XMLHttpRequestObject.status == 200) {                  obj.innerHTML =                    XMLHttpRequestObject.responseText;              }            }            XMLHttpRequestObject.send(null);          }       }     </script>   </head>    <body>     <H1>Display your comments</H1>     <form>       Enter your comments:       <input type = "text" name="text">        <br>       <br>       <input type = "button" value = "Display your comments"          onclick = "getData('comments.     </form>     <div >       <p>The fetched data will go here.</p>      </div>      </body>  </html>  

The Tomcat Web server supports Java code in JavaServer Pages (JSP) and Java servlets. JSPs are easier to work with, and use this markup to enclose Java code:

 <%    .    .    . %>

You can get the comments the user typed, sent to the server under the parameter name text, like this:

 <%   String text = request.getParameter("text");         .         .         . %>

That creates a Java String object containing the user’s comments. To display those comments, you can use the JSP out object’s println method, which sends text back to the browser:

 <%   String text = request.getParameter("text");   out.println("You typed ");   out.println(text); %>

This works fine, but it does allow the user to insert HTML, as shown in Figure 15.1, where the user has entered some comments.

image from book
Figure 15.1: The comments.html page

In this case, the user entered the relatively harmless HTML "<i>Hello</i> there." But what if he or she had entered HTML that included JavaScript code, such as this JavaScript, designed to redirect the browser to a malicious site:

 <script>location.href=www.malicious-site.com</script>

That’s an example of JavaScript insertion, and one way to fight against it is to convert sensitive HTML characters like < and > into their escaped and harmless equivalents, &lt; and &gt;. Escaping HTML characters like this renders HTML elements harmless.

You can perform this kind of conversion in Java using the String class’s replaceAll method, like this:

 <%    String text = request.getParameter("text");    text = text.replaceAll("<", "&lt;");    text = text.replaceAll(">", "&gt;");    out.println("You typed ");    out.println(text); %>

Now when you click the Display your comments button, you see the HTML itself, as shown in Figure 15.2.

image from book
Figure 15.2: Blocking HTML

The previous example demonstrated a way of defusing JavaScript insertion. Another type of malicious insertion you should guard against is SQL insertion. Believe it or not, some Ajax applications send SQL directly to the server, and, of course, it’s easy to modify that SQL maliciously. The main solution for SQL insertion, like the solution for so many Ajax security issues, is to leave the business rules, including SQL generation, on the server.

You should carefully check all data coming from the browser; one way hackers break or control applications is by feeding them invalid data.

For example, take a look at array.html, which asks users what element they want to fetch from an array on the server. Here’s what the code looks like:

 <html>    <head>      <title>Display an array element</title>      <script language = "javascript">       var XMLHttpRequestObject = false;        if (window.XMLHttpRequest) {         XMLHttpRequestObject = new XMLHttpRequest();       } else if (window.ActiveXObject) {         XMLHttpRequestObject = new            ActiveXObject("Microsoft.XMLHTTP");       }       function getData(dataSource, divID)        {          if(XMLHttpRequestObject) {           var obj = document.getElementById(divID);            XMLHttpRequestObject.open("GET", dataSource +              "?index=" + escape(document.getElementById               ("index").value));            XMLHttpRequestObject.onreadystatechange = function()            {              if (XMLHttpRequestObject.readyState == 4 &&                XMLHttpRequestObject.status == 200) {                  obj.innerHTML =                    XMLHttpRequestObject.responseText;              }            }            XMLHttpRequestObject.send(null);          }       }     </script>   </head>    <body>     <H1>Display an array element</H1>     <form>       Which array element do you want?       <input type = "text" name="index">        <br>       <br>       <input type = "button" value = "Display the element"          onclick = "getData('array.     </form>     <div >       <p>The fetched data will go here.</p>      </div>    </body>  </html> 

In the server-side script, array.jsp, you can create an array of strings like this in Java:

 <%    String[] array = {"tic", "tac", "toe"};          .          .          . %>

That creates the array ["tic", "tac", "toe"]. You can get the index of the element the user requested using the expression request.getParameter("index"), but that returns the index as a string. To convert that string to an integer array index you can work with, you can use the Integer class’s parseInt method this way:

 <%    String[] array = {"tic", "tac", "toe"};     int index = Integer.parseInt(request.getParameter("index"));          .          .          . %>

Now you can display the requested array element in the browser like this:

 <%    String[] array = {"tic", "tac", "toe"};    int index = Integer.parseInt(request.getParameter("index"));    out.println("The array element is ");    out.println(array[index]); %>

That works fine as long as you enter an array index from 0 to 2, as shown in Figure 15.3.

image from book
Figure 15.3: The array.html page

But if you enter an illegal value, you won’t see any response from the server because an error occurred and the out.println statements weren’t reached, as shown in Figure 15.4.

image from book
Figure 15.4: An error in the array.html application

This kind of error is easily overlooked, but it’s the source of some major problems. Until Microsoft patched the problem, Windows suffered from numerous array-overrun vulnerabilities where hackers used illegal array indices to overwrite legitimate Windows code.

The solution here is simply to do some bounds checking to make sure the index is legal for your array. Here’s how you can check whether you’re not dealing with a legal index and send an error message back to the browser:

 <%   String[] array = {"tic", "tac", "toe"};   int index = Integer.parseInt(request.getParameter("index"));   if(index < 0 || index > array.length){     out.println("Sorry, that array element is out of bounds.");   }     .     .     . %>

If the array index is legitimate, you can send back the array element, as shown here:

 <%   String[] array = {"tic", "tac", "toe"};   int index = Integer.parseInt(request.getParameter("index"));   if(index < 0 || index > array.length){     out.println("Sorry, that array element is out of bounds.");   }   else {     out.println("The array element is ");     out.println(array[index]);   } %>

Now if you enter an illegal value, you’ll get an error message, as shown in Figure 15.5.

image from book
Figure 15.5: Handling an error in the array.html application



Ajax Bible
Ajax Bible
ISBN: 0470102632
EAN: 2147483647
Year: 2004
Pages: 169

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net