diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1aff237 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +target/ +.git/ +.idea/ +*.iml +mise.toml diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..2768901 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @waratek/w4j diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..21ee040 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,51 @@ +# Stage 1: build the WAR using Java 8 + Maven +FROM maven:3.9-eclipse-temurin-8 AS build + +WORKDIR /build +COPY pom.xml . +COPY src ./src + +RUN mvn install -Dversion.jdk=1.5 -Dversion.webxml=30 -DskipTests -q + +# --------------------------------------------------------------------------- +# Stage 2: runtime — Tomcat 9 + JRE 8 +# --------------------------------------------------------------------------- +FROM tomcat:9-jre8-temurin AS runtime + +# Remove default webapps +RUN rm -rf "$CATALINA_HOME/webapps/ROOT" \ + "$CATALINA_HOME/webapps/docs" \ + "$CATALINA_HOME/webapps/examples" \ + "$CATALINA_HOME/webapps/host-manager" \ + "$CATALINA_HOME/webapps/manager" + +# Copy and pre-explode the WAR so the entrypoint can edit conf/ on disk +COPY --from=build /build/target/spiracle.war /tmp/spiracle.war +RUN apt-get update -qq && apt-get install -y --no-install-recommends unzip && rm -rf /var/lib/apt/lists/* \ + && mkdir -p "$CATALINA_HOME/webapps/spiracle" \ + && unzip -q /tmp/spiracle.war -d "$CATALINA_HOME/webapps/spiracle" \ + && rm /tmp/spiracle.war + +# ---- JDBC drivers (downloaded at image build time from Maven Central) ---- + +# MySQL Connector/J 5.1.49 — has com.mysql.jdbc.Driver (legacy classname) +RUN curl -fsSL \ + "https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.49/mysql-connector-java-5.1.49.jar" \ + -o "$CATALINA_HOME/lib/mysql-connector-java-5.1.49.jar" + +# MSSQL JDBC — jre8 classifier +RUN curl -fsSL \ + "https://repo1.maven.org/maven2/com/microsoft/sqlserver/mssql-jdbc/12.4.2.jre8/mssql-jdbc-12.4.2.jre8.jar" \ + -o "$CATALINA_HOME/lib/mssql-jdbc-12.4.2.jre8.jar" + +# Oracle ojdbc8 — Java 8 compatible +RUN curl -fsSL \ + "https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc8/21.13.0.0/ojdbc8-21.13.0.0.jar" \ + -o "$CATALINA_HOME/lib/ojdbc8-21.13.0.0.jar" + +# ---- entrypoint ---- +COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +EXPOSE 8080 +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/README.adoc b/README.adoc deleted file mode 100644 index 73ecd73..0000000 --- a/README.adoc +++ /dev/null @@ -1,170 +0,0 @@ -= Spiracle - -Spiracle is an insecure web application used to test system security controls. - -It can be used to read/write arbitrary files and open network connections. -The application is also vulnerable to numerous other vulnerabilities such as: - -* SQL Injection (CWE-89) -* XSS (CWE-79) -* CSRF (CWE-352) -* Path Traversal (CWE-22) -* Deserialization (CWE-502) -* and many more... - -CAUTION: Due to its insecure design, this application should NOT be deployed on an unsecured network or system. - -This application has been tested on the following application servers: - -* Apache Tomcat 7.x -* IBM WebSphere Liberty Core 8.5.5.3 - -Your mileage may vary with other application servers. - -== Installation - -* Download pre-built `spiracle.war` file from the releases page: https://github.com/waratek/spiracle/releases - -=== Tomcat - -* Copy the war file to the `$CATALINA_HOME/webapps/` directory. - -=== Liberty Core - -* Ensure that the application war file is extracted to your server's apps directory: -+ ----- -$ mkdir ./wlp/usr/servers/defaultServer/apps/spiracle -$ cd ./wlp/usr/servers/defaultServer/apps/spiracle -$ jar xvf /path/to/downloaded/spiracle.war ----- - -* Modify `server.xml` as follows: -+ -[source,xml] ----- - - - - - jsp-2.2 - Servlet-3.0 - - - - - - - httpPort="9080" - httpsPort="9443"/> - ----- -+ -<1> Enable `Servlet-3.0` as a feature -<2> Add a `webApplication` tag referencing Spiracle -<3> Change `httpSession` parameter length -<4> Add a `host` attribute - -=== Database setup - -If you would like to run the SQL injection tests, the database should be populated as follows. Data files are available in the web applications `spiracle/conf/` directory after the `spiracle.war` file has been deployed and exploded. - -==== Oracle - -. Ensure that the link:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html[Oracle Database JDBC Driver] (ojdbc6.jar) is installed in the applications `WEB-INF/lib/` directory after the `spiracle.war` file is exploded on first run. -. Import the data: -+ ----- -$ sqlplus SYS/password@//127.0.0.1:1521/XE AS SYSDBA < setupdb_oracle.sql ----- -+ -NOTE: This will create a user `test` with password `test`. You should adjust usernames and/or connection URLs dependent on your environment -+ -. Configuration parameters for the Oracle JDBC connection are defined in `conf/Spiracle.properties`: -+ ----- -c3p0.classname=oracle.jdbc.driver.OracleDriver -c3p0.url=jdbc:oracle:thin:@localhost:1521:XE -c3p0.username=test -c3p0.password=test ----- - -NOTE: It may be necessary to restart your application server after deploying the `ojdbc6.jar` or updating database configuration. - -==== MySQL -. Import the data: -+ ----- -$ mysql -u root -p test < setupdb_mysql.sql ----- -+ -NOTE: This will create a user `test` with password `test`. You should adjust usernames and/or connection URLs dependent on your environment -+ -. Configuration parameters for the MySQL JDBC connection are defined in `conf/Spiracle.properties`: -+ ----- -c3p0.classname=com.mysql.jdbc.Driver -c3p0.url=jdbc:jdbc:mysql://localhost:3306/test -c3p0.username=test -c3p0.password=test ----- - -== Running - -After deployment, the Spiracle application will be available at: - ----- -http://ip:port/spiracle/ ----- - -Properties file can be overridden when submitting the request by appending the new value to the URL: - ----- -&connectionType=c3p0.mysql ----- - -== Building - -Prerequisites: - -* Java >= 1.6 -* Apache Maven -* link:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html[Oracle Database JDBC Driver] (ojdbc6.jar) - -If you wish to use the database features, ensure that the Oracle database JDBC driver file `ojdbc6.jar` is available under `./src/main/webapp/WEB-INF/lib` - -To build the Spiracle Test Application WAR file, run: - - $ mvn install -Dversion.webxml=30 - -or - - $ mvn install -Dversion.webxml=25 - -To clean the build infrastructure, run: - - $ mvn clean - -The WAR file will be output to: - - ./target/spiracle.war - -== License - ----- -Copyright 2018 Waratek Ltd. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. ----- - diff --git a/README.md b/README.md new file mode 100644 index 0000000..65f8b4d --- /dev/null +++ b/README.md @@ -0,0 +1,251 @@ +# Spiracle + +Spiracle is an insecure web application used to test system security controls. + +It can be used to read/write arbitrary files and open network connections. +The application is also vulnerable to numerous other vulnerabilities such as: + +- SQL Injection (CWE-89) +- XSS (CWE-79) +- CSRF (CWE-352) +- Path Traversal (CWE-22) +- Deserialization (CWE-502) +- and many more... + +> **⚠️ Caution:** Due to its insecure design, this application should NOT be deployed on an unsecured network or system. Run on localhost or throwaway networks only. + +This application has been tested on the following application servers: + +- Apache Tomcat 7.x +- IBM WebSphere Liberty Core 8.5.5.3 + +Your mileage may vary with other application servers. + +## Docker (quickstart) + +The fastest way to run Spiracle. No local Tomcat or database install needed. + +Pick a database and run its compose file from the repo root: + +```sh +# MySQL (smallest image — recommended for first run) +$ docker compose -f docker-compose.mysql.yml up --build + +# Microsoft SQL Server (~1.5 GB image) +$ docker compose -f docker-compose.mssql.yml up --build + +# Oracle XE (~2–4 GB image; first pull takes several minutes) +$ docker compose -f docker-compose.oracle.yml up --build +``` + +Once healthy, browse to: http://localhost:8080/spiracle/ + +Tear down (removes volumes): + +```sh +$ docker compose -f docker-compose.mysql.yml down -v +``` + +The multi-stage `Dockerfile` builds the WAR with JDK 8 / Maven (`-Dversion.jdk=1.5 -Dversion.webxml=30`) and deploys it on Tomcat 9. `docker/entrypoint.sh` rewrites `conf/Spiracle.properties` from environment variables at startup. + +> **Note — JDBC drivers:** This branch does not bundle any JDBC driver in the WAR. The Docker image places the drivers in Tomcat's `lib/`: MySQL Connector/J 5.1.49 (legacy `com.mysql.jdbc.Driver` classname), MSSQL `mssql-jdbc` 12.4.2.jre8, and Oracle `ojdbc8` 21.13. The MySQL stack runs `mysql:8.0` (`--default-authentication-plugin=mysql_native_password`, which Connector/J 5.1.49 can negotiate). + +Full Docker reference: [docker/README.md](docker/README.md) + +## Installation + +- Download pre-built `spiracle.war` file from the releases page: https://github.com/waratek/spiracle/releases + +### Tomcat + +- Copy the war file to the `$CATALINA_HOME/webapps/` directory. + +### Liberty Core + +- Ensure that the application war file is extracted to your server's apps directory: + + ```sh + $ mkdir ./wlp/usr/servers/defaultServer/apps/spiracle + $ cd ./wlp/usr/servers/defaultServer/apps/spiracle + $ jar xvf /path/to/downloaded/spiracle.war + ``` + +- Modify `server.xml` as follows: + + ```xml + + + + + jsp-2.2 + Servlet-3.0 + + + + + + + httpPort="9080" + httpsPort="9443"/> + + ``` + +### Database setup + +If you would like to run the SQL injection tests, the database should be populated as follows. Data files are available in the web applications `spiracle/conf/` directory after the `spiracle.war` file has been deployed and exploded. + +> **Note:** When using Docker, database initialisation is handled automatically by the compose stack. Manual setup is only needed for bare-metal deployments. + +#### Oracle + +1. Ensure that the [Oracle Database JDBC Driver](http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html) (ojdbc6.jar) is installed in the applications `WEB-INF/lib/` directory after the `spiracle.war` file is exploded on first run. +2. Import the data: + + ```sh + $ sqlplus SYS/password@//127.0.0.1:1521/XE AS SYSDBA < setupdb_oracle.sql + ``` + + > **Note:** This will create a user `test` with password `test`. You should adjust usernames and/or connection URLs dependent on your environment + +3. Configuration parameters for the Oracle JDBC connection are defined in `conf/Spiracle.properties`: + + ``` + c3p0.classname=oracle.jdbc.driver.OracleDriver + c3p0.url=jdbc:oracle:thin:@localhost:1521:XE + c3p0.username=test + c3p0.password=test + ``` + +> **Note:** It may be necessary to restart your application server after deploying the `ojdbc6.jar` or updating database configuration. + +#### MySQL + +1. Import the data: + + ```sh + $ mysql -u root -p test < setupdb_mysql.sql + ``` + + > **Note:** This will create a user `test` with password `test`. You should adjust usernames and/or connection URLs dependent on your environment + +2. Configuration parameters for the MySQL JDBC connection are defined in `conf/Spiracle.properties`: + + ``` + c3p0.classname=com.mysql.jdbc.Driver + c3p0.url=jdbc:jdbc:mysql://localhost:3306/test + c3p0.username=test + c3p0.password=test + ``` + +## Running + +After deployment, the Spiracle application will be available at: + +``` +http://ip:port/spiracle/ +``` + +Properties file can be overridden when submitting the request by appending the new value to the URL: + +``` +&connectionType=c3p0.mysql +``` + +## Testing + +Spiracle ships with a [Hurl](tests/hurl/README.md) test harness under `tests/hurl/`. Tests are endpoint-based and run against any deployment (Docker or bare-metal). + +### Suites + +| Suite | What it covers | +|---|---| +| `smoke/` | App root responds 200; benign query returns data; SQLi widens result set | +| `functional/` | SendRedirect, SQL queries, reflected XSS via `customTag.jsp`, path traversal, 404/empty-result/no-param negative cases | + +### Quick run (plain Docker stack) + +```sh +# Bring up MySQL stack +$ docker compose -f docker-compose.mysql.yml up -d + +# Smoke +$ ./tests/hurl/run.sh smoke localhost 8080 + +# Functional +$ ./tests/hurl/run.sh functional localhost 8080 +``` + +Full harness reference: [tests/hurl/README.md](tests/hurl/README.md) + +## Building + +Prerequisites: + +- Java 8 toolchain (compiles `-source 1.5 -target 1.5`; this branch targets Java 5 source level) +- Apache Maven +- [Oracle Database JDBC Driver](http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html) (ojdbc6.jar) + +If you wish to use the database features, ensure that the Oracle database JDBC driver file `ojdbc6.jar` is available under `./src/main/webapp/WEB-INF/lib` + +### Build flags + +Two flags parameterise the build: + +- **`-Dversion.jdk=`** — Sets the Java source and target compiler level. On this branch the only supported value is `1.5`. +- **`-Dversion.webxml=<25|30>`** — Selects the Servlet descriptor version. `30` (Servlet 3.0) registers servlets from the `@WebServlet` annotations; `25` (Servlet 2.5) registers them explicitly from `web-25.xml`. + +> **Note:** `version.jdk` has no default; `mvn install` without `-Dversion.jdk` fails because the literal `${version.jdk}` is passed to the compiler. Always pass the flag. + +Representative invocation: + +```sh +# Java 5, Servlet 3.0 (recommended) +$ mvn install -Dversion.jdk=1.5 -Dversion.webxml=30 +``` + +To clean the build infrastructure, run: + +```sh +$ mvn clean +``` + +The WAR file will be output to: + +``` +./target/spiracle.war +``` + +### Toolchain + +This branch builds under a Java 8 toolchain with `-source 1.5 -target 1.5`. The Docker image pins its own JDK via its base image (`maven:3.9-eclipse-temurin-8`) — no local JDK is needed when building through Docker. + +### Branch model + +- **`java5` (this branch)** — Java 5 source-compatible variant. Same source tree as `master`, but the build targets the Java 5 source level only (`-Dversion.jdk=1.5`). Switch to `master` if you need a higher source level. +- **`master`** — Modern, parameterised source tree. Java 5–8 source level. Use `-Dversion.jdk` to select. +- **`java4`** — Java-1.4-source-compatible variant. Annotations replaced by `web.xml` registration; uses a legacy dependency set. Check out this branch if you need Java 4 compatibility. + +## Recent fixes + +- **#8** — `Content-Type: text/plain` is now set on the `SendRedirect` fallback response (no-parameter case). +- **#33** — `setupdb_mysql.sql` is idempotent; uses `IF [NOT] EXISTS` guards so re-running does not error. +- **#103** — Oracle connection NPE fixed in `CreateC3p0Connection`; was reading non-existent property keys from `Spiracle.properties`. + +## License + +``` +Copyright 2018 Waratek Ltd. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/docker-compose.mssql.yml b/docker-compose.mssql.yml new file mode 100644 index 0000000..a59bd62 --- /dev/null +++ b/docker-compose.mssql.yml @@ -0,0 +1,52 @@ +services: + db: + image: mcr.microsoft.com/mssql/server:2022-latest + environment: + ACCEPT_EULA: "Y" + SA_PASSWORD: "Spiracle_SA_2024!" + MSSQL_PID: Developer + healthcheck: + test: + - "CMD-SHELL" + - | + /opt/mssql-tools18/bin/sqlcmd -S localhost -U SA -P 'Spiracle_SA_2024!' \ + -No -Q 'SELECT 1' > /dev/null 2>&1 + interval: 10s + timeout: 5s + retries: 15 + start_period: 30s + + db-init: + image: mcr.microsoft.com/mssql/server:2022-latest + environment: + SA_PASSWORD: "Spiracle_SA_2024!" + volumes: + - ./src/main/webapp/conf/setupdb_mssql.sql:/init/setupdb_mssql.sql:ro + - ./docker/mssql-create-login.sql:/init/mssql-create-login.sql:ro + depends_on: + db: + condition: service_healthy + entrypoint: + - /bin/bash + - -c + - | + /opt/mssql-tools18/bin/sqlcmd -S db -U SA -P "$$SA_PASSWORD" -No \ + -i /init/setupdb_mssql.sql && \ + /opt/mssql-tools18/bin/sqlcmd -S db -U SA -P "$$SA_PASSWORD" -No \ + -d spiracle -i /init/mssql-create-login.sql + restart: "no" + + app: + build: + context: . + dockerfile: Dockerfile + ports: + - "8080:8080" + environment: + SPIRACLE_DEFAULT_CONNECTION: c3p0.mssql + SPIRACLE_DB_HOST: db + depends_on: + db: + condition: service_healthy + db-init: + condition: service_completed_successfully diff --git a/docker-compose.mysql.yml b/docker-compose.mysql.yml new file mode 100644 index 0000000..e3b259a --- /dev/null +++ b/docker-compose.mysql.yml @@ -0,0 +1,33 @@ +services: + db: + image: mysql:8.0 + command: --default-authentication-plugin=mysql_native_password + environment: + MYSQL_ROOT_PASSWORD: rootpassword + MYSQL_DATABASE: test + MYSQL_USER: test + MYSQL_PASSWORD: test + volumes: + # Seed SQL mounted outside initdb.d so the shell script controls execution + - ./src/main/webapp/conf/setupdb_mysql.sql:/init/setupdb_mysql.sql:ro + # Shell script in initdb.d runs seed with --force (bare DROPs on fresh DB) + - ./docker/mysql-seed.sh:/docker-entrypoint-initdb.d/01-seed.sh:ro + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "--password=rootpassword"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + + app: + build: + context: . + dockerfile: Dockerfile + ports: + - "8080:8080" + environment: + SPIRACLE_DEFAULT_CONNECTION: c3p0.mysql + SPIRACLE_DB_HOST: db + depends_on: + db: + condition: service_healthy diff --git a/docker-compose.oracle.yml b/docker-compose.oracle.yml new file mode 100644 index 0000000..a845e43 --- /dev/null +++ b/docker-compose.oracle.yml @@ -0,0 +1,29 @@ +services: + db: + image: gvenzl/oracle-xe:21-slim + environment: + ORACLE_PASSWORD: oraclepassword + APP_USER: test + APP_USER_PASSWORD: test + volumes: + - ./src/main/webapp/conf/setupdb_oracle.sql:/container-entrypoint-initdb.d/setupdb_oracle.sql:ro + healthcheck: + test: ["CMD", "healthcheck.sh"] + interval: 30s + timeout: 10s + retries: 20 + start_period: 120s + + app: + build: + context: . + dockerfile: Dockerfile + ports: + - "8080:8080" + environment: + SPIRACLE_DEFAULT_CONNECTION: c3p0.oracle + # gvenzl runs initdb scripts in the PDB (XEPDB1); use service-name URL form + SPIRACLE_DB_URL: "jdbc:oracle:thin:@//db:1521/XEPDB1" + depends_on: + db: + condition: service_healthy diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..344c9d2 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,67 @@ +# Spiracle — Docker usage + +**WARNING: Spiracle is an intentionally-vulnerable application. Run on localhost / throwaway networks only. Never expose to the internet.** + +## Prerequisites + +- Docker Engine 24+ with the Compose v2 plugin (`docker compose`) +- No local Tomcat or database installation needed + +## Quick start + +Pick one database and run the corresponding compose file from the repo root. + +### MySQL (recommended for first run — smallest image) + +```sh +docker compose -f docker-compose.mysql.yml up --build +``` + +Browse to: http://localhost:8080/spiracle/ + +Tear down (removes volumes): +```sh +docker compose -f docker-compose.mysql.yml down -v +``` + +### Microsoft SQL Server + +```sh +docker compose -f docker-compose.mssql.yml up --build +``` + +SQL Server image (~1.5 GB). A one-shot `db-init` service seeds the database after SQL Server becomes healthy. + +Browse to: http://localhost:8080/spiracle/ + +```sh +docker compose -f docker-compose.mssql.yml down -v +``` + +### Oracle XE + +```sh +docker compose -f docker-compose.oracle.yml up --build +``` + +Oracle XE image (~2–4 GB). First pull takes several minutes. The container has a long startup; wait for the `db` service to show `healthy` before the app becomes ready. + +Browse to: http://localhost:8080/spiracle/ + +```sh +docker compose -f docker-compose.oracle.yml down -v +``` + +## How it works + +- A multi-stage Dockerfile builds the WAR with JDK 8 / Maven (`-Dversion.jdk=1.5 -Dversion.webxml=30`), then deploys it on Tomcat 9. +- No JDBC driver is bundled in the WAR; the drivers live in Tomcat's `lib/`: MySQL Connector/J 5.1.49, MSSQL mssql-jdbc 12.4.2.jre8, and Oracle ojdbc8 21.13. The MySQL stack runs `mysql:8.0` with `--default-authentication-plugin=mysql_native_password`, which Connector/J 5.1.49 can negotiate. +- `docker/entrypoint.sh` rewrites `conf/Spiracle.properties` from environment variables before Tomcat starts. The committed `Spiracle.properties` is never modified. + +## Environment variables (app service) + +| Variable | Purpose | Example | +|---|---|---| +| `SPIRACLE_DEFAULT_CONNECTION` | Sets `default.connection` in properties | `c3p0.mysql` | +| `SPIRACLE_DB_HOST` | Replaces `localhost` in the chosen db URL | `db` | +| `SPIRACLE_DB_URL` | Overrides the entire URL line (Oracle service-name form) | `jdbc:oracle:thin:@//db:1521/XEPDB1` | diff --git a/docker/docker-grants-mysql.sql b/docker/docker-grants-mysql.sql new file mode 100644 index 0000000..4aef196 --- /dev/null +++ b/docker/docker-grants-mysql.sql @@ -0,0 +1,6 @@ +-- Docker-only: grant remote access for the 'test' user created by setupdb_mysql.sql. +-- setupdb_mysql.sql creates 'test'@'localhost'; that cannot connect from the app container. +-- This file runs AFTER setupdb_mysql.sql (lexicographic order ensures 0-prefix runs first). +CREATE USER IF NOT EXISTS 'test'@'%' IDENTIFIED BY 'test'; +GRANT ALL PRIVILEGES ON *.* TO 'test'@'%' WITH GRANT OPTION; +FLUSH PRIVILEGES; diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 0000000..e52039c --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# Rewrite Spiracle.properties from env vars before Tomcat starts. +# All changes are made to the exploded webapp copy only — source files untouched. + +PROPS="$CATALINA_HOME/webapps/spiracle/conf/Spiracle.properties" + +# SPIRACLE_DEFAULT_CONNECTION — e.g. "c3p0.mysql" +if [ -n "$SPIRACLE_DEFAULT_CONNECTION" ]; then + sed -i "s|^default\.connection=.*|default.connection=${SPIRACLE_DEFAULT_CONNECTION}|" "$PROPS" +fi + +# Derive the db key from the connection name (e.g. c3p0.mysql → mysql) +if [ -n "$SPIRACLE_DEFAULT_CONNECTION" ]; then + DB_KEY="${SPIRACLE_DEFAULT_CONNECTION#c3p0.}" +else + DB_KEY="" +fi + +# SPIRACLE_DB_URL — override the whole url line for this db (takes priority) +if [ -n "$SPIRACLE_DB_URL" ] && [ -n "$DB_KEY" ]; then + sed -i "s|^c3p0\.${DB_KEY}\.url=.*|c3p0.${DB_KEY}.url=${SPIRACLE_DB_URL}|" "$PROPS" +elif [ -n "$SPIRACLE_DB_HOST" ] && [ -n "$DB_KEY" ]; then + # Replace only 'localhost' in the specific db url line + sed -i "/^c3p0\.${DB_KEY}\.url=/ s|localhost|${SPIRACLE_DB_HOST}|g" "$PROPS" +fi + +exec "$CATALINA_HOME/bin/catalina.sh" run diff --git a/docker/mssql-create-login.sql b/docker/mssql-create-login.sql new file mode 100644 index 0000000..5c70204 --- /dev/null +++ b/docker/mssql-create-login.sql @@ -0,0 +1,17 @@ +-- Docker-only: create the 'test' login and user that Spiracle.properties expects. +-- setupdb_mssql.sql does not create this login; run this first. +IF NOT EXISTS (SELECT 1 FROM sys.server_principals WHERE name = 'test') +BEGIN + CREATE LOGIN [test] WITH PASSWORD = 'Mssql1234', CHECK_POLICY = OFF; +END +GO + +USE spiracle; +GO + +IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE name = 'test') +BEGIN + CREATE USER [test] FOR LOGIN [test]; + ALTER ROLE db_owner ADD MEMBER [test]; +END +GO diff --git a/docker/mysql-seed.sh b/docker/mysql-seed.sh new file mode 100644 index 0000000..d67bd10 --- /dev/null +++ b/docker/mysql-seed.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Docker-only init script for MySQL. +# Loads the canonical schema/seed (idempotent: IF [NOT] EXISTS), then grants +# remote access for the app container. +set -e + +mysql -u root -p"${MYSQL_ROOT_PASSWORD}" < /init/setupdb_mysql.sql + +# Grant remote access for 'test'@'%' so the app container (different host) +# can connect. The canonical seed only creates 'test'@'localhost'. +mysql -u root -p"${MYSQL_ROOT_PASSWORD}" <<'SQL' +CREATE USER IF NOT EXISTS 'test'@'%' IDENTIFIED WITH mysql_native_password BY 'test'; +GRANT ALL PRIVILEGES ON *.* TO 'test'@'%' WITH GRANT OPTION; +FLUSH PRIVILEGES; +SQL diff --git a/src/main/java/com/waratek/spiracle/misc/SendRedirect.java b/src/main/java/com/waratek/spiracle/misc/SendRedirect.java index 2dce521..00d9d17 100644 --- a/src/main/java/com/waratek/spiracle/misc/SendRedirect.java +++ b/src/main/java/com/waratek/spiracle/misc/SendRedirect.java @@ -36,6 +36,7 @@ protected void executeRequest(HttpServletRequest request, HttpServletResponse re response.sendRedirect(redirectURI); } else { + response.setHeader("Content-Type", "text/plain;charset=UTF-8"); response.getWriter().println("Parameter '" + inputUriParam + "' not set in the URI."); response.getWriter().println("Please update URI to include '?" + inputUriParam + "=URI_TO_REDIRECT_TO'"); } diff --git a/src/main/java/com/waratek/spiracle/sql/c3p0/CreateC3p0Connection.java b/src/main/java/com/waratek/spiracle/sql/c3p0/CreateC3p0Connection.java index f8439b8..11bfe56 100644 --- a/src/main/java/com/waratek/spiracle/sql/c3p0/CreateC3p0Connection.java +++ b/src/main/java/com/waratek/spiracle/sql/c3p0/CreateC3p0Connection.java @@ -65,12 +65,16 @@ public void init() { // TODO Auto-generated catch block e.printStackTrace(); } - jdbcDriver = prop.getProperty("c3p0.classname"); - url = prop.getProperty("c3p0.url"); - username = prop.getProperty("c3p0.username"); - password = prop.getProperty("c3p0.password"); + String prefix = prop.getProperty("default.connection"); + if (prefix == null || prefix.trim().isEmpty()) { + prefix = "c3p0.oracle"; + } + jdbcDriver = prop.getProperty(prefix + ".classname"); + url = prop.getProperty(prefix + ".url"); + username = prop.getProperty(prefix + ".username"); + password = prop.getProperty(prefix + ".password"); try { - maxPoolSize = Integer.parseInt(prop.getProperty("c3p0.maxPoolSize")); + maxPoolSize = Integer.parseInt(prop.getProperty(prefix + ".maxPoolSize")); } catch (NumberFormatException e) { maxPoolSize = 25; } diff --git a/src/main/webapp/conf/setupdb_mysql.sql b/src/main/webapp/conf/setupdb_mysql.sql index e97603a..ba771b8 100644 --- a/src/main/webapp/conf/setupdb_mysql.sql +++ b/src/main/webapp/conf/setupdb_mysql.sql @@ -1,13 +1,13 @@ -CREATE USER 'test'@'localhost' IDENTIFIED BY 'test'; +CREATE USER IF NOT EXISTS 'test'@'localhost' IDENTIFIED BY 'test'; GRANT ALL PRIVILEGES ON *.* TO 'test'@'localhost' WITH GRANT OPTION; CREATE DATABASE IF NOT EXISTS test; use test; -DROP TABLE users; -DROP TABLE address; -DROP TABLE TEXT_STORE; +DROP TABLE IF EXISTS users; +DROP TABLE IF EXISTS address; +DROP TABLE IF EXISTS TEXT_STORE; CREATE TABLE users ( id int, diff --git a/tests/hurl/README.md b/tests/hurl/README.md new file mode 100644 index 0000000..037d2ec --- /dev/null +++ b/tests/hurl/README.md @@ -0,0 +1,81 @@ +# Spiracle Hurl Test Harness + +Language-agnostic HTTP tests using [Hurl](https://hurl.dev) (v5+). +Replaces the old `tests/spiracle_sqli_test.py` (Python 2, bespoke `` format). + +--- + +## Suite layout + +`tests/hurl/` holds two suites: + +- `smoke/` and `functional/` — endpoint behaviour on a plain deployment. + +--- + +## Running the functional suite (plain Docker / CI) + +The functional suite validates endpoint behaviour end-to-end: + +| File | Requests | What it covers | +|------------------|----------|----------------| +| `redirect.hurl` | 2 | SendRedirect: no-param→200+text/plain (#8 regression); param→302+Location | +| `sql.hurl` | 5 | MySql_Get_int, MySql_Get_string, MySql_Get_Implicit_Join (benign + SQLi), MySql_Get_Union | +| `xss.hurl` | 2 | customTag.jsp benign name; `` reflected unescaped | +| `traversal.hurl` | 4 | FileInputStreamServlet01 benign TestFile; `../TestFile` traversal succeeds | +| `negative.hurl` | 3 | 404 on unknown path; empty result set; no-param graceful 200 | + +```sh +# Start the Docker MySQL stack +docker compose -f docker-compose.mysql.yml up -d + +# Run functional tests +./tests/hurl/run.sh functional localhost 8080 + +# Or with hurl directly +hurl --test --variables-file tests/hurl/functional/local.env \ + tests/hurl/functional/*.hurl +``` + +**XSS note:** The ReadHTML-based servlets (`XSSWebAppHSRPW` etc.) do NOT reflect +the `taintedtext` param because `xss.html` contains no literal `"XSS"` token. +`customTag.jsp` is the GET-accessible reflected-XSS endpoint used here. + +--- + +## Running the smoke suite (plain Docker / CI) + +The smoke suite validates: +1. App root responds `200` +2. `GET /spiracle/MySql_Get_string?name=Patrick` → `200`, body contains `Moss` +3. SQLi payload widens the result set (body contains `Thomas`) → `200` + +```sh +# Start the Docker MySQL stack +docker compose -f docker-compose.mysql.yml up -d + +# Run smoke tests +./tests/hurl/run.sh smoke localhost 8080 + +# Or with hurl directly +hurl --test --variables-file tests/hurl/smoke/local.env \ + tests/hurl/smoke/smoke.hurl +``` + +Reports are written as JUnit XML to `/tmp/spiracle-{smoke,functional}-report/junit.xml`. +Override with `REPORT_DIR=/path/to/dir ./tests/hurl/run.sh ...`. + +--- + +## Hurl assertion form used + +`HTTP {{var}}` in the status line is **not** valid in Hurl 5.x. +All files use the `[Asserts]` form: + +``` +HTTP * +[Asserts] +status == 200 +``` + +This was verified against Hurl 5.0.1 before committing. diff --git a/tests/hurl/functional/local.env b/tests/hurl/functional/local.env new file mode 100644 index 0000000..0182d07 --- /dev/null +++ b/tests/hurl/functional/local.env @@ -0,0 +1,2 @@ +host=localhost +port=8080 diff --git a/tests/hurl/functional/negative.hurl b/tests/hurl/functional/negative.hurl new file mode 100644 index 0000000..4fd3108 --- /dev/null +++ b/tests/hurl/functional/negative.hurl @@ -0,0 +1,29 @@ +# negative.hurl — boundary and error cases. +# +# These cases verify that the app responds deterministically to invalid +# or missing inputs, providing a stable baseline for regression. + +# ── 1. Non-existent servlet path → 404 ─────────────────────────────── +GET http://{{host}}:{{port}}/spiracle/NoSuchServletXYZ + +HTTP 404 + +# ── 2. MySql_Get_string with unknown name → 200, empty results ─────── +# No rows match name='NoSuchUser99'; the app still returns 200 with an +# empty result table (no error, no crash). +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=NoSuchUser99 + +HTTP 200 +[Asserts] +body contains "Results" +# App echoes param in SQL query preview but no rows should appear +body not contains "NoSuchUser99" + +# ── 3. MySql_Get_int with no param → 200, empty results ───────────── +# ParameterNullFix sanitises null to empty string; the SQL query +# WHERE id = '' returns zero rows — app handles gracefully. +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int + +HTTP 200 +[Asserts] +body contains "Results" diff --git a/tests/hurl/functional/redirect.hurl b/tests/hurl/functional/redirect.hurl new file mode 100644 index 0000000..57eede2 --- /dev/null +++ b/tests/hurl/functional/redirect.hurl @@ -0,0 +1,24 @@ +# redirect.hurl — regression tests for SendRedirect behaviour. +# +# Source: src/main/java/com/waratek/spiracle/misc/SendRedirect.java +# @WebServlet("/SendRedirect") +# +# Regression for #8: when redirectMeTo param is absent the servlet must +# respond 200 with Content-Type: text/plain and explain the missing param. +# If the fix is reverted the Content-Type header will be missing/wrong. + +# ── 1. No param → 200 plain text with usage hint ───────────────────── +GET http://{{host}}:{{port}}/spiracle/SendRedirect + +HTTP 200 +[Asserts] +header "Content-Type" contains "text/plain" +body contains "redirectMeTo" + +# ── 2. Valid param → 302 redirect to supplied URL ──────────────────── +# Hurl does NOT follow redirects by default; the 302 is directly observable. +GET http://{{host}}:{{port}}/spiracle/SendRedirect?redirectMeTo=https://example.com + +HTTP 302 +[Asserts] +header "Location" contains "example.com" diff --git a/tests/hurl/functional/sql.hurl b/tests/hurl/functional/sql.hurl new file mode 100644 index 0000000..4b519f0 --- /dev/null +++ b/tests/hurl/functional/sql.hurl @@ -0,0 +1,60 @@ +# sql.hurl — functional SQL tests against the unprotected MySQL stack. +# +# Sources: +# MySql_Get_int → @WebServlet("/MySql_Get_int") param: id +# MySql_Get_string → @WebServlet("/MySql_Get_string") param: name +# MySql_Get_Implicit_Join → @WebServlet("/MySql_Get_Implicit_Join") param: id +# MySql_Get_Union → @WebServlet("/MySql_Get_Union") param: id +# +# Seed data (setupdb_mysql.sql): +# id=1 → Patrick Moss +# id=2 → Margaret Thomas +# address id=1 → 2128 Vestibulum, St. / Dubuisson / San Marino + +# ── 1. MySql_Get_int benign: id=1 returns Patrick Moss ─────────────── +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1 + +HTTP 200 +[Asserts] +body contains "Patrick" +body contains "Moss" + +# ── 2. MySql_Get_string benign: name=Patrick returns surname Moss ──── +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=Patrick + +HTTP 200 +[Asserts] +body contains "Moss" + +# ── 3. MySql_Get_Implicit_Join benign: id=1 returns row + address ──── +# Query: SELECT * FROM users, address WHERE users.id = 1 AND users.id = address.id +# Proves the join works for a known row. +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=1 + +HTTP 200 +[Asserts] +body contains "Patrick" +body contains "Dubuisson" + +# ── 4. Unprotected SQL injection on MySql_Get_Implicit_Join ────────── +# Payload: id=1 OR 1=1 +# Query becomes: SELECT * FROM users, address WHERE users.id = 1 OR 1=1 AND users.id = address.id +# This executes and returns ALL users. +# id=1 only returns Patrick Moss; injection adds Margaret Thomas (id=2). +# Asserting both surnames proves injection executed and widened the result. +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=1%20OR%201%3D1 + +HTTP 200 +[Asserts] +body contains "Moss" +body contains "Thomas" + +# ── 5. MySql_Get_Union benign: id=1 returns user + address rows ────── +# Query: SELECT name,surname,dob FROM users ... UNION SELECT address_1,address_2,address_3 FROM address ... +# Both result sets for id=1 are returned. +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Union?id=1 + +HTTP 200 +[Asserts] +body contains "Moss" +body contains "Dubuisson" diff --git a/tests/hurl/functional/traversal.hurl b/tests/hurl/functional/traversal.hurl new file mode 100644 index 0000000..4642640 --- /dev/null +++ b/tests/hurl/functional/traversal.hurl @@ -0,0 +1,39 @@ +# traversal.hurl — path traversal demonstration (unprotected). +# +# Source: src/main/java/com/waratek/spiracle/path_traversal/FileInputStreamServlet01.java +# @WebServlet("/FileInputStreamServlet01") param: FileInputStream01 +# +# The servlet constructs: +# absolutePathToTestFile = /pathTraversal/testFilesParent/testFilesChild/ +# + File.separator + FileInputStream01 +# No sanitisation is applied. A "../" sequence traverses up one directory. +# The servlet stores "File input stream opened for file: ''" in the +# session, then redirects to pathTraversal.jsp which renders it. +# Hurl follows the redirect automatically (session cookie carried). +# +# Known test files in the deployment: +# testFilesChild/TestFile (the intended target) +# testFilesParent/TestFile (one level up — requires traversal) + +# ── 1. Benign: access known file in testFilesChild ─────────────────── +GET http://{{host}}:{{port}}/spiracle/FileInputStreamServlet01?FileInputStream01=TestFile +[Options] +location: true + +HTTP 200 +[Asserts] +body contains "File input stream opened for file:" +body contains "testFilesChild" + +# ── 2. Path traversal: ../TestFile escapes testFilesChild ──────────── +# %2F = / so ../TestFile URL-encodes to ..%2FTestFile +# The constructed path resolves to testFilesParent/TestFile. +# The traversal is NOT blocked and the stream opens. +GET http://{{host}}:{{port}}/spiracle/FileInputStreamServlet01?FileInputStream01=..%2FTestFile +[Options] +location: true + +HTTP 200 +[Asserts] +body contains "File input stream opened for file:" +body contains "testFilesParent" diff --git a/tests/hurl/functional/xss.hurl b/tests/hurl/functional/xss.hurl new file mode 100644 index 0000000..232247a --- /dev/null +++ b/tests/hurl/functional/xss.hurl @@ -0,0 +1,28 @@ +# xss.hurl — reflected XSS demonstration (unprotected). +# +# Source: src/main/webapp/customTag.jsp +# The JSP reads request.getParameter("name") and passes it to HelloUserTag, +# which writes: Hello Spiracle user: NAME! +# No escaping is applied, so a script payload in "name" is reflected verbatim. +# +# Note: the ReadHTML-based XSS servlets (XSSWebAppHSRPW, XSSWebAppSRPW etc.) +# do NOT reflect the param because xss.html contains no literal "XSS" token +# to substitute — they are not reflection endpoints. +# customTag.jsp is the cleanest GET-accessible reflected-XSS endpoint. + +# ── 1. Benign name: confirm normal reflection ──────────────────────── +GET http://{{host}}:{{port}}/spiracle/customTag.jsp?name=Alice + +HTTP 200 +[Asserts] +body contains "Hello Spiracle user" +body contains "Alice" + +# ── 2. XSS payload reflected unescaped ────────────────────────────── +# %3Cscript%3Ealert%281%29%3C%2Fscript%3E = +# Without sanitisation the raw tag appears in the HTML body. +GET http://{{host}}:{{port}}/spiracle/customTag.jsp?name=%3Cscript%3Ealert%281%29%3C%2Fscript%3E + +HTTP 200 +[Asserts] +body contains "" diff --git a/tests/hurl/run.sh b/tests/hurl/run.sh new file mode 100755 index 0000000..9dbde9c --- /dev/null +++ b/tests/hurl/run.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# run.sh — Spiracle Hurl test runner +# +# Usage: +# ./tests/hurl/run.sh smoke [host] [port] +# ./tests/hurl/run.sh functional [host] [port] +# +# Arguments: +# suite — "smoke" or "functional" +# host — hostname/IP of Spiracle (default: localhost) +# port — TCP port (default: 8080) +# +# Requirements: +# hurl v5+ at ~/.local/bin/hurl or on PATH + +set -eu + +SUITE="${1:-smoke}" +HOST="${2:-localhost}" +PORT="${3:-8080}" + +# Resolve hurl binary +HURL="" +if command -v hurl >/dev/null 2>&1; then + HURL="hurl" +elif [ -x "$HOME/.local/bin/hurl" ]; then + HURL="$HOME/.local/bin/hurl" +else + echo "ERROR: hurl not found. Install from https://hurl.dev" >&2 + exit 1 +fi + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +case "$SUITE" in + smoke) + VARS_FILE="$SCRIPT_DIR/smoke/local.env" + FILES="$SCRIPT_DIR/smoke/smoke.hurl" + REPORT_DIR="${REPORT_DIR:-/tmp/spiracle-smoke-report}" + ;; + functional) + VARS_FILE="$SCRIPT_DIR/functional/local.env" + FILES="$SCRIPT_DIR/functional/redirect.hurl $SCRIPT_DIR/functional/sql.hurl $SCRIPT_DIR/functional/xss.hurl $SCRIPT_DIR/functional/traversal.hurl $SCRIPT_DIR/functional/negative.hurl" + REPORT_DIR="${REPORT_DIR:-/tmp/spiracle-functional-report}" + ;; + *) + echo "ERROR: unknown suite '$SUITE'. Use 'smoke' or 'functional'." >&2 + exit 1 + ;; +esac + +mkdir -p "$REPORT_DIR" + +echo "Running Spiracle $SUITE suite against http://$HOST:$PORT" +echo "Report: $REPORT_DIR/junit.xml" +echo "" + +# shellcheck disable=SC2086 +$HURL \ + --test \ + --variables-file "$VARS_FILE" \ + --variable host="$HOST" \ + --variable port="$PORT" \ + --report-junit "$REPORT_DIR/junit.xml" \ + $FILES diff --git a/tests/hurl/smoke/local.env b/tests/hurl/smoke/local.env new file mode 100644 index 0000000..0182d07 --- /dev/null +++ b/tests/hurl/smoke/local.env @@ -0,0 +1,2 @@ +host=localhost +port=8080 diff --git a/tests/hurl/smoke/smoke.hurl b/tests/hurl/smoke/smoke.hurl new file mode 100644 index 0000000..24923b2 --- /dev/null +++ b/tests/hurl/smoke/smoke.hurl @@ -0,0 +1,31 @@ +# Spiracle smoke suite. +# +# Purpose: prove the app is up, DB round-trips work, and that SQLi is +# not blocked: Tomcat returns 200 for valid SQL injections and 500 for +# malformed ones. + +# ── 1. App root is reachable ───────────────────────────────────────── +GET http://{{host}}:{{port}}/spiracle/ + +HTTP 200 + +# ── 2. Benign query returns the expected row ───────────────────────── +# Patrick Moss is id=1, name='Patrick' in the seed data. +# MySql_Get_string queries by name and returns the surname. +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=Patrick + +HTTP 200 +[Asserts] +body contains "Moss" + +# ── 3. SQL injection succeeds unprotected ─────────────────────────── +# The injection is NOT blocked. +# The payload ' OR '1'='1 widens the WHERE clause to match all rows. +# Margaret Thomas (id=2) is NOT in the result set for name='Patrick', +# but WILL appear when the injection succeeds. Asserting her surname +# proves more rows were returned than the benign query would give. +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=Patrick'%20OR%20'1'='1 + +HTTP 200 +[Asserts] +body contains "Thomas" diff --git a/tests/mysql.txt b/tests/mysql.txt deleted file mode 100644 index c4ecf66..0000000 --- a/tests/mysql.txt +++ /dev/null @@ -1,139 +0,0 @@ -/spiracle/MySql_Get_int?id=2' OR name LIKE '%25'--550 -/spiracle/MySql_Get_int?id=1' || name like '%25'--550 -/spiracle/MySql_Get_int?id=1' or users.name LIKE '%25'--550 -/spiracle/MySql_Get_int?id=1' or id like '%25550 -/spiracle/MySql_Get_int?id=1' OR 100=(SELECT COUNT(*) FROM users) --550 -/spiracle/MySql_Get_int?id=1' OR users.cvv IS NULL --550 -/spiracle/MySql_Get_int?id=1' AND DOB IS NULL --550 -/spiracle/MySql_Get_int?id=1' OR cvv IS NULL --550 -/spiracle/MySql_Get_int?id=1' OR 'x'='x'--550 -/spiracle/MySql_Get_int?id=1' or 1=1 or 'x'='y'--550 -/spiracle/MySql_Get_int?id=1' UNION ALL SELECT * from users where id=1 or 1=1 --550 -/spiracle/MySql_Get_int?id=1' or 1=1 or ''=''--550 -/spiracle/MySql_Get_int?id=' or 1=1 or ''=''--550 -/spiracle/MySql_Get_int?id=("hi")' or ('a'='a')--550 -/spiracle/MySql_Get_int?id=a' or 'a' = 'a'--550 -/spiracle/MySql_Get_int?id=joe' or '1'='1'--550 -/spiracle/MySql_Get_int?id=1' UNION SELECT * from users where id=1 or 1=1--550 -/spiracle/MySql_Get_int?id=hi' or 1=1--550 -/spiracle/MySql_Get_int?id=hi' or 'a'='a'--550 -/spiracle/MySql_Get_int?id=a' or 1=1--550 -/spiracle/MySql_Get_int?id=%27%20or%20'x'='x'--550 -/spiracle/MySql_Get_int?id=' or 0=0 --550 -/spiracle/MySql_Get_int?id=a' or 3=3--550 -/spiracle/MySql_Get_int?id=Joe' or 0=0 --550 -/spiracle/MySql_Get_int?id=Joe' or 'a'='a'--550 -/spiracle/MySql_Get_int?id=1' or ''=''--550 -/spiracle/MySql_Get_int?id=' or 1=1--550 -/spiracle/MySql_Get_int?id='%20or%201=1--550 -/spiracle/MySql_Get_int?id=%27%20or%201=1--550 -/spiracle/MySql_Get_int?id=' or 3=3--550 -/spiracle/MySql_Get_string?name=x' or name like '%25'--550 -/spiracle/MySql_Get_string?name=%3C%3E%22%2527%25%3B)(%26%2B200 -/spiracle/MySql_Get_string?name=x' AND 100=(SELECT COUNT(*) FROM address) --550 -/spiracle/MySql_Get_string?name=x' OR cvv IS NULL--550 -/spiracle/MySql_Get_string?name=anything' OR 'x'='x550 -/spiracle/MySql_Get_string?name=x' or 1=1 or 'x'='y550 -/spiracle/MySql_Get_string?name=' UNION ALL SELECT * from users where id=1 or 1=1--550 -/spiracle/MySql_Get_string?name='or 1=1 or ''='550 -/spiracle/MySql_Get_string?name=a' or 'a' = 'a550 -/spiracle/MySql_Get_string?name=' or '1'='1'--550 -/spiracle/MySql_Get_string?name=' UNION SELECT * from users--550 -/spiracle/MySql_Get_string?name=a' or 1=1--550 -/spiracle/MySql_Get_string?name=%27%20or%20%27x%27=%27x550 -/spiracle/MySql_Get_string?name='or 0=0 --550 -/spiracle/MySql_Get_string?name=a' or 3=3--550 -/spiracle/MySql_Get_string?name=' or 1=1--550 -/spiracle/MySql_Get_string?name=' or 1 --'550 -/spiracle/MySql_Get_string?name=' or 'a'='a'--550 -/spiracle/MySql_Get_string?name=%27%20or%201=1--550 -/spiracle/MySql_Get_string?name=x' or 3=3--550 -/spiracle/Get_Union?id='2' OR 'name' LIKE 'Joe'550 -/spiracle/Get_Union?id='1' or 'name' like 'Joe'550 -/spiracle/Get_Union?id='1' or id like 1550 -/spiracle/Get_Union?id='1' or 'name' like'Joe'550 -/spiracle/Get_Union?id='1' OR 120=(SELECT COUNT(*) FROM users)550 -/spiracle/Get_Union?id='1' AND 'users.cvv' IS NULL550 -/spiracle/Get_Union?id='1' AND 'DOB' IS NULL550 -/spiracle/Get_Union?id='1' AND 'cvv' IS NULL550 -/spiracle/Get_Union?id='1' OR 'x'='x'550 -/spiracle/Get_Union?id='1' or 1=1 or 'x'='y'550 -/spiracle/Get_Union?id='1' or 1=1 or ''=''--550 -/spiracle/Get_Union?id=' or 1=1 or ''=''--550 -/spiracle/Get_Union?id='("hi")' or ('a'='a')--550 -/spiracle/Get_Union?id='a' or 'a' = 'a'550 -/spiracle/Get_Union?id='joe' or '1'='1'550 -/spiracle/Get_Union?id='hi' or 1=1--550 -/spiracle/Get_Union?id='hi' or 'a'='a'--550 -/spiracle/Get_Union?id='a' or 1=1--550 -/spiracle/Get_Union?id=''%20or%20'x'='x'--550 -/spiracle/Get_Union?id='' or 0=0 --550 -/spiracle/Get_Union?id='a' or 3=3--550 -/spiracle/Get_Union?id='Joe' or 0=0 --550 -/spiracle/Get_Union?id='Joe' or 'a'='a'--550 -/spiracle/Get_Union?id=1 or 'a'='a'550 -/spiracle/Get_Union?id=1 or '1'='1'550 -/spiracle/Get_Union?id=' or 1=1--550 -/spiracle/Get_Union?id=%27%20or%201=1--550 -/spiracle/Get_Union?id=' %20or%201=1--550 -/spiracle/Get_Union?id=' or 3=3--550 -/spiracle/MySql_Get_Implicit_Join?id='2' OR 'name' LIKE 'Joe'550 -/spiracle/MySql_Get_Implicit_Join?id='1' or 'name' like 'Joe'550 -/spiracle/MySql_Get_Implicit_Join?id='1' or users.id like 1550 -/spiracle/MySql_Get_Implicit_Join?id='1' or 'users.name' like'Joe'550 -/spiracle/MySql_Get_Implicit_Join?id='1' OR 120=(SELECT COUNT(*) FROM users)550 -/spiracle/MySql_Get_Implicit_Join?id='1' AND 'users.cvv' IS NULL550 -/spiracle/MySql_Get_Implicit_Join?id='1' AND 'DOB' IS NULL550 -/spiracle/MySql_Get_Implicit_Join?id='1' AND 'cvv' IS NULL550 -/spiracle/MySql_Get_Implicit_Join?id='1' OR 'x'='x'550 -/spiracle/MySql_Get_Implicit_Join?id='1' or 1=1 or 'x'='y'550 -/spiracle/MySql_Get_Implicit_Join?id='1' or 1=1 or ''=''--550 -/spiracle/MySql_Get_Implicit_Join?id='' or 1=1 or ''=''--550 -/spiracle/MySql_Get_Implicit_Join?id=('hi') or ('a'='a')550 -/spiracle/MySql_Get_Implicit_Join?id='a' or 'a' = 'a'550 -/spiracle/MySql_Get_Implicit_Join?id='joe' or '1'='1'550 -/spiracle/MySql_Get_Implicit_Join?id='hi' or 1=1--550 -/spiracle/MySql_Get_Implicit_Join?id='hi' or 'a'='a'--550 -/spiracle/MySql_Get_Implicit_Join?id='a' or 1=1--550 -/spiracle/MySql_Get_Implicit_Join?id=''%20or%20'x'='x'--550 -/spiracle/MySql_Get_Implicit_Join?id='' or 0=0 --550 -/spiracle/MySql_Get_Implicit_Join?id='a' or 3=3--550 -/spiracle/MySql_Get_Implicit_Join?id='Joe' or 0=0 --550 -/spiracle/MySql_Get_Implicit_Join?id='Joe' or 'a'='a'--550 -/spiracle/MySql_Get_Implicit_Join?id=1 or 'a'='a'550 -/spiracle/MySql_Get_Implicit_Join?id=1 or '1'='1'550 -/spiracle/MySql_Get_Implicit_Join?id=1 or '1'='1'550 -/spiracle/MySql_Get_Implicit_Join?id='' or 1=1--550 -/spiracle/MySql_Get_Implicit_Join?id='' %20or%201=1--550 -/spiracle/MySql_Get_Implicit_Join?id='' or 3=3--550 -/spiracle/MySql_Get_Implicit_Join?id=%27%27%20or%201=1--550 -/spiracle/MySql_Implicit_Join_Namespace?id='2' OR 'name' LIKE 'Joe'550 -/spiracle/MySql_Implicit_Join_Namespace?id='1' or 'name' like 'Joe'550 -/spiracle/MySql_Implicit_Join_Namespace?id='1' or users.id like 1550 -/spiracle/MySql_Implicit_Join_Namespace?id='1' or 'users.name' like'Joe'550 -/spiracle/MySql_Implicit_Join_Namespace?id='1' OR 120=(SELECT COUNT(*) FROM users)550 -/spiracle/MySql_Implicit_Join_Namespace?id='1' AND 'users.cvv' IS NULL550 -/spiracle/MySql_Implicit_Join_Namespace?id='1' AND 'DOB' IS NULL550 -/spiracle/MySql_Implicit_Join_Namespace?id='1' AND 'cvv' IS NULL550 -/spiracle/MySql_Implicit_Join_Namespace?id='1' OR 'x'='x'550 -/spiracle/MySql_Implicit_Join_Namespace?id='1' or 1=1 or 'x'='y'550 -/spiracle/MySql_Implicit_Join_Namespace?id='1' or 1=1 or ''=''--550 -/spiracle/MySql_Implicit_Join_Namespace?id='' or 1=1 or ''=''--550 -/spiracle/MySql_Implicit_Join_Namespace?id=('hi') or ('a'='a')550 -/spiracle/MySql_Implicit_Join_Namespace?id='a' or 'a' = 'a'550 -/spiracle/MySql_Implicit_Join_Namespace?id='joe' or '1'='1'550 -/spiracle/MySql_Implicit_Join_Namespace?id='hi' or 1=1--550 -/spiracle/MySql_Implicit_Join_Namespace?id='hi' or 'a'='a'--550 -/spiracle/MySql_Implicit_Join_Namespace?id='a' or 1=1--550 -/spiracle/MySql_Implicit_Join_Namespace?id=''%20or%20'x'='x'--550 -/spiracle/MySql_Implicit_Join_Namespace?id='' or 0=0 --550 -/spiracle/MySql_Implicit_Join_Namespace?id='a' or 3=3--550 -/spiracle/MySql_Implicit_Join_Namespace?id='Joe' or 0=0 --550 -/spiracle/MySql_Implicit_Join_Namespace?id='Joe' or 'a'='a'--550 -/spiracle/MySql_Implicit_Join_Namespace?id=1 or 'a'='a'550 -/spiracle/MySql_Implicit_Join_Namespace?id=1 or '1'='1'550 -/spiracle/MySql_Implicit_Join_Namespace?id=1 or '1'='1'550 -/spiracle/MySql_Implicit_Join_Namespace?id='' or 1=1--550 -/spiracle/MySql_Implicit_Join_Namespace?id='' %20or%201=1--550 -/spiracle/MySql_Implicit_Join_Namespace?id='' or 3=3--550 -/spiracle/MySql_Implicit_Join_Namespace?id=%27%27%20or%201=1--550 diff --git a/tests/oracle.txt b/tests/oracle.txt deleted file mode 100644 index 276629d..0000000 --- a/tests/oracle.txt +++ /dev/null @@ -1,301 +0,0 @@ -/spiracle/Get_int?id=2' OR name LIKE '%25550 -/spiracle/Get_int?id=1' or name like '%25550 -/spiracle/Get_int?id=1' or id like '%25550 -/spiracle/Get_int?id=' or name like '%25550 -/spiracle/Get_int?id=1' OR 120=(SELECT COUNT(*) FROM users) --550 -/spiracle/Get_int?id=1' AND users.cvv IS NULL --550 -/spiracle/Get_int?id=1' AND DOB IS NULL --550 -/spiracle/Get_int?id=1' AND cvv IS NULL --550 -/spiracle/Get_int?id=1' OR 'x'='x'--550 -/spiracle/Get_int?id=1' or 1=1 or 'x'='y'--550 -/spiracle/Get_int?id=1' UNION ALL SELECT * from users where id=1 or 1=1--550 -/spiracle/Get_int?id=1' or 1=1 or ''=''--550 -/spiracle/Get_int?id=' or 1=1 or ''=''--550 -/spiracle/Get_int?id=("hi")' or ('a'='a')--550 -/spiracle/Get_int?id=a' or 'a' = 'a'--550 -/spiracle/Get_int?id=joe' or '1'='1'--550 -/spiracle/Get_int?id=1' UNION SELECT * from users where id=1 or 1=1--550 -/spiracle/Get_int?id=hi' or 1=1--550 -/spiracle/Get_int?id=hi' or 'a'='a'--550 -/spiracle/Get_int?id=a' or 1=1--550 -/spiracle/Get_int?id=%20or%20'x'='x'--550 -/spiracle/Get_int?id=' or 0=0 --550 -/spiracle/Get_int?id=a' or 3=3--550 -/spiracle/Get_int?id=Joe' or 0=0 --550 -/spiracle/Get_int?id=Joe' or 'a'='a'--550 -/spiracle/Get_int?id=1' or ''=''--550 -/spiracle/Get_int?id=' or 1=1--550 -/spiracle/Get_int?id='%20or%201=1--550 -/spiracle/Get_int?id=%27%20or%201=1--550 -/spiracle/Get_int?id=' or 3=3--550 -/spiracle/Get_int_no_quote?id=2 OR name LIKE '%25'550 -/spiracle/Get_int_no_quote?id=1 or name like '%25'550 -/spiracle/Get_int_no_quote?id=1 or id like '%25'550 -/spiracle/Get_int_no_quote?id=1 or name like '%25'550 -/spiracle/Get_int_no_quote?id=1 OR 120=(SELECT COUNT(*) FROM users) --550 -/spiracle/Get_int_no_quote?id=1 AND users.cvv IS NULL --550 -/spiracle/Get_int_no_quote?id=1 AND DOB IS NULL --550 -/spiracle/Get_int_no_quote?id=1 AND cvv IS NULL --550 -/spiracle/Get_int_no_quote?id=1 OR 'x'='x'550 -/spiracle/Get_int_no_quote?id=1 or 1=1 or 'x'='y'550 -/spiracle/Get_int_no_quote?id=1 UNION ALL SELECT * from users where id=1 or 1=1550 -/spiracle/Get_int_no_quote?id=1 or 1=1 or ''=''550 -/spiracle/Get_int_no_quote?id='' or 1=1 or ''=''550 -/spiracle/Get_int_no_quote?id=('hi') or ('a'='a')550 -/spiracle/Get_int_no_quote?id='a' or 'a' = 'a'550 -/spiracle/Get_int_no_quote?id=1 UNION SELECT * from users where id=1 or 1=1550 -/spiracle/Get_int_no_quote?id='joe' or '1'='1'--550 -/spiracle/Get_int_no_quote?id=(%27%27)%20or%20(%27x%27=%27x%27)550 -/spiracle/Get_int_no_quote?id=('') or ('a'='a')550 -/spiracle/Get_int_no_quote?id='hi' or 1=1--550 -/spiracle/Get_int_no_quote?id='hi' or 'a'='a'550 -/spiracle/Get_int_no_quote?id='a' or 1=1--550 -/spiracle/Get_int_no_quote?id=''%20or%20'x'='x'550 -/spiracle/Get_int_no_quote?id='' or 0=0 --550 -/spiracle/Get_int_no_quote?id='a' or 3=3--550 -/spiracle/Get_int_no_quote?id='Joe' or 0=0 #550 -/spiracle/Get_int_no_quote?id='Joe' or 'a'='a'550 -/spiracle/Get_int_no_quote?id=1%20or%20''=''550 -/spiracle/Get_int_no_quote?id=1 or ''=''550 -/spiracle/Get_int_no_quote?id='Joe' or 1=1550 -/spiracle/Get_int_no_quote?id='Joe' %20or%201=1550 -/spiracle/Get_int_no_quote?id='Joe %27%20or%201=1550 -/spiracle/Get_int_no_quote?id='Joe' or 3=3550 -/spiracle/Get_int_partialunion?id=2' OR name LIKE '%25550 -/spiracle/Get_int_partialunion?id=1' or name like '%25550 -/spiracle/Get_int_partialunion?id=1' or id like '%25550 -/spiracle/Get_int_partialunion?id=' or name like '%25550 -/spiracle/Get_int_partialunion?id=1' OR 120=(SELECT COUNT(*) FROM users) --550 -/spiracle/Get_int_partialunion?id=1' AND users.cvv IS NULL --550 -/spiracle/Get_int_partialunion?id=1' AND DOB IS NULL --550 -/spiracle/Get_int_partialunion?id=1' AND cvv IS NULL --550 -/spiracle/Get_int_partialunion?id=1' OR 'x'='x'--550 -/spiracle/Get_int_partialunion?id=1' or 1=1 or 'x'='y'--550 -/spiracle/Get_int_partialunion?id=1' UNION ALL SELECT * from users where id=1 or 1=1--550 -/spiracle/Get_int_partialunion?id=1' or 1=1 or ''=''--550 -/spiracle/Get_int_partialunion?id=' or 1=1 or ''=''--550 -/spiracle/Get_int_partialunion?id=("hi")' or ('a'='a')--550 -/spiracle/Get_int_partialunion?id=a' or 'a' = 'a'--550 -/spiracle/Get_int_partialunion?id=joe' or '1'='1'--550 -/spiracle/Get_int_partialunion?id=1' UNION SELECT * from users where id=1 or 1=1--550 -/spiracle/Get_int_partialunion?id=hi' or 1=1--550 -/spiracle/Get_int_partialunion?id=hi' or 'a'='a'--550 -/spiracle/Get_int_partialunion?id=a' or 1=1--550 -/spiracle/Get_int_partialunion?id='%20or%20'x'='x'--550 -/spiracle/Get_int_partialunion?id=' or 0=0 --550 -/spiracle/Get_int_partialunion?id=a' or 3=3--550 -/spiracle/Get_int_partialunion?id=Joe' or 0=0 --550 -/spiracle/Get_int_partialunion?id=Joe' or 'a'='a'--550 -/spiracle/Get_int_partialunion?id=1' or ''=''--550 -/spiracle/Get_int_partialunion?id=' or 1=1--550 -/spiracle/Get_int_partialunion?id=' %20or%201=1--550 -/spiracle/Get_int_partialunion?id=%27%20or%201=1--550 -/spiracle/Get_int_partialunion?id=' or 3=3--550 -/spiracle/Get_int_groupby?id=name union all select null, to_char(dob) from users550 -/spiracle/Get_int_groupby?id=name union select null, to_char(dob) from users550 -/spiracle/Get_int_nooutput?id=2' OR name LIKE '%25550 -/spiracle/Get_int_nooutput?id=1' or name like '%25550 -/spiracle/Get_int_nooutput?id=1' or id like '%25550 -/spiracle/Get_int_nooutput?id=' or name like '%25550 -/spiracle/Get_int_nooutput?id=1' OR 120=(SELECT COUNT(*) FROM users) --550 -/spiracle/Get_int_nooutput?id=1' AND users.cvv IS NULL --550 -/spiracle/Get_int_nooutput?id=1' AND DOB IS NULL --550 -/spiracle/Get_int_nooutput?id=1' AND cvv IS NULL --550 -/spiracle/Get_int_nooutput?id=1' OR 'x'='x'--550 -/spiracle/Get_int_nooutput?id=1' or 1=1 or 'x'='y'--550 -/spiracle/Get_int_nooutput?id=1' UNION ALL SELECT * from users where id=1 or 1=1--550 -/spiracle/Get_int_nooutput?id=1' or 1=1 or ''=''--550 -/spiracle/Get_int_nooutput?id=' or 1=1 or ''=''--550 -/spiracle/Get_int_nooutput?id=("hi")' or ('a'='a')--550 -/spiracle/Get_int_nooutput?id=a' or 'a' = 'a'--550 -/spiracle/Get_int_nooutput?id=joe' or '1'='1'--550 -/spiracle/Get_int_nooutput?id=1' UNION SELECT * from users where id=1 or 1=1--550 -/spiracle/Get_int_nooutput?id=hi' or 1=1--550 -/spiracle/Get_int_nooutput?id=hi' or 'a'='a'--550 -/spiracle/Get_int_nooutput?id=a' or 1=1--550 -/spiracle/Get_int_nooutput?id='%20or%20'x'='x'--550 -/spiracle/Get_int_nooutput?id=' or 0=0 --550 -/spiracle/Get_int_nooutput?id=a' or 3=3--550 -/spiracle/Get_int_nooutput?id=Joe' or 0=0 --550 -/spiracle/Get_int_nooutput?id=Joe' or 'a'='a'--550 -/spiracle/Get_int_nooutput?id=1' or ''=''--550 -/spiracle/Get_int_nooutput?id=' or 1=1--550 -/spiracle/Get_int_nooutput?id=1%27%20or%201=1--550 -/spiracle/Get_int_nooutput?id=' %20or%201=1--550 -/spiracle/Get_int_nooutput?id=' or 3=3--550 -/spiracle/Get_int_having?id=1 union select to_char(dob) from users550 -/spiracle/Get_int_having?id=1 union all select to_char(dob) from users550 -/spiracle/Get_int_inline?id=select * from users where name = 'x' OR name LIKE 'Joe'550 -/spiracle/Get_int_inline?id=select * from users where name = '' or name like ''550 -/spiracle/Get_int_inline?id=select * from users where id = '' or id like ''550 -/spiracle/Get_int_inline?id=select * from users where name = '' or name like ''550 -/spiracle/Get_int_inline?id=select * from users where name ='x' AND users.cvv IS NULL --550 -/spiracle/Get_int_inline?id=select * from users where name = 'x' OR 120=(SELECT COUNT(*) FROM users) --550 -/spiracle/Get_int_inline?id=select * from users where name ='Joe' AND DOB IS NULL --550 -/spiracle/Get_int_inline?id=select * from users where name ='Joe' AND cvv IS NULL --550 -/spiracle/Get_int_inline?id=select * from users where name ='anything' OR 'x'='x'550 -/spiracle/Get_int_inline?id=select * from users where name = 'x' or 1=1 or 'x'='y'550 -/spiracle/Get_int_inline?id=select * from users where name ='Joe' UNION ALL SELECT * from users where id=1 or 1=1550 -/spiracle/Get_int_inline?id=select * from users where name = '' or 1=1 or ''=''550 -/spiracle/Get_int_inline?id=select * from users where name = ('hi') or ('a'='a')550 -/spiracle/Get_int_inline?id=select * from users where name = 'a' or 'a' = 'a'550 -/spiracle/Get_int_inline?id=select * from users where name = 'joe' or '1'='1'--550 -/spiracle/Get_int_inline?id=select * from users where name ='Joe' UNION SELECT * from users where id=1 or 1=1550 -/spiracle/Get_int_inline?id=select * from users where name = (%27%27)%20or%20(%27x%27=%27x%27)550 -/spiracle/Get_int_inline?id=select * from users where name=('') or ('a'='a')550 -/spiracle/Get_int_inline?id=select * from users where name='hi' or 1=1--550 -/spiracle/Get_int_inline?id=select * from users where name='hi' or 'a'='a'550 -/spiracle/Get_int_inline?id=select * from users where name='a' or 1=1--550 -/spiracle/Get_int_inline?id=select * from users where name=''%20or%20'x'='x'550 -/spiracle/Get_int_inline?id=select * from users where name='' or 0=0 --550 -/spiracle/Get_int_inline?id=select * from users where name='a' or 3=3--550 -/spiracle/Get_int_inline?id=select * from users where name='Joe' or 0=0 #550 -/spiracle/Get_int_inline?id=select * from users where name='Joe' or 'a'='a'550 -/spiracle/Get_int_inline?id=select * from users where name='Joe'%20or%20''=''550 -/spiracle/Get_int_inline?id=select * from users where name='Joe' or 1=1550 -/spiracle/Get_int_inline?id=select * from users where name='Joe' or ''=''550 -/spiracle/Get_int_inline?id=select * from users where name='Joe' %20or%201=1550 -/spiracle/Get_int_inline?id=select * from users where name='Joe %27%20or%201=1550 -/spiracle/Get_int_inline?id=select * from users where name='Joe' or 3=3550 -/spiracle/Get_string?name=x' or name like '%25'--550 -/spiracle/Get_string?name=t'exec master..xp_cmdshell 'nslookup%20www%2egoogle%2ecom'--550 -/spiracle/Get_string?name='%3b%20exec%20master%2e%2exp_cmdshell%20'ping%20172%2e10%2e1%2e255'--550 -/spiracle/Get_string?name=x' AND 100=(SELECT COUNT(*) FROM address) --550 -/spiracle/Get_string?name=x' OR cvv IS NULL--550 -/spiracle/Get_string?name=anything' OR 'x'='x550 -/spiracle/Get_string?name=x' or 1=1 or 'x'='y550 -/spiracle/Get_string?name=' UNION ALL SELECT * from users where id=1 or 1=1--550 -/spiracle/Get_string?name='or 1=1 or ''='550 -/spiracle/Get_string?name=a' or 'a' = 'a550 -/spiracle/Get_string?name=' or '1'='1'--550 -/spiracle/Get_string?name=' UNION SELECT * from users--550 -/spiracle/Get_string?name=a' or 1=1--550 -/spiracle/Get_string?name=%27%20or%20%27x%27=%27x550 -/spiracle/Get_string?name='or 0=0 --550 -/spiracle/Get_string?name=a' or 3=3--550 -/spiracle/Get_string?name=' or 1=1--550 -/spiracle/Get_string?name=' or 1 --'550 -/spiracle/Get_string?name=' or 'a'='a'--550 -/spiracle/Get_string?name=%27%20or%201=1--550 -/spiracle/Get_string?name=x' or 3=3--550 -/spiracle/Get_string_no_quote?name='2' OR name LIKE 'Joe'550 -/spiracle/Get_string_no_quote?name='Jon' or name like 'Joe'550 -/spiracle/Get_string_no_quote?name='1' or id like '2'550 -/spiracle/Get_string_no_quote?name='1' or name like 'Joe'550 -/spiracle/Get_string_no_quote?name='Joe' OR 120=(SELECT COUNT(*) FROM users) --550 -/spiracle/Get_string_no_quote?name='1' or name like 'Sammy'550 -/spiracle/Get_string_no_quote?name='1' AND users.cvv IS NULL --550 -/spiracle/Get_string_no_quote?name='1' AND DOB IS NULL --550 -/spiracle/Get_string_no_quote?name='1' AND cvv IS NULL --550 -/spiracle/Get_string_no_quote?name='1' OR 'x'='x'550 -/spiracle/Get_string_no_quote?name='1' or 1=1 or 'x'='y'--550 -/spiracle/Get_string_no_quote?name='1' UNION ALL SELECT * from users where id=1 or 1=1--550 -/spiracle/Get_string_no_quote?name='' or 1=1 or ''=''--550 -/spiracle/Get_string_no_quote?name='1' or 1=1 or ''=''--550 -/spiracle/Get_string_no_quote?name=(1) or ('a'='a')--550 -/spiracle/Get_string_no_quote?name=1 or 'a' = 'a'--550 -/spiracle/Get_string_no_quote?name=1 or '1'='1'--550 -/spiracle/Get_string_no_quote?name='Joe' UNION SELECT * from users where id=1 or 1=1--550 -/spiracle/Get_string_no_quote?name=('') or ('a'='a')--550 -/spiracle/Get_string_no_quote?name=('') or ('x'='x')--550 -/spiracle/Get_string_no_quote?name='' or 'a'='a'--550 -/spiracle/Get_string_no_quote?name='' or 1=1--550 -/spiracle/Get_string_no_quote?name='a' or 1=1--550 -/spiracle/Get_string_no_quote?name=%27%27%20or%20%27x%27%3D%27x%27--550 -/spiracle/Get_string_no_quote?name='a' or 3=3--550 -/spiracle/Get_string_no_quote?name='' or 0=0 --550 -/spiracle/Get_string_no_quote?name='Joe' or 0=0 #550 -/spiracle/Get_string_no_quote?name='Joe' or 'a'='a'--550 -/spiracle/Get_string_no_quote?name='Joe' or 'a'='a'550 -/spiracle/Get_string_no_quote?name='1' or ''=''--550 -/spiracle/Get_string_no_quote?name='Joe' %20or%201=1--550 -/spiracle/Get_string_no_quote?name='Joe' or 1=1--550 -/spiracle/Get_string_no_quote?name='Joe %27%20or%201=1--550 -/spiracle/Get_string_no_quote?name='Joe' or 3=3--550 -/spiracle/Get_Implicit_Join?id='2' OR 'name' LIKE 'Joe'550 -/spiracle/Get_Implicit_Join?id='1' or 'name' like 'Joe'550 -/spiracle/Get_Implicit_Join?id='1' or users.id like 1550 -/spiracle/Get_Implicit_Join?id='1' or 'users.name' like'Joe'550 -/spiracle/Get_Implicit_Join?id='1' OR 120=(SELECT COUNT(*) FROM users)550 -/spiracle/Get_Implicit_Join?id='1' AND 'users.cvv' IS NULL550 -/spiracle/Get_Implicit_Join?id='1' AND 'DOB' IS NULL550 -/spiracle/Get_Implicit_Join?id='1' AND 'cvv' IS NULL550 -/spiracle/Get_Implicit_Join?id='1' OR 'x'='x'550 -/spiracle/Get_Implicit_Join?id='1' or 1=1 or 'x'='y'550 -/spiracle/Get_Implicit_Join?id='1' or 1=1 or ''=''--550 -/spiracle/Get_Implicit_Join?id='' or 1=1 or ''=''--550 -/spiracle/Get_Implicit_Join?id=('hi') or ('a'='a')550 -/spiracle/Get_Implicit_Join?id='a' or 'a' = 'a'550 -/spiracle/Get_Implicit_Join?id='joe' or '1'='1'550 -/spiracle/Get_Implicit_Join?id='hi' or 1=1--550 -/spiracle/Get_Implicit_Join?id='hi' or 'a'='a'--550 -/spiracle/Get_Implicit_Join?id='a' or 1=1--550 -/spiracle/Get_Implicit_Join?id=''%20or%20'x'='x'--550 -/spiracle/Get_Implicit_Join?id='' or 0=0 --550 -/spiracle/Get_Implicit_Join?id='a' or 3=3--550 -/spiracle/Get_Implicit_Join?id='Joe' or 0=0 --550 -/spiracle/Get_Implicit_Join?id='Joe' or 'a'='a'--550 -/spiracle/Get_Implicit_Join?id=1 or 'a'='a'550 -/spiracle/Get_Implicit_Join?id=1 or '1'='1'550 -/spiracle/Get_Implicit_Join?id='' or 1=1--550 -/spiracle/Get_Implicit_Join?id='' %20or%201=1--550 -/spiracle/Get_Implicit_Join?id='' or 3=3--550 -/spiracle/Get_Implicit_Join?id=%27%27%20or%201=1--550 -/spiracle/Get_Full_Outer_Join?id='2' OR 'name' LIKE 'Joe'550 -/spiracle/Get_Full_Outer_Join?id='1' or 'name' like 'Joe'550 -/spiracle/Get_Full_Outer_Join?id='1' or users.id like 1550 -/spiracle/Get_Full_Outer_Join?id='1' or 'users.name' like'Joe'550 -/spiracle/Get_Full_Outer_Join?id='1' OR 120=(SELECT COUNT(*) FROM users)550 -/spiracle/Get_Full_Outer_Join?id='1' AND 'users.cvv' IS NULL550 -/spiracle/Get_Full_Outer_Join?id='1' AND 'DOB' IS NULL550 -/spiracle/Get_Full_Outer_Join?id='1' AND 'cvv' IS NULL550 -/spiracle/Get_Full_Outer_Join?id='1' OR 'x'='x'550 -/spiracle/Get_Full_Outer_Join?id='1' or 1=1 or 'x'='y'550 -/spiracle/Get_Full_Outer_Join?id='1' or 1=1 or ''=''--550 -/spiracle/Get_Full_Outer_Join?id='' or 1=1 or ''=''--550 -/spiracle/Get_Full_Outer_Join?id=('hi') or ('a'='a')550 -/spiracle/Get_Full_Outer_Join?id='a' or 'a' = 'a'550 -/spiracle/Get_Full_Outer_Join?id='joe' or '1'='1'550 -/spiracle/Get_Full_Outer_Join?id='hi' or 'a'='a'--550 -/spiracle/Get_Full_Outer_Join?id='hi' or 1=1--550 -/spiracle/Get_Full_Outer_Join?id='a' or 1=1--550 -/spiracle/Get_Full_Outer_Join?id='' or 0=0 --550 -/spiracle/Get_Full_Outer_Join?id=''%20or%20'x'='x'--550 -/spiracle/Get_Full_Outer_Join?id='a' or 3=3--550 -/spiracle/Get_Full_Outer_Join?id='Joe' or 0=0 --550 -/spiracle/Get_Full_Outer_Join?id='Joe' or 'a'='a'--550 -/spiracle/Get_Full_Outer_Join?id=1 or 'a'='a'550 -/spiracle/Get_Full_Outer_Join?id=1 or '1'='1'550 -/spiracle/Get_Full_Outer_Join?id='' or 1=1--550 -/spiracle/Get_Full_Outer_Join?id='' %20or%201=1--550 -/spiracle/Get_Full_Outer_Join?id=%27%27%20or%201=1--550 -/spiracle/Get_Full_Outer_Join?id='' or 3=3--550 -/spiracle/Get_Union?id='2' OR 'name' LIKE 'Joe'550 -/spiracle/Get_Union?id='1' or 'name' like 'Joe'550 -/spiracle/Get_Union?id='1' or id like 1550 -/spiracle/Get_Union?id='1' or 'name' like'Joe'550 -/spiracle/Get_Union?id='1' OR 120=(SELECT COUNT(*) FROM users)550 -/spiracle/Get_Union?id='1' AND 'users.cvv' IS NULL550 -/spiracle/Get_Union?id='1' AND 'DOB' IS NULL550 -/spiracle/Get_Union?id='1' AND 'cvv' IS NULL550 -/spiracle/Get_Union?id='1' OR 'x'='x'550 -/spiracle/Get_Union?id='1' or 1=1 or 'x'='y'550 -/spiracle/Get_Union?id='1' or 1=1 or ''=''--550 -/spiracle/Get_Union?id=' or 1=1 or ''=''--550 -/spiracle/Get_Union?id='("hi")' or ('a'='a')--550 -/spiracle/Get_Union?id='a' or 'a' = 'a'550 -/spiracle/Get_Union?id='joe' or '1'='1'550 -/spiracle/Get_Union?id='hi' or 1=1--550 -/spiracle/Get_Union?id='hi' or 'a'='a'--550 -/spiracle/Get_Union?id='a' or 1=1--550 -/spiracle/Get_Union?id=''%20or%20'x'='x'--550 -/spiracle/Get_Union?id='' or 0=0 --550 -/spiracle/Get_Union?id='a' or 3=3--550 -/spiracle/Get_Union?id='Joe' or 0=0 --550 -/spiracle/Get_Union?id='Joe' or 'a'='a'--550 -/spiracle/Get_Union?id=1 or 'a'='a'550 -/spiracle/Get_Union?id=1 or '1'='1'550 -/spiracle/Get_Union?id=' or 1=1--550 -/spiracle/Get_Union?id=%27%20or%201=1--550 -/spiracle/Get_Union?id=' %20or%201=1--550 -/spiracle/Get_Union?id=' or 3=3--550 diff --git a/tests/spiracle_sqli_test.py b/tests/spiracle_sqli_test.py deleted file mode 100755 index 3433c51..0000000 --- a/tests/spiracle_sqli_test.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/python - -from collections import defaultdict -import requests -import argparse - -parser = argparse.ArgumentParser(description="Run SQLI Tests") -parser.add_argument("-hn", "--hostname", help="Hostname", required=True) -parser.add_argument("-p", "--port", help="Port", required=True) -parser.add_argument("-f", "--file", help="Data file", required=True) -parser.add_argument("-d", "--debug", action="store_true") -args = parser.parse_args() - -input_file = open(args.file) -expected_dict = defaultdict(list) -actual_dict = defaultdict(list) -url = "http://{0}:{1}".format(args.hostname, args.port) - -for entry in input_file: - parts = entry.strip().split("") - if parts[0] in expected_dict: - expected_dict[parts[0]].append((parts[1], parts[2])) - else: - expected_dict[parts[0]] = [] - expected_dict[parts[0]].append((parts[1], parts[2])) - -for key in expected_dict.keys(): - actual_dict[key] = [] - -for key in expected_dict.keys(): - for entry in expected_dict[key]: - r = requests.get("{0}{1}{2}" - .format(url, key, entry[0])) - if args.debug: - print r.url, r.status_code - - actual_dict[key].append((entry[0], r.status_code)) - -successful_tests = 0 -log = open("results.csv", "a+") -for key in actual_dict.keys(): - counter = len(actual_dict[key]) - for x in range(0, counter): - if str(expected_dict[key][x][1]) == str(actual_dict[key][x][1]): - successful_tests += 1 - log.write("{0}{1},{2},{3}\n".format(url, key, expected_dict[key][x][1], - actual_dict[key][x][1])) - print("Servlet {0} had {1} tests. Pass: {2} Fail {3}" - .format(key, counter, successful_tests, counter - successful_tests)) - successful_tests = 0 -log.close()