User Registration by WPEverest WordPess plugin Arbitrary File Upload
REPORT ID: c0a58dff-7a5b-4cc0-82d6-2255e61d801c
The plugin contains an Arbitrary File Upload vulnerability. Due to a hardcoded encryption key and a missing file type validation, it is even possible to upload a php file to the website.
Let’s check the plugin
The profile_pic_upload() method in the UR_AJAX class includes the following code for image upload:
This is an common image upload solution that uploads the file to the UR_UPLOAD_URL . 'temp-uploads/' folder. It is uploaded to the temp folder because the ajax function only uploads the image to the website, but in order to set the uploaded image as a profile image, the user profile must be updated separately.
The upload_files contains contains the data of the uploaded file encrypted.
The purpose of encryption is to prevent unauthorized access to the data during profile updates (since the data is generated by the website in this case). It is only possible to decrypt and view the data using the correct encryption key, which should ideally be unique and kept confidential for each website. This means that the user should not know the encryption key (also referred to as the passphrase), and therefore cannot decrypt and view the data.
The crypt_the_string() function includes the following encrytion and decryption method, the action depends on the function parameter:
As we can see passphrase and iv are hardcoded in the function.
If we use the crypt_the_string() function to decrypt upload_files, then we get a serialized array, and when we deserialized it, the content will be something like this:
The ur_upload_profile_pic() function includes the following code for save the profile picture:
$upload_path = UR_UPLOAD_PATH . 'profile-pictures'; /*Get path of upload dir of User Registration for profile pictures*/
$upload = maybe_unserialize( crypt_the_string( $upload_file, 'd' ) );
if ( isset( $upload['file_name'] ) && isset( $upload['file_path'] ) && isset( $upload['file_extension'] ) ) {
$upload_path = $upload_path . '/';
$file_name = wp_unique_filename( $upload_path, $upload['file_name'] );
$file_path = $upload_path . sanitize_file_name( $file_name );
// Check the type of file. We'll use this as the 'post_mime_type'.
$filetype = wp_check_filetype( basename( $file_name ), null );
$moved = rename( $upload['file_path'], $file_path );
if ( $moved ) {
$attachment_id = wp_insert_attachment(
array(
'guid' => $file_path,
'post_mime_type' => $filetype['type'],
'post_title' => preg_replace( '/\.[^.]+$/', '', sanitize_file_name( $file_name ) ),
'post_content' => '',
'post_status' => 'inherit',
),
$file_path
);
if ( ! is_wp_error( $attachment_id ) ) {
include_once ABSPATH . 'wp-admin/includes/image.php';
// Generate and save the attachment metas into the database.
wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file_path ) );
}
}
}
As we can see, this decrypts the $upload_file and then moves and renames the uploaded file in the temp folder to the $upload_path folder using the rename() function. There is a wp_check_filetype() function in the code, but the file extension is not checked before renaming, which means that we can rename our png image file to any file.
Let’s see how we can exploit this vulnerability
How the exploit works step by step:
Register a user
Log in to the user
Upload the malicious exploit.png image file
Retrieve the encrypted file data from the response
Decrypt the file data
Modify the file extension to php in the file name
Encrypt the file data
Save the profile with the encrypted and modified file data
Since the encryption key is hardcoded, we can decrypt, modify and encrypt the file data.
The file exploit.png contains the following code:
<?php
echo 'md5("exploit"): ' . md5( 'exploit' );
As we can see, this is a php file that we saved with png extension.
The response will be a json containing the encrypted upload_files. We have to decrypt it with the php function using the hardcoded encryption key, which returns a serialized array, something like this:
Feel free to try and use the lana.solutions/vdb WordPress websites for testing. I set that only the php file in the exploit script can be uploaded. So all php files with other content are prohibited.
User Registration by WPEverest WordPess plugin Arbitrary File Upload
REPORT ID: c0a58dff-7a5b-4cc0-82d6-2255e61d801c
The plugin contains an Arbitrary File Upload vulnerability. Due to a hardcoded encryption key and a missing file type validation, it is even possible to upload a php file to the website.
Let’s check the plugin
The
profile_pic_upload()
method in theUR_AJAX
class includes the following code for image upload:This is an common image upload solution that uploads the file to the
UR_UPLOAD_URL . 'temp-uploads/'
folder. It is uploaded to the temp folder because the ajax function only uploads the image to the website, but in order to set the uploaded image as a profile image, the user profile must be updated separately.The file upload reponse will be json like this:
The
upload_files
contains contains the data of the uploaded file encrypted.The purpose of encryption is to prevent unauthorized access to the data during profile updates (since the data is generated by the website in this case). It is only possible to decrypt and view the data using the correct encryption key, which should ideally be unique and kept confidential for each website. This means that the user should not know the encryption key (also referred to as the passphrase), and therefore cannot decrypt and view the data.
The
crypt_the_string()
function includes the following encrytion and decryption method, the action depends on the function parameter:As we can see passphrase and iv are hardcoded in the function.
If we use the
crypt_the_string()
function to decryptupload_files
, then we get a serialized array, and when we deserialized it, the content will be something like this:file_name
:exploit.png
file_path
:/var/www/wp-content/uploads/user_registration_uploads/temp-uploads/exploit.png
file_extension
:png
As you can see, this contains the file name, path and extension.
This also means that the file has been successfully uploaded, as we can see the file path. Which is currently in the temp folder.
After that, we can save the profile picture with the profile details save function.
The
user_registration_before_save_profile_details()
method in theUR_Frontend
class contains the following code:The
ur_upload_profile_pic()
function includes the following code for save the profile picture:As we can see, this decrypts the
$upload_file
and then moves and renames the uploaded file in the temp folder to the$upload_path
folder using therename()
function. There is awp_check_filetype()
function in the code, but the file extension is not checked before renaming, which means that we can rename our png image file to any file.Let’s see how we can exploit this vulnerability
How the exploit works step by step:
Since the encryption key is hardcoded, we can decrypt, modify and encrypt the file data.
The file
exploit.png
contains the following code:As we can see, this is a php file that we saved with png extension.
Upload the file with the following HTTP request:
The response will be a json containing the encrypted
upload_files
. We have to decrypt it with the php function using the hardcoded encryption key, which returns a serialized array, something like this:file_name
:exploit.png
file_path
:/var/www/wp-content/uploads/user_registration_uploads/temp-uploads/exploit.png
file_extension
:png
It is important to change the extension only in file name in the deserialized array:
file_name
:exploit.png
needs to be changed toexploit.php
Then we have to encrypt the modified
upload_files
.Save the profile with the following HTTP request:
The
profile_pic_url
will be the modified and encryptedupload_files
.This exploit renames and moves the file, which we can access using a browser.
This is how the exploit works:
The exploit script
I created a PHP script that uploads the exploit php file:
Source: wpeverest_user_registration_upload_php_file_exploit.php
How to use:
We get something like this:
We can also check the file using a browser by opening the following link: https://lana.solutions/vdb/wpeverest-user-registration/wp-content/uploads/user_registration_uploads/profile-pictures/exploit.php
Try it
Feel free to try and use the lana.solutions/vdb WordPress websites for testing. I set that only the php file in the exploit script can be uploaded. So all php files with other content are prohibited.
Website: https://lana.solutions/vdb/wpeverest-user-registration/
Username: demo
Password: demo
References
Let's discuss
Attributes
Classification
Researcher
Tags
exploit file upload pythonSupport Us?
We would truly appreciate it if you bought us a bunny (food for a snow leopard).