What Happened
A public-facing web application with a SQL injection vulnerability became the entry point for an attack that ended with SYSTEM-level code execution on a Windows server. The attackers didn't drop a binary or write malware to disk. Instead, they used Oracle's native ability to compile Java code into stored schema objects, creating a post-exploitation toolkit called khunt that lived entirely inside the database.
The compromised database account had sufficient privileges to create Java objects. Once the attackers compiled their toolkit into the Oracle schema, they could execute arbitrary code at the operating system level without triggering traditional endpoint detection tools.
Timeline
The attack sequence follows a predictable pattern:
- Initial access: Attackers identified and exploited a SQL injection flaw in a web application.
- Privilege assessment: They determined the compromised database account could create Java stored procedures.
- Toolkit deployment: Attackers compiled khunt as Java objects within the Oracle schema.
- Privilege escalation: The toolkit enabled SYSTEM-level code execution on the underlying Windows server.
- Detection: Huntress researchers identified the attack during an investigation.
The gap between initial access and detection remains unknown, which is typical for attacks that don't write files to disk.
Which Controls Failed or Were Missing
Input validation at the application layer. The web application accepted untrusted input without proper sanitization, allowing SQL injection. This violates the first principle of secure coding: never trust user input.
Least privilege for database accounts. The application's database service account had permission to create Java objects and compile code within Oracle. A properly scoped account would have SELECT, INSERT, UPDATE, and DELETE permissions on specific tables, nothing more.
Database activity monitoring. The organization had no alerting for unusual database operations like Java object creation or compilation. Creating a stored Java procedure from a web application account should trigger immediate review.
Network segmentation. The database server could execute code that reached external systems. Databases should sit behind network controls that prevent outbound connections except to explicitly allowed backup or replication targets.
Endpoint detection coverage. Traditional EDR tools monitor file system activity and process execution. They don't inspect database schema objects. The organization lacked database-specific security monitoring that could detect code compilation or unusual stored procedure activity.
What the Standards Require
PCI DSS v4.0.1 Requirement 6.2.4 mandates that public-facing web applications are protected against known attacks, with SQL injection explicitly listed as a covered threat. Organizations must use automated technical solutions like web application firewalls or source code analysis tools.
Requirement 6.4.3 requires that scripts are prevented from running with elevated privileges. The database service account's ability to execute SYSTEM-level code through Java objects violates this control.
Requirement 7.2.2 addresses least privilege: access rights must be assigned based on job classification and function, limited to the least privileges necessary. A web application database account doesn't need Java compilation privileges.
OWASP ASVS v4.0.3 Requirement 5.3.4 states that database queries must use parameterized queries, stored procedures, or ORM frameworks to prevent SQL injection. The vulnerable application failed this basic control.
NIST 800-53 Rev 5 Control AC-6 (Least Privilege) requires that accounts operate with the minimum privileges necessary to accomplish assigned tasks. The over-privileged database account violated this control.
Control SI-4 (System Monitoring) requires monitoring for unauthorized database activities, including schema modifications. Creating and compiling Java objects should have triggered alerts.
Lessons and Action Items for Your Team
Audit your database service account privileges today. List every permission your application accounts have. If you see CREATE, COMPILE, or EXECUTE on Java objects, remove them. Your web application needs data access, not code compilation rights.
Implement parameterized queries everywhere. Review your codebase for string concatenation in SQL statements. Tools like Semgrep can find these patterns automatically. If you're using an ORM, verify it's configured to prevent raw SQL injection.
Deploy database activity monitoring. Tools like Imperva, McAfee Database Security, or Oracle Audit Vault can alert on schema changes, privilege escalations, and unusual query patterns. Set alerts for any CREATE or COMPILE operations from application accounts.
Segment your database network. Your database servers shouldn't initiate outbound connections to the internet. Configure firewall rules that allow only: (1) application tier to database on specific ports, (2) database to backup storage, (3) database to database for replication. Block everything else.
Test your SQL injection defenses. Run SQLMap or Burp Suite against your applications in a staging environment. If you find injection points, you've got work to do. Don't assume your WAF catches everything; test with the WAF enabled to verify.
Review Oracle-specific hardening. If you run Oracle, disable Java execution in the database unless you have a documented business need: EXEC DBMS_JAVA.SET_PROPERTY('JAVA_POOL_SIZE', '0');. Remove unnecessary packages and lock down the SYS and SYSTEM accounts.
Map your detection gaps. List the attack stages: SQL injection, privilege enumeration, Java compilation, code execution. Which of these would your current tools catch? The answer identifies your blind spots.
This attack succeeded because multiple controls failed in sequence. Your application had an injection flaw, your database account was over-privileged, and your monitoring didn't catch schema manipulation. Fix any one of these and the attack fails. Fix all three and you've built defense in depth that actually works.



