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纠正了错误机制,更加科学、健壮。