漏洞分析
需要让主合约的isSolved()函数返回True,才能拿到Flag。
让isSvd返回True,我们需要成功调用solve函数。而solve函数会检查调用者是否持有100个以上的鱼人币。那么如何才能获得100个以上的鱼人币呢?根据题目名称的提示,我们来到鱼人币合约的TransferFrom函数。
跟进_transfer函数:
问题出现在了254行,ERC20合约的转账操作 被定义为 转出者余额减少,转入者余额增加。但如图所示,合约并没有检查转出者的余额是否足够减少。这边产生了漏洞。即使from账户没有钱,也可以向任意账户转账。
需要让主合约的isSolved()函数返回True,才能拿到Flag。
让isSvd返回True,我们需要成功调用solve函数。而solve函数会检查调用者是否持有100个以上的鱼人币。那么如何才能获得100个以上的鱼人币呢?根据题目名称的提示,我们来到鱼人币合约的TransferFrom函数。
跟进_transfer函数:
问题出现在了254行,ERC20合约的转账操作 被定义为 转出者余额减少,转入者余额增加。但如图所示,合约并没有检查转出者的余额是否足够减少。这边产生了漏洞。即使from账户没有钱,也可以向任意账户转账。
pkexec 本地提权
Ubuntu、Debian、Fedora 和 CentOS 的默认安装环境上均测试通过。漏洞利用难度不高,最早引入问题的 commit 来自 2024 年,影响版本范围远超去年的 sudo 漏洞。
漏洞是本地触发,只有在获得有限权限的前提下提升至 root。
Polkit 是一个应用程序级别的工具集,通过定义和审核权限规则,实现不同优先级进程间的通讯:控制决策集中在统一的框架之中,决定低优先级进程是否有权访问高优先级进程。
Polkit 在系统层级进行权限控制,提供了一个低优先级进程和高优先级进程进行通讯的系统。和 sudo 等程序不同,Polkit 并没有赋予进程完全的 root 权限,而是通过一个集中的策略系统进行更精细的授权。
Ubuntu、Debian、Fedora 和 CentOS 的默认安装环境上均测试通过。漏洞利用难度不高,最早引入问题的 commit 来自 2024 年,影响版本范围远超去年的 sudo 漏洞。
漏洞是本地触发,只有在获得有限权限的前提下提升至 root。
Polkit 是一个应用程序级别的工具集,通过定义和审核权限规则,实现不同优先级进程间的通讯:控制决策集中在统一的框架之中,决定低优先级进程是否有权访问高优先级进程。
Polkit 在系统层级进行权限控制,提供了一个低优先级进程和高优先级进程进行通讯的系统。和 sudo 等程序不同,Polkit 并没有赋予进程完全的 root 权限,而是通过一个集中的策略系统进行更精细的授权。
CWP 中的一些函数(包括 require() 和 include() 函数)似乎会将 / .%00./处理成 / ../。同样,虽然它们的 stristr() 函数会忽略空字节,但它仍然会计算其大小,因此绕过了检查。我们不太确定具体原因,但这可能是由于他们的库中使用了类似 striptags() 的函数而导致的回归问题。
现在利用这个技巧,我们可以将服务器上的任何本地文件包含在内。我们拥有一个完整的文件包含漏洞,如果我们找到写入文件的方法,就可以获得预认证远程代码执行 (RCE)。然而,下一步并不像我们想象的那么简单,因为 CWP 自带名为 CWP-Secure-Kernel 的特殊 Unix 文件读写锁定设置。服务器不会轻易授予我们对日志或其他任何明显有用的文件进行写入或编辑的权限。
但利用我们的文件包含漏洞,我们可以访问受限的 API 部分。该部分需要 API 密钥才能访问,并且由于未在网站根目录中公开,因此无法直接访问。但通过利用我们的文件包含漏洞,发送如下请求将使服务器注册我们想要的任何 API 密钥。
现在利用这个技巧,我们可以将服务器上的任何本地文件包含在内。我们拥有一个完整的文件包含漏洞,如果我们找到写入文件的方法,就可以获得预认证远程代码执行 (RCE)。然而,下一步并不像我们想象的那么简单,因为 CWP 自带名为 CWP-Secure-Kernel 的特殊 Unix 文件读写锁定设置。服务器不会轻易授予我们对日志或其他任何明显有用的文件进行写入或编辑的权限。
但利用我们的文件包含漏洞,我们可以访问受限的 API 部分。该部分需要 API 密钥才能访问,并且由于未在网站根目录中公开,因此无法直接访问。但通过利用我们的文件包含漏洞,发送如下请求将使服务器注册我们想要的任何 API 密钥。
CWP CentOS Web 面板 – 预授权远程代码执行
以在 Shodan 或 Census 上找到。我们利用的漏洞链实现了以 root 用户身份执行完整的预认证远程命令,该漏洞链利用了文件包含漏洞 (CVE-2025-45467) 和文件写入漏洞 (CVE-2025-45466)。本文将介绍我们的漏洞研究过程,以及我们如何着手攻击这个特定目标。
以在 Shodan 或 Census 上找到。我们利用的漏洞链实现了以 root 用户身份执行完整的预认证远程命令,该漏洞链利用了文件包含漏洞 (CVE-2025-45467) 和文件写入漏洞 (CVE-2025-45466)。本文将介绍我们的漏洞研究过程,以及我们如何着手攻击这个特定目标。
我们可以看到,sub_3811E0调用完成之后,会通过test eax,eax判断eax的值是否为0,如果eax为0 则跳转到loc_3833BD,跳转过来之后结束winMain的运行。
很明显,eax是不为0的,因为我们在代码中可以看到,sub_3811E0函数的最后,通过mov eax,1的方式给eax赋值为了1,所以此时eax等于1.
eax等于1,那么程序就会连着执行四个call,分别是sub_383600、sub_381580、sub_381770、sub_382790。
我们先跟进到sub_383600。
sub_383600
IDA中双击进入到函数,熟悉的_memset内存分配
然后通过call SHGetFolderPathA获取系统路径,具体获取的值由参数决定。
很明显,eax是不为0的,因为我们在代码中可以看到,sub_3811E0函数的最后,通过mov eax,1的方式给eax赋值为了1,所以此时eax等于1.
eax等于1,那么程序就会连着执行四个call,分别是sub_383600、sub_381580、sub_381770、sub_382790。
我们先跟进到sub_383600。
sub_383600
IDA中双击进入到函数,熟悉的_memset内存分配
然后通过call SHGetFolderPathA获取系统路径,具体获取的值由参数决定。
其中第一个是[ebp + pszPath] ,也就是SHGetFolderPath函数获取到的路径。
第二个参数是aSEsetUpdateExe,IDA已经自动识别出来是%seset_update.exe
第三个参数是[ebp+NewFileName]
这里第二个参数前面的%s比较关键,基本可以推测sub_383320用于将push的第一个参数和第二个参数拼接起来放到第三个参数,也就是[ebp+NewFileName]。这里为什么不猜测sub_383320用于将应用程序拷贝到%appdata%路径并且重命名为eset_update.exe。 是因为我们可以看到GetModuleFileNameA获取到的路径会存放在[ebp+Filename]中,而在调用sub_383320的时候,并没有将[ebp+Filename]作为参数传入,所以sub_383320的功能应该是路径拼接
第二个参数是aSEsetUpdateExe,IDA已经自动识别出来是%seset_update.exe
第三个参数是[ebp+NewFileName]
这里第二个参数前面的%s比较关键,基本可以推测sub_383320用于将push的第一个参数和第二个参数拼接起来放到第三个参数,也就是[ebp+NewFileName]。这里为什么不猜测sub_383320用于将应用程序拷贝到%appdata%路径并且重命名为eset_update.exe。 是因为我们可以看到GetModuleFileNameA获取到的路径会存放在[ebp+Filename]中,而在调用sub_383320的时候,并没有将[ebp+Filename]作为参数传入,所以sub_383320的功能应该是路径拼接