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

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

前言

作业 答案
这个作业属于哪个课程 网络攻防实践
这个作业的要求在哪里 第十次作业 软件安全攻防--缓冲区溢出和shellcode
我在这个课程的目标是 学习、提高网络攻防的本领
这个作业在哪个具体方面帮助我实现目标 学习Linux操作系统安全攻防

1.本章知识点总结

1.1 软件安全概述

  • 攻击者能够轻易地对系统和网络实施攻击,很大程度上是因为安全漏洞在软件中的大规模存在,攻击者可以利用这些漏洞来违背系统和网络的安全属性。根据安全业界的统计,大多数成功攻击都是利用和破解已公布但未被修补的软件安全漏洞或不安全的软件配置,而这些安全漏洞不可避免地大量存在于日趋复杂化、更加可扩展和可交互,以及在互联网络中相互连通的各类软件之中。安全漏洞的类型多种多样,从最基本的缓冲区溢出,到格式化字符串漏洞、竞争条件漏洞、整数溢出,以及近年最流行的xSS跨站脚本、SQL注入等。
  • 安全漏洞在软件开发周期的各个环节(包括设计、编码、发布等)中都可能被引入,而只有软件设计与开发人员充分认识到安全漏洞的危害、掌握安全漏洞机理,以及如何避免漏洞的安全编程经验,并在软件厂商的软件开发生命周期中切实执行安全设计开发的流程,才有可能尽量地减少发布软件中的安全漏洞数量,降低它们对网络与现实世界所带来的影响与危害。

1.1.1 软件安全漏洞威胁

  • 安全漏洞定义: 在系统安全流程、设计、实现或内部控制中所存在的缺陷或弱点,能够被攻击者所利用并导致安全侵害或对系统安全策略的违反
  • 安全漏洞包括三个基本元素: 系统的脆弱性或缺陷、攻击者对缺陷的可访问性,以及攻击
    者对缺陷的可利用性。
  • 一个安全脆弱性或缺陷真正被称为安全漏洞,必须是攻击者具备至少一种攻击工具或技术能够访问和利用到这一缺陷。
  • 软件安全漏洞 则被定义为在软件的需求规范、开发阶段和配置过程中引入的缺陷实例,其执行会违反安全策略。软件安全
    漏洞同样符合安全漏洞的三个基本元素,同时被限制于在计算机软件中。

1.1.2 软件安全困境

软件安全困境三要素:复杂性(Complexity)、可扩展性(Extensibility )和连通性(Connectivity),软件的这三个要素共同作用,使得软件的安全风险管理成为了一个巨大的挑战,从而很难
根除安全漏洞。

  • 复杂性: 软件规模越来越大,越来越复杂,就意味着软件的bug会越来越多。
  • 可扩展性:现代软件往往都会提供一些扩展和交互渠道。软件的可扩展性功能和机制使得安全保证更加困难。很难阻止攻击者和恶意代码以不可预测的扩展方式来入侵软件和系统;分析可扩展性软件的安全性要比分析一个完全不能被更改的软件要困难得多。
  • 连通性:高度的连通性使得一个小小的软件缺陷就有可能影响非常大的范围,从而引发巨大的损失。

1.1.3 软件安全漏洞类型

软件安全漏洞类型从技术上主要包括如下几类:

  • 内存安全违规类

    • 内存安全违规类漏洞是在软件开发过程中在处理RAM 内存访问时所引入的安全缺陷,如缓冲区溢出漏洞和Double Free、Use-after-Free 等不安全指针问题等。
    • 不安全指针是指在计算机程序中存在的并没有指向适当类型对象的非法指针,在对这些指针进行引用时,往往会发生一些不可预期的后果,导致程序内存访问错误,而一旦攻击者可以控制这些指针指向的内存内容,那他们就可以利用这些问题构造出恶意攻击,获得软件的控制权
  • 输入验证类类

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

    • 竞争条件类缺陷是系统或进程中一类比较特殊的错误,通常在涉及多进程或多线程处
      理的程序中出现,是指处理进程的输出或者结果无法预测,并依赖于其他进程事件发生的
      次序或时间时,所导致的错误。
    • 在软件中比较常见的竞争条件类漏洞是Time -of check-to time -of- use (TOCTTOU)
      类漏洞
    • 符号链接竞争问题(symlink race)是另一种由于程序以不安全的方式创建文件所导致的竞争条件类漏洞
  • 权限混淆与提升类

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

1.2 缓冲区溢出基础概念

1.2.1 缓冲区溢出基本概念与发展过程

  • 缓冲区溢出是计算机程序中存在的一类内存安全违规类漏洞,在计算机程序向特定缓冲区内填充数据时,超出了缓冲区本身的容量,导致外溢数据覆盖了相邻内存空间的合法数据,从而改变程序执行流程破坏系统运行完整性。理想情况下,程序应检查每个输入缓冲区的数据长度,并不允许输入超出缓冲区本身分配的空间容量,但是大量程序总是假设数据长度是与所分配的存储空间是相匹配的,因而很容易产生缓冲区溢出漏洞。
  • 缓冲区溢出攻击发生的根本原因,可以认为是现代计算机系统的基础架构——冯●诺伊曼体系存在本质的安全缺陷,即采用了“存储程序”的原理,计算机程序的数据和指令都在同一内存中进行存储,而没有严格的分离。

1.2.2 缓冲区攻击背景知识

  • 编译器与调试器的使用

    • 用C/C++ 等高级编程语言编写的源码,需要通过编译器和连接器才能生成可直接在操作系统平台上运行的可执行程序代码。
    • 调试器是程序开发人员在运行时刻调试与分析程序行为的基本工具。
    • GCC最基本的用法是执行gcc -c test.c命令进行源码编译,生成test.o,然后执行 gcc -0 test test.o进行连接,生成test可执行程序,可以使用gcc test.c -o test同时完成编译和连接过程。
    • 处理多个源码文件、包含头文件、引用库文件等多种情况,程序开发人员通常编写或自动生成Makefile,来控制GCC的编译和连接过程。
    • 类UNIX平台.上进行程序的调试经常使用GDB调试器,如果需要在Linux等类UNIX平台,上分析程序安全漏洞、调试渗透攻击代码,GDB是一个必须掌握的工具。
  • 汇编语言基础知识

    • 常用的寄存器和它们对应的功能,从应用的角度一般将寄存器分为4类,即 通用寄存器、段寄存器、控制寄存器和其他寄存器。 通用寄存器如eax、ebx、ecx、edx等,主要用于普通的算术运算,保存数据、地址、偏移量、计数值等。我们需要特别注意通用寄存器中的“栈指针”寄存器esp,它在栈溢出攻击时是个关键的操纵对象。
    • 段寄存器在IA32架构中是16位的,一般用作段基址寄存器。控制寄存器用来控制处理器的执行流程,其中最关键的是eip, 也被称为“指令指针”,它保存了下一条即将执行的机器指令的地址,因而也成为各种攻击控制程序执行流程的关键攻击目标对象,而如何修改与改变将要被装载至eip寄存器的内存数据,以及修改为何地址,是包括缓冲区溢出在内渗透攻击的关键所在。其他寄存器中值得关注的是“扩展标志”eflags寄存器,由不同的标志位组成,用于保存指令执行后的状态和控制指令执行流程的标志信息。


  • 进程内存管理

    • Linux操作系统中的进程内存空间布局和管理机制

      • 程序在执行时,系统在内存中会为程序创建-一个虚拟的内存地址空间,在32位机上即4GB的空间大小,
        用于映射物理内存,并保存程序的指令和数据: 3GB (即0x0000000)以下为用户态空间,3GB .4GB为内核态空间;操作系统将可执行程序加载到新创建的内存空间中,程序-般包含.text、.bss 和.data三种类型的段,.text段 包含程序指令,在内存中被映射为只读,.data 段主要包含静态初始化的数据,而 .bss 段则主要包含未经初始化的数据,两者都被映射至可写的内存空间中。
      • 加载完成后,系统紧接着就开始为程序初始化“栈”(Stack)和“堆”(Heap),“栈”是一种后进先出的数据结
        构,其地址空间从高地址向低地址增长,Linux程序运行的环境变量env、运行参数argv、运行参数数量argc都被放置在“栈”底,然后是主函数及调用“栈”中各个函数的临时保存信息,“堆”则是一种先进先出的数据结构,用于保存程序动态分配的数据和变量,其地址空间从低地址往高地址增长,与“栈”正好相反;程序执行时,就会按照程序逻辑执行.text中的指令,并在“堆”和"栈”中保存和读取数据。
    • Windows操作系统中的进程内存空间布局和管理机制

      • Windows操作系统的进程内存空间2GB-4GB为内核态地址空间,用于映射Windows内核代码和一些核心态DLL,并用于存储一些内核态对象,0GB-2GB为用户态地址空间。高地址段映射大量程序共用系统DLL,1GB位置装载进程本身引用的DLL,可执行代码段从0x400000开始,同样有栈和堆存储各进程的执行数据。
  • 函数调用过程

    • 程序进行函数调用包括以下三个步骤:
      • 调用:调用者将函数调用参数、函数调用下一条指令的返回地址压栈,并跳转至被调用函数入口地址。
      • 序言: 被调用函数开始执行首先会进入序言阶段,将对调用函数的栈基址进行压栈保存,并创建自身函数的栈结构,具体包括将ebp寄存器赋值为当前栈基址,为本地函数局部变量分配栈地址空间,更新esp寄存器为当前栈顶指针等。
      • 返回: 被调用函数执行完功能将指令控制权返回给调用者之前,会进行返回阶段的操作,通常执行leave和ret指令,即恢复调用者的栈顶与栈底指针,并将之前压栈的返回地址装载至指令寄存器eip中,继续执行调用者在函数调用之后的下一条指令。

1.2.3 缓冲区溢出攻击原理

缓冲区溢出漏洞根据缓冲区在进程内存空间中的位置不同,又分为栈溢出、堆溢出和内核溢出 这三种具体技术形态

  • 栈溢出是指存储在栈上的一些缓冲区变量由于存在缺乏边界保护问题,能够被溢出并修改栈上的敏感信息(通常是返回地址),从而导致程序流程的改变。
  • 堆溢出则是存储在堆上的缓冲区变量缺乏边界保护所遭受溢出攻击的安全问题。
  • 内核溢出漏洞存在于些内核模块或程序中,是由于进程内存空间内核态中存储的缓冲区变
    量被溢出造成的。

缓冲区溢出安全漏洞的根本问题在于用户输入可控制的缓冲区操作缺乏对目标缓冲区的边界
安全保护,这其中包含两个要素:

  • 首先是程序中存在着缺乏边界安全保护的缓冲区操作(通
    常称为漏洞利用点)。
  • 其次是这个缓冲区操作必须是用户输入可以控制的,也就是说用户的输入可以直接或者间接地影响到这个不安全的缓冲区操作函数。

1.3 Linux栈溢出与Shellcode

1.3.1 Linux平台栈溢出攻击技术

Linux平台中的栈溢出攻击按照攻击数据的构造方式不同,主要有NSR、RSN和RS三种模式

  • NSR模式:NSR模式主要适用于被溢出的缓冲区变量比较大,足以容纳Shellcode的情况,其攻击数据从低地址到高地址的构造方式是一堆Nop指令(即空操作指令)之后填充Shellcode,再加上一些期望覆盖RET返回地址的跳转地址,从而构成了NSR攻击数据缓冲区。
  • RNS模式:一般用于被溢出的变量比较小,不足于容纳Shellcode的情况,攻击数据从低地址到高地址的构造方式是首先填充一些期望覆盖RET返回地址的跳转地址,然后是一堆Nop指令填充出“着陆区”,最后再是Shellcode。在溢出攻击后,攻击数据将在RET区段即溢出了目标漏洞程序的小缓冲区,并覆盖了栈中的返回地址,然后跳转到Nop指令所构成的“着陆区”,并最终执行Shellcode。
  • RS模式:在这种模式下能够精确定位出Shellcode在目标漏洞程序进程空间中的起始地址,因此也就无需引入Nop空指令构建“着陆区”。这种模式是将Shellcode放置在目标漏洞程序执行时的环境变量中,由于环境变量是位于Linux进程空间的栈底位置,因而不会受到各种变量内存分配与对齐因素的影响,其位置是固定的,可以通过如下公式进行计算:ret=0xc0000000 - sizeof(void*) - sizeof(FILENAME) - sizeof(Shellcode)

1.3.2 Linux平台的shellcode实现技术

  • Linux本地Shellcode实现机制
    Linux 中一个最简单的本地 Shellcode 的产生过程, 而这个过程事实上也体现了 Shellcode 的通用方法, 包括如下5个步骤:
    • 先用高级编程语言, 通常用C, 来编写 Shellcode 程序;
    • 编译并反汇编调试这个 Shellcode 程序;
    • 从汇编语言代码级别分析程序执行流程;
    • 整理生成的汇编代码, 尽量减小它的体积并使它可注入, 并可通过嵌入C语言进行运行测试和调试;
    • 提取汇编代码所对应的 opcode 二进制指令, 创建 Shellcode 指令数组。
  • Linux远程Shellcode实现机制
    Linux平台上的远程Shellcode实现机制与本地Shellcode实现机制是一样的,通过系统调用完成指定功能。Linux远程Shellcode需要让攻击目标程序创建socket监听指定的端口等待客户端连接,启动一个命令行Shell,并将命令行的输入输出与socket绑定,这样攻击者就可以通过socket客户端连接目标程序所在主机的开放端口,与服务端socket建立起通信通道,并获得远程访问Shell。

1.4 Windows平台上的栈溢出与Shellcode

由于Windows操作系统与Linux操作系统在进程内存空间布局、系统堆栈的处理方式、系统功能调用方式等方面上的实现差异,虽然栈溢出的基础原理和大致流程是一致的,但在具体的攻击实施细节、Shellcode编制等方面还存在着一些差别。

1.4.1 Windows平台栈溢出攻击技术

Windows操作系统平台在很多方面与Linux操作系统具有显著不同的实现机制,而在这些差异中,与成功攻击应用程序中栈溢出漏洞密切相关的主要有如下三点。

  • 对程序运行过程中废弃栈的处理方式差异:Windows会向废弃栈中写入一些随机的数据,而Linux则不进行任何的处理
  • 进程内存空间的分布导致RNS模式不适用,Linux栈0xC0000000附近,这些地址中没有空字节,Windows栈在0x00FFFFFF以下的用户空间,这些地址首字节均为0x00空字节
  • 系统功能调用实现方式差异:Linux系统中通过“int 80”中断处理来调用系统功能,而Windows系统则是通过操作系统中更为复杂的API及内核处理例程调用链来完成系统功能调用

1.4.2 Windows平台的shellcode实现技术

由于Windows操作系统并不提供直接的系统调用,而是提供一系列的API接口函数,因此Windows平台上的Shellcode实现较Linux系统具有一些差异,编写也更难一-些。为了使得Windows中的Shellcode能够调用操作系统功能以完成攻击目标,并能够在期望注入的不同目标程序中正常运行,我们需要考虑如下问题:

  • Shellcode必须可以找到所需的Windows 32 API函数,并生成函数调用表
  • 为了能够使用这些API函数,Shellcode必须找出目标程序己加载的函数地址,或者需自行加载所需函数库,获得所需函数在目标程序进程内存空间中的加载地址,并获得它们在目标程序进程内存空间中的加载地址
  • Shellcode需考虑消除空字节,以避免在字符串操作函数中被截断,如果目标程序有更进一步的过滤规则,那么Shellcode在编写时需添加一.些编码机制,以顺利通过过滤器Shellcode需确保自己可以正常退出,并使原来的目标程序进程继续运行或终止
  • 在目标系统环境存在异常处理和安全防护机制时,Shellcode需进一步考虑如何对
    抗这些机制。

Windows本地Shellcode
在Windows平台上,典型的本地Shellcode同样也是启动一个命令行Shell,即"command.com"或"cmd.exe",Windows32的系统API中提供了system()函数调用,可以用于启动指定程序或运行特定命令,在调用system ("command.com")之后即可启动命令行程序。

Windows远程Shellcode

与Linux系统类似,更为常用的Shellcode是可以在远程渗透攻击中使用的,能够给出shell网络访问的远程Shellcode.在Linux中,可以用dup20复制标准I/O的文件句柄,然后执行(“/bin/sh”)即可,在Windows系统虽然原理是一样的,但具体实现时没这么简单。

Windows远程Shellcode大致过程如下:

  • 创建一个服务器端socket, 并在指定的端口上监听
  • 通过accept()接受客户端的网络连接
  • 创建子进程,运行“cmd.exe", 启动命令行
  • 创建两个管道,命令管道将服务器端socket 接收(recv) 到的客户端通过网络输
    入的执行命令,连接至cmd.exe的标准输入;然后输出管道将cmd.exe的标准输出连接至
    服务器端socket的发送(send), 通过网络将运行结果反馈给客户端

1.5 堆溢出攻击

堆溢出是缓冲区溢出中第二种类型的攻击方式,由于堆中的内存分配与管理机制较栈更复杂,不同操作系统平台的实现机制具有显著的差异。堆中没有可以直接覆盖的返回地址,因此堆溢出攻击比栈溢出更难。

  • 函数指针改写 :要求被溢出的缓冲区临近全局函数指针存储地址,且在其低地址方向上。此时向缓冲区填充数据,如果没有边界控制和判断,就可以覆盖函数指针所在的内存区,改写函数指针的指向地址,则程序在使用这个函数指针的时候就会执行shellcode。
  • C++ 类对象虚函数表改写 :使用了虚函数机制的C++类,如果它的类成员变量中存在可被溢出的缓冲区,那么就可以进行堆溢出攻击,通过覆盖类对象的虚函数指针,使其指向一个特殊构造的虚函数表,从而转向执行攻击者恶意注入的指令。
  • Linux下堆管理glibc库free()函数本身漏洞 :Linux操作系统的堆管理是通过glibc库来实现的,通过称为Bin的双向循环链表来保存内存空闲块的信息。glibc库中的free()函数在处理内存块回收时,会将被释放的空闲块和与之相邻的块合并,利用精心构造的块可以在合并时覆盖Bin前指针的内容。

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

  • 尝试杜绝溢出的防御技术
  • 允许溢出但不让程序改变执行流程的防御技术
  • 无法让攻击代码执行的防御技术

2.实践总结

对于汇编语言、计算机的一些常用寄存器与常用知识不熟练,还需要课后补习

3.参考资料

posted @ 2020-05-06 19:16  王晨20199120  阅读(186)  评论(0编辑  收藏  举报