chang_00

By Sau Sheong Chang

In this article, excerpted from my book Go Web Programming, I show you how to create an HTML form that allows you to submit data to your web application and place it in a form.html file.

A common XSS attack is the persistent XSS vulnerability. This happens when data provided by an attacker is saved to the server and then displayed to other users as it is. For example, say there is a vulnerable forum site, which allows its users to create posts or comments to be saved and read by other users. An attacker can then post a comment that includes malicious JavaScript code within the <script> tag. Since the forum displays the comment as it is and whatever is within the <script> tag is not shown to the user, the malicious code is executed with the user’s permissions but without the user’s knowledge. The normal way to prevent this is to escape whatever is passed into the system before displaying or storing it. However, as with most exploits and bugs, the biggest culprit is the human factor.

Let’s jump on some code now. Let’s create an HTML form that allows us to submit data to our web application and place it in a form.html file.


Listing 1  Form for submitting XSS attack

<html>
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <title>Go Web Programming</title>
   </head>
   <body>
     <form action="/process" method="post">
       Comment: <input name="comment" type="text">
      <hr/>
      <button id="submit">Submit</button>
     </form>
   </body>
 </html>

Then we change our handler accordingly to process the data from this form:


Listing 2  Testing an XSS attack

package main
  
 import (
   "net/http"
   "html/template"
 )
  
 func process(w http.ResponseWriter, r *http.Request) { 
 t, _ := template.ParseFiles("tmpl.html") 
   t.Execute(w, r.FormValue("comment"))
 }
  
 func form(w http.ResponseWriter, r *http.Request) { 
   t, _ := template.ParseFiles("form.html") 
   t.Execute(w, nil) 
 }
  
 func main() {
   server := http.Server{
     Addr: "127.0.0.1:8080",
   }
   http.HandleFunc("/process", process)
   http.HandleFunc("/form", form)
   server.ListenAndServe()
 }

In our tmpl.html we clean up the output a bit to let us see the results better.


Listing 3  Cleaned up tmpl.html

<html>
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <title>Go Web Programming</title>
   </head>
   <body>
     <div>{{ . }}</div>
   </body>
 </html>

Now let’s compile the server and start it up, then go to http://127.0.0.1:8080/form. Enter this into the input text field and click on the submit button:

<script>alert('Pwnd!');</script>

 

chang_01

Figure 1  Form for creating a XSS attack


A web application using a different template engine that doesn’t scrub the input and displays user input directly on a web page will get an alert message, or potentially any other malicious code that the attacker writes. As you would probably realize, the Go template engine protects you from such mistakes because even if you don’t scrub the input, when the input is displayed on the screen, it will be converted into escaped HTML.


chang_02

Figure 2 Input is escaped


If you inspect the source code of the page you’ll see something like this:

<html>
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     <title>Go Web Programming</title>
   </head>
   <body>
     <div>&lt;script&gt;alert(&#39;Pwnd!&#39;);&lt;/script&gt;</div>
   </body>
 </html>

This doesn’t just work on HTML, it also works on XSS attacks on JavaScript, CSS and even URLs. Does this mean we’re saved from ourselves if we use the Go template engine? Well, no, nothing really saves us from ourselves and there are ways of getting around this. In fact Go allows us to do this if we really want to.