20199325 2019-2020-2 《网络攻防实践》第10周作业
一、学习总结
1.1软件安全概述
1.1.1软件安全漏洞威胁
安全漏洞定义:在系统安全流程、设计、实现或内部控制中所存在的缺陷或弱点,能够被攻击者所利用并导致安全侵害或对系统安全策略的违反
1.1.2软件安全困境
软件中的困境三要素:复杂性、可扩展性、连通性
1.1.3软件安全漏洞类型
软件安全漏洞从技术上主要包括如下几类:
- 内存安全违规类:在处理RAM内存访问时所引入的安全缺陷,在c/c++等编程语言所编写的软件程序中,由于这类语言支持任意的内存分配与归还,这些操作没有进行保护内存安全,因而容易引入此类漏洞。
- 输入验证类:软件程序在对用户输入进行数据验证时存在的错误,没有保证输入数据的正确性、合法性和安全性,从而导致可能被恶意攻击或利用。
- 竞争条件类:系统或进程中一类比较特殊的错误,通常在涉及多进程或多线程处理的程序中出现,是指处理进程的输出或者结果无法预测,并依赖于其他进程事件发生的次序或时间,所导致的错误。
- 权限混淆与提升类:权限混淆与提升类漏洞是指计算机程序由于自身编程疏忽或被第三方欺骗,从而滥用其权限,或赋予第三方不该给予的权限。
1.2缓冲区溢出基本概念
1.2.1缓冲区溢出基本概念
缓冲区溢出是计算机程序中存在的一类内存安全违规类漏洞,在计算机程序向特定缓冲区内填充数据时,超出了缓冲区本身的容量,导致外溢数据覆盖了相邻内存空间的合法数据,从而改变程序执行流程破坏系统运行完整性。
1.2.2缓冲区溢出攻击背景知识
- 编译器与调试器的使用
- 汇编语言基础知识
- 进程内存管理
- 函数调用过程
1.2.3缓冲区溢出攻击原理
缓冲区溢出漏洞根据缓冲区在进程内存空间中的位置不同,又分为栈溢出、堆溢出和内核溢出这三种具体技术形态。
- 栈溢出是指存储在栈上的一些缓冲区变量由于存在缺乏边界保护问题,能够被溢出并修改栈上的敏感信息,从而导致程序流程的改变。
- 堆溢出则是存储在堆上的缓冲区变量缺乏边界保护所遭受溢出攻击的安全问题,
- 内核溢出漏洞存在于一些内核块或程序中,是由于进程内存空间内核态中存储的缓冲区变量被溢出造成的。其中栈溢出在各类缓冲区溢出漏洞中是最容易理解,也是最早被发现和利用的技术形态。
1.3 Linux平台上的栈溢出与 Shellcode
1.3.1Linux平台栈溢出攻击技术
Linux平台栈溢出攻击按照攻击数据的构造方式不同,主要有NSR
、RNS
和RS
三种模式。
NSR模式:NSR模式主要适用于被溢出的缓冲区变量比较大,足以容纳Shellcode的情况,其攻击数据从低地址到高地址的构造方式是一堆Nop指令(即空操作指令)之后填充Shelleode,再加上一些期望覆盖RET返回地址的跳转地址,从而构成了NSR攻击数据缓冲区。
RNS模式:一般用于被溢出的变量比较小,不足于容纳Shellcode的情况,攻击数据从低地址到高地址的构造方式是首先填充一些期望覆盖RET
返回地址的跳转地址,然后是一堆Nop指令填充出“着陆区”,最后再是Shellcode。在溢出攻击之后,攻击数据将在RET区段即溢出了目标漏洞程序的小缓冲区,并覆盖了栈中的返回地址,然后跳转至Nop指令所构成的“着陆区”,并最终执行Shellcode。
RS模式:在这种模式下能够精确地定位出Shellcode在目标漏洞程序进程空间中的起始地址,因此也就无须引入Nop空指令构建“着陆区”。这种模式是将Shellcode放置在目标漏洞程序执行时的环境变量中,由于环境变量是位于Linux进程空间的栈底位置,因而不会受到各种变量内存分配与对齐因素的影响,其位置是固定的,可以通过如下公式进行计算:
1.3.2Linux本地和远程的Shellcode实现机制
本地实现机制:
Linux系统本地Shellcode通常提供的功能就是为攻击者启动一个命令行Shell。一般通过execve()函数启动/bin/sh提供命令行。
本地产生Shellcode的过程:
- 先用高级编程语言,通常用C,来编写Shellcode程序;
- 编译并反汇编调试这个Shellcode程序:
- 从汇编语言代码级别分析程序执行流程;
- 整理生成的汇编代码,尽量减小它的体积并使它可注入,并可通过嵌入C语言进行运行测试和调试;
- 提取汇编代码所对应的opcode二进制指令,创建Shellcode指令数组。
远程实现机制:
远程实现机制方法与本地一致。
1.4Windows平台栈溢出攻击技术
1.4.1 Windows平台栈溢出攻击技术机理
与Linux平台实现机制(与栈溢出相关)差异:
- 对程序运行过程中废弃栈的处理方式差异:Windows会向废弃栈中写入一些随机的数据,而Linux则不进行任何的处理
- 进程内存空间的分布导致RNS模式不适用,Linux栈0xC0000000附近,这些地址中没有空字节,Windows栈在0x00FFFFFF以下的用户空间,这些地址首字节均为0x00空字节
- 系统功能调用实现方式差异:Linux系统中通过“int 80”中断处理来调用系统功能,而Windows系统则是通过操作系统中更为复杂的API及内核处理例程调用链来完成系统功能调用
1.4.2 Windows平台的Shellcode实现
- shellcode必须可以找到所需要的Windows32 API函数,并生成函数调用表
- 为了能够使用API函数,shellcode必须找到目标程序已加载的函数地址
- shellcode需考虑消除空字节,以免在字符串操作函数中被截断
- shellcode需确保自己可以正常退出,并使原来的目标程序进程继续运行或终止
- 在目标系统环境存在异常处理和安全防护机制时,shellcode需进一步考虑如何应对这些机制
1.5堆溢出攻击
1.5.1函数指针改写、C++类对象虚函数表改写以及 Linux 下堆管埋漏洞来说明堆溢出攻击的基本原理
- 函数指针改写:此种攻击方式要求被溢出的缓冲区临近全局函数指针存储地址,且在其低地址方向上。如果向缓冲区填充数据的时候,如果没有边界控制和判断的话,缓冲区溢出就会自然的覆盖函数指针所在的内存区,从而改写函数指针的指向地址,则程序在使用这个函数指针调用原先的期望函数的时候就会转而执行shellcode
- C++类对象虚函数表改写:使用了虚函数机制的C++类,如果它的类成员变量中存在可被溢出的缓冲区,那么就可以进行堆溢出攻击,通过覆盖类对象的虚函数指针,使其指向一个特殊构造的虚函数表,从而转向执行攻击者恶意注入的指令
- Linux下堆管理glibc库free()函数本身漏洞:攻击者可以通过精心构造unlinkme内存块进行free()函数堆溢出攻击
1.6 缓冲区溢出攻击的防御技术
1.6.1缓冲区溢出攻击的防御技术
- 尝试杜绝溢出的防御技术:第一种采取如高级差错程序fault injection,通过Fuzz注入测试来寻找代码的安全漏洞,或者在编译器上引入针对缓冲区的便捷保护检查机制如Jone & Kelly针对gcc的数组边界检查、Compaq C对编译器进行改进杜绝溢出。
- 允许溢出但不让程序改变执行流程的防御技术:第二种防御技术允许溢出发生,但对可能影响到程序流程的关键数据结构实施严密的安全保护,不让程序改变其执行流程,从而阻断溢出攻击。
- 无法让攻击代码执行的防御技术:第三种通过堆栈不可执行限制来防御缓冲区溢出攻击,通过CPU硬件和各种操作系统内核补丁来支
2.学习中遇到的问题及解决
了解汇编语言基础,并通过实验楼做一些基础的缓冲区溢出的实验,自己的虚拟机容易搞崩。
3.感悟和思考
需要了解更多的基础知识,linux、windows等不同的平台所需要的基础知识也都不一样,所以需要更多的去关注最新的技术知识,充实自己。