Golang代码审计之XSS、SQL注入漏洞审计及修复
跨站脚本攻击(XSS):
问题代码:
package main
import (
"fmt"
"html/template"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
message := r.FormValue("message")
tmpl := template.Must(template.ParseFiles("index.html"))
tmpl.Execute(w, message)
})
http.ListenAndServe(":8080", nil)
}
在上面的示例中,应用程序接受名为"message"的参数,并将其直接插入到HTML模板中。这种情况下存在潜在的XSS漏洞,因为攻击者可以在"message"参数中注入恶意的JavaScript代码,导致该代码在用户的浏览器中执行。
要修复这个问题,我们可以使用Go语言的html/template包中的自动转义功能,确保任何用户输入都被正确地转义。修改后的代码如下:
package main
import (
"fmt"
"html/template"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
message := template.HTMLEscapeString(r.FormValue("message"))
tmpl := template.Must(template.ParseFiles("index.html"))
tmpl.Execute(w, message)
})
http.ListenAndServe(":8080", nil)
}
在修复后的代码中,我们使用了template.HTMLEscapeString函数对用户输入进行转义,以防止XSS攻击。
SQL注入
问题代码:
package main
import (
"database/sql"
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
username := r.FormValue("username")
password := r.FormValue("password")
db, err := sql.Open("mysql", "user:password@/database")
if err != nil {
fmt.Println(err)
return
}
query := fmt.Sprintf("SELECT * FROM users WHERE username='%s' AND password='%s'", username, password)
rows, err := db.Query(query)
if err != nil {
fmt.Println(err)
return
}
// 处理查询结果...
})
http.ListenAndServe(":8080", nil)
}
在上面的示例中,用户输入的username和password直接被拼接到SQL查询语句中,这种情况下容易受到SQL注入攻击。攻击者可以通过在输入字段中注入恶意的SQL代码来绕过身份验证或执行未经授权的操作。
为了修复这个问题,我们应该使用参数化查询或预编译语句来处理用户输入。这样可以确保用户输入不会被解释为SQL代码的一部分。以下是修复后的示例:
package main
import (
"database/sql"
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
username := r.FormValue("username")
password := r.FormValue("password")
db, err := sql.Open("mysql", "user:password@/database")
if err != nil {
fmt.Println(err)
return
}
query := "SELECT * FROM users WHERE username=? AND password=?"
rows, err := db.Query(query, username, password)
if err != nil {
fmt.Println(err)
return
}
// 处理查询结果...
})
http.ListenAndServe(":8080", nil)
}
在修复后的代码中,我们使用了参数化查询,使得用户输入的数据以参数的形式传递给查询语句,而不是直接拼接到字符串中。