Skip to content

Conversation

adamziel
Copy link
Collaborator

@adamziel adamziel commented Oct 17, 2022

What problem does this PR solve?

PHP handles file uploads by referring to the $_FILES superglobal variable. This PR prepopulates it with any files attached to the request.

Related to #34

The data flow:

  • The Service Worker detects any JavaScript files attached to the request
  • It passes them verbatim to the WASM worker for rendering together with the rest of the request
  • WASM worker converts the JavaScript Files to a PHP-compliant $_FILES data format before dispatching the request. The tmp_name key is populated by taking the raw bytes from the JS File and storing them in a temporary file in the PHP filesystem.

Importantly, the information stored in $_FILES are subject to safety checks. To quote the PHP documentation at https://www.php.net/manual/en/function.is-uploaded-file.php:

is_uploaded_file

Returns true if the file named by filename was uploaded via HTTP POST. This is useful to help ensure that a malicious user hasn't tried to trick the script into working on files upon which it should not be working--for instance, /etc/passwd.

This sort of check is especially important if there is any chance that anything done with uploaded files could reveal their contents to the user, or even to other users on the same system.

For proper working, the function is_uploaded_file() needs an argument like $_FILES['userfile']['tmp_name'], - the name of the uploaded file on the client's machine $_FILES['userfile']['name'] does not work.

We don’t run the PHP request machinery in WASM, so is_uploaded_file() fails by default. This commit circumvents the problem by introducing three new C functions:

  • pib_init_uploaded_files_hash – allocates a HashTable to keep track of the legitimate uploads
  • pib_register_uploaded_file – adds a file to the HashTable
  • pib_destroy_uploaded_files_hash – frees the HashTable

They are used to tell PHP which uploads are legitimate and should pass the safety checks.

Caveats

  • The request handler can now serve the uploaded files. They are assumed to be stored in /wp-content/uploads – it’s a limiting assumption that will need to be revisited sooner than later.
  • Static files are served with a mime type based on their file extension. This is unsafe, unreliable, and may lead to code execution vulnerabilities if a PHP file is uploaded with a different extension.

PHP handles file uploads by referring to the $_FILES superglobal variable. This commit prepopulates it with any files attached to the request.

The data flow:

* The Service Worker detects any JavaScript files attached to the request
* It passes them verbatim to the WASM worker for rendering together with the rest of the request
* WASM worker converts the JavaScript Files to a PHP-compliant $_FILES data format before dispatching the request. The `tmp_name` key is populated by taking the raw bytes from the JS `File` and storing them in a temporary file in the PHP filesystem.

Importantly, the information stored in $_FILES are subject to safety checks. To quote the PHP documentation at https://www.php.net/manual/en/function.is-uploaded-file.php:

> is_uploaded_file
>
> Returns true if the file named by filename was uploaded via HTTP POST. This is useful to help ensure that a malicious user hasn't tried to trick the script into working on files upon which it should not be working--for instance, /etc/passwd.
>
> This sort of check is especially important if there is any chance that anything done with uploaded files could reveal their contents to the user, or even to other users on the same system.
>
> For proper working, the function is_uploaded_file() needs an argument like $_FILES['userfile']['tmp_name'], - the name of the uploaded file on the client's machine $_FILES['userfile']['name'] does not work.

We don’t run the PHP request machinery in WASM, so is_uploaded_file() fails by default. This commit circumvents the problem by introducing three new C functions:

* pib_init_uploaded_files_hash – allocates a HashTable to keep track of the legitimate uploads
* pib_register_uploaded_file – adds a file to the HashTable
* pib_destroy_uploaded_files_hash – frees the HashTable

They are used to tell PHP which uploads are legitimate and should pass the safety checks.

## Caveats

* The request handler can now serve the uploaded files. They are assumed to be stored in `/wp-content/uploads` – it’s a limiting assumption that will need to be revisited sooner than later.
* Static files are served with a mime type based on their file extension. This is unsafe, unreliable, and may lead to code execution vulnerabilities if a PHP file is uploaded with a different extension.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant