Novell eDirectory是一个的跨平台的目录服务器。 Novell eDirectory在处理用户请求构造回应时存在输入验证漏洞,远程攻击者可能利用此漏洞在服务器上执行任意指令。 Novell的HTTP协议栈(httpstk)没有检查客户端所提供的HTTP Host请求头(如Host: www.host.com)的值。当服务器在准备HTTP重新定向响应调用snprintf()时可能会触发这个漏洞,导致以加载httpstk库进程的权限执行任意指令。C++伪代码如下: #define HTTPHDR_HOST_FIELD 211 char szHttp[] = "HTTP"; char szHttps[] = "HTTPS"; char szHttpS[] = "http%s://"; char szCrlf[] = "\r\n"; char szS[] = "s"; char szD[] = ":%d"; char szS_3[] = "%s"; BYTE nullbyte = '\0'; typedef struct SAL_AddrBuf_t { short sin_family; u_short sin_port; struct in_addr sin_addr; struct in6_addr sin6_addr; char sa_data[42]; } SAL_AddrBuf; class HRequest { public: int SendRedirectRsp(void); int SendHeader(int); int SendNotFoundRsp(void); int SendEndOfContent(void); int RspSetHdrValue(char *, char *); bool ReqIsSecureChannel(void); char *ReqHdrValue(unsigned int); SAL_AddrBuf *ReqHostAddress(void); private: int BuildRedirectURL(unsigned int, bool, char...
Novell eDirectory是一个的跨平台的目录服务器。 Novell eDirectory在处理用户请求构造回应时存在输入验证漏洞,远程攻击者可能利用此漏洞在服务器上执行任意指令。 Novell的HTTP协议栈(httpstk)没有检查客户端所提供的HTTP Host请求头(如Host: www.host.com)的值。当服务器在准备HTTP重新定向响应调用snprintf()时可能会触发这个漏洞,导致以加载httpstk库进程的权限执行任意指令。C++伪代码如下: #define HTTPHDR_HOST_FIELD 211 char szHttp[] = "HTTP"; char szHttps[] = "HTTPS"; char szHttpS[] = "http%s://"; char szCrlf[] = "\r\n"; char szS[] = "s"; char szD[] = ":%d"; char szS_3[] = "%s"; BYTE nullbyte = '\0'; typedef struct SAL_AddrBuf_t { short sin_family; u_short sin_port; struct in_addr sin_addr; struct in6_addr sin6_addr; char sa_data[42]; } SAL_AddrBuf; class HRequest { public: int SendRedirectRsp(void); int SendHeader(int); int SendNotFoundRsp(void); int SendEndOfContent(void); int RspSetHdrValue(char *, char *); bool ReqIsSecureChannel(void); char *ReqHdrValue(unsigned int); SAL_AddrBuf *ReqHostAddress(void); private: int BuildRedirectURL(unsigned int, bool, char *); char *path; HDR_LOOKUP_TBL *ValueTable; unsigned int uint; int something; Page 2 SOCKET sock; SAL_AddrBuf name; }; int HRequest::BuildRedirectURL(unsigned int stackid, bool fl_https, char *redirect_url) { register char *colon, *crlf; register size_t length; register unsigned short port; // Original just recycled stackid // Stack variables SAL_AddrBuf SAL; char *szHostHdrValue; SAL_AddrBuf *pSAL; int retval; // Zero-out the local SAL_AddrBuf structure memset(&SAL,0,66); // Fill in the class' SAL_AddrBuf structure with IP and port pSAL = ReqHostAddress(); SAL.sin_family = pSAL->sin_family; // This fills in the redirect port in SAL.sin_port retval = PStkEnumTransports(stackid, 2, &Callback, &SAL); if ((retval != 0) && (retval != SERR_CALLBACK_CANCELLED)) { return(0); } // Obtain a pointer to the user-supplied HTTP Host-Header value szHostHdrValue = ReqHdrValue(HTTPHDR_HOST_FIELD); if (szHostHdrValue == NULL) { return(SERR_INVALID_REQUEST); } // Exclude colon and/or CRLF from length of host header value colon = strchr(szHostHdrValue, ':'); if (colon == NULL) { crlf = strstr(szHostHdrValue, szCrlf); if (crlf == NULL) { length = strlen(szHostHdrValue); } else { length = crlf - szHostHdrValue; } } else { length = colon - szHostHdrValue; } // Determine if the redirect URL should be https:// or http:// if (fl_https) { redirect_url += sprintf(redirect_url, szHttpS, szS); } else { redirect_url += sprintf(redirect_url, szHttpS, nullbyte); } // Append the Host-Header value to the redirect URL _snprintf(redirect_url, length+1, szS_3, szHostHdrValue); redirect_url += length; Page 3 // Is IPv4 if (SAL.sin_family == AF_INET) { if (retval == ERROR_SUCCESS) { if (SAL.sin_port == 0) { return(SERR_OBJECT_NOT_FOUND); } else { memcpy((void *)&SAL.sin_addr.s_addr, (void *)&pSAL->sin_addr.s_addr, 4); } } } // Is IPv6 else if (SAL.sin_family == AF_INET6) { if (retval == ERROR_SUCCESS) { if (SAL.sin_port == 0) { return(SERR_OBJECT_NOT_FOUND); } else { memcpy((void *)&SAL.sin6_addr.u, (void *)&pSAL->sin6_addr.u, 16); } } } // Convert the port from network byte order to host byte order port = ntohs(SAL.sin_port); // Append the port to the redirect URL if it is non-standard if ((fl_https && port == 443) || (!fl_https && port == 80)) { return(ERROR_SUCCESS); } sprintf(redirect_url, szD, port); return(ERROR_SUCCESS); } int HRequest::SendRedirectRsp(void) { register int retval; register bool fl_https; // Stack variables char redirect_url[64]; char *memblock; unsigned int stackid; // Determine if the connection is operating over SSL fl_https = ReqIsSecureChannel(); if (!fl_https) { retval = PStkGetProtocolStackByName(szHttps, &stackid); } else { retval = PStkGetProtocolStackByName(szHttp, &stackid); } if (retval == ERROR_SUCCESS) { // Call this function to begin building the redirect URL retval = BuildRedirectURL(stackid, fl_https, redirect_url); // Remaining code snipped for brevity } BuildRedirectURL()调用snprintf()将用户提供的HTTP Host请求头值存储倒64字节的缓冲区。这段代码的预期行为是将客户端重新定向到请求中所指定的有效URL。在正确的环境中,snprintf()的长度参数被设置为目标缓冲区所能容纳的最大字节数,但无论目标缓冲区是否能够容纳,这段代码都使用长度参数指定从Host请求头值所拷贝的字节数。因此恶意的攻击者可以指定超过64字节的Host请求头值触发标准的栈溢出。 Novell eDirectory <= 8.7.3.8 目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载: http://support.novell.com/security-alerts