Given the following code:
package main
import (
"fmt"
"net/http"
"github.com/go-chi/chi/v5"
)
func homeHandler(w http.ResponseWriter, r *http.Request) {
bio := `<script>alert("You have been hacked!! XD") </script>`
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, "<h1>Welcome to my site!!!! </h1> <p>Bio:"+bio+"</p>")
}
func contactHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, "<h1> Contact Page </h1><p> To get in touch, email me at <a href=\"mailto:example@example.test\"> exampke@example.test </a>.")
}
func faqHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, `<h1> FAG Page </h1><p> Why blah bla bla blah? When yada, yada, yada.. </a>.
`)
}
func main() {
r := chi.NewRouter()
r.Get("/", homeHandler)
r.Get("/contact", contactHandler)
r.Get("/faq", faqHandler)
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Page Not Found", http.StatusNotFound)
})
fmt.Println("Starting the server on :3000...")
http.ListenAndServe(":3000", r)
}
Notes
- If we run the above web server, we will notice that an alert will pop-up in our browser telling us that we were hacked.
- In other words, the
<script>alert("You have been hacked!! XD") </script>
was not interpreted as text but rendered as code. - To avoid this, we could have scaped it but encoding the string.
Non Scaped version of code
func homeHandler(w http.ResponseWriter, r *http.Request) {
bio := `<script>alert("You have been hacked!! XD") </script>`
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, "<h1>Welcome to my site!!!! </h1> <p>Bio:"+bio+"</p>")
}
Scaped version of code
func homeHandler(w http.ResponseWriter, r *http.Request) {
bio := `<script>alert("You have been hacked!! XD") </script>`
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, "<h1>Welcome to my site!!!! </h1> <p>Bio:"+bio+"</p>")
}
- Now, even though we could make it but ourselves, the html library from Go could actually saved us the manual effort.
- Here is one example:
hello.gohtml
<h1> Hello, {{.Name}} </h1>
<p>Bio: {{.Bio}}</p>
main.go with Go HTML template (Printing to stdout)
package main
import (
"html/template"
"os"
)
type User struct {
Name string
Bio string
}
func main() {
t, err := template.ParseFiles("hello.gohtml")
if err != nil {
panic(err)
}
user := User{
Name: "Alex Rabocse",
Bio: `<script>alert("You have been hacked!! XD") </script>`, // Notice that the bio is not scaped.
}
t.Execute(os.Stdout, user)
if err != nil {
panic(err)
}
- Whe we execute the above code, we will see that the HTML library did the scaping for us:
go run main.go
<h1> Hello, Alex Rabocse </h1>
<p>Bio: <script>alert("You have been hacked!! XD") </script></p>
- This does not solve SQL injections, that would be with a different package but the example shows how the library could help us with a basic example for HTML.