nosurf
クロスサイト リクエスト フォージェリ攻撃の防止に役立つ Go の HTTP パッケージです。これはミドルウェアのように機能するため、基本的にすべての Go HTTP アプリケーションと互換性があります。
CSRF は顕著な脆弱性ではありますが、Go の Web 関連パッケージ インフラストラクチャの大部分は、CSRF チェックを実装していないか、実装する必要のないマイクロフレームワークで構成されています。
nosurf
、 http.Handler
をラップし、すべての安全でない (GET/HEAD/OPTIONS/TRACE 以外) メソッドに対する CSRF 攻撃をチェックするCSRFHandler
を提供することで、この問題を解決します。
nosurf
Go 1.1 以降が必要です。
あらゆるhttp.Handler
(フレームワーク、独自のハンドラーなど) をサポートし、それ自体のように動作します。
正確な URL、グロブ、または正規表現によって、特定のエンドポイントを 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 トークンは非標準の方法で送信されることがあります。たとえば、本文またはリクエストは、フィールドの 1 つがトークンである JSON エンコードされたメッセージです。
このような場合は、次のいずれかの除外方法を使用して、ハンドラー (パス) を自動検証から除外する必要があります。
func (h *CSRFHandler) ExemptFunc(fn func(r *http.Request) bool)func (h *CSRFHandler) ExemptGlob(パターン文字列)func (h *CSRFHandler) ExemptGlobs(パターン ...文字列)func (h *CSRFHandler) ExemptPath(パス文字列)func (h *CSRFHandler) ExemptPaths(paths ...string)func (h *CSRFHandler) ExemptRegexp(re インターフェイス{})func (h *CSRFHandler) ExemptRegexps(res ...インターフェイス{})
後で、Cookie からトークンを手動で取得し、 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. StatusBadRequest)return }// クールにやってください}
問題を抱えている問題を見つけるか、新しい問題を開きます。
話し合う。
ブランチ、コミット、テスト。
プルリクエストを作成するか、課題にコミットを添付します。