Attackers turned an ordinary SQL injection bug into SYSTEM-level control of a Windows server by compiling their own malware inside the Oracle database itself. Huntress published the case on August 5, 2026, after investigating an intrusion its platform caught on July 27. The toolkit, which the attackers named khunt, consists of six Java objects and a set of khunt_* PL/SQL wrappers that live as schema objects in the database, so the operator gets command execution, credential theft and file access without ever dropping an executable on disk.

None of the individual pieces are new. Oracle has shipped an embedded JVM since the late 1990s, and running operating system commands through it has been a pentest party trick for at least two decades. What makes this worth reading is that Huntress says the technique is rarely documented actually being used in the wild, and the intrusion shows exactly how the gap between a web form and domain-level credentials closes when one database account is over-provisioned.

RelatedDuneSlide Turns a Cursor Prompt Into Full Code Execution

  • Entry was an autocomplete search field in a public Java web app on Apache Tomcat that passed unvalidated input straight to Oracle over JDBC.
  • The attackers used CREATE JAVA SOURCE to compile khunt into the database, then called it through PL/SQL wrappers, which means no file was written to disk to get code execution.
  • KhuntCmd ran cmd.exe /c whoami and came back as SYSTEM, because the Oracle service on Windows runs with those rights by default.
  • Payoff was credential theft: the operators copied the SAM, SYSTEM and SECURITY registry hives to disk as khunt*.hiv files under the Oracle directory.
The khunt attack chain, from a web search box to SYSTEM on WindowsUnvalidated input from an autocomplete search field in a public Tomcat application travels over a JDBC connection into an Oracle database using an over-privileged application account. Inside the database the attackers issue CREATE JAVA SOURCE to compile six Java objects, expose them through khunt PL/SQL wrappers, and call KhuntCmd, which launches cmd.exe with SYSTEM privileges on the Windows host. They then copy the SAM, SYSTEM and SECURITY registry hives and a task list to the Oracle directory. STAGE 1 · GETTING IN Public Tomcat appautocomplete search field JDBC connectioninput never validated Oracle Databaseapp account, over-privileged STAGE 2 · BUILDING THE TOOLKIT INSIDE THE DATABASE CREATE JAVA SOURCEcompiled by the embedded JVM khunt_* wrappersPL/SQL calls the Java methods KhuntCmd → cmd.exeruns as NT AUTHORITY\SYSTEM Nothing is written to disk until stage 3, so file-based detection sees nothing Stage 3: reg.exe copies SAM, SYSTEM, SECURITY hives to [drive]:\Oracle\khunt*.hiv genztech.blog
Fig 1 The whole chain hinges on one thing: a database account that could author Java. Take that away and the injection is still a data-theft problem, but it stops being a host compromise.

What actually happened on July 27?

Huntress did not find this by watching the database. Its detection fired on the Windows host, on a credential-theft rule that noticed reg.exe running with oracle.exe as its parent process. That is a strange parent for a registry export, and it was the thread that unravelled the rest. Working backwards through Apache access logs, the responders found the injectable endpoint: an autocomplete search feature in a public-facing Java application that fed whatever a visitor typed into an Oracle query over JDBC.

The account behind that JDBC connection could create Java sources. That is the entire pivot. Once the operators could issue CREATE JAVA SOURCE statements through the injection, they compiled six components into the schema and wrapped each one in PL/SQL so it could be invoked with a plain SQL call. KhuntCmd loaded cmd.exe and ran arbitrary commands. KhuntHash pulled usernames and password material out of Oracle's internal user table. KhuntFS and KhuntFS2 listed, read, searched and sized files. KhuntT was a ping, a way to confirm the install had taken. KhuntUnzip handled archives.

  1. Jul 27, 2026Huntress alerted on credential theft reg.exe spawned by oracle.exe on a Windows database server
  2. During the intrusionSAM, SYSTEM and SECURITY hives copied written as khuntSAM.hiv, khuntSYSTEM.hiv, khuntSECURITY.hiv, plus khunttasks.txt from tasklist /svc
  3. Aug 5, 2026Huntress publishes the analysis requests traced to 178.162.151[.]229

The registry hives are the tell that this was not smash and grab. SAM plus SYSTEM gives you local account hashes offline, SECURITY gives you cached domain material and service account secrets. Whoever ran this wanted credentials to move sideways with, not just the contents of one database.

Why does a database get you SYSTEM on Windows?

Oracle Database ships with a Java Virtual Machine inside it. That is a feature, not a bolt-on: stored procedures can be written in Java, and CREATE JAVA SOURCE stores the source as a schema object and compiles it in place. Oracle classifies those objects alongside procedures, so an account holding the CREATE PROCEDURE system privilege can author one. From there, a Java method calling Runtime.exec runs as whatever user the database process runs as.

On Windows, that user is very often SYSTEM. The database service is installed to run with local system rights so it can touch its own files, memory and services without argument, which is convenient right up until someone reaches the JVM through a web form. On Linux the same chain lands you as the oracle user instead, which is bad but survivable. The Windows default is what turns a SQL injection in a search box into full host ownership in one hop, with no exploit, no privilege escalation bug and no patch that would have stopped it.

How is this different from a normal webshell?

Traitkhunt, inside OracleClassic Tomcat webshellSQL Server xp_cmdshell
Where the code livesJava objects in a database schemaA .jsp file in the web rootA built-in extended procedure
Touches disk to installNoYes, a file per shellNo, it ships with the product
Privileges inheritedThe database service account, SYSTEM on WindowsThe Tomcat service userThe SQL Server service account
How defenders find itQuery the data dictionary for JAVA objectsFile integrity monitoring, antivirusCheck whether sp_configure enabled it
Survives a web app redeployYes, it is in the databaseNo, the deploy wipes itYes
Off by defaultNo, if the account can create proceduresNot applicableYes, disabled since 2005

The comparison that matters is the last two rows. Microsoft learned this lesson in public: xp_cmdshell was the standard SQL Server escalation path until it was switched off by default, and now finding it enabled is itself an alert. Oracle's Java path has no equivalent switch, because it is not a single dangerous feature you can turn off. It is a legitimate capability that becomes dangerous the moment the wrong account holds a very ordinary privilege. And because the toolkit lives in the database rather than the application, the usual remediation reflex of redeploying the web app leaves the backdoor exactly where it was.

What should you check in your own Oracle estate today?

Three queries and one detection rule cover most of the exposure. Start by asking which accounts can author Java at all, since that privilege is what the whole chain rests on:

-- who can create procedure-class objects, including Java sources
SELECT grantee, privilege FROM dba_sys_privs
 WHERE privilege IN ('CREATE PROCEDURE','CREATE ANY PROCEDURE');

-- who holds the Java roles
SELECT grantee, granted_role FROM dba_role_privs
 WHERE granted_role IN ('JAVASYSPRIV','JAVAUSERPRIV');

Any account used by a public-facing web application should appear in neither result. If one does, that is the finding, whether or not anyone has abused it yet. Then look for objects that should not exist:

-- Java objects outside the Oracle-supplied schemas
SELECT owner, object_name, object_type, created
  FROM dba_objects
 WHERE object_type LIKE 'JAVA%'
   AND owner NOT IN ('SYS','SYSTEM','XDB','MDSYS','ORDSYS','CTXSYS','WMSYS','OLAPSYS');

-- the specific toolkit
SELECT owner, object_name, object_type FROM dba_objects
 WHERE UPPER(object_name) LIKE 'KHUNT%';

On the host side, the highest-value rule is the one that caught this: alert on reg.exe, cmd.exe, powershell.exe or tasklist.exe with oracle.exe as the parent process. A database engine has no business spawning a shell, so the false positive rate is close to zero and the signal is unambiguous. Add file paths matching khunt*.hiv and khunttasks.txt, and block the reported source address 178.162.151[.]229, though treat that IP as historical rather than a lasting control.

RelatedAtlassian Rovo AI Still Leaks Jira Data via Prompt Injection

The real fix is upstream of all of it, and Huntress says so plainly: parameterise the queries, validate the input, and cut the application's database account down to the reads and writes it genuinely needs. An account that serves an autocomplete box has no reason to be able to compile Java.

Who is actually exposed here?

Not everyone running Oracle. The exposure is specific: a database reachable, even indirectly, from a public application that concatenates user input into SQL, using an account provisioned by whoever built the app rather than by whoever runs the database. That combination is most common in long-lived internal line-of-business systems, the ones written years ago by a team that has since moved on, where the connection string got a generous grant early to make something work and nobody revisited it.

Vendor-supplied applications deserve a hard look too, since the deployment guide often specifies the privileges the app account needs and administrators grant them without argument. If that guide asks for CREATE PROCEDURE on an internet-facing system, the vendor is asking you to accept this exact chain.

What to watch · 2026
  • Whether khunt shows up again. A named, reusable toolkit with wrappers and a connectivity checker is built for repeat use, not for one job. A second sighting would tell us this is a crew's standard kit rather than an improvisation.
  • Whether Oracle tightens the default. There is no sp_configure equivalent to flip here. A supported way to deny an account the ability to author Java, without breaking legitimate Java stored procedures, would remove the pivot outright.
  • Windows service accounts. The SYSTEM default is doing the heavy lifting in this chain. Running the database under a dedicated low-privilege service account is unglamorous and would have contained this to the database.

Our take

The interesting part of this case is not the malware. Six Java classes that shell out, read files and dump hashes are unremarkable code, and any competent operator could write them in an afternoon. The interesting part is the choice of where to put them. By living inside the database, khunt sits in a place most security tooling does not inspect at all: endpoint agents watch processes and files, web application firewalls watch requests, and almost nobody is diffing the data dictionary for objects that appeared overnight.

That blind spot is structural, and it is the same shape as several other quiet corners of enterprise infrastructure, the ones where a system has a legitimate scripting or extension capability that nobody thinks of as a code execution surface. Databases have it. So do backup agents, monitoring platforms and CI runners. The lesson is not to fear Oracle's JVM. It is that any component allowed to compile and run code deserves the same privilege scrutiny you would give a shell, and that a decade-old injection bug is still perfectly capable of ending in domain credentials when the account behind it was never scoped.

Primary sources

Original analysis by GenZTech. Reported by BleepingComputer and The Hacker News.