nosurf
é um pacote HTTP para Go que ajuda a prevenir ataques de falsificação de solicitação entre sites. Ele atua como um middleware e, portanto, é compatível com basicamente qualquer aplicativo Go HTTP.
Embora o CSRF seja uma vulnerabilidade proeminente, a infraestrutura de pacotes relacionados à web do Go consiste principalmente em microestruturas que não implementam verificações de CSRF, nem deveriam.
nosurf
resolve esse problema fornecendo um CSRFHandler
que agrupa seu http.Handler
e verifica ataques CSRF em todos os métodos não seguros (não GET/HEAD/OPTIONS/TRACE).
nosurf
requer Go 1.1 ou posterior.
Suporta qualquer http.Handler
(frameworks, seus próprios manipuladores, etc.) e age como se fosse um.
Permite isentar endpoints específicos de verificações de CSRF por meio de uma URL exata, um glob ou uma expressão regular.
Permite especificar seu próprio manipulador de falhas. Quer apresentar ao hacker um dedo médio ASCII em vez do velho HTTP 400
? Sem problemas.
Usa tokens mascarados para mitigar o ataque BREACH.
Não possui dependências fora da biblioteca padrão Go.
pacote mainimport ("fmt""github.com/justinas/nosurf""html/template""net/http")var templateString string = `<!doctype html><html><body>{{ if .name }}< p>Seu nome: {{ .name }}</p>{{ end }}<form action="/" method="POST"><input type="text" name="name"><!-- Tente remover isso ou alterar seu valor e veja o que acontece --><input type="hidden" name="csrf_token" value="{{ .token }}"><input type="submit" value="Send"></form></body>< /html>`var templ = template.Must(template.New("t1").Parse(templateString))func myFunc(w http.ResponseWriter, r *http.Request) {contexto:= make(mapa[string]string)context["token"] = nosurf.Token(r)if r.Method == "POST" {context["nome"] = r.FormValue("nome") }templ.Execute(w, contexto) }func main() {myHandler := http.HandlerFunc(myFunc)fmt.Println("Ouvindo em http://127.0.0.1:8000/")http.ListenAndServe(":8000", nosurf.New(myHandler)) }
Em alguns casos, o token CSRF pode ser enviado de uma forma não padrão, por exemplo, um corpo ou solicitação é uma mensagem codificada em JSON com um dos campos sendo um token.
Nesse caso, o manipulador(caminho) deve ser excluído de uma verificação automática usando um dos métodos de isenção:
func (h *CSRFHandler) ExemptFunc(fn func(r *http.Request) bool)func (h *CSRFHandler) ExemptGlob(padrão string)func (h *CSRFHandler) ExemptGlobs(padrões ...string)func (h *CSRFHandler) IsemptPath(cadeia de caminho)func (h *CSRFHandler) ExemptPaths(caminhos ...string)func (h *CSRFHandler) ExemptRegexp(re interface{})func (h *CSRFHandler) ExemptRegexps(res ...interface{})
Posteriormente, o token deve ser verificado obtendo manualmente o token do cookie e fornecendo o token enviado no corpo através de: VerifyToken(tkn, tkn2 string) bool
.
Exemplo:
func HandleJson (w http.ResponseWriter, r *http.Request) {d := struct{X,Y intTkn string }{}json.Unmarshal(ioutil.ReadAll(r.Body), &d)if !nosurf.VerifyToken(nosurf.Token(r), d.Tkn) {http.Errorf(w, "token CSRF incorreto", http. StatusBadRequest)retornar }// faça algo legal}
Encontre um problema que o incomoda / abra um novo.
Discutir.
Ramifique, comprometa-se, teste.
Faça uma solicitação pull/anexe os commits ao problema.