Introduction
A SQL injection flaw in the NSA's Ghidra reverse engineering framework allows any authenticated BSim user to escalate to PostgreSQL superuser privileges by injecting SQL commands through a crafted username in the password change flow. For the thousands of security researchers, malware analysts, and government teams who rely on Ghidra's BSim feature for binary function similarity analysis, this vulnerability turns a routine credential management operation into a full database compromise vector.
Ghidra is a free, open source software reverse engineering framework developed by the National Security Agency, publicly released in 2019. With over 61,000 GitHub stars and widespread adoption across government agencies, private sector security teams, and independent researchers, it serves as the primary free alternative to commercial tools like IDA Pro. BSim, the affected component, is Ghidra's built in function similarity search framework that uses a PostgreSQL backend to store and query binary function signatures.
Technical Information
Root Cause
The vulnerability resides in the changePassword() method of the PostgresFunctionDatabase class within Ghidra's BSim feature. This method constructs SQL ALTER ROLE statements using string interpolation, inserting the username value directly between double quote delimiters without any escaping.
Here is the vulnerable code from Ghidra 12.0.4 and earlier:
// VULNERABLE — Ghidra 12.0.4 and earlier buffer.append("ALTER ROLE \""); buffer.append(username); // username inserted verbatim, no escaping! buffer.append("\" WITH PASSWORD '"); for (char ch : newPassword) { if (ch == '\'') { buffer.append(ch); // manual single-quote doubling for password } buffer.append(ch); } buffer.append('\'');
Notice the critical asymmetry: the password receives manual single quote escaping, but the username is directly concatenated between double quote delimiters with no escaping at all. A username containing a literal double quote character (") breaks out of the identifier quoting and allows arbitrary SQL injection into the ALTER ROLE statement.
Attack Flow
The full CVSS v4.0 vector string is CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N, reflecting a network accessible, low complexity attack with high impact across confidentiality, integrity, and availability.
The exploitation sequence proceeds as follows:
-
Authentication: The attacker authenticates to the BSim server with any valid user credentials. This is the only prerequisite, and any user with BSim access qualifies.
-
Crafted PasswordChange Message: The attacker sends a
PasswordChangenetwork message containing a specially crafted username parameter with embedded double quotes. For example, a username such asuser"; CREATE ROLE attacker SUPERUSER;--would break out of the intendedALTER ROLEstatement and inject an additional command to create a superuser account. -
SQL Execution: The
PostgresFunctionDatabase.changePassword()method interpolates the malicious username into theALTER ROLEstatement and executes it against the PostgreSQL backend without parameterized queries or prepared statements. -
Privilege Escalation: The injected SQL commands execute with the privileges of the database connection used by the BSim server. Successful injection enables the attacker to escalate to PostgreSQL superuser status, granting full control over the database: reading, modifying, or deleting all data; creating new database users; and executing administrative functions.
CVSS Scoring
| Metric | CVSS v3.x | CVSS v4.0 |
|---|---|---|
| Base Score | 8.8 (High) | 8.7 (High) |
| Attack Vector | Network | Network |
| Attack Complexity | Low | Low |
| Privileges Required | Low | Low |
| User Interaction | None | None |
| Confidentiality Impact | High | High (VC:H) |
| Integrity Impact | High | High (VI:H) |
| Availability Impact | High | High (VA:H) |
The CVSS v4.0 score was assessed by the CNA (VulnCheck) as 8.7, while the CVSS v3.x score is 8.8. Both agree on the core assessment: network accessible, low complexity, authenticated privilege escalation with high system impact.
Related Vulnerability
Security bulletin SB20260515104 identifies a second, distinct SQL injection vulnerability in the BSim search filter types. This separate flaw fails to neutralize special elements in XML protocol messages used over the BSim network query protocol, allowing injection of arbitrary SQL commands through a different attack surface. Organizations addressing CVE-2026-49498 should evaluate this related flaw as well.
Patch Information
The vulnerability was fixed in Ghidra 12.1, released on May 13, 2026. The GitHub Security Advisory GHSA-vv7r-2rhf-5h7g explicitly lists the patched version as 12.1, and VulnCheck independently confirms the affected range as Ghidra 11.0 through versions prior to 12.1.
The patch targets the changePassword() method in Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/PostgresFunctionDatabase.java. Here is the patched version from Ghidra 12.1:
// PATCHED — Ghidra 12.1 buffer.append("ALTER ROLE "); Utils.escapeIdentifier(buffer, username); // proper identifier escaping buffer.append(" WITH PASSWORD '"); Utils.escapeLiteral(buffer, new String(newPassword), true); // proper literal escaping buffer.append('\'');
The fix introduces two key changes:
-
Username handling: Instead of wrapping the raw username in double quotes manually, the fix delegates to
org.postgresql.core.Utils.escapeIdentifier(). This is the PostgreSQL JDBC driver's built in utility that properly escapes any embedded double quote characters by doubling them (e.g.,my"userbecomes"my""user"), which is the correct way to safely embed identifiers in PostgreSQL SQL statements. A new import fororg.postgresql.core.Utilswas added to support this. -
Password handling: The previously hand rolled single quote escaping loop was replaced with
Utils.escapeLiteral(), the corresponding PostgreSQL JDBC utility for safely escaping string literals. While the old manual escaping was functionally adequate, using the library function is more robust and consistent.
This is a textbook example of replacing ad hoc string escaping with well tested library functions, a practice that eliminates an entire class of injection bugs. Users running Ghidra 11.0 through 12.0.x with a BSim PostgreSQL backend should upgrade to Ghidra 12.1 (or the latest 12.1.2 release) to apply this fix.
You can compare the vulnerable and patched source files directly:
Affected Systems and Versions
The vulnerability affects Ghidra versions 11.0 through 12.0.x (inclusive). Specifically, any Ghidra installation that uses the BSim feature with a PostgreSQL database backend is vulnerable. Installations using BSim with other database backends, or installations not using BSim at all, are not affected by this specific flaw.
The patched version is Ghidra 12.1, released May 13, 2026. The latest available release at time of writing is Ghidra 12.1.2.
Vendor Security History
Ghidra's security track record reveals a recurring pattern of injection and trust boundary vulnerabilities:
- CVE-2019-16941: An early vulnerability that allowed attackers to compromise exposed systems when Ghidra's experimental mode was running, highlighting risks from the tool's network facing features.
- GHSA-j3xg-fc2p-4jc4 (Log4j): A remote code injection vulnerability stemming from the Log4j library during the widespread Log4Shell crisis.
- GHSA-cqfj-5crw-rh6p (Command Injection in launch.sh): A command injection flaw where user provided command line arguments were passed to the Java application launch without sanitization.
- CVE-2026-4946 (Command Execution via Auto Generated Comments): Discovered by AHA! (Austin Hackers Anonymous) and the Mobasi Security Team, this high severity flaw (CVSS 8.8) allowed a malicious binary to trigger arbitrary command execution when an analyst clicked on auto generated comments. The
CFStringAnalyzerextracted strings from Mach O binaries, andAnnotation.javainterpreted@executedirectives, executing commands viaProcessBuilderwithout confirmation. Patched in Ghidra 12.0.3. - SB20260515104 (Nine Vulnerabilities, May 2026): The current cluster includes two SQL injection flaws (including CVE-2026-49498), command injection in URL annotation handling, improper cryptographic signature verification in
PKIAuthenticationModule.authenticate(), deserialization of untrusted data in shared project connections, denial of service viaExportTrie.parseTrie(), path traversal inSameDirDebugInfoProvider, and two use after free vulnerabilities in decompilation code.
The NSA has demonstrated a responsible disclosure and patching process, publishing security advisories through GitHub and coordinating with external researchers. The advisory for GHSA-vv7r-2rhf-5h7g was published by internal NSA development staff, and external organizations such as Oceanit have also contributed to identifying and resolving vulnerabilities. The researcher credited with discovering CVE-2026-49498 is Sean Nejad (@allsmog).
The NSA acknowledges the security risk explicitly on its Ghidra page, noting "there are known security vulnerabilities within certain versions of Ghidra" and advising users to review security advisories before proceeding.
References
- NVD: CVE-2026-49498
- GitHub Security Advisory: GHSA-vv7r-2rhf-5h7g
- VulnCheck Advisory: Ghidra SQL Injection in PostgreSQL Password Change via Unescaped Username
- Ghidra Security Advisories (GitHub)
- Ghidra Releases (GitHub)
- Patched Source: PostgresFunctionDatabase.java (Ghidra 12.1)
- Vulnerable Source: PostgresFunctionDatabase.java (Ghidra 12.0.4)
- SB20260515104: Multiple Vulnerabilities in Ghidra
- NSA Ghidra Official Page
- CISA Known Exploited Vulnerabilities Catalog
- CVE-2026-4946: Ghidra Command Execution via Auto Generated Comments



