nosurf
Cross-Site Request Forgery 공격을 방지하는 데 도움이 되는 Go용 HTTP 패키지입니다. 미들웨어처럼 작동하므로 기본적으로 모든 Go HTTP 애플리케이션과 호환됩니다.
CSRF가 두드러진 취약점임에도 불구하고 Go의 웹 관련 패키지 인프라는 대부분 CSRF 검사를 구현하지도 구현하지도 않는 마이크로 프레임워크로 구성됩니다.
nosurf
http.Handler
를 래핑하고 모든 안전하지 않은(GET/HEAD/OPTIONS/TRACE가 아닌) 메소드에 대한 CSRF 공격을 확인하는 CSRFHandler
를 제공하여 이 문제를 해결합니다.
nosurf
Go 1.1 이상이 필요합니다.
모든 http.Handler
(프레임워크, 자체 핸들러 등)를 지원하고 그 자체처럼 작동합니다.
정확한 URL, glob 또는 정규식을 통해 CSRF 검사에서 특정 엔드포인트를 면제할 수 있습니다.
자신만의 실패 핸들러를 지정할 수 있습니다. 해커에게 기존 HTTP 400
대신 ASCII 가운데 손가락을 제시하고 싶으십니까? 괜찮아요.
BREACH 공격을 완화하기 위해 마스크된 토큰을 사용합니다.
Go 표준 라이브러리 외부에는 종속성이 없습니다.
package mainimport ("fmt""github.com/justinas/nosurf""html/template""net/http")var templateString string = `<!doctype html><html><body>{{ if .name }}< p>귀하의 이름: {{ .name }}</p>{{ end }}<form action="/" method="POST"><input type="text" name="name"><!-- 이것을 제거하거나 변경해 보십시오. 값을 입력하고 무슨 일이 일어나는지 확인하세요 --><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) {context := make(map[string]string)context["token"] = nosurf.Token(r)if r.Method == "POST" {context["name"] = r.FormValue("name") }templ.Execute(w, 컨텍스트) }func main() {myHandler := http.HandlerFunc(myFunc)fmt.Println("http://127.0.0.1:8000/"에서 듣기http.ListenAndServe(":8000", nosurf.New(myHandler)) }
어떤 경우에는 CSRF 토큰이 비표준 방식을 통해 전송될 수 있습니다. 예를 들어 본문이나 요청은 필드 중 하나가 토큰인 JSON 인코딩 메시지입니다.
이러한 경우 예외 방법 중 하나를 사용하여 핸들러(경로)를 자동 확인에서 제외해야 합니다.
func (h *CSRFHandler) ExemptFunc(fn func(r *http.Request) bool)func (h *CSRFHandler) ExemptGlob(패턴 문자열)func (h *CSRFHandler) ExemptGlobs(패턴 ...string)func (h *CSRFHandler) ExemptPath(경로 문자열)func(h *CSRFHandler) ExemptPaths(경로 ...string)func(h *CSRFHandler) ExemptRegexp(re 인터페이스{})func (h *CSRFHandler) ExemptRegexps(res ...interface{})
나중에 쿠키에서 토큰을 수동으로 가져오고 다음을 통해 VerifyToken(tkn, tkn2 string) bool
으로 전송된 토큰을 제공하여 토큰을 확인 해야 합니다 .
예:
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, "CSRF 토큰이 잘못되었습니다.", http. 상태잘못된요청)반환 }// 멋대로 해봐}
당신을 괴롭히는 문제를 찾거나 새로운 문제를 열어보세요.
논의하다.
분기하고, 커밋하고, 테스트하세요.
끌어오기 요청을 하거나 이슈에 커밋을 첨부합니다.