
nosurf の 1.2.0 より前のすべてのバージョンは、受信リクエストに対して同一オリジンチェックを適用できていませんでした。
これは、Go 標準ライブラリの net/http.Request 型の .URL.Scheme フィールドに依存して、
最初にリクエストが HTTPS で提供されていることを確認し、その後にのみ同一オリジンチェックを適用していたためです。
前述の Scheme フィールドは、受信リクエスト時に Go HTTP サーバーによって入力されません:
// For server requests, the URL is parsed from the URI // supplied on the Request-Line as stored in RequestURI. For // most requests, fields other than Path and RawQuery will be // empty.
なぜなら、一般的なケースでは Go はリクエストが TLS 上で行われているかを判断できないからです (TLS を終端するリバースプロキシなどが存在する可能性があるため)。
これにより、攻撃者はあなたのウェブサイトに対して安全でないクロスオリジンリクエスト を発行できる可能性があります。
同一オリジンチェックの実装に加えて、nosurf は 二重送信 Cookie パターン を使用して CSRF からも保護しています。
これは、変更を伴うクロスオリジンリクエストを成功させるには、
攻撃者があなたのウェブサイト上のページ、またはあなたのウェブサイトのサブドメイン上の
ページのコンテンツを制御している必要もあることを意味します。
これは XSS によって達成される可能性があります。または、あなたがウェブサイトのユーザーに HTML コンテンツの制御を意図的に与えている場合です
(例: あなたがホスティングプロバイダー example.com であり、ユーザーが alice.example.com にウェブサイトをホストすることを許可している場合)。
このリポジトリの PoC は、後者のケースの攻撃を示しており、 攻撃者がウェブサイトのメインドメインのサブドメイン上のコンテンツを制御しています。
Go と Caddy が必要です。サーバーを手動で実行してください:
$ go run attacker.go & go run target.go & caddy run
または Process Compose を使用:
$ process-compose
https://attacker.target.localhost にアクセスしてください。
ボタンをクリックして https://target.localhost にフォームを送信し、リクエストが正常に完了することを確認してください。
この問題の修正は nosurf 1.2.0 でリリースされました。
問題を報告してくれた Patrick O'Doherty に感謝します。