khunt — Oracle In-Database Java Post-Exploitation Toolkit

SQL injection in a public-facing Java/Tomcat autocomplete endpoint to CREATE JAVA SOURCE RCE as NT AUTHORITY\SYSTEM, with no executable ever written to disk.
Threat
khunt toolkit (Oracle in-database)
Severity
EXPLOITED ITW
Type
Web-app exploitation · in-DB post-exploitation · credential theft
Initial Access
SQL injection (T1190) via autocomplete/search endpoint
Version
v0.1 · 2026-08-06
Author
HuntPack
Confidence
High (single primary vendor IR report, two corroborating outlets)
01

Executive Summary

Huntress published incident research on 2026-08-05 describing an intrusion that began with a textbook SQL injection flaw and ended with operating-system remote code execution as NT AUTHORITY\SYSTEM. The entry point was an autocomplete/search form on a public-facing Java application fronted by Apache Tomcat that failed to validate input; the application passed the attacker's SQL straight through its JDBC connection to a backend Oracle Database. No CVE, no zero-day, no novel exploit: the vulnerability was unparameterised input.

What makes this pack worth building is what the attacker did after the injection. Rather than dropping a binary, they used Oracle's embedded JVM and the CREATE JAVA SOURCE statement to compile and store a post-exploitation toolkit named khunt directly inside the database as schema objects, then exposed it to SQL callers through khunt_* PL/SQL wrappers. The toolkit shipped six components: KhuntCmd (launches cmd.exe and runs arbitrary OS commands from a SQL statement), KhuntHash (reads Oracle's internal user table and writes usernames and password data to a file), KhuntFS and KhuntFS2 (file listing, reading, searching, size checks), KhuntT (a ping-style liveness check for the toolkit), and KhuntUnzip (archive extraction).

With the toolkit installed, the actor ran cmd.exe /c whoami, confirmed SYSTEM-level privileges inherited from the Oracle service, enumerated services with tasklist /svc, and copied the SAM, SECURITY and SYSTEM registry hives using PowerShell-invoked reg.exe and esentutl.exe, staging everything into the Oracle installation directory. The detection that started the investigation was the credential-theft activity, not the injection: reg.exe spawned from an oracle.exe parent.

The highest-value defensive angle is the process-lineage break. Endpoint tooling does not inspect Java classes or PL/SQL wrappers living inside an Oracle schema, so the toolkit itself is effectively invisible to EDR. What is not invisible is the moment the database process forks a shell. Every OS-level action in this intrusion descends from oracle.exe, and a healthy database server almost never spawns cmd.exe or powershell.exe.

Defender priority: hunt for command interpreters and credential-access binaries whose parent or grandparent is an Oracle service process (oracle.exe, tnslsnr.exe, extproc.exe, oradim.exe). Then go into the database itself and enumerate JAVA SOURCE / JAVA CLASS objects — the toolkit is a schema object, so no file-based scan will ever find it.

02

Source Review & Web Hunter Notes

TierSourceKey findingCarry forward
Tier 1Huntress — "Toolkit Installation via SQL Injection Shows the Classics Still Hit" (2026-08-05, Nahorney & Tigges)Primary IR write-up. Names the six khunt Java components and the khunt_* PL/SQL wrappers, the CREATE JAVA SOURCE delivery path over JDBC from Tomcat, the attacker IP, the four staged .hiv files and khunttasks.txt, and the reg.exe-from-oracle.exe detection. Publishes an IOC table.Yes — every atomic indicator in this pack traces to this report
Tier 2BleepingComputer — "Hackers run khunt post-exploitation toolkit from Oracle database" (2026-08-05, Abrams)Independent restatement. Adds that the injectable endpoint was an autocomplete search feature, confirms the 2026-07-27 detection date, the attacker IP, and that the report does not confirm whether hive files were successfully exfiltrated.Partial — corroboration + the "exfil unconfirmed" caveat
Tier 2eSecurity Planet — "Oracle SQL Injection Attack Enables Remote Code Execution" (2026-08-05, Underhill)Summary plus a defensive framing: least privilege on the app's database account, auditing Oracle objects and SQL logs for unexpected Java source creation.Partial — hardening framing only

Research notes and decisions

  • No hashes exist to ship. The toolkit never lands on disk as a file, so no vendor published a SHA256. Any hash row in the IOC CSV would be invented. The CSV therefore ships the IP and the four staged artifact filenames, and says so explicitly in a comment.
  • No CVE. This is an application input-validation defect, not a product vulnerability. Do not wait for a patch — there is nothing to patch.
  • The technique is old, the sighting is not. Huntress notes the approach has been described for years (they reference an oraexec-style technique) but is rarely documented in the wild. Treat the TTP as durable and the infrastructure as perishable.
  • Victim and environment details deliberately omitted. The reported staging path was on an F: volume; this pack matches on the \Oracle\ directory component and the khunt filename prefix rather than a drive letter, so the detections port to any environment.
  • Gap: no source describes the exact SQL payload, the specific application, or any post-hive-dump lateral movement. Hunt content for those steps is hypothesis-driven, not intel-driven, and is marked as such in the coverage map.
03

Hunt Brief & Attack Chain

Attack chain

#StepTelemetryHunt angle
1SQL injection against an autocomplete/search endpoint on a public-facing Java/Tomcat appApache/Tomcat access.log; WAF logs; network flowRepeated high-volume requests to one query endpoint from a single source; SQL keywords in query strings (Q5, native hunts)
2SQL relayed to Oracle over the app's JDBC connectionOracle unified audit trail; V$SQL; listener logDDL from the application schema; any CREATE JAVA statement (native hunts)
3CREATE JAVA SOURCE compiles the khunt toolkit into the schemaOracle DBA_OBJECTS / DBA_SOURCE; unified auditNew JAVA SOURCE / JAVA CLASS objects; object names matching KHUNT% (native hunts)
4khunt_* PL/SQL wrappers expose the Java methods to SQL callersOracle DBA_PROCEDURES; unified auditNew packages/procedures in the app schema that call DBMS_JAVA or a Java class
5KhuntCmd launches cmd.exe /c whoami — RCE confirmed as SYSTEMProcessRollup2Q1, Q3, Q7 — command interpreter with an Oracle parent
6tasklist /svc enumerates services, output staged to khunttasks.txtProcessRollup2Q4, Q7 — discovery burst plus the khunt filename prefix
7PowerShell drives reg.exe to save the SECURITY and SYSTEM hivesProcessRollup2Q2, Q3 — hive export from a database-parented process
8esentutl.exe copies the SAM and SECURITY hivesProcessRollup2Q2 — esentutl touching a registry hive path
9Hive copies and task list staged in the Oracle directory for exfiltrationProcessRollup2 command lines; network egressQ4, Q6 — khunt-prefixed artifacts, local data staging
10KhuntHash writes Oracle account credentials to a fileOracle audit; file telemetryNative hunts — no reliable EDR signal, flagged as a coverage gap

Hunt hypotheses (ordered by fidelity)

  1. H1 — Database service spawns a command interpreter. If khunt (or any in-database RCE technique) is used, an Oracle service process becomes the parent of cmd.exe or powershell.exe. Covers T1190/T1505.001/T1059.003. Falcon: ProcessRollup2. Expected FP: RMAN/OPatch wrapper scripts. Confidence: high.
  2. H2 — Registry hive export from a database-parented process. Credential access via reg save or esentutl against SAM/SECURITY/SYSTEM. Covers T1003.002/T1003.004. Falcon: ProcessRollup2. Expected FP: backup and DR tooling. Confidence: high.
  3. H3 — khunt-named artifacts appear in command lines. Any reference to khunt in a process command line is campaign-specific. Falcon: ProcessRollup2. Expected FP: negligible. Confidence: high (but only fires on this exact tooling).
  4. H4 — Web tier spawns a shell. The Tomcat/Java process forking a command interpreter is the generic form of the same entry point and also catches JSP webshells. Falcon: ProcessRollup2. Expected FP: build agents, Java apps that legitimately shell out. Confidence: medium.
  5. H5 — Discovery burst under a database-parented shell. whoami, tasklist, systeminfo, net executed in short order beneath an Oracle process. Falcon: ProcessRollup2 aggregated. Confidence: medium-high.
  6. H6 — Local data staging in the Oracle install directory. Hive and text artifacts written into \Oracle\. Covers T1074.001. Confidence: medium.
  7. H7 — Contact with the reported attacker infrastructure. Inbound or outbound traffic involving the published source IP. Falcon: NetworkConnectIP4 / NetworkReceiveAcceptIP4. Confidence: medium and highly perishable.
  8. H8 — Anomalous child-process baseline for Oracle services. Stack-count every child of the Oracle binaries and review the long tail. Confidence: low individually, high as a triage surface.

Steps 2, 3, 4 and 10 have no endpoint telemetry. They live entirely inside the database engine and are only reachable through the Oracle audit trail and data-dictionary queries in section 7. A pack that only runs the CQL will miss the persistence mechanism itself.

04

Consolidated IOC Table

TypeValueConfidenceActionContextExpiry
IPv4178.162.151[.]229mediumdetectSource of the injection traffic against the vulnerable endpoint, identified from Apache access logs by request volume.2026-11-06
Filenamekhunttasks.txthighdetectOutput of tasklist /svc, staged in the Oracle install directory.2027-02-06
FilenamekhuntSAM.hivhighdetectSAM hive copy produced with esentutl.exe.2027-02-06
FilenamekhuntSECURITY.hivhighdetectSECURITY hive copy produced with reg.exe.2027-02-06
Filenamekhunt_SECURITY.hivhighdetectSecond SECURITY hive copy, produced with esentutl.exe. Note the underscore — both spellings were observed.2027-02-06
FilenamekhuntSYSTEM.hivhighdetectSYSTEM hive copy produced with reg.exe.2027-02-06
Path fragment\Oracle\ staging directorymediumhuntAll five artifacts were staged inside the Oracle installation directory on a non-system volume.2026-11-06
DB object nameKhuntCmd, KhuntHash, KhuntFS, KhuntFS2, KhuntT, KhuntUnziphighhuntJava objects compiled into the Oracle schema. Search DBA_OBJECTS.OBJECT_NAME; not visible to any file-based scanner.2027-02-06
DB object patternKHUNT%highhuntVendor-recommended search string for SQL logs and the data dictionary; also matches the khunt_* PL/SQL wrappers.2027-02-06
BehaviourCREATE JAVA SOURCE issued by an application schemahighdetectThe delivery mechanism itself. An application account should never author Java sources.No expiry
Behaviourcmd.exe child of oracle.exehighdetectThe RCE bridge from the database layer to the OS. This is the signal that opened the original investigation.No expiry

No file hashes are published for khunt and none are invented here. The toolkit exists as compiled Oracle schema objects, so there is no on-disk sample to hash. If your own IR produces one, add it to the CSV in section 10.

05

Affected Surface & Telemetry Matrix

SurfaceExposureRequired telemetryPriorityGap risk
Windows host running Oracle DatabaseRCE as SYSTEM via the database service token; local credential theftFalcon ProcessRollup2 / SyntheticProcessRollup2CriticalLow — standard sensor coverage
Oracle Database engine (schema objects)Toolkit resident as Java + PL/SQL objects; survives reboots and file scansOracle unified audit trail, DBA_OBJECTS, DBA_SOURCECriticalHigh — most orgs do not ship Oracle audit to the SIEM
Public-facing Java/Tomcat applicationUnparameterised input on an autocomplete/search endpointApache/Tomcat access.log, WAF logsCriticalHigh — web logs are often not centralised
Application database accountOver-provisioned rights allowed Java source authoring and procedure executionDBA_SYS_PRIVS, DBA_ROLE_PRIVS, DBA_TAB_PRIVSHighMedium — point-in-time audit, not streamed
Local Windows account credentialsSAM/SECURITY/SYSTEM hives copied; hashes and LSA secrets recoverable offlineProcessRollup2, Windows Security 4688/4663CriticalLow
Oracle internal credential storeKhuntHash read the internal user table and wrote credentials to a fileOracle unified audit on SYS.USER$ accessHighHigh — no EDR visibility at all
Network egress from the database tierStaged archives available for exfiltrationNetworkConnectIP4, firewall/proxy logsMediumMedium
06

ATT&CK Mapping

TacticTechniqueObserved behaviourQuery or control
Initial AccessT1190 — Exploit Public-Facing ApplicationSQL injection through an autocomplete/search form on a Java/Tomcat app, relayed to Oracle over JDBCQ5, Q6, native web-log hunts, M1050/M1026
PersistenceT1505.001 — Server Software Component: SQL Stored Procedureskhunt Java classes compiled into the schema with CREATE JAVA SOURCE, exposed via khunt_* PL/SQL wrappersNative Oracle data-dictionary hunts (section 7)
ExecutionT1059.003 — Windows Command ShellKhuntCmd launches cmd.exe /c whoami from a SQL statementQ1, Q3, Q7
ExecutionT1059.001 — PowerShellPowerShell used to invoke reg.exe for hive copiesQ1, Q2, Q3
Privilege EscalationT1078.003 — Valid Accounts: Local AccountsCommands inherit the Oracle service token, giving NT AUTHORITY\SYSTEM without any escalation exploitHardening tier 1 (service account de-privileging)
Defense EvasionT1027 — Obfuscated/Compressed Files and InformationToolkit lives as database objects, never as a file; EDR and AV do not inspect Oracle schema contentsNative Oracle hunts; Database Activity Monitoring
Credential AccessT1003.002 — OS Credential Dumping: Security Account Managerreg.exe and esentutl.exe copies of the SAM hiveQ2, Q3
Credential AccessT1003.004 — OS Credential Dumping: LSA SecretsSECURITY hive copied twice (both reg.exe and esentutl.exe variants)Q2, Q3
Credential AccessT1555 — Credentials from Password StoresKhuntHash reads Oracle's internal user table and writes usernames and password data to a fileOracle audit on SYS.USER$; coverage gap for EDR
DiscoveryT1007 — System Service Discoverytasklist /svc, output saved to khunttasks.txtQ4, Q7
DiscoveryT1033 — System Owner/User Discoverywhoami to confirm SYSTEM contextQ7
DiscoveryT1083 — File and Directory DiscoveryKhuntFS / KhuntFS2 list, read, search and size files on the hostNative Oracle hunts; coverage gap for EDR
CollectionT1074.001 — Local Data StagingHive copies and the task list staged together in the Oracle install directoryQ4, Q6
CollectionT1560 — Archive Collected DataKhuntUnzip provides archive handling inside the databaseNative Oracle hunts
07

Native Audit-Log Hunts (non-CQL)

These are the checks that find the parts of this intrusion EDR cannot see. Run them as a read-only DBA and treat any hit as an incident, not a finding. All statements below are enumeration only — they read the data dictionary and the audit trail and change nothing.

A. Oracle — enumerate Java objects in the database

-- Every Java object in the database, newest first. On a clean system the only
-- rows should be Oracle-shipped objects owned by SYS / SYSTEM / ORDSYS / MDSYS.
SELECT owner, object_name, object_type, created, last_ddl_time, status
  FROM dba_objects
 WHERE object_type IN ('JAVA SOURCE','JAVA CLASS','JAVA RESOURCE')
 ORDER BY created DESC;

-- The vendor-recommended name search. Matches the six khunt Java classes and the
-- khunt_* PL/SQL wrappers in one pass.
SELECT owner, object_name, object_type, created
  FROM dba_objects
 WHERE UPPER(object_name) LIKE 'KHUNT%';

-- Java objects owned by anything that is not an Oracle-shipped schema.
SELECT owner, COUNT(*) AS java_objects
  FROM dba_objects
 WHERE object_type LIKE 'JAVA%'
   AND owner NOT IN ('SYS','SYSTEM','ORDSYS','MDSYS','XDB','CTXSYS','EXFSYS','OLAPSYS')
 GROUP BY owner
 ORDER BY java_objects DESC;

B. Oracle — audit trail for Java-source creation and OS bridging

-- Unified auditing: any DDL that authored a Java source, or any call into the
-- DBMS_JAVA package. Requires unified auditing to be enabled (playbook 2).
SELECT event_timestamp, dbusername, os_username, userhost, client_program_name,
       action_name, object_schema, object_name, sql_text
  FROM unified_audit_trail
 WHERE (UPPER(sql_text) LIKE '%CREATE%JAVA%SOURCE%'
     OR UPPER(sql_text) LIKE '%DBMS_JAVA%'
     OR UPPER(sql_text) LIKE '%KHUNT%')
 ORDER BY event_timestamp DESC;

-- Shared-pool residue: cached SQL text that touched Java or the khunt objects.
-- Useful even without auditing, but volatile -- capture it before any restart.
SELECT sql_id, parsing_schema_name, last_active_time, sql_fulltext
  FROM v$sql
 WHERE UPPER(sql_fulltext) LIKE '%JAVA SOURCE%'
    OR UPPER(sql_fulltext) LIKE '%KHUNT%';

-- Stored PL/SQL source that references a Java call spec or DBMS_JAVA.
SELECT owner, name, type, line, text
  FROM dba_source
 WHERE UPPER(text) LIKE '%LANGUAGE JAVA%'
    OR UPPER(text) LIKE '%DBMS_JAVA%'
    OR UPPER(name) LIKE 'KHUNT%';

C. Oracle — privilege audit on the application account

-- Which accounts can author Java or run arbitrary procedures? The application
-- schema should appear in NONE of these result sets.
SELECT grantee, privilege
  FROM dba_sys_privs
 WHERE privilege IN ('CREATE ANY PROCEDURE','CREATE PROCEDURE',
                     'CREATE ANY LIBRARY','CREATE LIBRARY',
                     'EXECUTE ANY PROCEDURE','JAVA SYSCLASS',
                     'CREATE ANY TABLE','ALTER SYSTEM')
 ORDER BY grantee;

-- EXECUTE on the Java bridge packages granted to PUBLIC or to an app account.
SELECT grantee, owner, table_name AS package_name, privilege
  FROM dba_tab_privs
 WHERE table_name IN ('DBMS_JAVA','DBMS_JAVA_TEST','DBMS_SCHEDULER','UTL_FILE','DBMS_LOB')
   AND privilege = 'EXECUTE'
 ORDER BY grantee;

-- Java runtime permissions -- the row that lets a Java class shell out is a
-- java.io.FilePermission ... execute, or a java.lang.RuntimePermission.
SELECT grantee, type_name, name, action, enabled
  FROM dba_java_policy
 WHERE UPPER(type_name) LIKE '%RUNTIMEPERMISSION%'
    OR UPPER(action) LIKE '%EXECUTE%';

D. Tomcat / Apache access log — the injection itself

# The reported source IP, across every rotated access log.
grep -rF "178.162.151.229" /var/log/apache2/ /opt/tomcat/logs/

# SQL keywords in query strings -- the injectable endpoint was an autocomplete
# search, so the payload arrives URL-encoded in a GET parameter.
grep -rEi "(create[+ %]java|union[+ %]select|dbms_|utl_|%27|'--|xp_cmdshell)" \
     /var/log/apache2/access.log*

# Request-volume outliers against a single endpoint. The original investigation
# identified the actor purely from how much traffic one source sent to one path.
awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -25

E. Windows event log — the OS half, if Falcon is not deployed

  • Security 4688 (process creation, requires command-line auditing): filter ParentProcessName ending in oracle.exe, tnslsnr.exe, extproc.exe or oradim.exe. Any hit is worth reading.
  • Security 4663 / 4656 (object access) on %SystemRoot%\System32\config\SAM and ...\SECURITY, once SACLs are in place.
  • Sysmon 1 (process create) with the same parent filter; Sysmon 11 (file create) for *.hiv and khunt* anywhere on the volume.
  • System 7045 / 7036 — confirm which identity the Oracle services run as. If it is LocalSystem, every khunt command would have run as SYSTEM.
  • PowerShell 4104 (script block logging) for reg save, esentutl, and any script writing into the Oracle directory.
08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first — every "Open in Falcon" button below uses this selection.

None of these queries carry an in-query time filter. Set the window with the console time picker; each card records the intended lookback as a // LOOKBACK: comment. Start every hunt at Q1 — it is the single highest-value query in this pack.

Q1 · Oracle service process spawning a command interpreter
CONF HIGHFP LOWCOST LOW

Looks for: any Windows command interpreter or script host whose parent is an Oracle server binary. This is the exact lineage that exposed the intrusion — KhuntCmd can only reach the OS by making the database process fork a shell. FP: RMAN backup wrappers and OPatch runs shell out legitimately and carry recognisable script paths.

// HUNT: Oracle database service spawning a Windows command interpreter
// MITRE: T1190, T1505.001, T1059.003, T1059.001 | CONF: high  FP: low  COST: low
// REQUIRES: ProcessRollup2 on Windows hosts running Oracle Database
// FALSE POSITIVES: RMAN / OPatch / OEM agent wrapper scripts legitimately shell out
// TUNING: exclude your own maintenance wrappers by path, e.g. append
//   | CommandLine!=/\\opatch\\|\\rman_backup\\|\\oem_agent\\/i
// LOOKBACK: 30d -- set the window in the console time picker
#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/
| ParentBaseFileName=/^(oracle|tnslsnr|extproc|extproc32|oradim|emagent)\.exe$/i
| FileName=/^(cmd|powershell|pwsh|wscript|cscript|mshta|rundll32|bash)\.exe$/i
| table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, TargetProcessId])
| sort(@timestamp, order=desc, limit=200)
Q2 · Registry hive export via reg.exe or esentutl.exe
CONF HIGHFP MEDIUMCOST LOW

Looks for: the credential-theft step — reg.exe or esentutl.exe copying the SAM, SECURITY or SYSTEM hive, or writing a .hiv file. Both utilities were used in this intrusion, against overlapping hives. FP: backup, DR and migration tooling copies hives on schedule; those runs are parented by the backup agent, not by a shell.

// HUNT: SAM / SECURITY / SYSTEM registry hive export to a file
// MITRE: T1003.002, T1003.004 | CONF: high  FP: medium  COST: low
// REQUIRES: ProcessRollup2 with command lines on Windows servers
// FALSE POSITIVES: backup / DR / server-migration agents legitimately export hives
// TUNING: exclude your backup agent lineage, e.g. append
//   | ParentBaseFileName!=/^(veeamagent|backupexec|acronis|dpm|ntbackup)\.exe$/i
// LOOKBACK: 30d -- set the window in the console time picker
#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/
| FileName=/^(reg|reg32|esentutl|regedit)\.exe$/i
| CommandLine=/(hklm\\(sam|security|system)|\\config\\(sam|security|system)|\.hiv\b)/i
| table([@timestamp, aid, ComputerName, UserName, GrandparentBaseFileName, ParentBaseFileName, FileName, CommandLine])
| sort(@timestamp, order=desc, limit=200)
Q3 · Any process descending from an Oracle service binary
CONF HIGHFP LOWCOST LOW

Looks for: the second generation of the lineage. Q1 catches oracle.exe → cmd.exe; this catches oracle.exe → cmd.exe → reg.exe and oracle.exe → powershell.exe → esentutl.exe, which is how the hive copies actually ran. Grandparent matching is what keeps the shell-in-the-middle from hiding the origin.

// HUNT: second-generation descendants of an Oracle service process
// MITRE: T1505.001, T1059.003, T1003.002 | CONF: high  FP: low  COST: low
// REQUIRES: ProcessRollup2 with GrandparentBaseFileName populated
// FALSE POSITIVES: OPatch and OEM agent job chains produce multi-level trees
// TUNING: if OPatch is noisy, append | CommandLine!=/\\opatch\\/i
// LOOKBACK: 30d -- set the window in the console time picker
#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/
| (ParentBaseFileName=/^(oracle|tnslsnr|extproc|oradim)\.exe$/i or GrandparentBaseFileName=/^(oracle|tnslsnr|extproc|oradim)\.exe$/i)
| FileName!=/^(conhost|werfault|oracle|tnslsnr)\.exe$/i
| table([@timestamp, aid, ComputerName, UserName, GrandparentBaseFileName, ParentBaseFileName, FileName, CommandLine])
| sort(@timestamp, order=desc, limit=200)
Q4 · khunt-named artifacts and toolkit objects in command lines
CONF HIGHFP LOWCOST MEDIUM

Looks for: the campaign's own naming convention — the four staged hive copies, the task list output, and the six Java class names — anywhere in a process command line. Named-tooling matching only fires on this exact toolkit, so treat a miss as uninformative and a hit as confirmed compromise.

// HUNT: khunt toolkit artifact and object names on the command line
// MITRE: T1074.001, T1003.002, T1007 | CONF: high  FP: low  COST: medium
// REQUIRES: ProcessRollup2 with command lines
// FALSE POSITIVES: essentially none -- the string is campaign-specific
// TUNING: none needed; if a benign internal tool uses the prefix, anchor on the
//   full artifact names only by dropping the bare khunt alternative
// LOOKBACK: 90d -- set the window in the console time picker
#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/
| CommandLine=/(khunttasks\.txt|khuntsam\.hiv|khuntsecurity\.hiv|khunt_security\.hiv|khuntsystem\.hiv|khuntcmd|khunthash|khuntfs2|khuntfs|khuntunzip|khunt_)/i
| table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
| sort(@timestamp, order=desc, limit=200)
Q5 · Traffic involving the reported injection source IP
CONF MEDIUMFP LOWCOST LOW

Looks for: inbound or outbound connections involving the address the injection traffic came from. FP: low, but this is the most perishable content in the pack — a single reported source IP from one incident. A miss proves nothing; retire the row once it expires rather than carrying it forever.

// HUNT: connections involving the reported khunt injection source address
// MITRE: T1190 | CONF: medium  FP: low  COST: low
// REQUIRES: NetworkConnectIP4 / NetworkReceiveAcceptIP4
// FALSE POSITIVES: none expected; the address is not shared hosting per the report
// TUNING: not required at FP low -- but expire this indicator on 2026-11-06
// LOOKBACK: 90d -- set the window in the console time picker
#event_simpleName=/^(NetworkConnectIP4|NetworkReceiveAcceptIP4)$/
| RemoteAddressIP4="178.162.151.229"
| table([@timestamp, aid, ComputerName, LocalAddressIP4, LocalPort, RemoteAddressIP4, RemotePort, ContextBaseFileName])
| sort(@timestamp, order=desc, limit=200)
Q6 · Java / Tomcat web tier spawning a shell or discovery binary
CONF MEDIUMFP MEDIUMCOST LOW

Looks for: the generic form of the entry point. The application tier here only relayed SQL, but the same lineage catches JSP webshells and any other application-server RCE, so it is worth running on the whole web estate rather than just the DB host. FP: build agents, CI runners and Java apps that legitimately invoke helper processes will fire; scope by host group first.

// HUNT: application server (Java / Tomcat / IIS) spawning a shell or discovery tool
// MITRE: T1190, T1059.003, T1505.003 | CONF: medium  FP: medium  COST: low
// REQUIRES: ProcessRollup2 on internet-facing application servers
// FALSE POSITIVES: build agents, CI runners, Java apps that shell out by design
// TUNING: scope to internet-facing hosts and drop known build servers, e.g. append
//   | ComputerName!=/^(BUILD|CI|JENKINS)-/i
// LOOKBACK: 30d -- set the window in the console time picker
#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/
| ParentBaseFileName=/^(java|javaw|tomcat\d*|catalina|httpd|nginx|w3wp)\.exe$/i
| FileName=/^(cmd|powershell|pwsh|whoami|net|net1|systeminfo|tasklist|reg|esentutl|certutil|bitsadmin)\.exe$/i
| table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
| sort(@timestamp, order=desc, limit=200)
Q7 · Discovery burst beneath a database-parented shell
CONF MEDIUMFP MEDIUMCOST MEDIUM

Looks for: the orientation phase — whoami, tasklist /svc, systeminfo, net — clustered on one host under a shell that a database service started. Aggregation raises confidence: one whoami is noise, four discovery binaries in one lineage is an operator. FP: DBA troubleshooting sessions and monitoring scripts; check whether an interactive logon exists for the same window.

// HUNT: clustered host/service discovery under a database-parented shell
// MITRE: T1033, T1007, T1057, T1082 | CONF: medium  FP: medium  COST: medium
// REQUIRES: ProcessRollup2 with command lines
// FALSE POSITIVES: DBA troubleshooting and monitoring agents run the same binaries
// TUNING: raise the Hits floor from 2 to 4 in a noisy estate, and exclude your
//   monitoring service account with | UserName!=/^svc_monitor$/i
// LOOKBACK: 7d per run -- set the window in the console time picker
#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/
| GrandparentBaseFileName=/^(oracle|tnslsnr|extproc|oradim|java|javaw)\.exe$/i
| FileName=/^(whoami|tasklist|systeminfo|net|net1|ipconfig|nltest|quser|hostname|arp)\.exe$/i
| groupBy([aid, ComputerName, UserName, GrandparentBaseFileName], function=[count(as=Hits), count(FileName, distinct=true, as=DistinctTools), collect(CommandLine, limit=25)], limit=400)
| DistinctTools > 2
| sort(Hits, order=desc, limit=100)
Q8 · Baseline: stack-count every child of the Oracle binaries
CONF MEDIUMFP HIGHCOST MEDIUM

Looks for: everything the Oracle services have ever launched in your estate, sorted rarest-first. This is a triage surface rather than an alert — run it once to build the allow-list that tunes Q1 and Q3, then keep it for quarterly review. FP: by design, every row is a "false positive" until you read it; the value is in the tail with a host count of one.

// HUNT: rarest child processes of Oracle service binaries (baseline builder)
// MITRE: T1505.001, T1059 | CONF: medium  FP: high  COST: medium
// REQUIRES: ProcessRollup2 across all Oracle database hosts
// FALSE POSITIVES: this is a stack-count, not a detection -- most rows are benign
// TUNING: review only rows where Hosts = 1; promote the frequent, benign rows into
//   the exclusion list used by Q1 and Q3 rather than tuning this query itself
// LOOKBACK: 90d -- set the window in the console time picker
#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/
| ParentBaseFileName=/^(oracle|tnslsnr|extproc|extproc32|oradim|emagent)\.exe$/i
| groupBy([ParentBaseFileName, FileName], function=[count(as=Hits), count(aid, distinct=true, as=Hosts), collect(CommandLine, limit=5)], limit=1000)
| sort(Hits, order=asc, limit=200)
09

CrowdStrike Custom IOA Recommendations

Two of the eight queries are strong enough to promote from Investigate-only to a Custom IOA. The rest stay as scheduled hunt searches. Build IOAs under Endpoint security → Custom IOA rule groups → Process Creation, and run each in Monitor for at least seven days before switching to Detect or Block.

IOA-1 — Database service spawns a command interpreter (from Q1)

FieldValue
Rule nameDETECT — Oracle service spawns command shell (in-database RCE)
Rule typeProcess Creation
SeverityCritical
Parent Image FileName.*\\(oracle|tnslsnr|extproc|extproc32|oradim|emagent)\.exe
Grandparent Image FileName(leave empty)
Image FileName.*\\(cmd|powershell|pwsh|wscript|cscript|mshta|rundll32)\.exe
Command Line.*
ExclusionsCommand line containing your RMAN, OPatch or OEM agent script paths. Add them as an exclusion pattern, not by weakening the parent match.
ActionMonitor for 7 days → Detect. Consider Block only after the exclusion list is stable — blocking a shell under a production database can break patching.

IOA-2 — Hive export by a shell-parented process (from Q2 + Q3)

FieldValue
Rule nameDETECT — SAM/SECURITY/SYSTEM hive export from a server shell
Rule typeProcess Creation
SeverityCritical
Parent Image FileName.*\\(cmd|powershell|pwsh)\.exe
Image FileName.*\\(reg|esentutl|regedit)\.exe
Command Line.*(hklm\\(sam|security|system)|\\config\\(sam|security|system)|\.hiv).*
ExclusionsYour backup agent's own lineage. Scope the rule group to server host groups so workstation imaging tools do not fire it.
ActionMonitor for 7 days → Block. Hive export from an interactive shell on a database server has no legitimate use.

Stays as a scheduled search (Investigate-only)

  • Q4 — named-tooling match. Very high precision but zero recall against a renamed toolkit; better as a daily scheduled search with email alerting than as an IOA.
  • Q5 — single-IP indicator. Put it in Falcon IOC Management with detect, not in an IOA.
  • Q6, Q7 — medium FP; run weekly and tune before considering promotion.
  • Q8 — baseline stack-count. Never an IOA; run quarterly to refresh the exclusion lists for IOA-1.

Falcon cannot see inside the Oracle schema. No IOA, IOC or ML model will detect the khunt objects themselves — only the moment they touch the OS. The database-side controls in sections 7, 12 and 13 are not optional extras here, they are the other half of the coverage.

10

Machine-Readable IOC Appendix

Falcon IOC Management CSVbulk import
type,value,action,severity,expiration,description,tags
ipv4,178.162.151.229,detect,high,2026-11-06,khunt SQL injection source address,campaign:khunt
filename,khunttasks.txt,detect,high,2027-02-06,tasklist /svc output staged by khunt,campaign:khunt
filename,khuntSAM.hiv,detect,critical,2027-02-06,SAM hive copy staged by khunt,campaign:khunt
filename,khuntSECURITY.hiv,detect,critical,2027-02-06,SECURITY hive copy staged by khunt,campaign:khunt
filename,khunt_SECURITY.hiv,detect,critical,2027-02-06,second SECURITY hive copy via esentutl,campaign:khunt
filename,khuntSYSTEM.hiv,detect,critical,2027-02-06,SYSTEM hive copy staged by khunt,campaign:khunt
# No file hashes are published for khunt and none are invented here. The toolkit is
# compiled into the Oracle schema as Java objects, so there is no on-disk sample to
# hash. Add sha256 rows only from your own incident-response sample.
# Falcon IOC Management has no object-name type -- the six Java class names and the
# KHUNT% pattern are database-side and belong in the Oracle hunts, not this CSV.
Oracle in-database object huntrun as read-only dba
-- One-shot triage: does this database carry the toolkit?
SELECT owner, object_name, object_type, created, status
  FROM dba_objects
 WHERE UPPER(object_name) LIKE 'KHUNT%'
    OR (object_type LIKE 'JAVA%'
        AND owner NOT IN ('SYS','SYSTEM','ORDSYS','MDSYS','XDB','CTXSYS','OLAPSYS'))
 ORDER BY created DESC;

-- Named components reported by the vendor.
SELECT owner, object_name, object_type
  FROM dba_objects
 WHERE UPPER(object_name) IN ('KHUNTCMD','KHUNTHASH','KHUNTFS','KHUNTFS2',
                              'KHUNTT','KHUNTUNZIP');
Behavioral signaturesdurable, survives renaming
BEHAV-1  oracle.exe | tnslsnr.exe | extproc.exe | oradim.exe is the parent of
         cmd.exe | powershell.exe | wscript.exe | cscript.exe            [Q1]
BEHAV-2  reg.exe or esentutl.exe writing a copy of the SAM, SECURITY or
         SYSTEM hive, parented by a shell rather than a backup agent     [Q2]
BEHAV-3  an Oracle service binary as GRANDPARENT of reg.exe, esentutl.exe,
         whoami.exe or tasklist.exe                                     [Q3, Q7]
BEHAV-4  three or more distinct discovery binaries in one process tree on a
         database server within a short window                          [Q7]
BEHAV-5  java.exe | javaw.exe | tomcat*.exe as the parent of a command
         interpreter on an internet-facing host                         [Q6]
BEHAV-6  files written into the Oracle installation directory whose name
         begins with a tool prefix and ends in .hiv or .txt             [Q4]
BEHAV-7  DATABASE-SIDE: a CREATE JAVA SOURCE statement issued by an
         application schema, or any new JAVA SOURCE / JAVA CLASS object
         outside the Oracle-shipped schemas                             [section 7]
BEHAV-8  DATABASE-SIDE: a PL/SQL package or procedure in an application
         schema whose body declares LANGUAGE JAVA or calls DBMS_JAVA    [section 7]
Privilege & configuration auditpreventive checklist
[ ] Which identity do the Oracle Windows services run as? LocalSystem is the
    reason cmd.exe /c whoami returned NT AUTHORITY\SYSTEM.
[ ] Does the application's database account hold CREATE PROCEDURE,
    CREATE ANY PROCEDURE, CREATE LIBRARY or any JAVA privilege? It should not.
[ ] Is EXECUTE on DBMS_JAVA or DBMS_JAVA_TEST granted to PUBLIC?
[ ] Is the Oracle JVM (JAVAVM) component actually installed and used? If no
    application needs it, its removal eliminates this entire technique.
[ ] Is unified auditing enabled, and does any policy cover CREATE JAVA SOURCE,
    CREATE PROCEDURE and DBMS_JAVA execution?
[ ] Is the Oracle audit trail shipped to the SIEM, or does it only exist on the
    host an attacker with SYSTEM can edit?
[ ] Is the database host reachable from the internet, directly or via the app
    tier's network path? Can it initiate outbound connections?
[ ] Are the application's queries parameterised end to end, including the
    autocomplete / typeahead endpoints that nobody threat-models?
[ ] Is there a WAF in front of the application, and does it inspect the
    typeahead endpoint's query string?
[ ] If hives were copied: have all local account passwords been rotated, and
    the machine account password reset?
11

Detection Validation Gates

Gate 1 — Telemetry ready

  • Confirm the Falcon sensor is installed and reporting on every Oracle database host. Run #event_simpleName=/^ProcessRollup2$/ | ComputerName=/^DB/i | groupBy([ComputerName], limit=200) and reconcile against the DBA team's inventory. Database servers are a classic sensor-coverage hole.
  • Confirm command-line capture is on. If CommandLine is empty, Q2, Q4, Q6 and Q7 all silently return nothing.
  • Confirm GrandparentBaseFileName is populated in your tenant's process events — Q3 and Q7 depend on it.
  • Confirm Oracle unified auditing is enabled and reaching the SIEM. Without it, four of the ten attack-chain steps have no evidence source at all.

Gate 2 — Benign baseline

  • Run Q8 over 90 days before enabling anything. Record every child process the Oracle binaries legitimately launch in your estate; that list becomes the exclusion set for IOA-1.
  • Run Q2 over 30 days and identify every backup or DR product that exports hives on schedule. Note the parent process, not the file path — an attacker can drop a binary at the same path.
  • Run Q6 across the web estate and separate build/CI hosts from genuinely internet-facing ones.

Gate 3 — Positive tests (authorised lab only)

  • On a lab database host, have a DBA start a benign child process from a scheduled Oracle job and confirm Q1 and Q8 both surface it. This validates the lineage fields without simulating the attack.
  • Export a SYSTEM hive on a lab server using your normal backup tool and confirm Q2 fires and that your backup exclusion correctly suppresses it.
  • Create a harmless Java source object in a lab schema (CREATE JAVA SOURCE returning a constant) and confirm the section 7 data-dictionary query and the unified audit policy both catch it. This is the single most important test in the pack, because it validates the only control that sees the persistence mechanism.
  • Do not attempt to reproduce OS command execution from the database. The enumeration test above proves the detection without creating an exploitable object.

Gate 4 — Promotion criteria

  • IOA-1 moves Monitor → Detect after seven consecutive days with zero unexplained hits.
  • IOA-2 moves Monitor → Block after the backup exclusion has been verified against a full backup cycle, including monthly and quarterly jobs.
  • The Oracle audit policy is considered deployed only once its events are queryable in the SIEM, not once it is enabled on the host.
12

Hardening — Tiered

This intrusion needed three separate failures to reach SYSTEM: unvalidated input in the application, an over-privileged database account, and a database service running as LocalSystem. Fixing any one of them breaks the chain. The controls below are ordered by how much of the chain they remove per unit of deployment friction.

Immediate — deploy this week
  • Revoke Java and procedure-creation privileges from every application database account. The vendor's own conclusion: even if injection succeeds, the account should not be able to author Java sources or execute stored procedures. MITRE M1026 (Privileged Account Management); CIS Oracle Database Benchmark — restrict system privileges to DBA roles. Verify with the dba_sys_privs query in section 7C. See playbook 1.
  • Revoke EXECUTE ON DBMS_JAVA and DBMS_JAVA_TEST from PUBLIC. These packages are the documented bridge between PL/SQL and the embedded JVM. CIS Oracle Database Benchmark — "Revoke EXECUTE ANY PROCEDURE / package grants from PUBLIC"; MITRE M1026. See playbook 1.
  • Audit which identity the Oracle Windows services run as, and plan the move off LocalSystem. Every khunt OS command inherited SYSTEM purely from the service token. Running the database under a dedicated least-privilege account turns full host compromise into a limited one. MITRE M1026; Microsoft Security Baseline — service accounts; Oracle Database Installation Guide for Windows (Oracle Home User). See playbook 3.
  • Enable a Custom IOA in Monitor mode for database services spawning shells (IOA-1). MITRE M1040 (Behavior Prevention on Endpoint). Zero risk in Monitor, and it starts building the exclusion list immediately.
  • Block inbound access to the database host from anything except the application tier. A host-based firewall rule is a same-day change. MITRE M1030 (Network Segmentation); CIS Windows Benchmark — Windows Defender Firewall.
Near term — 1 to 4 weeks, pilot first
  • Enable Oracle unified auditing for CREATE JAVA SOURCE, CREATE PROCEDURE, CREATE LIBRARY and DBMS_JAVA execution, and ship the trail to the SIEM. This is the only telemetry that sees the toolkit being installed. MITRE M1047 (Audit); CIS Oracle Database Benchmark — enable unified auditing; Oracle Database Security Guide. See playbook 2.
  • Parameterise the application's queries and put a WAF in front of the typeahead/autocomplete endpoints. Autocomplete handlers are frequently hand-written outside the ORM, which is exactly why this one was injectable. MITRE M1050 (Exploit Protection); OWASP ASVS V5 — input validation and parameterised queries. ⚠ best-practice, no formal CIS benchmark for bespoke app code.
  • Deny outbound internet from the database tier by default. Staged hive copies are only valuable if they can leave. MITRE M1030; CIS Windows Benchmark — outbound firewall rules.
  • Enable LSA protection (RunAsPPL) and Credential Guard where supported on the server estate. Does not stop offline hive cracking, but removes the easier in-memory path an actor takes next. MITRE M1043 (Credential Access Protection); Microsoft Security Baseline for Windows Server. See playbook 4.
  • Promote IOA-1 to Detect and IOA-2 to Block once gate 4 is met. MITRE M1040.
  • Add SACLs on %SystemRoot%\System32\config\SAM and SECURITY, and forward event 4663. MITRE M1047; CIS Windows Benchmark — Object Access auditing.
Strategic — 1 to 3 months
  • Remove the Oracle JVM (JAVAVM/JServer) from databases that do not need it. This deletes the technique rather than detecting it. It is an invasive, tested-in-a-clone change with vendor coordination, and some Oracle features depend on the JVM — treat the compatibility survey as the first deliverable, not the removal. MITRE M1042 (Disable or Remove Feature or Program); Oracle Database Administrator's Guide — removing the Java virtual machine.
  • Re-architect so the database tier is not reachable from the DMZ and the app account is per-service, not shared. MITRE M1030, M1026; NIST SP 800-53 SC-7.
  • Deploy Database Activity Monitoring or Oracle Database Vault in front of the production estate. DAM sees the SQL that EDR structurally cannot. MITRE M1047; Oracle Database Vault Administrator's Guide.
  • Institute an application security programme covering SQLi: SAST/DAST in CI, and annual penetration testing that explicitly includes typeahead and search endpoints. MITRE M1016 (Vulnerability Scanning); OWASP SAMM. ⚠ best-practice, no formal benchmark.
  • If hives were copied, plan a full local-credential rotation and a domain credential review. Hashes recovered offline do not expire on their own.
13

Deployable Playbooks

Every step below changes production state. Run each in a non-production clone first, and read the Rollback line before you run the command, not after.

Playbook 1 — De-privilege the application database account

Prerequisites: DBA (SYSDBA) access; the exact application schema name; an agreed maintenance window; a confirmed database backup. Reboot required: no — but the application should be restarted to refresh pooled connections. Rollback: re-grant with the recorded output of step 1 (the SPOOL file captures the pre-change state verbatim; each revoked privilege maps to one GRANT statement).

-- 1. CAPTURE THE CURRENT STATE FIRST. This file is your rollback script.
SPOOL /secure/backout/app_privs_2026-08-06.log
SELECT 'GRANT ' || privilege || ' TO ' || grantee || ';'
  FROM dba_sys_privs WHERE grantee = UPPER('&app_schema');
SELECT 'GRANT ' || granted_role || ' TO ' || grantee || ';'
  FROM dba_role_privs WHERE grantee = UPPER('&app_schema');
SPOOL OFF

-- 2. Revoke the privileges that made CREATE JAVA SOURCE possible.
REVOKE CREATE ANY PROCEDURE FROM &app_schema;
REVOKE CREATE PROCEDURE     FROM &app_schema;
REVOKE CREATE ANY LIBRARY   FROM &app_schema;
REVOKE CREATE LIBRARY       FROM &app_schema;
REVOKE EXECUTE ANY PROCEDURE FROM &app_schema;
REVOKE JAVA SYSCLASS        FROM &app_schema;

-- 3. Remove the PUBLIC grants on the PL/SQL-to-Java bridge packages.
REVOKE EXECUTE ON DBMS_JAVA      FROM PUBLIC;
REVOKE EXECUTE ON DBMS_JAVA_TEST FROM PUBLIC;

-- 4. Confirm. Both queries must return zero rows.
SELECT grantee, privilege FROM dba_sys_privs
 WHERE grantee = UPPER('&app_schema')
   AND privilege IN ('CREATE ANY PROCEDURE','CREATE PROCEDURE',
                     'CREATE ANY LIBRARY','CREATE LIBRARY',
                     'EXECUTE ANY PROCEDURE','JAVA SYSCLASS');
SELECT grantee FROM dba_tab_privs
 WHERE table_name IN ('DBMS_JAVA','DBMS_JAVA_TEST') AND grantee = 'PUBLIC';

-- 5. Restart the application's connection pool and run a full functional test.
--    If the application genuinely needs one of these privileges, grant back the
--    single narrowest one from the spool file rather than reverting the lot.

Playbook 2 — Audit Java-source creation and ship it to the SIEM

Prerequisites: Oracle 12c or later with unified auditing available; SYSDBA; a SIEM collector already reading from the database host or via a database connector. Reboot required: no (a database restart is required only when converting from mixed-mode to pure unified auditing). Rollback: NOAUDIT POLICY khunt_java_watch; then DROP AUDIT POLICY khunt_java_watch; — this removes the policy and stops collection with no other side effects.

-- 1. Create a policy covering the toolkit-delivery actions.
CREATE AUDIT POLICY khunt_java_watch
  ACTIONS CREATE JAVA SOURCE,
          ALTER JAVA SOURCE,
          DROP JAVA SOURCE,
          CREATE PROCEDURE,
          CREATE LIBRARY,
          EXECUTE ON DBMS_JAVA,
          EXECUTE ON DBMS_JAVA_TEST;

-- 2. Enable it for everyone, including privileged users.
AUDIT POLICY khunt_java_watch;

-- 3. Verify the policy is live.
SELECT policy_name, enabled_option, user_name
  FROM audit_unified_enabled_policies
 WHERE policy_name = 'KHUNT_JAVA_WATCH';

-- 4. Prove collection works: create and immediately drop a harmless Java source
--    in a LAB schema, then confirm it appears in the trail and in the SIEM.
SELECT event_timestamp, dbusername, userhost, action_name, object_name, sql_text
  FROM unified_audit_trail
 WHERE unified_audit_policies LIKE '%KHUNT_JAVA_WATCH%'
 ORDER BY event_timestamp DESC FETCH FIRST 20 ROWS ONLY;

-- 5. Set a retention that survives an incident: audit data an attacker with
--    SYSTEM can purge locally is not evidence. Forward it off-host.

Playbook 3 — Move the Oracle Windows services off LocalSystem

Prerequisites: local administrator on the database host; a dedicated service account (managed service account or domain user with a long random password held in your PAM tool); a full outage window; a tested restore. This is the highest-impact and highest-risk change in the pack. Reboot required: yes — services must be stopped and the host restarted after the ACL changes. Rollback: set each service back to LocalSystem with sc.exe config <service> obj= LocalSystem and reboot; the ACL grants added in step 3 are additive and can be left in place or removed with icacls /remove.

# 1. Inventory the services and their current identity. Record this output --
#    it is the rollback state.
Get-CimInstance Win32_Service |
  Where-Object { $_.Name -like 'Oracle*' } |
  Select-Object Name, StartName, State, PathName |
  Format-Table -AutoSize

# 2. Confirm which of them are running as LocalSystem.
Get-CimInstance Win32_Service |
  Where-Object { $_.Name -like 'Oracle*' -and $_.StartName -eq 'LocalSystem' } |
  Select-Object Name, StartName

# 3. Grant the new service account what Oracle needs on the Oracle Home and the
#    data/diag directories BEFORE changing the service identity.
$svc = 'DOMAIN\REPLACE_WITH_ORACLE_SERVICE_ACCOUNT'
icacls 'C:\app\oracle\product' /grant "${svc}:(OI)(CI)M" /T
icacls 'C:\app\oracle\oradata' /grant "${svc}:(OI)(CI)M" /T
icacls 'C:\app\oracle\diag'    /grant "${svc}:(OI)(CI)M" /T

# 4. Grant the account "Log on as a service" via your GPO or secedit, then
#    switch each service over. Do ONE service, verify, then continue.
sc.exe config OracleServiceREPLACE_WITH_SID obj= "$svc" password= "REPLACE_WITH_PASSWORD"
sc.exe config OracleREPLACE_WITH_HOME_TNSListener obj= "$svc" password= "REPLACE_WITH_PASSWORD"

# 5. Reboot, then confirm the database is healthy AND that the identity changed.
Get-CimInstance Win32_Service |
  Where-Object { $_.Name -like 'Oracle*' } |
  Select-Object Name, StartName, State

# 6. Post-change validation: from a SQL session, confirm that any OS-touching
#    call now runs without SYSTEM rights. The Falcon-side check is that Q1 and Q3
#    now show a non-SYSTEM UserName for any legitimate Oracle child process.

Playbook 4 — LSA protection and hive-access auditing on database servers

Prerequisites: local administrator or GPO edit rights; confirmation that no third-party authentication provider or smart-card DLL on the host is unsigned (RunAsPPL blocks unsigned LSA plugins); a pilot ring of one non-production database server. Reboot required: yes — RunAsPPL takes effect at boot. Rollback: delete the RunAsPPL value and reboot (see step 4); on hardware with UEFI lock enabled, removal additionally requires the documented Microsoft UEFI-lock removal procedure, so pilot before enabling the lock.

# 1. PRE-FLIGHT: list LSA plugins that would break under PPL. Investigate any
#    unsigned result before continuing.
reg query HKLM\SYSTEM\CurrentControlSet\Control\Lsa /v "Notification Packages"
reg query HKLM\SYSTEM\CurrentControlSet\Control\Lsa /v "Security Packages"

# 2. Enable LSA protection (no UEFI lock, so it stays reversible).
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa' `
  -Name 'RunAsPPL' -Value 1 -PropertyType DWORD -Force

# 3. Audit access to the hive files themselves, so a copy attempt is logged even
#    if the process lineage is missed. Enable Object Access auditing first.
auditpol /set /subcategory:"File System" /success:enable /failure:enable
$sam = "$env:SystemRoot\System32\config\SAM"
$acl = Get-Acl $sam -Audit
$rule = New-Object System.Security.AccessControl.FileSystemAuditRule(
  'Everyone','Read','None','None','Success')
$acl.AddAuditRule($rule)
Set-Acl -Path $sam -AclObject $acl

# 4. ROLLBACK for step 2, if an authentication provider breaks after reboot:
#    Remove-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa' `
#      -Name 'RunAsPPL' -Force ; then reboot.

# 5. Verify after reboot -- event 12 from Wininit confirms LSASS started
#    as a protected process.
Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='Microsoft-Windows-Wininit'} -MaxEvents 20 |
  Select-Object TimeCreated, Id, Message
14

Containment Runbook

Do not restart the database or the host before evidence capture. The shared pool (V$SQL) holds the attacker's SQL text and is lost on restart, and it may be the only record of the injection if unified auditing was not enabled.

PhaseActionsOwnerEvidence to capture
0 · Triage
0–30 min
Run Q1, Q3 and Q4 scoped to the suspect host. Run the section 7A object query against the database. Confirm whether this is khunt, a different in-database technique, or a benign DBA action.SOC L2Query output with timestamps; the dba_objects result set
1 · Isolate
30–60 min
Network-contain the host in Falcon. Block the application tier's route to the database at the firewall — do not simply stop the application, or you lose the live connection evidence. Preserve, do not reboot.SOC L2 + NetworkContainment timestamp; firewall rule change ID
2 · Capture
1–3 h
Memory image of the host. Export V$SQL, DBA_OBJECTS, DBA_SOURCE and the unified audit trail. Collect the full source of every suspect Java object. Copy all Tomcat/Apache access logs off-host. Hash and preserve any *.hiv and khunt* files found in the Oracle directory.DFIR + DBAMemory image; SQL exports; web logs; staged artifact hashes
3 · Scope
3–8 h
Run Q1–Q8 estate-wide, not just on the suspect host. Run the section 7A query against every Oracle instance — the same application account may be used across environments. Check whether the staged hives left the network (proxy, firewall, DLP).Threat huntingEstate-wide query results; egress verdict
4 · Eradicate
8–24 h
Drop the khunt Java and PL/SQL objects (DROP JAVA SOURCE / DROP PACKAGE) only after capture is complete and signed off. Delete the staged artifacts. Apply playbook 1 immediately so the account cannot recreate them. Fix the injectable endpoint or take it offline.DBA + AppDevObject drop log; code fix or WAF rule ID
5 · Rotate
24–72 h
Treat every local account on the host as compromised: rotate all local passwords, reset the machine account password twice, and rotate any credential stored in the Oracle wallet or the application config. Rotate all Oracle database account passwords — KhuntHash read the internal user table. Review for any domain account cached on the host.IAM + DBARotation ticket; account list
6 · Recover
3–7 d
Prefer rebuilding the host over cleaning it: a toolkit that lived as a schema object may have siblings you did not enumerate. Restore the database from a backup predating the first JAVA SOURCE creation timestamp, or verify object-by-object. Restore network access only after playbooks 1 and 2 are in place.Infrastructure + DBARebuild record; restore point justification
7 · Harden & verify
1–3 wk
Complete the Immediate and Near-term hardening tiers. Promote IOA-1 and IOA-2 per gate 4. Re-run gate 3's positive tests on the rebuilt host to prove the detections work in the new configuration.Security engineeringChange records; passing gate-3 test results

Analyst triage checklist for a single Q1 or Q3 hit

  1. What is the full process tree? Record parent, grandparent, and the command line of each.
  2. Is the parent genuinely an Oracle service binary, or a same-named binary in a non-Oracle path? Check ImageFileName, not just ParentBaseFileName.
  3. What identity did the child run as? NT AUTHORITY\SYSTEM on a database-parented shell is the reportable condition.
  4. Is there an interactive logon on the host in the same window? A DBA at a console explains a lot; no logon explains nothing.
  5. Does a scheduled Oracle job, RMAN backup or OPatch run cover this timestamp? Ask the DBA before escalating, and ask for the job definition, not a verbal yes.
  6. Run Q4 on the host. Any hit ends triage and starts an incident.
  7. Run the section 7A object query on the instance. This is the step analysts skip and it is the one that finds the toolkit.
  8. Check the Apache/Tomcat logs for injection-shaped requests in the hours before the process event, and pull the source addresses.
15

Detection Coverage Map

TechniqueBehaviourCQLIOACoverage
T1190SQL injection against a public-facing app endpointQ5 (IP only), Q6 (lineage)Partial — needs web/WAF logs; EDR cannot see the request
T1505.001CREATE JAVA SOURCE compiles the toolkit into the schemaGAP — Oracle unified audit + section 7 only
T1505.001khunt_* PL/SQL wrappers expose Java to SQL callersGAPDBA_SOURCE query only
T1059.003KhuntCmd launches cmd.exe from a SQL statementQ1, Q3, Q7IOA-1Good
T1059.001PowerShell used to drive reg.exeQ1, Q2, Q3IOA-1, IOA-2Good
T1078.003Commands inherit the Oracle service SYSTEM tokenQ1, Q3 (via UserName)IOA-1Partial — detected as context, prevented only by playbook 3
T1003.002SAM hive copied with reg.exe / esentutl.exeQ2, Q3IOA-2Good
T1003.004SECURITY hive copied twice, two different utilitiesQ2, Q3IOA-2Good
T1555KhuntHash dumps Oracle's internal user table to a fileGAP — Oracle audit on SYS.USER$ only; no EDR signal
T1007 / T1033tasklist /svc, whoami under a DB-parented shellQ4, Q7Good
T1083KhuntFS / KhuntFS2 file browsing from inside the databaseGAP — in-database file I/O leaves no process event
T1074.001Artifacts staged in the Oracle install directoryQ4Partial — caught via command line, not a file-write event
T1560KhuntUnzip archive handling inside the databaseGAP — section 7 object enumeration only
Post-exfilStaged hives leaving the networkQ5 (single IP)Partial — needs proxy/DLP, not covered by this pack

Read the gaps honestly. Five of fourteen rows are gaps and every one of them sits inside the database engine. That is the defining property of this threat, not a shortcoming of the queries: Falcon has no visibility into Oracle schema objects, so the CQL in section 8 covers the OS-facing half of the intrusion well and the in-database half not at all. A team that deploys only the queries will detect this actor at the moment they run whoami — which is real value, and is exactly how the original incident was found — but will never see the toolkit, will not know it persists after cleanup, and will not detect a quieter operator who stays inside the database. Closing those rows requires the Oracle-side controls: unified auditing (playbook 2), the data-dictionary hunts in section 7, and eventually Database Activity Monitoring. Detection validation for all of this is in section 11; the single most important test there is gate 3's benign CREATE JAVA SOURCE, because it is the only one that proves the gap rows are covered by something.

16

Hunt Summary Ticket

Copy into your case management system
TITLE:      khunt -- Oracle in-database Java post-exploitation toolkit via SQL injection
SEVERITY:   Critical (confirmed in the wild; RCE as NT AUTHORITY\SYSTEM, credential theft)
SCOPE:      All Windows hosts running Oracle Database; all internet-facing Java/Tomcat
            applications with an Oracle backend; the database accounts those apps use.

HYPOTHESIS: An actor reached the Oracle database through unvalidated input on a public
            web endpoint, used CREATE JAVA SOURCE to compile a post-exploitation toolkit
            into the schema, and executed OS commands as SYSTEM without writing an
            executable to disk. Endpoint telemetry sees only the child processes; the
            toolkit itself is a database object and is invisible to EDR.

QUERIES:    Q1 Oracle service spawns a command interpreter          CONF high / FP low
            Q2 SAM|SECURITY|SYSTEM hive export (reg, esentutl)      CONF high / FP med
            Q3 Second-generation descendants of Oracle binaries     CONF high / FP low
            Q4 khunt-named artifacts and objects on command lines   CONF high / FP low
            Q5 Traffic involving the reported injection source IP   CONF med  / FP low
            Q6 Java/Tomcat web tier spawning a shell                CONF med  / FP med
            Q7 Discovery burst under a database-parented shell      CONF med  / FP med
            Q8 Baseline stack-count of Oracle child processes       CONF med  / FP high

DO FIRST:   1. Run Q1 estate-wide. It is the highest-value single query in this pack.
            2. Run the section 7A data-dictionary query on EVERY Oracle instance --
               object_name LIKE 'KHUNT%' and non-Oracle-owned JAVA% objects.
            3. Audit the application database account for CREATE PROCEDURE / JAVA
               privileges and for EXECUTE ON DBMS_JAVA granted to PUBLIC.
            4. Confirm which identity the Oracle Windows services run as.

FINDINGS:   [ ] Q1 hits: ____   [ ] Q2 hits: ____   [ ] Q3 hits: ____   [ ] Q4 hits: ____
            [ ] KHUNT% objects found in any instance: yes / no
            [ ] Non-Oracle-owned JAVA objects found: yes / no
            [ ] Oracle services running as LocalSystem: yes / no
            [ ] Application account holds Java/procedure privileges: yes / no

GAPS:       No EDR coverage for CREATE JAVA SOURCE, the khunt_* PL/SQL wrappers,
            KhuntHash credential theft from SYS.USER$, KhuntFS file browsing, or
            KhuntUnzip. All five require Oracle unified auditing (playbook 2) or the
            data-dictionary hunts in section 7. No file hashes exist for this toolkit.
            No source describes the SQL payload or any post-hive-dump lateral movement.

ACTIONS:    [ ] Deploy IOA-1 in Monitor mode                        Owner: ______  Due: ______
            [ ] Deploy IOA-2 in Monitor mode                        Owner: ______  Due: ______
            [ ] Playbook 1 -- de-privilege the app DB account       Owner: ______  Due: ______
            [ ] Playbook 2 -- unified audit on Java source creation Owner: ______  Due: ______
            [ ] Playbook 3 -- Oracle services off LocalSystem       Owner: ______  Due: ______
            [ ] Playbook 4 -- RunAsPPL + hive SACLs                 Owner: ______  Due: ______
            [ ] Parameterise the typeahead/autocomplete endpoints   Owner: ______  Due: ______
            [ ] Import IOC CSV (section 10), expiry 2026-11-06 / 2027-02-06

OWNER:      ______________________
VERSION:    v0.1 -- 2026-08-06 -- HuntPack
17

Changelog

v0.12026-08-06Initial pack. Built from the Huntress incident report of 2026-08-05 plus two corroborating outlets. Eight CQL hunt queries, two Custom IOA recommendations, Oracle-side data-dictionary and unified-audit hunts, four deployable playbooks with rollback, and an eight-phase containment runbook. Six atomic indicators shipped (one IPv4, five staged filenames); no hashes shipped because none are published and the toolkit has no on-disk form.
nextpendingRevisit when a second sighting is published. Priorities: a file-write detection for the staged artifacts if a suitable Falcon event proves reliable, Oracle audit parsing rules for the SIEM, and expiry review of the source IP on 2026-11-06.
18

References

TierSourceUsed forAccess date
Tier 1Huntress — Toolkit Installation via SQL Injection Shows the Classics Still HitPrimary incident research: toolkit components, delivery via CREATE JAVA SOURCE, staged artifact filenames, source address, process lineage, vendor IOC table and mitigations2026-08-06
Tier 2BleepingComputer — Hackers run khunt post-exploitation toolkit from Oracle databaseCorroboration; autocomplete search endpoint as the injection point; unconfirmed exfiltration caveat2026-08-06
Tier 2eSecurity Planet — Oracle SQL Injection Attack Enables Remote Code ExecutionCorroboration; least-privilege and Oracle-monitoring framing for the hardening section2026-08-06
FrameworkMITRE ATT&CK T1505.001 — Server Software Component: SQL Stored ProceduresPersistence mapping for the in-database toolkit and its PL/SQL wrappers2026-08-06
FrameworkMITRE ATT&CK T1190 — Exploit Public-Facing ApplicationInitial access mapping2026-08-06
FrameworkMITRE ATT&CK T1003.002 — OS Credential Dumping: Security Account ManagerCredential access mapping for the hive copies2026-08-06
MitigationMITRE M1026 — Privileged Account ManagementDatabase account de-privileging and service-account hardening2026-08-06
MitigationMITRE M1042 — Disable or Remove Feature or ProgramStrategic removal of the Oracle JVM where unused2026-08-06
BenchmarkCIS Oracle Database BenchmarkPrivilege restriction, PUBLIC grant removal, unified auditing baseline2026-08-06
VendorMicrosoft — Configuring Additional LSA Protection (RunAsPPL)Playbook 4 prerequisites, enablement and rollback2026-08-06