Del Security

Security Research

Plesk Advisor SQLi to Root Code Execution

Plesk Obsidian's Advisor extension ships with a SQL injection reachable by any authenticated user, including the lowest-privilege Customer account. We walk through the root cause -- a textbook concatenation bug behind an access control misconfiguration -- and what makes the psa database a particularly valuable target.

3 min read
#plesk#sql injection#access control#vulnerability research

TL;DR

We found a SQL Injection in Plesk Obsidian Advisor. The lowest-privilege Customer account can read the entire psa database.

This post covers the SQLi vulnerability only. We have confirmed that this bug serves as the first stage of a broader chain leading to significantly higher impact, but the downstream vulnerabilities remain unpatched. Those details will be published separately after remediation.


The Advisor Extension

Plesk Obsidian ships with the Advisor extension installed by default. It provides server optimization recommendations — SSL certificate status, domain configuration checks, that sort of thing. Buried in it is an endpoint for searching domain recommendation data:

GET /modules/advisor/index.php/recommendation/get-data
    ?recommendationCode=SslDomains
    &pageSize=100
    &search=USER_INPUT

An unremarkable search feature. The trouble starts when two things go wrong at the same time.


When Two Things Go Wrong at Once

1) Access Control: What an Empty Array Means

Look at the access control configuration in RecommendationController:

// RecommendationController.php
protected $_accessLevel = [];  // empty array

In Plesk’s access control framework, an empty array means “no role restrictions.” The intent was probably “not configured” or “use defaults,” but the actual behavior is allow all authenticated users — including Customers.

Advisor aggregates server-wide domain status. It’s an admin-facing feature. There is no reason for a Customer account to reach this data.

2) SQL Injection: A Classic That Refuses to Die

Here’s the path from search parameter to SQL query:

// RecommendationController.php
public function getDataAction(): void {
    $search = $this->_request->getParam('search');  // no filtering
    $items = $step->getDataQuery()
        ->setSearch($search)  // passed as-is
        ->execute();
}

And the query builder in DomainQuery.php:

// DomainQuery.php, line 55
protected function setSearchWhere(array &$where) {
    if ($this->search) {
        $where[] = '{%prefix%}displayName LIKE \'%' . $this->search . '%\'';
    }
}

User input concatenated directly into a SQL string. No escaping. No parameter binding. A somewhat embarrassing bug class to find in 2026, but here we are.


Root Cause

This is a combination of two bugs:

  • Missing input validation — The search parameter is concatenated into a SQL string without escaping or parameter binding.
  • Access control misconfiguration_accessLevel = [] is interpreted as “no restrictions,” exposing a server administration feature to Customer accounts.

Remove either one and the vulnerability doesn’t exist. If access is restricted, the SQLi is unreachable. If the query is parameterized, access doesn’t matter.


Disclosure Scope

This post covers the Advisor SQL Injection only.

We have confirmed that data extracted through this SQLi can be combined with additional vulnerabilities to achieve significantly higher impact, including root-level command execution. Those vulnerabilities remain unpatched, so the rest of the chain will be published separately after remediation.


Proof of Concept

Full chain execution — from Customer login to uid=0(root) in a single command:

PoC: Customer to Root RCE on Plesk Obsidian 18.0.76


Patch

This SQLi was fixed in Advisor 1.10.14 and Advisor 1.9.18:

  • Advisor 1.10.14 for Plesk Obsidian 18.0.53+
  • Advisor 1.9.18 for Plesk Obsidian 18.0.53 or below

If you’re running Plesk older than 18.0.53 and Advisor older than 1.9.18, update immediately.


Timeline

DateEvent
2025-10-02Vulnerability discovered during authorized security audit
2025-10-09Full chain (SQLi to Root RCE) confirmed
2026-03-31Plesk Obsidian 18.0.77 released — SQLi patched in Advisor 1.9.18 (older than 18.0.53) and Advisor 1.10.14 (18.0.53+)

DVE-2026-016. Patched by Advisor 1.9.18 (Plesk < 18.0.53) and 1.10.14 (Plesk 18.0.53+).

For commercial use or inquiries, please contact us.