Skip to content

Latest commit

 

History

History
66 lines (43 loc) · 2.99 KB

File metadata and controls

66 lines (43 loc) · 2.99 KB

#4.3 Cross site scripting Today's websites have much more dynamic content in order to improve user experience, which means we can provide dynamic information depends on every individual's behavior. However, there is a thing called "Cross site scripting" (known as "XSS") always attacking dynamic websites, and static websites are completely fine at this time.

Attackers often inject malicious scripts like JavaScript, VBScript, ActiveX or Flash into those websites that have loopholes. Once they have successful injection, your user information will be stolen and your website will full of spam, also they can change user settings to whatever they want.

If you want to prevent this kind of attack, you'd better combine two following approaches:

  • Verification all data from users, which we talked about previous section.
  • Give special handling for data that will be responded to clients, in order to prevent any injected script runs on browsers.

So how can we do these two jobs in Go? Fortunately, package html/template has some useful functions to escape data as follows:

  • func HTMLEscape(w io.Writer, b []byte) escapes b to w.
  • func HTMLEscapeString(s string) string returns string after escaped from s.
  • func HTMLEscaper(args ...interface{}) string returns string after escaped from multiple arguments.

Let's change the example in section 4.1:

fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // print at server side
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // responded to clients

If we try to input user name as <script>alert()</script>, we will see following content in the browser:

Figure 4.3 JavaScript after escaped

Functions in package html/template help you escape all HTML tags, what if you just want to print <script>alert()</script> to browsers? You should use text/template instead.

import "text/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")

Output:

Hello, <script>alert('you have been pwned')</script>!

Or you can use type template.HTML: Variable content will not be escaped if it's type is template.HTML.

import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", template.HTML("<script>alert('you have been pwned')</script>"))

Output:

Hello, <script>alert('you have been pwned')</script>!

One more example of escape

import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")

Output:

Hello, &lt;script&gt;alert(&#39;you have been pwned&#39;)&lt;/script&gt;!

##Links