TL;DR

Ngày 20/04/2026, đội SIWE công bố 4 lỗ hổng bảo mật trong plugin spruceid/discourse-siwe-auth — plugin Sign-In with Ethereum chính thức cho Discourse — đã tồn tại hơn 3 năm trong production. Nghiêm trọng nhất là một lỗi authentication bypass hoàn toàn: server đọc danh tính Ethereum từ một trường form ẩn do client gửi, thay vì từ địa chỉ đã được chữ ký SIWE verify. Kẻ tấn công chỉ cần ký bằng ví của mình rồi đổi trường form sang địa chỉ nạn nhân là login được luôn. Bản rewrite signinwithethereum/discourse-siwe-auth v1.1.0+ đã fix toàn bộ. ENS DAO forum và các forum hệ sinh thái đã migrate; người dùng cần reconnect ví.

Công bố có gì

Bug được phát hiện trong lúc đội SIWE đang viết lại plugin tháng trước, không phải qua audit hay bug bounty. Sau 30 ngày embargo (thông báo upgrade ngày 20/03/2026 trên forum ENS), chi tiết kỹ thuật được công khai vào 20/04/2026.

Bốn vấn đề được liệt kê theo mức độ:

  • Critical — Account takeover qua trường form chưa verify.
  • High — Key account bằng ENS name thay vì địa chỉ Ethereum.
  • Medium — Nonce replay trong phiên.
  • Medium — Dữ liệu hiển thị (ENS name, avatar) do client tự submit, không verify.

Tính tới thời điểm công bố, chưa có CVE được gán. Không có PoC public — bản vá đã ra và các forum lớn đã migrate trước.

Vì sao đáng lưu tâm

Đây là lớp xác thực của một plugin được recommend chính thức bởi docs login.xyz, dùng cho các forum quản trị DAO — nơi phiếu bầu và danh tính on-chain có giá trị thật. Việc bất kỳ ai cũng có thể đăng nhập thành bất kỳ ai suốt 3+ năm đồng nghĩa với: mọi tài khoản forum từng link SIWE đều nằm trong diện giả định đã bị lộ. Đáng nói là bug không phức tạp về mặt crypto — chỉ là một lỗi rất cổ điển: tin vào dữ liệu client gửi lên.

Câu hỏi khó chịu: tại sao hơn 3 năm không ai phát hiện? Plugin open source, code public, đã tích hợp vào nhiều forum DAO có TVL lớn. Cảnh báo chung cho bất kỳ luồng auth nào có chữ ký: địa chỉ phải luôn được derive từ signature verify được server-side, không bao giờ đọc từ field do client submit song song.

Chi tiết kỹ thuật 4 lỗi

1. Critical — Account takeover qua eth_account form field

Server cũ đọc địa chỉ người dùng từ một trường form ẩn tên eth_account do client gửi, thay vì từ siwe_message.address đã được chữ ký verify. Kịch bản tấn công:

  1. Attacker ký SIWE message hợp lệ bằng ví của chính họ.
  2. Trước khi submit, attacker sửa trường eth_account thành địa chỉ của nạn nhân.
  3. Server verify chữ ký (pass, vì ký bằng ví attacker), rồi tra account bằng eth_account (địa chỉ nạn nhân) — login thành công với phiên của nạn nhân.

Fix: bỏ hoàn toàn field identity do client submit, UID luôn derive từ siwe_message.address đã verify.

2. High — Key account bằng ENS name

Plugin link account Discourse với ENS name chứ không phải địa chỉ Ethereum thô. Khi một domain ENS đổi chủ (bán, hết hạn, transfer), chủ mới tự động inherit tài khoản forum của chủ cũ. Fix: UID là raw address; ENS name resolve server-side và forward-verify (resolve tên → ra address → so với address hiện tại).

3. Medium — Nonce replay

Nonce trong session không bị xoá sau khi dùng, cho phép replay chữ ký trong cùng phiên. Fix một dòng Ruby: session.delete(:nonce) ngay trước bước so sánh.

4. Medium — Dữ liệu hiển thị chưa verify

Client có thể submit bất kỳ ENS name và avatar URL nào cho profile. Fix: resolve server-side qua ENS Metadata Service.

So sánh plugin cũ vs mới

Khía cạnhspruceid/discourse-siwe-auth ≤0.1.2Mới signinwithethereum/discourse-siwe-auth ≥1.1.0
Nguồn identityForm field eth_account (client)siwe_message.address đã verify
Key accountENS nameRaw Ethereum address
NonceKhông invalidate sau khi dùngXoá trước khi compare
Display data (ENS, avatar)Client submitServer resolve qua ENS Metadata
MaintainerSpruceID (legacy)SIWE team

Ai bị ảnh hưởng

Mọi Discourse forum cài plugin SIWE phiên bản cũ — chủ yếu là các forum quản trị web3/DAO. Đã được xác nhận migrate: ENS DAO governance forum (discuss.ens.domains). Admin các forum còn lại cần coi đây là ưu tiên cao, vì một tài khoản moderator/admin bị takeover có thể kéo theo thiệt hại quản trị lớn hơn nhiều so với vote thường.

Action items cho admin & user

Admin:

  • Gỡ spruceid/discourse-siwe-auth, cài signinwithethereum/discourse-siwe-auth v1.1.0+.
  • Config siwe_ethereum_rpc_url trỏ tới một RPC endpoint riêng (cần cho server-side ENS resolve).
  • Nếu chưa thể upgrade ngay: tạm tắt plugin qua Admin Settings → Plugins → discourse-siwe → uncheck discourse siwe enabled.
  • Audit log audit: tìm các phiên SIWE login bất thường từ trước tới giờ.

User:

  • Sau khi admin upgrade, phải reconnect ví Ethereum trong profile settings — liên kết cũ bị invalidate.
  • Review hoạt động tài khoản, đặc biệt post/vote/DM trong thời gian dài trước đó.

Tiếp theo

Legacy repo spruceid/discourse-siwe-auth coi như deprecated; nguồn chính thức mới là signinwithethereum/discourse-siwe-auth. Đội SIWE nhiều khả năng sẽ xin CVE chính thức và bổ sung security advisory. Với các dự án web3 khác đang dùng pattern auth tương tự (ví dụ SIWE plugin cho các CMS khác, tích hợp tự viết), đây là lúc nên tự audit xem mình có lặp chính xác lỗi lấy identity từ client thay vì từ signature không.

Nguồn: ENS DAO forum — disclosure post #3, spruceid/discourse-siwe-auth, Jalil Wahdat on X.