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; // esi@1 int bSuccess; // eax@1 const wchar_t *i; // eax@2 wchar_t *wcsSlashTemp; // ebx@6 int wcsTemp; // eax@6 int wcs_Exten; // eax@6 int v8; // esi@9 int v10; // eax@11 int v11; // ST04_4@13 int v12; // eax@13 int ExtenDll; // eax@19 int Extenisa; // eax@20 int ExtenExe; // eax@21 int ExtenCgi; // eax@22 int ExtenCom; // eax@23 int ExtenMap; // eax@24 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 < 0 ) goto SubEnd; for ( i = (const wchar_t *)STRU::QueryStr((char *)pW3_URL_INFO + 228); ; i = Str + 1 ) { Str = _wcschr(i, '.'); ***********N1************ if ( !Str ) break; ++dotCount; if ( dotCount > W3_URL_INFO::sm_cMaxDots ) break; bSuccess = STRU::Copy(&Url_FileExtenName, Str); if ( bSuccess < 0 ) goto SubEnd; wcsSlashTemp = _wcschr(Str, '/'); ***********N2************ JUMPOUT(wcsSlashTemp, 0, loc_5A63FD37); wcsTemp = STRU::QueryStr(&Url_FileExtenName); wcsMaohaoTemp = _wcschr((const wchar_t *)wcsTemp, ':'); ***********N3************ JUMPOUT(wcsMaohaoTemp, 0, loc_5A63FD51); wcs_Exten = STRU::QueryStr(&Url_FileExtenName); __wcslwr((wchar_t *)wcs_Exten); if ( META_SCRIPT_MAP::FindEntry(&Url_FileExtenName, &Entry) ) { *((_DWORD *)pW3_URL_INFO + 201) = Entry; JUMPOUT(wcsSlashTemp, 0, loc_5A63FDAD); STRU::Reset((char *)pW3_URL_INFO + 404); break; } if ( STRU::QueryCCH(&Url_FileExtenName) == 4 ) { ExtenDll = STRU::QueryStr(&Url_FileExtenName); if ( !_wcscmp(L".dll", (const wchar_t *)ExtenDll) || (Extenisa = STRU::QueryStr(&Url_FileExtenName), !_wcscmp(L".isa", (const wchar_t *)Extenisa)) ) JUMPOUT(loc_5A63FD89); ExtenExe = STRU::QueryStr(&Url_FileExtenName); if ( !_wcscmp(L".exe", (const wchar_t *)ExtenExe) || (ExtenCgi = STRU::QueryStr(&Url_FileExtenName), !_wcscmp(L".cgi", (const wchar_t *)ExtenCgi)) || (ExtenCom = STRU::QueryStr(&Url_FileExtenName), !_wcscmp(L".com", (const wchar_t *)ExtenCom)) ) JUMPOUT(loc_5A63FD89); ExtenMap = STRU::QueryStr(&Url_FileExtenName); JUMPOUT(_wcscmp(L".map", (const wchar_t *)ExtenMap), 0, loc_5A63FD7B); } } if ( *((_DWORD *)pW3_URL_INFO + 201) || (v10 = *((_DWORD *)pW3_URL_INFO + 202), v10 == 3) || v10 == 2 || (v11 = *(_DWORD *)(*((_DWORD *)pW3_URL_INFO + 204) + 0xC4C), v12 = STRU::QueryStr(url_FileName), bSuccess = SelectMimeMappingForFileExt(v12, v11, (char *)pW3_URL_INFO + 756, (char *)pW3_URL_INFO + 1012), 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; // ebx@1 const unsigned __int16 *pUrl; // ecx@4 const wchar_t *i; // edi@6 signed int isXingHao; // edx@8 const unsigned __int16 cWizard; // ax@10 const unsigned __int16 *pWizard; // esi@11 int cTemp; // eax@17 int pCharTemp; // esi@23 const unsigned __int16 *pCharUser; // eax@43 const unsigned __int16 byteChar; // cx@44 const wchar_t cSlash; // ax@50 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文件映射配置图
IIS7文件映射配置图
从上面的关键分析和图中,可以看出,IIS6存在解析漏洞是由于其设计上的问题导致,IIS6只简单地根据扩展名来识别,而IIS7是进行通配符匹配来定夺请求文件是否是某脚本类型,可见IIS7纠正了错误机制,更加科学、健壮。