原子操作
TOCTTOU竞争条件是由于检查操作和使用操作之间的间隔(也称窗口期)而导致的,原子操作旨在消除检查和使用操作之间的间隔,将检查和使用操作原子化,该对策需要操作系统级的支持。
重复检查和使用
竞争条件漏洞能否成功被利用,取决于攻击者能否赢得检查与使用之间的窗口,即能否在检查与使用间隔期间改变程序的输出,重复检查和使用方法旨在使攻击者更加难于赢得窗口 ,参考如下代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
struct stat stat1,stat2,stat3;
int fd1,fd2,fd3;
if(access("/tmp/XYZ",O_RDWR)){
fprintf(stderr,"Permission Denied\n");
return -1;
} //Window1
else fd1=open("/tmp/XYZ",O_RDWR);
//Window2
if(access("/tmp/XYZ",O_RDWR)){
fprintf(stderr,"Permission Denied\n");
return -1;
} //Window3
else fd2=open("/tmp/XYZ",O_RDWR);
//Window4
if(access("/tmp/XYZ",O_RDWR)){
fprintf(stderr,"Permission Denied\n");
return -1;
} //Window5
else fd3=open("/tmp/XYZ",O_RDWR);
fstat(fd1,&stat1);
fstat(fd2,&stat2);
fstat(fd3,&stat3);
if(stat1.st_ino == stat2.st_ino &&stat2.st_ino == stat3.st_ino){
write_to_file(fd1);
}
else{
fprintf(stderr,"Race Condition Detected");
return -1;
}
}
该代码通过执行多次access()和open(),并且对fd1、fd2、fd3进行检查,只有三次相同才向文件写入,使得攻击者赢得竞争条件变得十分简单,因为他需要赢得5次窗口,错过任何一次都会失败。
粘性符号链接保护
大多数的TOCTTOU竞争条件漏洞都与/tmp目录下的符号链接有关,所以ubuntu采取了一种内置的保护机制,阻止程序在特定条件下使用符号链接,在这种对策下,即使攻击者能够赢得窗口,也不能造成其他伤害。该对策只应用于人人可写的粘性目录,例如/tmp,在ubuntu下默认开启,可以使用如下命令开启
sudo sysctl -w kernel.yama.protected_sticky_symlinks=1
例如,在该对策下,只有当符号链接的拥有者是当前粘性目录的拥有者或者符号链接的euid,fopen函数才允许打开指定文件。