seed-labs 竞态条件漏洞

竞态条件漏洞

概述

竞态条件是指一个系统或程序的输出结果取决于其他不可控制事件执行的时间顺序

一个常见的漏洞

当一个程序的两个并发线程同时访问共享资源时,如果执行时间和顺序不同,会产生影响,这时就称作发生了竞态条件
检查时间和使用时间。如果条件检查和实际资源使用之间存在一小段时间,如果这段时间内发生变化,则建立在检查结果上的 使用的授权就有安全问题,这就是检查于使用时间差漏洞。

实验

#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main()
{
    char *fn = "/tmp/XYZ";
    char buffer[60];
    FILE *fp;

    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");

    return 0;
}
ubuntu 14/16: sudo sysctl -w fs.protected_symlinks=0
./attack_process

防御手段

1)消除时间差
2)阻止其他人在这个时间内做事情
3)增大攻击者的难度
4)在攻击者胜利后,阻止他造成破坏

原子化

如果是系统本身可以通过上锁来实现原子化,对于文件,在检查和使用之间把目标文件锁上,这样其他进程就没发使用了

重复检查和使用

让竞争者胜利变动艰难,一个有趣的方案被提出,在代码中加入更多的竞态条件,攻击者只有全赢才能成功

粘滞符号链接保护

大多数TOCTTOU竞态条件漏洞与/tmp目录中的符号链接有关,因此自带了一个内置保护机制防止程序在特定情况下跟随符号链接

在linux文件系统中,文件目录有个比较特殊的比特位,叫粘滞位比特,当设置这个比特位时,只有文件所有者,目录所有者,或者root用户才能重新命名

最小权限原则

通常漏洞问题包含了程序的权限大于实际需求权限,所有违反了最小权限原则,

seteuid
设置当前进程的有效用户ID,如果当前进程的有效用户ID是root,那么参数uid参数可以是任意值

setuid 
它设置当前进程的用户ID,如果当前进程有效用户Id不是root,这个函数行为与seteuid一致,

problems

1 Does the following program have a race condition vulnerability?

if (!access("/etc/passwd", W_OK)) {
/ the real user has the write permission/
f = open("/tmp/X", O_WRITE);
write_to_file(f);
}
else {
/ the real user does not have the write permission /
fprintf(stderr, "Permission denied\n");
}
不,/etc/passwd是一个受保护的文件,普通用户没有对它的写访问权限。所以if块永远不会被执行。

2 How many race conditions does attackers have to win in the following program?

int main()
{
struct stat stat1, stat2;
int fd1, fd2;
if (access("tmp/XYZ", O_RDWR)) {
fprintf(stderr, "Permission denied\n");
return -1;
}
else fd1 = open("/tmp/XYZ", O_RDWR);

if (access("tmp/XYZ", O_RDWR)) {
fprintf(stderr, "Permission denied\n");
return -1;
}
else fd2 = open("/tmp/XYZ", O_RDWR);

// Check whether fd1 and fd2 have the same inode.
fstat(fd1, &stat1);
fstat(fd2, &stat2);

if(stat1.st_ino == stat2.st_ino) {
write_to_file(fd1);
}
else {
fprintf(stderr, "Race condition detected\n");
return -1;
}
return 0;
}

假设所有文件名都是/tmp/XYZ,而不是tmp/XYZ,这在某些地方是不正确的。

第一个竞争是access和fd1open之间的竞争,我们必须创建一个从/tmp/XYZ到要更改的文件的符号链接。

第二个是在fd1 open和第二次访问之间,我们必须更新符号链接并将其指向用户可以访问的文件。

第三种是在第二次访问和fd2开放之间,类似于第一次比赛。

In the open() system call, it first checks whether the user has the required permission to access the target file, then it actually opens the file. There seems to be a check-and-then use pattern. Is there a race condition problem caused by this pattern?
在open()系统调用中,检查用户权限和打开文件是一个原子操作,因此只有open()调用不可能有竞争条件。

The least-privilege principle can be used to effectively defend against the race condition attacks discussed in this chapter. Can we use the same principle to defeat buffer-overflow attacks? Why or why not? Namely, before executing the vulnerable function, we disable the root privilege; after the vulnerable function returns, we enable the privilege back.
如果问题是指在strcpy()调用之前禁用根权限,然后再启用它,那么它将不起作用,因为实际的攻击发生在我们从bof()函数返回时。如果我们在bof()调用之前禁用root权限,在调用之后启用它,那么我们就可以防止攻击。

If we can lock a file, we can solve the race condition problem by locking a file during the check-and-use window, because no other process can use the file during the time window. Why don't we use this approach to solve the race condition problems discussed in this chapter?

A file is locked out to other processes only if it's already open. During the check-and-open process, it's impossible to lock a file. Any locks created can be ignored by the malicious process.
只有文件已经打开时,它才会被锁定到其他进程。在检查和打开过程中,不可能锁定文件。恶意进程可以忽略创建的任何锁。**加粗样式**
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值