Race_Condition_ex
7.1. Does the following Set-UID 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块永远不会被执行。
7.2. Assume we develop a new system call, called faccess(int fd, int mode), which is identical to access(), except that the file to be checked is specified by the file descriptor fd. Does the following program have a race condition problem?
int f = open("/tmp/x", O_WRITE);
if (!faccess(f, W_OK)) {
write_to_file(f)
} else {
close(f);
}
有
open 检查有效用户
access检查真实用户
/tmp/x指向目标文件 open /tmp/x 指向realuid的文件 faccess /tmp/x指向 目标文件 write_to_file
7.3. 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;
}
3假设所有文件名都是/tmp/XYZ,而不是tmp/XYZ,这在某些地方是不正确的。
第一个竞争是access & fd1 open之间的竞争,我们必须创建一个从/tmp/XYZ到要更改的文件的符号链接。
第二个是在 fd1 open and the second access之间,我们必须更新符号链接并将其指向用户可以访问的文件。
第三种是在the second access and fd2 open 之间,类似于第一个竞争。
7.4. 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-thenuse pattern. Is there a race condition problem caused by this pattern?
在open()系统调用中,检查用户权限和打开文件是一个原子操作,因此只有open()调用不可能有竞争条件。
7.5. 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权限,在调用之后启用它,那么我们就可以防止攻击。
7.6. The following root-owned Set-UID program needs to write to a file, but it wants to ensure that the file is owned by the user. It uses stat() to get the file owner’s ID, and compares it with the real user ID of the process. If they do not match, the program will exit. Please describe whether there is a race condition in the program? If so, please explain how you can exploit the race condition. The manual of stat() can be found online.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main()
{
struct stat statbuf;
uid_t real_uid;
FILE* fp;
fp = fopen("/tmp/XYZ", "a+");
stat("/tmp/XYZ", &statbuf);
printf("The file owner’s user ID: %d\n", statbuf.st_uid);
printf("The process’s real user ID: %d\n", getuid());
// Check whether the file belongs to the user
if (statbuf.st_uid == getuid()) {
printf("IDs match, continue to write to the file.\n");
// write to the file ...
if (fp) fclose(fp);
} else {
printf("IDs do not match, exit.\n");
if (fp) fclose(fp);
return -1;
}
return 0;
}
使用stat()获取文件所有者的ID,并将其与进程的实际用户ID进行比较
有 /tmp/XYZ先指向realuid的文件 stat之后 指向target文件
7.7. The following root-owned Set-UID program needs to write to a file, but it wants to ensure that the file is owned by the user. It uses fstat() to get the file owner’s ID, and compares it with the real user ID of the process. If they do not match, the program will exit. Please describe whether there is a race condition in the program? If so, please explain how you can exploit the race condition. The manual of fstat() and fileno() can be found online.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main()
{
struct stat statbuf;
uid_t real_uid;
FILE* fp;
fp = fopen("/tmp/XYZ", "a+");
fstat(fileno(fp), &statbuf);
printf("The file owner’s user ID: %d\n", statbuf.st_uid);
printf("The process’s real user ID: %d\n", getuid());
// Check whether the file belongs to the user
if (statbuf.st_uid == getuid()) {
printf("IDs match, continue to write to the file.\n");
// write to the file ...
if (fp) fclose(fp);
} else {
printf("IDs do not match, exit.\n");
if (fp) fclose(fp);
return -1;
}
return 0;
}
stat和lstat的区别:当文件是一个符号链接时,lstat返回的是该符号链接本身的信息;而stat返回的是该链接指向的文件的
fstat区别于另外两个系统调用的地方在于,fstat系统调用接受的是 一个“文件描述符”,而另外两个则直接接受“文件全路径”。文件描述符是需要我们用open系统调用后才能得到的,而文件全路经直接写就可以了。
fileno()函数--获取已经打开的文件的文件描述符
7.8. 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?
只有文件已经打开时,它才会被锁定到其他进程。在检查和打开过程中,不可能锁定文件。恶意进程可以忽略创建的任何锁。
7.9. Does the following privileged Set-UID program have a race condition problem? If so, where is the attack window? Please also describe how you would exploit this race condition window.
filename = "/tmp/XYZ";
fd = open (filename, O_RDWR);
status = access (filename, W_OK);
...
... (code omitted) ...
...
if (status == ACCESS_ALLOWED) {
write_to_file(fd);
} else {
fprintf(stderr, "Permission denied\n");
}
7.10. Please use the least-privilege principle to fix the race condition problem in the following program.
if (access("/tmp/XYZ", W_OK) == ACCESS_ALLOWED) {
f = open("/tmp/XYZ", O_WRITE);
write_to_file(f);
}
else {
fprintf(stderr, "Permission denied\n");
}
p145
#include <stdio.h> #include<unistd.h> int main() { uid_t real_uid = getuid(); uid_t eff_uid = geteuid(); char * fn = "/tmp/XYZ"; char buffer[60]; FILE *fp; /* get user input */ scanf("%50s", buffer ); seteuid(real_uid); 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"); seteuid(eff_uid); }
这里报segment fault的原因是,在我们修改EID之后,事实上使用seed用户的身份去对root用户的相关内容进行操作,因为不同用户的内存空间不同,这回导致segment fault。
原文地址:https://www.cnblogs.com/tanwlanyue/p/15024036.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 「源码分析」— 为什么枚举是单例模式的最佳方法
- 如何记忆 Spring Bean 的生命周期
- 系统学习Stream
- Java回调的四种写法(反射、直接调用、接口调用、Lamda表达式)
- 避开NullPointerException的10条建议
- REST服务,使用Dubbo还是SpringMVC?
- Linux系统下Anaconda的安装和使用教程
- Flutter Dojo设计之道——利用Github打造完善的开源项目
- 最强 Redis 客户端 lettuce 已支持 Redis6客户端
- 还在手动整理数据库文档?试试这个工具
- Elasticsearch 常见的 8 种错误及最佳实践
- Spark流式状态管理
- Scala中的IO操作及ArrayBuffer线程安全问题
- 设计模式之单例模式
- Roslyn 理解 msbuild 的清理过程