//Cyber Battlefield/Server Side Scripting

In previous lessons we explored client side scripts, which are programs embedded in the HTML code for a web page; programs that the browser (web client) executes. In this lesson, we explore server side scripts, which are programs that the web server machine runs in response to something done by a web client (browser).

A first look at a server side script

A server side script is a program run on a web server that generates content (usually HTML) for a web client or otherwise responds to some web client action. The simplest server side script is one that generates HTML content which then gets sent to the browser on the other end. These scripts can be written in a number of languages, including JavaScript. Of course we'll use JavaScript, since we already know it. We start off by looking at an old familiar example: a script that writes "G O N A V Y !" 1,000 times. We've already done this as a client side script, now we'll do this as a server side script. To start off with, look at these links:
  1. ex0.html, client side
  2. ex0.jsx?, server side
  3. ex0.jsx, server side (source)
Note that the link to the script has the "?" at the end, indicating to the server that it's a script to execute and not a file to serve/send. The code for the server side is almost the same as the client side. The big difference is: what gets executed where, and what actually gets sent. The following should illustrate the differences:
Client Side – client sends GET for ex0.html
Server finds
<HTML>
  <HEAD> ... </HEAD>
  <BODY>
    <SCRIPT type="text/javascript">
      var iter = 0;
      while (iter < 1000) {
        document.write("G O N A V Y ! ");
        iter = iter + 1;
      }
    </SCRIPT>
  </BODY>
</HTML>
, server sends
<HTML>
  <HEAD> ... </HEAD>
  <BODY>
    <SCRIPT type="text/javascript">
      var iter = 0;
      while (iter < 1000) {
        document.write("G O N A V Y ! ");
        iter = iter + 1;
      }
    </SCRIPT>
  </BODY>
</HTML>
, browser executes & renders as

Server Side – client sends GET for ex0.jsx?
server finds & executes
function () {
  var out = "";
  var iter = 0;
  while(iter < 1000) {
    out = out + "G O N A V Y ! ";
    iter = iter + 1;
  }
  return out;
}
, server sends
, browser renders as
Now, which version do you think is better for this job of printing GO NAVY! 1,000 times? Why? Which side assumes risk of running vulnerable code in each version?

Sending data to server side scripts with forms

Let's consider a very simple interactive web-page that converts a temperature in Fahrenheit into Celsius. We'll look at a client side version of this and a server side version, side-by-side.
Client Side Fahrenheit-to-Celsius Converter Server Side Fahrenheit-to-Celsius Converter
°F

(shift+refresh to return)
°F

(browser back-button to return)
<form name="clientSide" onsubmit="return false;">
  <input type="text" name="fahrenheit"> &#176;F
  <input type="button" value="Convert" 
	 onclick="var f = document.forms.cc.fahrenheit.value;
		  var c = 5/9*(f - 32);
		  document.body.innerHTML = c + ' &#176;C';
		  ">
</form>
<form name="serverSide"
	  action="http://rona.academy.usna.edu/~sy110/lec/wwwSrvr/f2c.jsx" 
	  method="get">
  <input type="text" name="fahrenheit"> &#176;F
  <input type="button" onclick="submit();" value="Convert">
</form>

Verify that both work, then try look for differences in how they work from the user's perspective. You should notice that the client side version keeps you at the same URL. The client side form has onsubmit="return false;" and a small Mathematical computation after the onclick for the button input. The server side version, however, takes you to a different URL — and a strange one at that! The server side URL ends with something like:

f2c.jsx?fahrenheit=45
Additionally, while the form also has onsubmit="return false" there are two additional attributes within the form start tag: action and method, and finally, the onclick for the button input has the value "submit()". These are the key differences that tell you, the user, that the page will send input to the server for processing.

There are two basic mechanisms for sending arguments (inputs) to server side scripts: GET and POST. The GET mechanism is simpler and is what we see here as a value for the method attribute. The GET method sends the user's input as part of the URL. Recall that the server will record the file system path of a GET request URL in its server access logs. So, in this case, the file system path contains the user's input and this means that the value a user enters into a form executing a server side script will be permanently entered into the server's access logs.

The URL for the script ends with a "?" followed by name=value pairs that give the names and values of the parameters the server side script will use as inputs. Interestingly, we don't need the nice fancy web page with the form field and button in order to use this conversion script. Simply enter the URL
http://rona.academy.usna.edu/~sy110/lec/wwwSrvr/f2c.jsx?fahrenheit=78
in your browser's address bar with different values for "fahrenheit" and you can get the conversions directly. In other words, without typing anything into the form and without clicking the button, you can send a GET request. The server still processes your input, sending the browser the results. This presents a potential security risk if the server side program (script) has not taken into account unanticipated user input.

Here are a couple of URLs from the wild that you can copy and paste into your browser's address bar, then edit the name=value pairs - look for the = signs and edit the content on the right-side of the = sign. You should have noticed that in both URLs above, there are multiple arguments (inputs) which are separated by &'s. Usually, each text box on the form will generate a name=value pair in the URL, but there may be other aspects on the page that also contribute to a name=value pair in the URL.

f2c.jsx
function(fahrenheit) {
   var c = 5/9*(fahrenheit - 32);
   return c + ' &#176;C';
}
The server side script f2c.jsx is very simple, as you see - the code performs that same Mathematical computation that the client side version performed. In looking at it, don't worry about the function(fahrenheit){ ... } wrapped around the code except to accept that it's there, and to know that inside the ( )'s is/are the parameter (input) names that the code needs to execute. If more than one parameter name is expected, then each name is separated by commas. The corresponding form on the page will contain an input element for each of these function parameters in the ( )'s for the server side script. So, in the case of the f2c.html file, there is a form with a text box that accepts user input: <input type="text" name = "fahrenheit"> which is not a coincidence. The names of the inputs in the form must match the parameter names for the server side script.
The script ends by returning a string. That string becomes the <body> contents of the HTML code that gets sent to the browser. These server side scripts can do many things, including read from and write to files sitting on the server. How one would do that with JavaScript is way outside the scope of this course and, actually, is dependent on the particular JavaScript interpreter you're using. We're using the JSEXT interpreter, in case you'd like to look into this more deeply.

Now, let's turn to the browser's part in a server side scripted system. We could make use of server side scripts using only the tools we already know: we could write client side scripts that build a URL string with the name/value pairs determined by some interaction with the user. However, that's not how it's usually done. Usually server side scripts are called automatically using a feature of forms we haven't yet discussed: submit. Form elements were actually introduced specifically to get user input and call server side scripts. There is a DOM function called submit() that automatically grabs the value attribute for each named form input element, and builds the name/value pairs from the names and values of those input elements. The first part of the URL that will be called, i.e. everything before the "?", comes from the form's action attribute. Recall the server side example's form element was defined like this:

<form name="cs" 
	  action="http://rona.academy.usna.edu/~sy110/lec/wwwSrvr/f2c.jsx" 
	  method="get">
  <input type="text" name="fahrenheit"> &#176;F
  <input type="button" onclick="submit()" value="Convert">
  </form>
Here's how things work:
  1. The user enters a value (say, 78.3) in the fahrenheit named text-input.
  2. The user clicks the Convert button.
  3. The button's onclick script is executed, which simply calls the submit() function from the DOM - this is a client side action.
  4. The submit function builds a URL as follows (because the form's method attribute is GET):
    http://rona.academy.usna.edu/~sy110/lec/wwwSrvr/f2c.jsx?fahrenheit=78.3
           \______________________________________________/ \________/ \__/
        from the FORM's "action" attribute                   INPUT      INPUT element's
                                                             element's  value
                                                             name	  
  5. The browser sends the above link in a GET request to the server specified in the URL.
  6. The server executes and returns the new page - logging the GET request in its access logs.

Now we are in a position to understand why our client side only use of forms always included the form attribute definition onsubmit="return false;", it was to stop the browser from trying to form a URL and pull up a new page!

Note: if you hit enter after typing something into the text box, the form is automatically submitted. This can be turned off, but it's a bit of a pain, since Explorer does it differently than the other browsers. One way to do this is to keep the form element's onsubmit="return false;" attribute definition. When our button calls submit(), the form's onsubmit is bypassed.

A silly exercise

Here's a bit of a silly exercise, but one that will show whether or not you've got the mechanism down for all of this: Create a web page that takes a number from the user and prints that many GONAVY!'s. You should be able to modify existing scripts and web pages to make that work for both client side and server side.

Question 1: if you choose a big number, which version is faster?

Question 2: why?

The Trap of Client-Side Validation
In an October 2012 blog post, Chris Foster pointed out a vulnerability in a JavaScript library called filepicker.io. The vulnerability boils down to this: they use client side input validation and, as we know, an attacker can bypass client side validation.

Lots of businesses and individuals are moving to "cloud storage", which means that a big company (like amazon.com) stores your data for you, and you / your company can access the data from anywhere. Filepicker.io is a JavaScript library (http://api.filepicker.io/v0/filepicker.js) that you include in your HTML just like we've already done, and it provides easy-to-use functions that allow the website to give users the ability to upload files to cloud storage space owned by the website. Now, the website will be charged more or less money for that cloud storage depending on how many gigabytes of storage they use. For that reason (and others) the site needs to limit the size of files that can be uploaded. Filepicker.io provides that functionality, but checks the file size client side. In the blog post, Mr. Foster demonstrates that he can send the the same GET requests to cause a file to be uploaded to a site's cloud storage that the filepicker.io library would send from a script that he wrote (a glorified application of netcat). The difference is that, with his script, the client side validation code is completely bypassed. Thus, he can lie about the file-size when he uploads with his script, and can upload as big a file as he likes to the website's cloud storage ... which could end up costing big money!

Validation / Sanitizing Input

If a user wanted to print 10,000,000 GONAVY!'s in his browser window using a client side script, that'd be his own business. If a user wanted to do that using a server side scripted system, on my server, that'd be another matter altogether. It'd be my server that was slowed down processing the script, and all that silly data would be sent out over my network. So I'd like to put a limit, maybe of 5,000, on the size of the number I'd allow my server script to process. This means that I should check the number and refuse the request if it's too big ... or, I suppose, if it's not a valid number. This is called input validation. I might also decide to change the value of the user input to something that is acceptable. In this case we say we're sanitizing the input. There are two places I could decide to do validation and sanitizing of user input, on the client or on the server.

Let's look at client side validation first. Your instructor will have a a server side script for you like this:

function (N) {
  var out = "";
  var iter = 0;
  while(iter < N)
  {
    out = out + "G O N A V Y ! ";
    iter = iter + 1;
  }
  return out;
}
that you can use. It's expecting a URL with a name/value pair for the name N, like this: "?N=800". The web page should take N, the number of times to print GONAVY!, from the user via forms, and call the server side script with it. When you have that working, modify the HTML form so it refuses to submit to the server with N > 5,000. Only if N < 5000 should the JavaScript attached to the button's onclick attribute should execute submit(). (Remember to keep the form's onsubmit="return false;" set.)

So, instead of just the onclick = "submit()" you need to insert an if statement that checks to see if the value the user entered into the input text box for N is > 5,000, and either sanitize that value (change it) or do nothing and include an else for the submit().

This is client side validation. It is not the best choice for validation and sanitizing user input when using a server side script. What's the problem here? Well, someone who's up to no good can still hammer my server with requests for N=999999999999 because they can always craft the appropriate URL without using the original web page (the form and the button), thus bypassing my client side validation. In other words, if the user understands HTML forms and JavaScript, the user can view the HTML source code, and see the client side validation, build the appropriate URL, never clicking the button, thus never executing that if statement you just put into your HTML source code to stop user's from sending a larger N value to the server. The browser simply sends the GET request for the URL the user built to the server with N=999999999999. The server crashes. Therefore it's critical to also use server side validation when there is a server side script. In this case. we could do something simple like this in the server side script itself:

function (N) {
  if (N > 5000) {
    N = 0;
  }
  var out = "";
  var iter = 0;
  while(iter < N) {
    out = out + "G O N A V Y ! ";
    iter = iter + 1;
  }
  return out;
}

This is server side input validation ( if (N > 5000)) and server side sanitizing user input ({ N = 0; }). Now, it doesn't matter whether the user uses the form or the URL to send the GET request. The server is protected.

Extra Example You Can Try

There is a script at
http://rona.academy.usna.edu/~sy110/lec/wwwSrvr/checkers.jsx
that creates a page with a nice checkerboard pattern whose dimensions are given to the script as values named rows and cols.

Try to craft a URL from that information alone to get a page with the checkerboard pattern. [click to show answer]

Next, try to create an HTML file with a form that allows the user to enter a number of rows and a number of columns and submits them to the script to get the checkerboard pattern. Use one of the examples from above as a starting point. [click to show answer]