漏洞简介
友加畅捷管理系统是一款专为小微商贸流通企业设计的财务业务一体化管理软件,涵盖进销存、财务、分销及移动管理等多个模块,旨在帮助企业实现高效的业务运营和财务核算。
该系统的 Sysconfig/GetZTList 接口存在未授权访问漏洞,攻击者无需任何认证即可直接访问该接口,从而获取敏感信息。此漏洞可能导致企业内部数据泄露,包括但不限于用户列表、配置信息等,对企业的运营安全和数据隐私构成严重威胁。
影响版本
13.7004.1053.1000
fofa语法
icon_hash="2049187099" || fid="zzt8lL7SUwIIZQXZY6rTSw=="
漏洞分析
在 SysconfigController 找到 GetZTList 方法处理逻辑如下

表明需要一个pwd参数,即可返回 DBOperation.GetZTList 的内容,跟进看下它的实现逻辑

- 框架行为: 在 ASP.NET (或 ASP.NET Core) MVC/Web API 框架中,当一个 Action 方法的参数是引用类型(如
string)且在 HTTP 请求中未提供该参数时,模型绑定器会为该参数赋其默认值。对于string类型,其默认值为null。 - 代码执行路径: 因此,当攻击者请求
GetZTList接口而不带pwd参数时,GetZTList(string pwd)方法中的pwd变量值为null。 - 条件判断绕过: 代码会执行
if (string.op_Inequality(pwd, "-1")),这等同于if (pwd != "-1")。由于pwd是null,null != "-1"的结果为true。因此,程序会进入if代码块,而不是else分支。 - 过滤逻辑缺陷: 在
if代码块内部,程序会执行Where条件进行过滤:m => string.op_Equality(m.ZTPwd, "") || m.ZTPwd == null || string.op_Equality(m.ZTPwd, jmPwd)- 由于
pwd为null,jmPwd = EncDecString.EncryptPWD(null)的结果很可能是null或空字符串""(取决于EncryptPWD方法的实现)。 - 情况一:
jmPwd为null。 过滤条件变为m.ZTPwd == "" || m.ZTPwd == null || m.ZTPwd == null,简化为m.ZTPwd == "" || m.ZTPwd == null。 - 情况二:
jmPwd为""。 过滤条件变为m.ZTPwd == "" || m.ZTPwd == null || m.ZTPwd == "",同样简化为m.ZTPwd == "" || m.ZTPwd == null。
- 由于
- 最终结果: 无论
EncryptPWD(null)的具体返回值是什么,最终的过滤逻辑都会返回所有ZTPwd字段为空字符串或null的账套列表。这实质上是列出了系统中所有未设置密码的账套。

- 代码的业务逻辑是通过
pwd参数来验证用户身份,并返回其有权访问的账套列表。 - 代码中存在一个关键的条件判断:
if (string.op_Inequality(pwd, "-1")),这等同于if (pwd != "-1")。 - 正常逻辑分支 (
pwd不等于"-1"): 当pwd不为"-1"时,程序会执行if代码块。此代码块会将传入的pwd参数进行加密(EncDecString.EncryptPWD(pwd)),然后与配置文件中每个账套的ZTPwd字段进行比对。只有密码为空、null或匹配成功的账套才会被返回。这是预期的、受保护的业务逻辑。 - 漏洞逻辑分支 (
pwd等于"-1"): 当pwd参数的值正好为字符串"-1"时,程序会跳过if代码块,执行else if代码块。在此分支中,代码会遍历zts(即从配置文件sysconfig_zts中加载的所有账套列表),并不做任何密码校验,直接将所有账套的详细信息添加到ztList中并返回。
再看前端 js 里有关此路由的调用如下,pwd参数可有可无

或者是 pwd=-1

漏洞复现
GET /Sysconfig/GetZTList HTTP/1.1
Host: youjiasoft.mrxn.net

响应包含数据库连接信息、应用安装物理路径等敏感信息。

