20199130 2019-2020-2《网络攻防实践》第十次作业
20199130 2019-2020-2《网络攻防实践》第十次作业
| 本次作业属于那个课程 | 《网络攻防实践》 |
|---|---|
| 这个作业要求在哪里 | 《软件安全攻防——缓冲区溢出和Shellcode》 |
| 作业正文 | 下述正文 |
攻击者利用安全漏洞的存在性对系统和网络实施攻击,而安全漏洞的类型多种多样:最基本的缓冲区溢出,格式化字符串漏洞,竞争条件漏洞,整数溢出,以及近些年流行的XSS跨站脚本,SQL注入等。同时,针对安全漏洞的渗透技术由堆溢出、内核溢出、对抗EDP(数据执行保护)机制的ret2libc攻击、对抗ASLR(地址空间布局随机化)机制的Heap Spraying攻击等等。
1. 软件安全漏洞威胁:
1.1 安全漏洞
定义:在系统安全流程、设计、实践或内部控制中所存在的缺陷或弱点,能够被攻击者所利用并导致安全侵害或系统安全策略的违反。
基本要素:系统的脆弱性或缺陷、攻击者对缺点的可访问性、攻击者队缺陷的可利用性
软件安全漏洞的定义:在软件的需求规范、开发阶段和配置过程中引入的缺陷实例,其执行会违反安全策略。基本要素:符合安全漏洞的三要素,同时被限制于计算机软件中。
1.2 软件安全困境
软件安全“困境三要素”:复杂性、可扩展性、连通性
复杂性:由于软件规模的巨大和复杂,软件的bug会越来越多,运行Windows XP、Windows Server 2003及更新版本操作系统的计算机,依靠内核和应用程序来保护系统,但无法彻底消除系统bug。
可扩展性:现代软件为支持更加优化的软件架构,会提供一些扩展和交互渠道例如动态装载设备驱动和模块,他们支持可扩展性,客户端通过运行编译或解释执行的虚拟机允许运行移动代码。但因为可扩展软件大多数没有完善安全保护机制,导致很难组织攻击者和恶意代码以不可预测的扩展方式来入侵软件和系统。
连通性:互联网的普及使得全球更多的软件系统都联通在一起,控制关键基础设施的重要信息系统也与互联网建立了连通性。这使得一个小小的软件缺陷有可能影响很大的范围(例如蠕虫的大规模传播),同时高度的连通性使得网络攻击引发一些现实世界中的故障(电话网故障,电力系统遭受攻击造成大规模停电事故)
1.3 软件安全漏洞类型
- 内存安全未归类:在软件开发过程中在处理RAM内存访问时所引入的安全缺陷,如缓冲区溢出漏洞和Double Free、Use-after-Free等。主要出现在C/C++等编程语言所编写的软件中,因为它支持任意的内存分配与归还、任意的指针计算、转换,而这些操作通常没有进行保护确保内存安全,因而非常容易引入此类漏洞。而Java由于通过禁止指针计算与转换实施内存垃圾跟踪与收集能够解决此类安全漏洞。
- 输入验证类:指软件程序在对用户输入进行数据验证存在的错误,没有保证输入数据的正确性、合法性和安全性,从而导致可能被恶意攻击与利用。它根据输入位置、恶意输入内容被软件程序的使用方式的不同,包含格式化字符吊、 SQL注入、代码注入、远程文件包含、目录遍历、XSS、HTTP Header注入、HTTP响应分割错误等多种安全漏洞技术形式。主要针对Web应用程序的输入验证类漏洞。
- 竞争条件类:是系统或进程中一类比较特殊的错误,通常在涉及多进程或多线程处理的程序中出现,是指处理进程的输出或者结果无法预测,并依赖于其他进程事件发生的次序或时间时所导致的错误。比较常见的一类是Time-of-check-lo-time-of-use (TOCTTOU) 类漏洞,当程序检查以个谓词条件(比如是否符合认证要求)之后,就可以通过另一进程对谓词条件进行修改从而改变条件状态,从而导致检查时刻和使用时刻的条件状态不一致产生安全漏洞。
- 权限混淆与提升类:指计算机程序由于自身编程疏忽或被第三方欺骗,从而滥用其权限,或赋与第三方不该给予的权限。其主要技术形式:Web 应用程序中的跨站请求伪造(Cross-Site Request Forgery, CSRF)、Clickjacking、 FTP 反弹攻击、权限提升、“越狱” (jailbreak)等。
2. 缓冲区溢出基础概念
2.1 缓冲区溢出定义
缓冲区溢出:计算机程序中存在的一类内存安全违规类漏洞,在计算机程序向特定缓冲区内填充数据时,由于超出了缓冲区本身的容量,导致外溢数据覆盖了相邻内存空间的合法数据,从而改变了程序执行流程破坏系统运行完整性。缓冲区溢岀漏洞通常多见于C/C++语言程序中的memcpy、strcpy()等内存与字符串复制函数的引用位置
2.2 缓冲区溢出攻击背景知识
(1)编译器与调试器的使用:使用C/C++等高级编程语言编写的源码,需要通过编译器 (Compiler)和连接器(Linker)才能生成可直接在操作系统平台上运行的可执行程序代码。类UNIX平台上进行程序的调试经常使用GDB调试器,GDB调试 器提供程序断点管理、执行控制、信息查看等多种类型的功能指令:住断点管理方面,通过break/clcar来设置和移除断点,enable/disable来启用或禁用断点,watch设置监视表达式值改变时的程序中断;在执行控制方而,基本指令包括run (运行程序)、attach (调试已运行进程)、continue (继续运行)、next (单步代码执行并不进入函数调用)、nexti (単步指令执行并不进入函数调用)、step (单步代码并跟入函数调用)、stepi (单步指令并跟入函 数调用)等:在信息査看方面,比较常用的指令包括info (査看各种信息)、backtrace (显示调用栈)、x (限制指定地址内容)、print (显示表达式值)、list (列出程序源码,需调试程序带符号编译)、disass(反汇编指定函数)等。
(2)汇编语言基础知识:尤其是IA32 (Intel 32位)架构下的汇编语言是掌握软件渗透攻击代码技术的底层基础。在IA32汇编语言中,从应用的角度将寄存器分为4类,即
- 通用寄存器:eax、ebx、ecx、edx,主要用于普通的算术运算,保存数 据、地址、偏移晨、计数值等。
- 段寄存器:一般用作段基址寄存器
- 控制寄存器:用来控制处理器的执行流程,其中最关键的是eip,也被称为“指令指针”,它保存了下一条即将执行的机器指令的地址,因而也成为各种攻击控制程序执行流程的关键攻击目标对象,而如何修改与改变将要被装载金eip寄存器的内存数据,以及修改为何地址,是内渗透攻击的关键。
- 其他寄存器:扩展标志eflags寄存器,由不同的标志位组成,用于保存指令执行后的状态和控制指令执行流程的标志信息
![]()
![]()
(3)进程内存管理:是最主要的软件安全漏洞类型,Linux操作系统中的进程内存空间布局和管理机制:程序在执行时,系统在内存中会为程序创建一个虚拟的内存地址空间,操作系统将可执行程序加载到新创建的内存空间中,程序一般包含.text, .bss和.data三种类型的段。.text段包含程序指令,在内存中被映射为只读,.data段主要包含静态初始化的数据,而.bss段则要包含未经初始化的数据,两者都被映射至可写的内存空间中;加载完成后,系统为程序初始化“栈”和“堆”,Linux程序运行的环境变量env、运行参数argv、 运行参数数量argc都被放置在“栈”底,然后是主函数及调用“栈”中各个函数的临时保存信息
(4)函数调用过程:栈结构与函数调用过程的底层细节是理解栈溢出攻击的重要基础,栈溢出攻击就是针对函数调用过程中返冋地址在栈中的存储位置,进行缓冲区溢出,从而改写返回地址使处理器指令寄存器跳转至指定位置执行恶意代码。两个与栈密切相关的寄存器为ebp和esp,分别保存当前运行函数的栈底地址和栈顶地址,两个密切相关的指令为push和pop,分别是将数据压入栈,及将栈顶数据弾出至特定寄存器。程序进行函数调用的过程有如下三个步骤:
调用(call):调用者将函数调用参数、函数调用下一条指令的返回地址压栈,并跳转至被调用函数入口地址
序言(prologue):被调用函数开始执行首先会进入序言阶段,将对调用函数的栈基址进行压栈保存,并创建自身函数的栈结构
返回(return):被调用函数执行完功能将指令控制权返回给调用者之前,会进行返回阶段的操作,通常执行leave和ret指令

main函数中进行了func函数调用,对调用参数压栈并通过call指令再保存返回地址后跳转到func函数;func函数中,前3条指令构建栈结构,在完成函数功能(这里为对参数求和)后,最后两条指令回复main函数的堆栈并返回下一条指令继续运行。
3. 缓冲区溢出攻击原理
3.1 缓冲区溢出漏洞类别
根据缓冲区在进程内存空间中的位置不同分为
(1)栈溢出:存储在栈上的一些缓冲区变量由于存在缺乏边界保护问题能够被溢出并修改栈上的敏感信息
(2)堆溢出:存储在堆上的缓冲区变量缺乏边界保护所遭受溢出攻击的安全问题
(3)内核溢出:存在于一些内核模块或程序中,由于进程内存空间内核中存储的缓冲区变量被溢出造成的
3.2 缓冲区溢出安全漏洞的基本原理
缓冲区溢出安全漏洞的根本问题在于用户输入可控制的缓冲区操作缺乏对目标缓冲区的边界安全保护:首先是程序中存在着缺乏边界安全保护的缓冲区操作(通常称为漏洞利用点),其次是这个缓冲区操作必须是用户输入可以控制的,因此攻击者可以向漏洞利用点注入他们恶意构造的数据,才能溢出缓冲区,并执行他们所预期的恶意指令。
Linux平台上的栈溢出与Shellcode
Linux平台栈溢出攻击技术
Linux平台中的栈溢出按照攻击数据构造方式的不同,分为三种模式:NSR、RNS、RS
NSR模式:适用于被溢出的缓冲区变量比较大,足以容纳Shellcode的恬况,其攻击数据从低地址到高地址的构造方式是一堆Nop指令(即空操作指令)之后填充Shellcodc, 再加上一些期望覆盖RET返回地址的跳转地址,从而构成 NSR攻击数据缓冲区
RNS模式:一般用于被溢出的变量比较小,不足以容纳Shellcode的情况,攻击数据从低地址到高地址的构造方式是首先壊充一些期望覆盖RET返回地址的跳转地址,然后是一堆Nop指令填充出“着陆区”,最后再是 Shellcode
RS模式:在这种模式下能够精确地定位出Shellcode在目标漏洞程序进程空间中的起始地址,无须引入Nop 空指令构建“着陆区”
计算公式:ret = OxcOOOOOOO-sizeof(void *)-sizeof(FILENAME)-sizeof(Shellcode)
在渗透攻击程序本地调用目标漏洞程序时,使用execve()函数将Shellcode的环境变量数组传递到目标漏洞程序进程空间中。
4.3 Linux平台的Shellcode实现技术
Shellcode:是一段机器指令,符合Intel 32位指令规范的一串CPU指令,被用于溢出之后改变系统正常流程,转而执行Shellcode以完成渗透攻击的目的。
- Linux本地Shellcode实现机制
功能:为攻击者启动一个命令行Shell
- Linux远程Shellcode实现机制
其原理与本地Shellcode完全一致,通过执行一系列的系统调用实现目的
5. Windows平台上的栈溢出与Shellcode
5.1 Windows平台栈溢出攻击技术机理
(1)对程序运行过程中废弃栈的处理方式差异
(2)进程内存空间的布局差异
(3)系统功能调用的实现方式差异

使用LoadLibrary()函数加载msvcrt.dll动态链接库,并通过GetprocAddress()函数获得system函数的加载入口地址,赋值给ProAdd函数指针;然后通过函数指针调用system()函数,启动Shell;最后,Shellcode调用函数exit()退出当前进程。
5.2 堆溢出攻击
缓冲区溢出攻击的防御技术:
(1)尝试杜绝溢出的防御技术:开发一些工具和查错程序例如fault injection等,通过Fuzz注入测试来寻找代码的安全漏洞
(2)允许溢出但不让程序改变执行流程的防御技术:StackGuard、PointGuard、ProPolice、Stack Shield
(3)无法让攻击代码执行的防御技术:return-2-libc攻击技术,让CPU按照特定顺序需执行系统中已经存在的代码


浙公网安备 33010602011771号