Published on

XSS - Cross Site Scripting Vulnerability

Authors

Many developers are aware of Cross Site Scripting (XSS), but few have attempted to use it to exploit a web application. Despite being listed as a top 10 security risk by OWASP since 2003, XSS remains a prevalent vulnerability. The OWASP Top 10 security risks version from 2013 provides a comprehensive overview of XSS, including information on attack vectors, vulnerabilities, and the technical and business impacts of a successful XSS attack.

In short

You are vulnerable if you do not ensure that all user supplied input is properly escaped, or you do not verify it to be safe via server-side input validation, before including that input in the output page. source


_14
package main
_14
_14
import (
_14
"io"
_14
"net/http"
_14
)
_14
_14
func handler(w http.ResponseWriter, r *http.Request) {
_14
io.WriteString(w, r.URL.Query().Get("param1"))
_14
}
_14
func main() {
_14
http.HandleFunc("/", handler)
_14
http.ListenAndServe(":8080", nil)
_14
}

As Content-Type HTTP response header is not explicitly defined, Go http.DetectContentType default value will be used, which follows the WhatWG spec. So, the Content-Type HTTP response header will depends on param1 values. If the params1 contains plain text it will return text/plain but if user pass it using html markup it will automatically return text/html.

Here the proove:


_15
❯ curl -i http://localhost:8000/\?param1\="<script>alert(1)</script>"
_15
HTTP/1.1 200 OK
_15
Date: Tue, 24 Jan 2023 07:48:56 GMT
_15
Content-Length: 25
_15
Content-Type: text/html; charset=utf-8
_15
_15
<script>alert(1)</script>%
_15
_15
❯ curl -i http://localhost:8000/\?param1\=test
_15
HTTP/1.1 200 OK
_15
Date: Tue, 24 Jan 2023 07:49:10 GMT
_15
Content-Length: 4
_15
Content-Type: text/plain; charset=utf-8
_15
_15
test%

Then, how to fix those problem? Fun fact, even using text/template it won't help to preventing XSS, since it does not sanitize user input. The correct solution is using html/template


_17
package main
_17
_17
import (
_17
"html/template"
_17
"net/http"
_17
)
_17
_17
func handler(w http.ResponseWriter, r *http.Request) {
_17
param1 := r.URL.Query().Get("param1")
_17
tmpl := template.New("hello")
_17
tmpl, _ = tmpl.Parse(`{{define "T"}}{{.}}{{end}}`)
_17
tmpl.ExecuteTemplate(w, "T", param1)
_17
}
_17
func main() {
_17
http.HandleFunc("/", handler)
_17
http.ListenAndServe(":8000", nil)
_17
}

Let's try again using script alert and other html sample.


_13
❯ curl -i http://localhost:8000/\?param1\="<script>alert(1)</script>"
_13
HTTP/1.1 200 OK
_13
Date: Tue, 24 Jan 2023 07:55:21 GMT
_13
Content-Length: 37
_13
Content-Type: text/plain; charset=utf-8
_13
_13
❯ curl -i http://localhost:8000/\?param1\="<h1>whassup</h1>"
_13
HTTP/1.1 200 OK
_13
Date: Tue, 24 Jan 2023 08:01:56 GMT
_13
Content-Length: 28
_13
Content-Type: text/plain; charset=utf-8
_13
_13
&lt;h1&gt;whassup&lt;/h1&gt;%

Yes, the output properly encoded and sanitized. So using html/template can prevent xss attack, keep in mind when processing input from user please sanitize first and make sure not trigger script execution that lead to XSS attack.