|
| 1 | +# boundarycheck |
| 2 | + |
| 3 | +A live cross-DBMS validator for `data/xml/boundaries.xml`. For every reachable DBMS it builds the |
| 4 | +**real** injected value for each boundary (through sqlmap's own `agent.prefixQuery` / `suffixQuery` / |
| 5 | +`cleanupPayload`, not a re-implementation) across representative host-query contexts, runs it against |
| 6 | +the engine, and classifies each boundary via three oracles: |
| 7 | + |
| 8 | +``` |
| 9 | +W boolean TRUE/FALSE variants are valid AND their row counts differ |
| 10 | +T time an inline conditional sleep delays on TRUE, not on FALSE (MySQL / PostgreSQL) |
| 11 | +I inband an injected marker surfaces in the result set (table cross-join / UNION) |
| 12 | +. inert valid SQL but no channel discriminated in the contexts tried |
| 13 | +x invalid a syntax / semantic error on this engine |
| 14 | +``` |
| 15 | + |
| 16 | +It prints a `boundary x engine` matrix plus the boundaries usable via **no** oracle on any engine |
| 17 | +(the "no working context found" review candidates). Any engine that does not connect is **skipped** |
| 18 | +and reported as such — never silently counted as covered. |
| 19 | + |
| 20 | +> Scope: covers boolean + inline-time (MySQL/PG) + inband over a sampled set of contexts. It does |
| 21 | +> **not** model an error-based oracle, inline time on MSSQL/Oracle (statement/privilege-gated sleep), |
| 22 | +> or every possible host context. So a boundary flagged "usable via no oracle" may still work via one |
| 23 | +> of those — confirm before acting. |
| 24 | +
|
| 25 | +--- |
| 26 | + |
| 27 | +## Quick start (throwaway MySQL + PostgreSQL) |
| 28 | + |
| 29 | +```bash |
| 30 | +pip install pymysql psycopg2-binary # python drivers (see below for MSSQL/Oracle) |
| 31 | +./run.sh # spins up 2 containers, runs, tears everything down |
| 32 | +``` |
| 33 | + |
| 34 | +`run.sh` is fully disposable: it creates two containers, waits for readiness, runs the tool, and |
| 35 | +removes them again on exit (including Ctrl-C / failure). Nothing persists. |
| 36 | + |
| 37 | +--- |
| 38 | + |
| 39 | +## Full lab (all four engines) — step by step |
| 40 | + |
| 41 | +The tool's built-in default endpoints (override any via env var — see below): |
| 42 | + |
| 43 | +| engine | host:port | user / pass | db / service | |
| 44 | +|------------|-------------------|----------------------|--------------| |
| 45 | +| MySQL | `127.0.0.1:13306` | `root` / `root` | — | |
| 46 | +| PostgreSQL | `127.0.0.1:15432` | `esp` / `pass` | `espdb` | |
| 47 | +| MSSQL | `127.0.0.1:11433` | `sa` / `Esp_pass123` | — | |
| 48 | +| Oracle | `127.0.0.1:1521` | `system` / `oracle` | `FREEPDB1` | |
| 49 | + |
| 50 | +### 1. Python drivers |
| 51 | + |
| 52 | +```bash |
| 53 | +pip install pymysql psycopg2-binary pymssql oracledb |
| 54 | +``` |
| 55 | + |
| 56 | +(Install only the ones you need — a missing driver just skips that engine.) |
| 57 | + |
| 58 | +### 2. Start the containers |
| 59 | + |
| 60 | +```bash |
| 61 | +# MySQL (fast) |
| 62 | +docker run -d --rm --name bcheck-mysql -e MYSQL_ROOT_PASSWORD=root -p 13306:3306 mysql:8.4 |
| 63 | + |
| 64 | +# PostgreSQL (fast) |
| 65 | +docker run -d --rm --name bcheck-pg -e POSTGRES_USER=esp -e POSTGRES_PASSWORD=pass -e POSTGRES_DB=espdb -p 15432:5432 postgres:16 |
| 66 | + |
| 67 | +# MSSQL (slower; ~30-60s to accept connections) |
| 68 | +docker run -d --rm --name bcheck-mssql -e ACCEPT_EULA=Y -e MSSQL_SA_PASSWORD=Esp_pass123 -p 11433:1433 mcr.microsoft.com/mssql/server:2022-latest |
| 69 | + |
| 70 | +# Oracle Free (slowest; first boot can take a few minutes and the image is large) |
| 71 | +docker run -d --rm --name bcheck-oracle -e ORACLE_PASSWORD=oracle -p 1521:1521 gvenzl/oracle-free:slim |
| 72 | +``` |
| 73 | + |
| 74 | +Give MSSQL/Oracle time to finish initialising before running the tool (watch `docker logs -f <name>`). |
| 75 | + |
| 76 | +### 3. Run |
| 77 | + |
| 78 | +```bash |
| 79 | +python3 boundarycheck.py # from anywhere; it locates the sqlmap root itself |
| 80 | +``` |
| 81 | + |
| 82 | +### 4. Override an endpoint (optional) |
| 83 | + |
| 84 | +``` |
| 85 | +BC_MYSQL=host:port:user:pass |
| 86 | +BC_POSTGRES=host:port:user:pass:db |
| 87 | +BC_MSSQL=host:port:user:pass |
| 88 | +BC_ORACLE=host:port:user:pass:service # service_name goes in the db slot |
| 89 | +``` |
| 90 | + |
| 91 | +```bash |
| 92 | +BC_MYSQL=10.0.0.5:3306:root:secret python3 boundarycheck.py |
| 93 | +``` |
| 94 | + |
| 95 | +### 5. Tear down |
| 96 | + |
| 97 | +```bash |
| 98 | +docker rm -f bcheck-mysql bcheck-pg bcheck-mssql bcheck-oracle |
| 99 | +``` |
| 100 | + |
| 101 | +--- |
| 102 | + |
| 103 | +## Notes |
| 104 | + |
| 105 | +- **Faithfulness:** the tool imports the `plugins.dbms.*` packages so each DBMS's `unescaper` is |
| 106 | + registered. Without that, `SELECT '[RANDSTR]'` renders as a bare identifier instead of the real |
| 107 | + `0x`-hex / `CHR()` literal and concat-style boundaries are mis-reported. A `_faithful_or_die()` |
| 108 | + self-check aborts if the registration ever fails to load. |
| 109 | +- **Side-effect-free on the target data:** it creates a scratch table `bc` (and a `boundarycheck` |
| 110 | + database on MySQL), and drops them on completion. DML boundaries write only to a spare `note` column. |
| 111 | +- Engines are used purely as SQL oracles over localhost throwaway containers — do not point the |
| 112 | + override env vars at anything you care about. |
0 commit comments