20199106 2019-2020-2 《网络攻防实践》第十周作业

20199106 2019-2020-2 《网络攻防实践》第十周作业

作业说明

这个作业属于哪个课程 网络攻防实践
这个作业的要求在哪里 第十次作业: 软件安全攻防--缓冲区溢出和shellcode
我在该课程的目标 对网络攻防技术有一个比较全面的认识,能够掌握基本的攻防操作。
这个作业在哪个具体方面帮助我实现目标 学习了软件安全攻防--缓冲区溢出和shellcode。

作业正文

实践内容

软件安全概述

  • 安全漏洞:包括软件安全漏洞,硬件、个人与组织管理中存在的、能够被攻击者利用来破坏安全策略的弱点。软件安全漏洞是目前最常见,也是影响范围最大的安全漏洞类型。

  • 软件安全困境:

    • 复杂性:软件规模膨胀更快更复杂,意味着软件的bug越来越多,只要攻击者能够从中发现少数几个可利用的安全漏洞,就可以利用这些安全漏洞来危害软件的使用者。
    • 可扩展性:现代软件的可扩展性难以阻止攻击者和恶意代码以不可预测的扩展方式来入侵软件和系统。
    • 连通性:高强度的连通性使一个小小的软件缺陷就可能造成巨大损失,蠕虫的大规模传播就验证了连通性对软件安全的影响作用。
  • 软件安全漏洞类型:

    • 内存安全违规类:

      • 定义:是在软件开发过程中在处理RAM内存访问时所引入的安全缺陷,如缓冲区溢出漏洞(最基础的内存安全问题)和Double Free、Use-after-Free等不安全指针问题。
    • 输入验证类:

      • 定义:指软件程序在对用户输入进行数据验证没有保证输入数据的正确性、合法性和安全性,导致可能被恶意攻击与利用。
      • 类型:包含格式化字符串、SQL注入、代码注入、远程文件包含、目录遍历、XSS、HTTP Header注入、HTTP响应分割错误等多种安全漏洞技术形式。
    • 竞争条件类:

      • 定义:指处理程序的输出或者结果无法预测,并且依赖于其他进程事件发生的次序或时间时导致的错误。
      • 类型:Time-of-check-to-time-of-use(TOCTTOU)类漏洞;符号链接竞争问题。
    • 权限混淆与提升类:

      • 定义:是指计算机程序由于自身编程疏忽或被第三方欺骗从而滥用其权限,或赋予第三方不该给予的权限。
      • 类型:具体技术形式有Web应用程序中的跨站请求伪造(Cross-Site Request Forgery,CSRF)、Clickjacking、FTP反弹攻击、权限提升、“越狱”(jailbreak)等。

缓冲区溢出基础概念

  • 基本概念:是一类内存安全违规类漏洞,计算机程序向特定缓冲区内填充数据超出了缓冲区本身的容量,导致外溢数据覆盖了相邻内存空间的合法数据,从而改变程序执行流程破坏系统运行完整性。常见于C/C++语言程序中memcpy()、strcpy()等内存与字符串复制函数的引用位置(这些函数并不检查内存越界问题,程序员缺乏安全编程意识、经验与技巧)。

  • 根本原因:现在计算机系统的基础架构——冯·诺依曼体系存在本质的安全缺陷,采用了“存储程序”的原理,计算机程序的数据和指令在同一内存中进行存储,没有严格的分离。使得攻击者可以将输入的输入通过利用缓冲区溢出漏洞,入股程序在内存空间中与数据区相邻存储的关键指令,从而达到程序执行恶意注入指令的攻击目的。

  • 背景知识:

    • 编译器与调试器的使用:使用C/C++等高级编程语言编写的源码,需要通过编译器(Compiler)和连接器(Linker)才能生成可直接在操作系统平台上运行的可执行程序代码。调试器(Debugger)是开发人员在运行时刻调试与分析程序行为的基本工具。

    • C/C++编程语言最著名的编译与连接器是GCC。 GCC最基本的用法是执行gcc –c test.c 命令进行源码编译,生成test.o;执行gcc –o test test.o进行连接,生成test可执行程序,可以使用gcc test.c –o test 同时完成编译和连接过程。

    • 类UNIX平台上进行程序的调试使用 GDB 调试器,提供程序断点管理、执行控制、信息查看等多种类型的功能指令。

    • 汇编语言基础知识:

      • 汇编语言(尤其IA32)是理解软件安全漏洞机理,掌握软件渗透攻击代码技术的底层基础。
      • IA32架构中的寄存器分类:
        • 通用寄存器:如eax、ebx、ecx、edx等。主要用于普通的算术运算,保存数据、地址、偏移量、计数值等;
        • 段寄存器:在IA32构架中是16位,用作段基址寄存器;
        • 控制寄存器:用来控制处理器的执行流程,其中最关键的是指令指针eip,它保存下一条即将执行的机器指令的地址;
        • 其他寄存器:“扩展标志”eflags寄存器,由不同的标志位组成,用于保存指令执行后的状态和控制指令执行流程的标志信息。
      • IA32架构中的关键寄存器及功能:
      • 在IA32构架汇编语言中,有Intel和AT&T两种汇编格式。具体指令理解和编写可分别参考:《Intel汇编语言程序涉及》,《AT&T汇编语言格式》和《AT&T汇编语言与GCC内嵌汇编简介》。
    • 进程内存管理

      • Linux操作系统的进程管理机制:
        • 程序执行时,系统创建虚拟的内存地址空间来映射物理内存,保存程序指令和数据;
        • 操作系统将可执行程序加载到新创建的内存空间中,程序一般包含.text(包含程序指令,在内存中被映射为只读)、.bss(主要包含未经初始化的数据,被映射到可写的内存空间中)和.data(主要包含静态初始化数据,被映射到可写的内存空间中)三种类型的段;
        • 紧接着开始为程序初始化"栈"和"堆",“栈”底存放程序环境变量env、运行参数argv、运行参数数量argc,然后是主函数及调用函数的临时保存信息。“堆”,保存程序动态分配的数据和变量;
        • 程序执行时会按照逻辑执行.text中的指令,在堆,栈中读取和保存数据。
        • 但是程序不能区分指令和数据,所以恶意数据也会被当成指令执行。
      • Linux平台内存空间分布:

  • 函数调用
    • 栈溢出攻击就是针对函数调用过程中返冋地址在栈中的存储位置,进行缓冲区溢出,从而改写返回地址,达到让处理器指令寄存器跳转至攻击者指定位置执行恶意代码的目的。
    • 程序的函数调用过程有三步:
      • 调用(call):调用者将函数调用参数、函数调用下一条指令的返回地址压栈,并跳转至被调用函数入口地址;
      • 序言(prologue):被调用函数开始执行首先会进入序言阶段,将对调用函数的栈基址进行压栈保存,并创建自身函数的栈结构,具体包括将ebp寄存器赋值为当前栈基址,为本地函数局部变量分配栈地址空间,更新esp寄存器为当前栈顶指针等;
      • 返回(return):被调用函数执行完功能将指令控制权返回给调用者之前,会进行返回阶段的操作,通常执行leaveret指令,即恢复调用者的栈顶与栈底指针,并将之前压栈的返回地址装载至指令寄存器eip中,继续执行调用者在函数调用之后的下一条指令;
  • 攻击原理:
    • 缓冲区漏洞根据缓冲区在进程内存空间中的位置不同,分为:

      • 栈溢出:指存储在栈上的一些缓冲区变量由于存在缺乏边界保护问题,能够被溢出并修改栈上的敏感信息(通常是返回地址),从而导致程序流程的改变。
      • 堆溢出:存储在堆上的缓冲区变量缺乏边界保护所遭受溢出攻击的安全问题。
      • 内核溢出:存在于内核模块或程序中,是由于进程内存空间内核态中存储的缓冲区变量被溢出造成的。
    • Linux系统可能采取对抗缓冲区溢出的防范措施,需要先取消,再重现攻击:

      • 取消“栈上数据不可执行”保护echo 0 > /proc/sys/kerne/exec-shield
      • 取消“地址空间随机化”保护:echo 0 > /proc/sys/kernel/randomize_va_space
      • 编译时取消“/GS”保护:加上gcc编译选项 –fno-stack-protecto
    • 栈溢出安全漏洞示例:局部变量存储在栈上,位于main()函数【return 0】返回地址之下,在return_input()函数中执行gets函数将用户终端输入到array缓冲区时,如果输入超过30字节的字符串就会发生缓冲区溢出(压栈的方向是函数返回地址->栈底地址->临时变量地址),向上覆盖,一旦覆盖RET返回地址可能导致程序崩溃。

Linux栈溢出与Shellcode

  • Linux平台栈溢出攻击技术:按照攻击数据的构造方式不同,主要有NSR、RNS和RS三种模式。NSR和RNS模式适用于本地缓冲区溢出和远程栈溢出攻击,而RS模式只能用于本地缓冲区溢出攻击。
    • NSR模式:主要适用于被溢出的缓冲区变量比较大,足以容纳Shellcode的情况,其攻击数据从低地址到高地址的构造一堆Nop指令填充Shellcode,加上一些期望覆盖RET返回地址的跳转地址,从而构成了NSR攻击数据缓冲区。
    • RNS模式:一般用于被溢出的变量比较小,不足于容纳Shellcode的情况。攻击数据从低地址到高地址的构造方式是,先填充一些期望覆盖RET返回地址的跳转地址,然后是一堆Nop指令填充出“着陆区”,最后再是Shellcode。
    • RS模式:能够精确地定位出Shellcode在目标漏洞程序进程空间中的起始地址,因此也就无需引入Nop空指令构建“着陆区”。这种模式是将Shellcode放置在目标漏洞程序执行时的环境变量中,由于位置是固定的,可以通过公式计算ret=0xc0000000-sizeof(void*)-sizeof(FILENAME)-sizeof(Shellcode)
  • Linux的shellcode实现技术:Shellcode就是符合Intel 32位指令规范的一串CPU指令,被用于溢出之后改变系统正常流程,转而执行Shellcode以完成渗透测试者的攻击目的,通常是为他提供一个访问系统的本地或远程命令行访问。
    • Linux本地shellcode实现机制:Linux系统本地Shellcode通常提供的功能就是为攻击者启动一个命令行Shell。
    • Shellcode的通用方法:先用高级编程语言,通常用C,来编写Shellcode程序;编译并反汇编调试这个Shellcode程序;从汇编语言代码级别分析程序执行流程;整理生成的汇编代码,尽量减小它的体积并使它可注入,并可通过嵌入C语言进行运行测试和调试;提取汇编代码所对应的opcode二进制指令,创建Shellcode指令数组。
    • Linux远程Shellcode实现机制:实现原理与本地Shellcode完全一致,也是通过执行一系列的系统调用来完成指定的功能。Linux远程Shellcode需要让攻击目标程序创建socket监听指定的端口等待客户端连接,启动一个命令行Shell,并将命令行的输入输出与socket绑定,这样攻击者就可以通过socket客户端连接目标程序所在主机的开放端口,与服务端socket建立起通信通道,并获得远程访问Shell。

Windows栈溢出与Shellcode

  • 栈溢出攻击技术
    • 与Linux攻击技术的主要差异
      • 程序运行过程中拥有大量的函数调用,当一个函数调用完返回至调用者执行下一条指令前会有恢复栈基和栈顶指针的操作,Windows会向废弃栈中写入一些随机的数据,Linux则不做任何处理。这导致Windows平台中构建缓冲区数据在栈中植入恶意指令时,会面临限制。
      • Linux系统进程内存空间中栈底指针在0xc0x0000000之下,这些地址中没有空字节;Windows系统栈位置处于0x00FFFFFF以下的用户内存空间一般为0x0012****地址附近,而这些地址的首字节均为0x00空字节。
      • Windows通过操作系统中更为复杂的API及内核处理例程调用链来完成系统功能调用。攻击者在执行shellcode就要考虑系统功能调用的区别。
    • Windows系统上典型的Shellcode是启动一个命令行shell,即“command.com”或“cmd.exe”,API中提供了system()函数调用,可以用于启动指定程序或特定命令。

堆溢出攻击

  • 定义:缓冲区溢出中第二种类型的攻击方式。堆中并没有可以直接覆盖并修改指令寄存器指针的返回地址,因此需要利用堆中一些会影响程序执行流程的关键变量,如函数指针、C++类对象中的虚函数表,或挖掘岀堆中进行数据操作时可能存在的向指定内存地址改写内容的漏洞机会。
  • 基本原理
    • 函数指针改写:缓冲区临近全局函数指针存储地址,且在其低地址方向。那么当向缓冲区填充数据时,如果没有边界判断和控制的话,那么缓冲区溢出之后就会自然地覆盖函数指针所在的内存区,从而改写函数指针的指向地址。攻击者只需将指针指向hellcode入口地址。
    • C++类对象虚函数表改写:使用虚函数机制的C++类的类成员变量中存在可被溢出的缓冲区,则可通过覆盖类对象的虚函数指针,使其指向一个特殊构造的虚函数表,从而执行注入指令。
    • Linux下堆管理glibc库free()函数本身漏洞:Linux操作系统中的堆管理是通过glibc库实现的,使用的内存管理算法被称为dlmalloc,使用了被称为Bin的双向循环链表来存储内存空闲块信息。glibc库中的free()函数提供了将4字节值写入任意内存地址的机会。free()函数在处理内存块回收时,需要将己被释放的空闲块和与之相邻的空闲块进行合并,因此将会把符合条件的空闲块从Bin链表中unlink摘出来,合并之后再将新的空闲块插回链表中。攻击者可以利用此特性构造空闲块,达成覆盖。

缓冲区溢出攻击的防御技术

  • 尝试杜绝溢出的防御技术:编写正确的、不存在缓冲区溢出安全漏洞的软件代码。依靠fault injection等查错程序、Fuzz注入测试寻找漏洞、在编译器上引入针对缓冲区的边界保护检查机制。
  • 允许溢出但不让程序改变执行流程的防御技术:对关键数据结构进行严密保护,不让程序改变其执行流程,如Canary、SafeSEH技术等。
  • 无法让攻击代码执行的防御技术:尝试解决冯.诺依曼体系的本质缺陷,通过堆栈不可执行限制来防御。

实践过程

假期特惠,暂不用实践,以后补上。

学习中遇到的问题及解决

问题:汇编语言零基础,理解起来有点困难。
解决:先从简单基础的入手。

学习感想和体会

原理大体能看得懂,动手操作可能就。。。总之继续努力吧。

posted @ 2020-05-07 07:22  happycarrot  阅读(142)  评论(0编辑  收藏  举报