IIS 文件名解析漏洞扼要分析

  • A+
所属分类:lcx

IIS文件名解析漏洞扼要分析

作者: golds7n

交流: daemon[at]t00ls.net

概括: 从技术角度分析IIS6文件名解析漏洞的原理与IIS7的相关情况。

a.IIS6错误解析文件类型现象

1、当WEB目录下,文件名以 xxx.asp;xxx.xxx 来进行命名的时候,此文件将送交asp.dll解析(也就是执行脚本)

2、当WEB目录下,在访问以 xxx.asp 命名的目录下的任意文件时,此文件将送交asp.dll解析(也就是执行脚本)

通过对IIS6的核心文件类型解析相关文件的逆向后,整理出下面的核心处理代码。

//reverse code by golds7n with ida
int __thiscall Url(void *this, char *UrlStruct)
{
  void *pW3_URL_INFO; // [email protected]
  int bSuccess; // [email protected]
  const wchar_t *i; // [email protected]
  wchar_t *wcsSlashTemp; // [email protected]
  int wcsTemp; // [email protected]
  int wcs_Exten; // [email protected]
  int v8; // [email protected]
  int v10; // [email protected]
  int v11; // [email protected]
  int v12; // [email protected]
  int ExtenDll; // [email protected]
  int Extenisa; // [email protected]
  int ExtenExe; // [email protected]
  int ExtenCgi; // [email protected]
  int ExtenCom; // [email protected]
  int ExtenMap; // [email protected]
  int Entry; // [sp+Ch] [bp-148h]@6
  wchar_t *wcsMaohaoTemp; // [sp+10h] [bp-144h]@6
  unsigned int dotCount; // [sp+14h] [bp-140h]@1
  wchar_t *Str; // [sp+18h] [bp-13Ch]@3
  char *url_FileName; // [sp+1Ch] [bp-138h]@1
  char Url_FileExtenName; // [sp+20h] [bp-134h]@1
  char v25; // [sp+50h] [bp-104h]@1

 dotCount = 0;
  pW3_URL_INFO = this;
  STRU::STRU(&Url_FileExtenName, &v25, 0x100u);
  url_FileName = (char *)pW3_URL_INFO + 228;
  bSuccess = STRU::Copy((char *)pW3_URL_INFO + 228, UrlStruct);
  if ( bSuccess  W3_URL_INFO::sm_cMaxDots )
      break;
    bSuccess = STRU::Copy(&Url_FileExtenName, Str);
    if ( bSuccess = 0) )
    v8 = 0;
  else
SubEnd:
    v8 = bSuccess;
  STRU::_STRU(&Url_FileExtenName);
  return v8;
}

上述代码中,作星号标记的是N1,N2,N3,分别检测点号,反斜杠和分号。

大概流程为:

请求 /aaa.asp;xxxx.jpg

N1:从头部查找查找 "."号,获得 .asp;xxxx.jpg

N2:查找";"号,如果有则内存截断

N3:查找"/",如果有则内存截断

最终,将保留下来 .asp 字符串,从META_SCRIPT_MAP脚本映射表里与扩展名匹配对比,并反馈给了asp.dll处理

b.IIS7是否延续了漏洞

IIS7的核心处理代码:

//reverse code by golds7n with ida
const unsigned __int16 *__stdcall MatchPathInUrl(const unsigned __int16 *url_User, unsigned __int32 url_Length, const unsigned __int16 *IIS_MAP_Wizard)
{
  const unsigned __int16 *p; // [email protected]
  const unsigned __int16 *pUrl; // [email protected]
  const wchar_t *i; // [email protected]
  signed int isXingHao; // [email protected]
  const unsigned __int16 cWizard; // [email protected]
  const unsigned __int16 *pWizard; // [email protected]
  int cTemp; // [email protected]
  int pCharTemp; // [email protected]
  const unsigned __int16 *pCharUser; // [email protected]
  const unsigned __int16 byteChar; // [email protected]
  const wchar_t cSlash; // [email protected]
  const unsigned __int16 *Str2; // [sp+8h] [bp-8h]@11
  signed int bFound; // [sp+Ch] [bp-4h]@3

 p = IIS_MAP_Wizard;
  if ( *IIS_MAP_Wizard != '*' || IIS_MAP_Wizard[1] )
  {
    bFound = 1;
    if ( *IIS_MAP_Wizard == '/' )
    {
      p = IIS_MAP_Wizard + 1;
      bFound = 0;
      ++IIS_MAP_Wizard;
    }
    pUrl = url_User;
    if ( *url_User == '/' )
    {
      pUrl = url_User + 1;
      ++url_User;
    }
LABEL_6:
    for ( i = pUrl; ; i += pCharTemp )
    {
      while ( *p == '?' )
      {
        if ( !*i )
          return 0;
        if ( *i == '/' )
          goto LABEL_30;
        ++p;
        ++i;
      }
      isXingHao = 0;
      if ( *p == '*' )
      {
        ++p;
        isXingHao = 1;
      }
      cWizard = *p;
      if ( !*p )
        break;
      pWizard = p;
      Str2 = p;
      if ( cWizard != '*' )
      {
        do
        {
          if ( cWizard == '?' )
            break;
          if ( !cWizard )
            break;
          ++pWizard;
          cWizard = *pWizard;
          Str2 = pWizard;
        }
        while ( *pWizard != '*' );
      }
      if ( isXingHao )
      {
        if ( !*pWizard )
        {
          cTemp = (int)&i[pWizard - p];
          if ( cTemp > (unsigned int)&pUrl[url_Length] )
            return 0;
          while ( *(_WORD *)cTemp != '/' && *(_WORD *)cTemp && *i != '/' && *i )
          {
            ++i;
            cTemp += 2;
          }
        }
        pCharTemp = pWizard - p;
        while ( _wcsncmp(i, p, pCharTemp) )
        {
          if ( !*i )
            return 0;
          if ( *i == '/' )
            goto LABEL_29;
          ++i;
        }
      }
      else
      {
        pCharTemp = pWizard - p;
        if ( _wcsncmp(i, p, pCharTemp) )
        {
LABEL_29:
          pUrl = url_User;
LABEL_30:
          if ( !bFound )
            return 0;
          while ( *pUrl != '/' )
          {
            if ( !*pUrl )
              return 0;
            ++pUrl;
          }
          if ( !*pUrl )
            return 0;
          p = IIS_MAP_Wizard;
          ++pUrl;
          url_User = pUrl;
          goto LABEL_6;
        }
      }
      p = Str2;
      pUrl = url_User;
    }
    if ( isXingHao )
    {
      cSlash = *i;
      if ( *i == '/' )
        return i;
      do
      {
        if ( !cSlash )
          break;
        ++i;
        cSlash = *i;
      }
      while ( *i != '/' );
    }
    if ( *i != '/' && *i )
      goto LABEL_30;
    return i;
  }
  pCharUser = url_User;
  do
  {
    byteChar = *pCharUser;
    ++pCharUser;
  }
  while ( byteChar );
  return &url_User[pCharUser - (url_User + 1)];
}

MatchPathInUrl(const unsigned __int16 *url_User, unsigned __int32 url_Length, const unsigned __int16 *IIS_MAP_Wizard)

参数url_User是用户提交的路径参数,类似PHOST/DEFAULT WEB SITE/aa.asp;xxx.jpg,由 服务/站点名称/请求路径 构成,IIS_MAP_Wizard是在管理器文件映射里的每个表项,譬如*.ASP

比较的结果就是,拿aa.asp;xxx.jpg与*.ASP进行匹配,显然结果是不匹配的(/xxx.asp/xxx.jpg,是拿xxx.jpg和*.ASP进行匹配)。

c.总结

IIS6文件映射配置图

IIS 文件名解析漏洞扼要分析

IIS7文件映射配置图

IIS 文件名解析漏洞扼要分析

从上面的关键分析和图中,可以看出,IIS6存在解析漏洞是由于其设计上的问题导致,IIS6只简单地根据扩展名来识别,而IIS7是进行通配符匹配来定夺请求文件是否是某脚本类型,可见IIS7纠正了错误机制,更加科学、健壮。

文章来源于lcx.cc:IIS 文件名解析漏洞扼要分析

相关推荐: Bypass xss过滤的测试方法

0x00 背景 本文来自于《Modern Web Application Firewalls Fingerprinting and Bypassing XSS Filters》其中的bypass xss过滤的部分,前面有根据WAF特征确定是哪个WAF的测试方法…

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: