CVE-2023-38148 Internet Connection Sharing 远程代码执行漏洞分析

admin 2024年5月17日21:26:13评论20 views字数 12083阅读40分16秒阅读模式

文章发于:

基本信息

依赖于ICS服务,Internet Connect Sharing,对应注册表,依赖ipnathlp.dll

HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesSharedAccess

漏洞存在于处理DHCP请求时,由于没有检查边界,导致在使用memset时使用的长度参数来源于数据包内,可以导致栈溢出。服务调试参考第二个参考链接。

影响版本

环境搭建

参考https://github.com/ruijanlee/h3cc/blob/master/h3cc_ruijanlee/doc/c8.md,同时加一个Linux,网卡使用第二个网卡,使得Linux发出的DHCP包能够被Windows接收到。

技术分析&调试

静态分析

对比补丁修复前后的逻辑,有两个明显的不同点,有两种产生漏洞的可能的地方。

  1. 在修复版本中在进行 if ( *((_BYTE *)a2 + 230) > 0x20u )判断之前先调用了 DumpDhcpHeaderInfo,在漏洞代码中先进行判断在调用DumpDhcpHeaderInfo

  2. 在修复版本中如果满足 if ( *((_BYTE *)a2 + 230) > 0x20u ) 则进入if内,在结束if语句时会通过跳转略过一部分处理逻辑,而在未修复版本内则还会继续处理。

可以看出 a2 + 230_NH_BUFFER 结构体内的某个长度字段,该处为判断这个长度字段存储的长度,该漏洞应该是溢出漏洞,并且在产生漏洞的地方需要读取该字段。

所以漏洞应该是第二点所说的,产生在略过的逻辑中。

// 未修复代码void __fastcall DhcpProcessMessage(struct _DHCP_INTERFACE *a1, struct _NH_BUFFER *a2){ ......  memset_0(&v12, 0, 0x40ui64);  if ( *((_BYTE *)a2 + 230) > 0x20u )  {    if ( v4 != (CInterfaceMonitor *)&WPP_GLOBAL_Control && (*((_BYTE *)v4 + 28) & 2) != 0 && *((_BYTE *)v4 + 25) >= 4u )      WPP_SF_dD(        *((_QWORD *)v4 + 2),        97i64,        &WPP_2a3aeb8dd77c3a1919c551579bb6cf5d_Traceguids,        *((unsigned __int8 *)a2 + 230),        32);    _InterlockedIncrement((volatile signed __int32 *)&DhcpStatistics);  }  DumpDhcpHeaderInfo(a2);// 修复代码void __fastcall DhcpProcessMessage(struct _DHCP_INTERFACE *a1, struct _NH_BUFFER *a2){  ......  memset_0(&v11, 0, 0x40ui64);  DumpDhcpHeaderInfo(a2);  if ( *((_BYTE *)a2 + 230) > 0x20u )  {    if ( WPP_GLOBAL_Control != (CInterfaceMonitor *)&WPP_GLOBAL_Control      && (*((_BYTE *)WPP_GLOBAL_Control + 28) & 2) != 0      && *((_BYTE *)WPP_GLOBAL_Control + 25) >= 4u )    {      WPP_SF_dd(        *((_QWORD *)WPP_GLOBAL_Control + 2),        97i64,        &WPP_df007ca3347434f5610fc5a17e95e0a3_Traceguids,        *((unsigned __int8 *)a2 + 230),        32);    }    goto LABEL_10;  }LABEL_10:    _InterlockedIncrement((volatile signed __int32 *)&DhcpStatistics);// 这里多了调用    goto LABEL_11;    ......LABEL_11:  EnterCriticalSection(&DhcpInterfaceLock);  if ( *((int *)a1 + 19) < 0 )  {    LeaveCriticalSection(&DhcpInterfaceLock);
略过的代码中,读取了a2参数的代码如下:
  if ( DhcpExtractOptionsFromMessage((struct _NH_BUFFER *)((char *)a2 + 228), *((_DWORD *)a2 + 55), &v11) )  .....  if ( !v12 )  {    .....    DhcpProcessBootpMessage(a1, a2, &v11);    goto LABEL_11;  }  .....  if ( DhcpIsLocalHardwareAddress((unsigned __int8 *)a2 + 256, *((unsigned __int8 *)a2 + 230)) )  {    ....  }  v7 = *(unsigned __int8 *)(v12 + 2);  if ( v7 == 1 )  {    .....    DhcpProcessDiscoverMessage(a1, a2, &v11);  }  else if ( *(_BYTE *)(v12 + 2) == 3 )  {    ......    DhcpProcessRequestMessage(a1, a2, &v11);  }  ......    }    if ( !DhcpArpForDad )    {      v10 = *(_DWORD *)(v13 + 2);      DhcpRemoveArpEntry(v10);      DhcpCancelLease(v10, (unsigned __int8 *)a2 + 256, *((unsigned __int8 *)a2 + 230));   .....  }  else  {    if ( *(_BYTE *)(v12 + 2) != 7 )    {      if ( *(_BYTE *)(v12 + 2) == 8 )      {        ......        DhcpProcessInformMessage(a1, a2, &v11);      }      else      {        ......      }      goto LABEL_11;    }    if ( !DhcpArpForDad )    {      DhcpRemoveArpEntry(*((_DWORD *)a2 + 60));      DhcpCancelLease(*((_DWORD *)a2 + 60), (unsigned __int8 *)a2 + 256, *((unsigned __int8 *)a2 + 230));    }   ......  }
查看这些函数代码,在 DhcpProcessBootpMessage函数中有如下逻辑
void __fastcall DhcpProcessBootpMessage(  v3 = a2;  v5 = (char *)v3 + 228;  ......      else      {        if ( !DhcpSendUnicastMessagesEnabled          || v5[10] < 0          || DhcpAddArpEntry(v6, (unsigned __int8 *)v5 + 28, (unsigned __int8)v5[2], v23) )// 这个函数触发了漏洞        {// movzx   r8d, byte ptr [r15+2]           ; Size        ...

前面知道 a2 + 230是长度字段,v5=v2+228,传入 DhcpAddArpEntry的size参数为v5+2,也就是a2 + 230DhcpAddArpEntry函数中,Row为栈内结构体,memcpy传入的长度参数为a2 + 230,也就是补丁中判断的长度参数。MIB_IPNET_ROW2结构体定义可以在这找到,其大小为0x58

__int64 __fastcall DhcpAddArpEntry(DWORD a1, unsigned __int8 *Src, size_t Size, struct _DHCP_INTERFACE *a4){  MIB_IPNET_ROW2 Row;  ......  v4 = (unsigned int)Size;  .....    memset_0(&Row, 0, sizeof(Row));    Row.InterfaceIndex = DhcpAdapterIndex;    Row.Address.Ipv4.sin_family = 2;    Row.Address.Ipv4.sin_addr.S_un.S_addr = a1;    Row.PhysicalAddressLength = v4;    memcpy_0(Row.PhysicalAddress, Src, v4);    ......    return v11;  }}

所以漏洞触发路径为 DhcpProcessMessage->DhcpProcessBootpMessage->DhcpAddArpEntry->memcpy_0,当长度参数过长时可以利用memcpy触发栈溢出。

动态调试

使用windbg附加到svchost进程,在ipnathlp!DhcpProcessMessage断点,而后触发DHCP请求,windbg在 ipnathlp!DhcpProcessMessage断下 由于不知道 DhcpProcessMessage的a2结构体定义,此处构造正常的DHCP请求,并在调试器中查看这个结构体成员信息。单步运行到判断长度的地方,此时rsi指向传入的 _NH_BUFFER结构体,

0:004> uipnathlp!DhcpProcessMessage+0x7f:00007ff9`c00176f3 488dbee4000000  lea     rdi,[rsi+0E4h]00007ff9`c00176fa 41b604          mov     r14b,400007ff9`c00176fd 807f0220        cmp     byte ptr [rdi+2],20h00007ff9`c0017701 7636            jbe     ipnathlp!DhcpProcessMessage+0xc5 (00007ff9`c0017739)00007ff9`c0017703 493bdc          cmp     rbx,r1200007ff9`c0017706 742a            je      ipnathlp!DhcpProcessMessage+0xbe (00007ff9`c0017732)00007ff9`c0017708 44847b1c        test    byte ptr [rbx+1Ch],r15b00007ff9`c001770c 7424            je      ipnathlp!DhcpProcessMessage+0xbe (00007ff9`c0017732)

可以在调试器内看到 (_BYTE *)a2 + 230)值为6

0:004> db rdi+200000203`faa1fdb6  06 00 1a cc 8a 61 00 00-80 00 00 00 00 00 00 00  .....a..........00000203`faa1fdc6  00 00 00 00 00 00 00 00-00 00 00 0c 29 c2 3a 42  ............).:B00000203`faa1fdd6  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fde6  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fdf6  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fe06  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fe16  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fe26  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

而该处数据来源于DHCP客户端发送的DHCP请求,在wireshark中可以看到数据包中刚好有长度字段值为6,说明(_BYTE *)a2 + 230)处有可能是数据包内的Hardware address length。

CVE-2023-38148 Internet Connection Sharing 远程代码执行漏洞分析

此时调用栈:

0:004> kChild-SP          RetAddr               Call Site0000000e`3487f480 00007ff9`c00143a4     ipnathlp!DhcpProcessMessage+0x860000000e`3487f540 00007ff9`c0006ecf     ipnathlp!DhcpReadCompletionRoutine+0x6440000000e`3487f5a0 00007ff9`eebe32ea     ipnathlp!NhpIoCompletionRoutine+0x6f0000000e`3487f5d0 00007ff9`eeb22f86     ntdll!RtlpTpIoCallback+0xca0000000e`3487f610 00007ff9`ee0a7614     ntdll!TppWorkerThread+0x4560000000e`3487f910 00007ff9`eeb226b1     KERNEL32!BaseThreadInitThunk+0x140000000e`3487f940 00000000`00000000     ntdll!RtlUserThreadStart+0x21
此时尝试手动将(_BYTE *)a2 + 230)修改为0xfe,继续运行,但没有触发异常。
0:004> db rdi+200000203`faa1fdb6  06 00 1a cc 8a 61 00 00-80 00 00 00 00 00 00 00  .....a..........00000203`faa1fdc6  00 00 00 00 00 00 00 00-00 00 00 0c 29 c2 3a 42  ............).:B00000203`faa1fdd6  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fde6  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fdf6  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fe06  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fe16  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fe26  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0:004> eb rdi+2 fe0:004> db rdi+200000203`faa1fdb6  fe 00 1a cc 8a 61 00 00-80 00 00 00 00 00 00 00  .....a..........00000203`faa1fdc6  00 00 00 00 00 00 00 00-00 00 00 0c 29 c2 3a 42  ............).:B00000203`faa1fdd6  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fde6  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fdf6  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fe06  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fe16  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................00000203`faa1fe26  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................0:002> gBreakpoint 0 hitipnathlp!DhcpProcessMessage:00007ff9`c0017674 48895c2418      mov     qword ptr [rsp+18h],rbx ss:0000000e`346ff630=00000203faa7e350

改为单步调试,再次发起DHCP请求,发现没有进入到漏洞函数 DhcpProcessBootpMe

ssage中,原因是v13不为0,条件不成立,不会调用 DhcpProcessBootpMessage

if ( !v13 )  {    if ( WPP_GLOBAL_Control != (CInterfaceMonitor *)&WPP_GLOBAL_Control      && (*((_BYTE *)WPP_GLOBAL_Control + 28) & 2) != 0      && *((_BYTE *)WPP_GLOBAL_Control + 25) >= 4u )    {      WPP_SF_(*((_QWORD *)WPP_GLOBAL_Control + 2), 98i64, &WPP_2a3aeb8dd77c3a1919c551579bb6cf5d_Traceguids);    }    DhcpProcessBootpMessage(a1, a2, &v12);      // 这里触发漏洞    goto LABEL_25;  }
对v13下写断点
0:004> ba w1 rsp+0x380:004> gBreakpoint 6 hitmsvcrt!memset+0x35:00007ff9`ed1046b5 4983e908        sub     r9,8
触发断点,此时调用栈如下,对应代码为 memset_0(a3, 0, 0x40ui64);
0:004> kChild-SP          RetAddr               Call Site0000000e`3487f418 00007ff9`c0015b63     msvcrt!memset+0x350000000e`3487f420 00007ff9`c0017754     ipnathlp!DhcpExtractOptionsFromMessage+0x7b0000000e`3487f480 00007ff9`c00143a4     ipnathlp!DhcpProcessMessage+0xe00000000e`3487f540 00007ff9`c0006ecf     ipnathlp!DhcpReadCompletionRoutine+0x6440000000e`3487f5a0 00007ff9`eebe32ea     ipnathlp!NhpIoCompletionRoutine+0x6f0000000e`3487f5d0 00007ff9`eeb22f86     ntdll!RtlpTpIoCallback+0xca0000000e`3487f610 00007ff9`ee0a7614     ntdll!TppWorkerThread+0x4560000000e`3487f910 00007ff9`eeb226b1     KERNEL32!BaseThreadInitThunk+0x140000000e`3487f940 00000000`00000000     ntdll!RtlUserThreadStart+0x21
此处将目标内存清零,不符合前面说的条件,继续运行,再次触发写断,调用栈为
0:004> kChild-SP          RetAddr               Call Site0000000e`3487f420 00007ff9`c0017754     ipnathlp!DhcpExtractOptionsFromMessage+0x4280000000e`3487f480 00007ff9`c00143a4     ipnathlp!DhcpProcessMessage+0xe00000000e`3487f540 00007ff9`c0006ecf     ipnathlp!DhcpReadCompletionRoutine+0x6440000000e`3487f5a0 00007ff9`eebe32ea     ipnathlp!NhpIoCompletionRoutine+0x6f0000000e`3487f5d0 00007ff9`eeb22f86     ntdll!RtlpTpIoCallback+0xca0000000e`3487f610 00007ff9`ee0a7614     ntdll!TppWorkerThread+0x4560000000e`3487f910 00007ff9`eeb226b1     KERNEL32!BaseThreadInitThunk+0x140000000e`3487f940 00000000`00000000     ntdll!RtlUserThreadStart+0x21
对应在DhcpExtractOptionsFromMessage的代码如下,当OptionID为0x35时进入case语句内
v9 = (struct _DHCP_OPTION *)((char *)a1 + 240);OptionID = v9->OptionID;    if ( OptionID )    {      switch ( OptionID )        case 0x35u:          if ( v6 != (CInterfaceMonitor *)&WPP_GLOBAL_Control            && (*((_BYTE *)v6 + 28) & 2) != 0            && *((_BYTE *)v6 + 25) >= 4u )          {            WPP_SF_(*((_QWORD *)v6 + 2), 44i64, &WPP_2a3aeb8dd77c3a1919c551579bb6cf5d_Traceguids);            v6 = WPP_GLOBAL_Control;          }          if ( BYTE1(v9->OptionID) )          {            a3[1] = v9;          }

_DHCP_OPTION结构体定义如下,对应于DHCP请求内的option

typedef DWORD DHCP_OPTION_ID;struct _DHCP_OPTION{  DHCP_OPTION_ID OptionID;  LPWSTR OptionName;  LPWSTR OptionComment;  DHCP_OPTION_DATA DefaultValue;  DHCP_OPTION_TYPE OptionType;};0:002> db rdi00000203`faa1fea4  35 01 03 3d 07 01 00 0c-29 c2 3a 42 32 04 c0 a8  5..=....).:B2...00000203`faa1feb4  89 cd 0c 0f 44 45 53 4b-54 4f 50 2d 54 35 50 37  ....DESKTOP-T5P700000203`faa1fec4  34 45 53 51 12 00 00 00-44 45 53 4b 54 4f 50 2d  4ESQ....DESKTOP-00000203`faa1fed4  54 35 50 37 34 45 53 3c-08 4d 53 46 54 20 35 2e  T5P74ES<.MSFT 5.00000203`faa1fee4  30 37 0e 01 03 06 0f 1f-21 2b 2c 2e 2f 77 79 f9  07......!+,./wy.

CVE-2023-38148 Internet Connection Sharing 远程代码执行漏洞分析

根据RFCrfc2132 option 53为传递DHCP消息类型,第一个字节是操作编号,第二个字节恒为1,第三个字节是消息类型,范围是1-9CVE-2023-38148 Internet Connection Sharing 远程代码执行漏洞分析CVE-2023-38148 Internet Connection Sharing 远程代码执行漏洞分析

根据代码,当DHCP中含有option 53一定会进入 DhcpExtractOptionsFromMessageif ( BYTE1(v9->OptionID) ),把a3[1]赋值为不为零的值。CVE-2023-38148 Internet Connection Sharing 远程代码执行漏洞分析回到DhcpProcessMessage内,v13就不为0,不能进入触发漏洞的逻辑CVE-2023-38148 Internet Connection Sharing 远程代码执行漏洞分析

重新构造DHCP数据包,,删除option53并将 Hardware address length改为100,单步调试,成功进入到 DhcpAddArpEntry函数内。

0:004> kChild-SP          RetAddr               Call Site0000000e`3487f2a0 00007ff9`c0016766     ipnathlp!DhcpAddArpEntry+0x14a0000000e`3487f380 00007ff9`c0017797     ipnathlp!DhcpProcessBootpMessage+0x5ea0000000e`3487f480 00007ff9`c00143a4     ipnathlp!DhcpProcessMessage+0x1230000000e`3487f540 00007ff9`c0006ecf     ipnathlp!DhcpReadCompletionRoutine+0x6440000000e`3487f5a0 00007ff9`eebe32ea     ipnathlp!NhpIoCompletionRoutine+0x6f0000000e`3487f5d0 00007ff9`eeb22f86     ntdll!RtlpTpIoCallback+0xca0000000e`3487f610 00007ff9`ee0a7614     ntdll!TppWorkerThread+0x4560000000e`3487f910 00007ff9`eeb226b1     KERNEL32!BaseThreadInitThunk+0x140000000e`3487f940 00000000`00000000     ntdll!RtlUserThreadStart+0x21
在调试器中可以看到,执行memcpy时长度参数为0x64,继续运行则触发了栈溢出,进程异常退出。
0:005> gBreakpoint 9 hitipnathlp!DhcpAddArpEntry+0x184:00007ff9`c0012570 e83db80600      call    ipnathlp!memcpy (00007ff9`c007ddb2)0:005> rr8r8=00000000000000640:005> gSTATUS_STACK_BUFFER_OVERRUN encountered(1858.3b4): Break instruction exception - code 80000003 (first chance)KERNELBASE!UnhandledExceptionFilter+0x7c:00007ff9`ec55dd3c cc              int     30:005> kChild-SP          RetAddr               Call Site0000000e`34b7efa0 00007ff9`c007d096     KERNELBASE!UnhandledExceptionFilter+0x7c0000000e`34b7f0c0 00007ff9`c007d229     ipnathlp!_raise_securityfailure+0x1a0000000e`34b7f0f0 00007ff9`c0012600     ipnathlp!_report_gsfailure+0x1690000000e`34b7f180 00007ff9`c0016766     ipnathlp!DhcpAddArpEntry+0x2140000000e`34b7f260 00007ff9`c0017797     ipnathlp!DhcpProcessBootpMessage+0x5ea0000000e`34b7f360 00007ff9`c00143a4     ipnathlp!DhcpProcessMessage+0x1230000000e`34b7f420 00007ff9`c0006ecf     ipnathlp!DhcpReadCompletionRoutine+0x6440000000e`34b7f480 00007ff9`eebe32ea     ipnathlp!NhpIoCompletionRoutine+0x6f0000000e`34b7f4b0 00007ff9`eeb22f86     ntdll!RtlpTpIoCallback+0xca0000000e`34b7f4f0 00007ff9`ee0a7614     ntdll!TppWorkerThread+0x4560000000e`34b7f7f0 00007ff9`eeb226b1     KERNEL32!BaseThreadInitThunk+0x140000000e`34b7f820 00000000`00000000     ntdll!RtlUserThreadStart+0x210:005> gntdll!NtWaitForWorkViaWorkerFactory+0x14:00007ff9`eeb70aa4 c3              ret

wireshrk中可以看到数据包协议为Bootp。

CVE-2023-38148 Internet Connection Sharing 远程代码执行漏洞分析

PoC参考简单实现的DHCP Client并将option 53注释,将 Hardware address length改为0x100。这个栈溢出长度和内容均为内容可控

小结

这个漏洞起源于memcpy时src和len参数均来源于数据包内,为用户可控,导致攻击者可以通过设置过长长度触发memcpy越界写入,触发时的漏洞函数为处理BOOTP协议,这个协议是DHCP协议前身,DHCP兼容这个协议,在处理Bootp消息时,没有检查长度导致在复制mac时产生溢出。

参考链接

https://bbs.kanxue.com/thread-278835.htm

https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/preparing-to-debug-the-service-application#-enabling-the-debugging-of-the-initialization-code

原文始发于微信公众号(闲聊趣说):CVE-2023-38148 Internet Connection Sharing 远程代码执行漏洞分析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月17日21:26:13
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CVE-2023-38148 Internet Connection Sharing 远程代码执行漏洞分析http://cn-sec.com/archives/2499594.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息