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/Dockerfile b/Dockerfile new file mode 100644 index 0000000..909c212 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,86 @@ +# ============================================================================= +# Parameterised multi-version build for Spiracle (Java 6 .. 25). +# +# A SINGLE Dockerfile builds and runs the app on any Java version by varying +# these build args. Defaults reproduce the historical Java 8 / Tomcat 9 image. +# +# BUILD_JDK JDK image used to COMPILE the WAR and assemble Tomcat +# (8|11|17|21|25). No single JDK can target every source +# level, so it is picked per band. +# VERSION_JDK -Dversion.jdk source/target level (1.6|1.7|1.8|9..25). +# VERSION_WEBXML Servlet descriptor (25|30). +# MAVEN_OPTS Extra JVM flags for Maven (the matrix sets --add-opens for +# build JDK >= 16, which the legacy plugins need). +# TOMCAT_MAJOR Tomcat major line (9 for Java 8+; 7/8 for the Java 6/7 tail). +# TOMCAT_VERSION Apache Tomcat patch release (from the dist archive). +# RUNTIME_BASE JRE image the agent actually instruments (e.g. +# eclipse-temurin:17-jre). This is the "run on Java N" knob. +# +# All network/extraction work happens in the BUILD stage (modern image, working +# apt/curl/jar). The runtime stage only COPYs a self-contained Tomcat, so it +# needs nothing but a JRE + shell — it works on minimal or legacy (Java 6/7) +# bases whose package repos are dead. See docs/multi-version-testing.md. +# ============================================================================= + +# ARGs consumed by a FROM must be declared in the global scope (before the +# first FROM). BUILD_JDK selects the build image; RUNTIME_BASE the runtime image. +ARG BUILD_JDK=8 +ARG RUNTIME_BASE=eclipse-temurin:8-jre + +# --------------------------------------------------------------------------- +# Stage 1: build the WAR and assemble a self-contained Tomcat with the WAR +# exploded and the JDBC drivers in place. BUILD_JDK must support the requested +# VERSION_JDK source level (JDK 8 -> 1.6/1.7/1.8; JDK 25 -> 8..25). +# --------------------------------------------------------------------------- +FROM maven:3.9-eclipse-temurin-${BUILD_JDK} AS build + +ARG VERSION_JDK=1.8 +ARG VERSION_WEBXML=30 +# The pinned legacy Maven plugins (war-plugin 2.4 …) do deep reflection that +# JDK 16+ blocks by default; the matrix sets MAVEN_OPTS to the needed +# --add-opens for build JDK >= 16 (empty on JDK 8/11). +ARG MAVEN_OPTS="" +ENV MAVEN_OPTS=${MAVEN_OPTS} +ARG TOMCAT_MAJOR=9 +ARG TOMCAT_VERSION=9.0.118 + +WORKDIR /build +COPY pom.xml . +COPY src ./src + +RUN mvn install -Dversion.jdk=${VERSION_JDK} -Dversion.webxml=${VERSION_WEBXML} -DskipTests -q + +# Assemble Tomcat under /opt/tomcat: download (archive.apache.org keeps every +# patch; dlcdn only the latest), drop default webapps, explode the WAR with +# `jar`, and fetch the JDBC drivers into lib/. NOTE: ojdbc8 / mssql-jdbc.jre8 +# need Java 8+ and won't load on the Java 6/7 tail (logged, non-fatal); MySQL +# Connector/J 5.1.49 works on every level. +RUN set -eux; \ + curl -fsSL "https://archive.apache.org/dist/tomcat/tomcat-${TOMCAT_MAJOR}/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz" -o /tmp/tomcat.tgz; \ + mkdir -p /opt/tomcat; \ + tar xzf /tmp/tomcat.tgz -C /opt/tomcat --strip-components=1; \ + rm /tmp/tomcat.tgz; \ + rm -rf /opt/tomcat/webapps/*; \ + mkdir -p /opt/tomcat/webapps/spiracle; \ + (cd /opt/tomcat/webapps/spiracle && jar xf /build/target/spiracle.war); \ + curl -fsSL "https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.49/mysql-connector-java-5.1.49.jar" \ + -o /opt/tomcat/lib/mysql-connector-java-5.1.49.jar; \ + curl -fsSL "https://repo1.maven.org/maven2/com/microsoft/sqlserver/mssql-jdbc/12.4.2.jre8/mssql-jdbc-12.4.2.jre8.jar" \ + -o /opt/tomcat/lib/mssql-jdbc-12.4.2.jre8.jar; \ + curl -fsSL "https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc8/21.13.0.0/ojdbc8-21.13.0.0.jar" \ + -o /opt/tomcat/lib/ojdbc8-21.13.0.0.jar + +# --------------------------------------------------------------------------- +# Stage 2: runtime. Just a JRE + the assembled Tomcat — no package installs, +# so any JRE base works (Temurin 8..25, or a legacy Azul Zulu 6/7 for the tail). +# --------------------------------------------------------------------------- +FROM ${RUNTIME_BASE} AS runtime + +ENV CATALINA_HOME=/usr/local/tomcat +ENV PATH="${CATALINA_HOME}/bin:${PATH}" + +COPY --from=build /opt/tomcat ${CATALINA_HOME} +COPY --chmod=0755 docker/entrypoint.sh /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..4e06f9e --- /dev/null +++ b/README.md @@ -0,0 +1,261 @@ +# 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.6 -Dversion.webxml=30`) and deploys it on Tomcat 9. `docker/entrypoint.sh` rewrites `conf/Spiracle.properties` from environment variables at startup. + +> **Note — JDBC drivers:** No JDBC driver is bundled 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 | Agent required | What it covers | +|---|---|---| +| `smoke/` | No | App root responds 200; benign query returns data; unblocked SQLi widens result set (confirming injections succeed without agent) | +| `functional/` | No | SendRedirect, SQL queries, reflected XSS via `customTag.jsp`, path traversal, 404/empty-result/no-param negative cases | +| `rasp/` | Yes (Waratek RASP) | 579-case SQL injection matrix (139 MySQL, 301 Oracle, 139 MSSQL); asserts status `550`, which is only emitted when the Waratek agent intercepts the query | + +> **Note:** The `rasp/` suite requires the Waratek RASP agent attached to Tomcat. The agent supports Java 6 through 25, which is why this matrix lives on `master` (Java 6+) and not on the `java4`/`java5` branches. + +To build and run the rasp suite across the whole Java 6–25 range from a single parameterised `Dockerfile`, use `scripts/rasp-matrix.sh` (e.g. `./scripts/rasp-matrix.sh test 17 mysql` or `./scripts/rasp-matrix.sh sweep "8 11 17 21 25" mysql`). See [docs/multi-version-testing.md](docs/multi-version-testing.md) for the design and the version matrix. + +### 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 +``` + +The `rasp/` suite will fail on a plain deployment — expected. Run it only with the Waratek agent attached to Tomcat. + +Full harness reference: [tests/hurl/README.md](tests/hurl/README.md) + +## Building + +Prerequisites: + +- Java 8 toolchain (compiles `-source/-target` from `1.6` upward) +- 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. Supported values on `master`: `1.6`, `1.7`, `1.8`. (Java 6 is the floor: the Waratek RASP agent supports Java 6 through 25, so the protected matrix targets Java 6+.) +- **`-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 invocations: + +```sh +# Java 8, Servlet 3.0 (recommended) +$ mvn install -Dversion.jdk=1.8 -Dversion.webxml=30 + +# Java 6, Servlet 3.0 (minimum supported level) +$ mvn install -Dversion.jdk=1.6 -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. 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 + +- **`master` (this branch)** — Modern, parameterised source tree. Java 6+ source level (`-Dversion.jdk=1.6|1.7|1.8`). The only branch the Waratek RASP suite runs against, since the agent supports Java 6 through 25. +- **`java5`** — Java 5 source-compatible variant (same source tree, built at `-Dversion.jdk=1.5`). No RASP suite — the agent does not support Java 5. +- **`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..edd7b74 --- /dev/null +++ b/docker-compose.mssql.yml @@ -0,0 +1,62 @@ +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 + args: + # Defaults reproduce the historical Java 8 image. Override via the + # environment (see scripts/rasp-matrix.sh) to build for Java 6..25. + BUILD_JDK: "${BUILD_JDK:-8}" + VERSION_JDK: "${VERSION_JDK:-1.8}" + VERSION_WEBXML: "${VERSION_WEBXML:-30}" + RUNTIME_BASE: "${RUNTIME_BASE:-eclipse-temurin:8-jre}" + TOMCAT_MAJOR: "${TOMCAT_MAJOR:-9}" + TOMCAT_VERSION: "${TOMCAT_VERSION:-9.0.118}" + MAVEN_OPTS: "${MAVEN_OPTS:-}" + 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..4d3c502 --- /dev/null +++ b/docker-compose.mysql.yml @@ -0,0 +1,43 @@ +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 + args: + # Defaults reproduce the historical Java 8 image. Override via the + # environment (see scripts/rasp-matrix.sh) to build for Java 6..25. + BUILD_JDK: "${BUILD_JDK:-8}" + VERSION_JDK: "${VERSION_JDK:-1.8}" + VERSION_WEBXML: "${VERSION_WEBXML:-30}" + RUNTIME_BASE: "${RUNTIME_BASE:-eclipse-temurin:8-jre}" + TOMCAT_MAJOR: "${TOMCAT_MAJOR:-9}" + TOMCAT_VERSION: "${TOMCAT_VERSION:-9.0.118}" + MAVEN_OPTS: "${MAVEN_OPTS:-}" + 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..761025e --- /dev/null +++ b/docker-compose.oracle.yml @@ -0,0 +1,39 @@ +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 + args: + # Defaults reproduce the historical Java 8 image. Override via the + # environment (see scripts/rasp-matrix.sh) to build for Java 6..25. + BUILD_JDK: "${BUILD_JDK:-8}" + VERSION_JDK: "${VERSION_JDK:-1.8}" + VERSION_WEBXML: "${VERSION_WEBXML:-30}" + RUNTIME_BASE: "${RUNTIME_BASE:-eclipse-temurin:8-jre}" + TOMCAT_MAJOR: "${TOMCAT_MAJOR:-9}" + TOMCAT_VERSION: "${TOMCAT_VERSION:-9.0.118}" + MAVEN_OPTS: "${MAVEN_OPTS:-}" + 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-compose.rasp-agent.yml b/docker-compose.rasp-agent.yml new file mode 100644 index 0000000..4ee5b51 --- /dev/null +++ b/docker-compose.rasp-agent.yml @@ -0,0 +1,23 @@ +# ============================================================================= +# Overlay compose that attaches the Waratek RASP agent to the app container. +# +# The agent binary is NOT shipped in this repo. Point AGENT_DIR at a prepared +# agent directory (waratek.jar, core.jar, compiler-8.jar, a standalone +# waratek.properties and a SQL-injection rules.armr). scripts/rasp-matrix.sh +# prepares that directory for you (`setup-agent`). +# +# Usage (layered on top of a database compose file): +# +# AGENT_DIR=/abs/path/to/agent docker compose \ +# -f docker-compose.mysql.yml -f docker-compose.rasp-agent.yml up -d +# +# The agent supports Java 6..25, so this overlay is version-independent — it +# works against any image the parameterised Dockerfile produces. +# ============================================================================= +services: + app: + environment: + # catalina.sh honours CATALINA_OPTS; this attaches the agent at JVM start. + CATALINA_OPTS: "-javaagent:/opt/waratek/waratek.jar -Dcom.waratek.WaratekProperties=/opt/waratek/waratek.properties" + volumes: + - "${AGENT_DIR:?set AGENT_DIR to a prepared Waratek agent directory}:/opt/waratek:rw" diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..0e0fb71 --- /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.6 -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/docs/multi-version-testing.md b/docs/multi-version-testing.md new file mode 100644 index 0000000..877d34a --- /dev/null +++ b/docs/multi-version-testing.md @@ -0,0 +1,174 @@ +# Multi-version testing (Java 6 – 25) from one Dockerfile + +The Waratek RASP agent supports **Java 6 through 25**. To prove the +SQL-injection matrix (`tests/hurl/rasp`, 440 cases) blocks on every one of those +runtimes, Spiracle builds and runs under any Java version **without a Dockerfile +per version**. A single parameterised `Dockerfile` is driven by five build args; +a small matrix in `scripts/rasp-matrix.sh` maps a Java version onto those args. + +``` +scripts/rasp-matrix.sh ── matrix: Java 6..25 → build args + │ + ├─ docker-compose..yml (build.args from env) + ├─ docker-compose.rasp-agent.yml (attaches the Waratek agent) + └─ Dockerfile (ARG-parameterised, one file) +``` + +## The two axes + +"Run on Java N" is ambiguous — two things vary independently, and the matrix +sets both: + +| Axis | Build arg(s) | What it controls | +|---|---|---| +| **Runtime JRE** | `RUNTIME_BASE` | the JVM the agent actually instruments — the real "run on Java N" | +| **Source/target level** | `VERSION_JDK` + `BUILD_JDK` | the bytecode level the WAR is compiled to | + +`VERSION_JDK` is fed to Maven as `-Dversion.jdk` (the pom's +`maven.compiler.source`/`target`). Its spelling flips at Java 9: `1.6`, `1.7`, +`1.8`, then bare `9` … `25`. + +## The build args + +| Arg | Default | Meaning | +|---|---|---| +| `BUILD_JDK` | `8` | JDK image used to **compile** (`maven:3.9-eclipse-temurin-${BUILD_JDK}`) | +| `VERSION_JDK` | `1.8` | `-Dversion.jdk` source/target level | +| `VERSION_WEBXML` | `30` | Servlet descriptor (25 or 30) | +| `RUNTIME_BASE` | `eclipse-temurin:8-jre` | JRE image the app runs on | +| `TOMCAT_MAJOR` | `9` | Tomcat major line | +| `TOMCAT_VERSION` | `9.0.118` | Tomcat patch (installed from `archive.apache.org`) | + +The defaults reproduce the historical Java 8 / Tomcat 9 image, so a plain +`docker compose build` is unchanged. + +### Why the runtime is "JRE base + assembled Tomcat" + +Docker Hub only publishes `tomcat:9-jreN` tags for **LTS** JREs (8, 11, 17, 21). +Instead, the **build stage** downloads Tomcat from the Apache archive +(`archive.apache.org`, which keeps every patch — `dlcdn` keeps only the latest), +explodes the WAR into it with `jar`, and drops in the JDBC drivers. The runtime +stage then just `COPY`s that self-contained Tomcat onto a plain JRE image and +installs **nothing** — no apt/curl/unzip. This makes the runtime uniform for +every Java the base ships (Temurin 8–25) *and* works on legacy bases whose +package repos are dead (the Azul Zulu 6/7 images used for the tail). + +## The version matrix + +`scripts/rasp-matrix.sh matrix ` resolves a version. Bands: + +| Java | `VERSION_JDK` | `BUILD_JDK` | `RUNTIME_BASE` | Tomcat | +|---|---|---|---|---| +| 6 | `1.6` | 8 | `azul/zulu-openjdk:6` | 7.0.x | +| 7 | `1.7` | 8 | `azul/zulu-openjdk:7` | 8.5.x | +| 8 | `1.8` | 8 | `eclipse-temurin:8-jre` | 9.0.x | +| 9–10 | `9`/`10` | 11 | `eclipse-temurin:11-jre` | 9.0.x | +| 11 | `11` | 11 | `eclipse-temurin:11-jre` | 9.0.x | +| 12–16 | `12`…`16` | 17 | `eclipse-temurin:17-jre` | 9.0.x | +| 17 | `17` | 17 | `eclipse-temurin:17-jre` | 9.0.x | +| 18–20 | `18`…`20` | 21 | `eclipse-temurin:21-jre` | 9.0.x | +| 21 | `21` | 21 | `eclipse-temurin:21-jre` | 9.0.x | +| 22–24 | `22`…`24` | 25 | `eclipse-temurin:${N}-jre` | 9.0.x | +| 25 | `25` | 25 | `eclipse-temurin:25-jre` | 9.0.x | + +**Why a `BUILD_JDK` band and not one JDK?** `javac` drops old `-source/-target` +support over time (target 1.6 needs JDK ≤ 11; target 25 needs JDK 25). Five LTS +build JDKs cover the whole range. The non-LTS rows compile at their exact level +but **run** on the nearest LTS JRE that hosts that bytecode (e.g. Java 13 → built +with JDK 17, runs on `temurin:17-jre`) because Temurin has no `13-jre` image. Set +`RUNTIME_BASE` yourself (BellSoft Liberica, SapMachine, …) if you need the exact +non-LTS JRE. + +## Caveats / edges + +- **Java 6 & 7 (the tail)** — Tomcat 9 and Temurin both floor at Java 8, so the + tail runs **Tomcat 7/8 on an Azul Zulu JRE 6/7 base** (Azul still publishes + these; Temurin/Docker-official do not). `ojdbc8`/`mssql-jdbc.jre8` need Java 8+ + and won't load there, so **only MySQL works on 6/7**. **Both 6 and 7 are + verified end-to-end** — build + agent attach + rasp/mysql 139/139 → 550 — after + three fixes that the tail surfaced: + 1. **Build** — `zulu:6`'s base OS has dead apt repos, so installing packages + in the runtime stage failed. The Dockerfile now assembles Tomcat entirely + in the **build stage** and `COPY`s it in; the runtime stage installs + nothing, so any JRE base works. + 2. **Deploy** — `SpiracleInit` eagerly `Class.forName`s every JDBC driver but + caught only `ClassNotFoundException`. The Java-8 drivers throw + `UnsupportedClassVersionError` (a `LinkageError`) on JRE 6/7, which made + Tomcat 8.5 fail the context ("One or more listeners failed to start"; + Tomcat 9 tolerated it). Broadened to `catch (Throwable)`. + 3. **Connect** — JRE 6 speaks only TLS 1.0, but `mysql:8.0` requires TLS 1.2+, + so the SSL handshake died (`SSLException: protocol_version`). The mysql URL + now sets `useSSL=false` (fine for the local throwaway DB; harmless on 8–25). + The agent attaches on JRE 6/7 because `compiler-8.jar` covers the 6–8 tier + (the bundle ships `compiler-{8,17,21,25}.jar`). +- **Non-LTS old versions (9, 10, 12–16, 18–20)** have no Temurin JRE image; the + matrix runs them on the nearest LTS JRE. Override `RUNTIME_BASE` for an exact + JRE. +- **`tomcat:9-jre25`** may not be published; the tarball-install path sidesteps + this — only `eclipse-temurin:25-jre` must exist (it does). +- **rasp suite DB coverage** — `tests/hurl/rasp/` ships matrices for **MySQL + (139) and Oracle (301)** only; there is no MSSQL rasp suite. The agent rule is + `vendor(any)`, so MSSQL injection would be blocked too, but the MSSQL Docker + stack (`docker-compose.mssql.yml`) currently fails to seed in this environment + (`db-init`: SA login fails → `spiracle` DB not created) — a pre-existing stack + issue independent of this work. + +## The agent + +The RASP suite needs the Waratek agent attached. The agent binary is **not** in +this repo. `scripts/rasp-matrix.sh setup-agent` copies a prepared agent +(`AGENT_SRC`, default `../agent-test`) to `AGENT_DIR` (default `../agent-run`) +and writes: + +- a **standalone** `waratek.properties` (`com.waratek.ControllerPresent=false`) + so the agent runs headless with local rules — no Portal/controller needed; +- a **SQL-injection PROTECT** `rules.armr`: + + ``` + sql("Block SQL injection from HTTP, any vendor"): + vendor(any) + input(http) + injection(successful-attempt, failed-attempt) + protect(message: "...", severity: Very-High) + endsql + ``` + + The block message is hardcoded in the agent and surfaced as a + `java.sql.SQLException` only on a `protect` action; Spiracle's + `SelectUtil.verifySQLException` maps that exact message to **HTTP 550**, which + the rasp suite asserts. + +`docker-compose.rasp-agent.yml` mounts `AGENT_DIR` at `/opt/waratek` and sets +`CATALINA_OPTS=-javaagent:/opt/waratek/waratek.jar …`. + +## Usage + +```sh +# Inspect the resolved args for a version +./scripts/rasp-matrix.sh matrix 17 + +# Build only +./scripts/rasp-matrix.sh build 21 mysql + +# Build + attach agent + run the rasp suite + tear down +./scripts/rasp-matrix.sh test 17 mysql +./scripts/rasp-matrix.sh test 21 oracle + +# Sweep several versions and print a PASS/FAIL summary +./scripts/rasp-matrix.sh sweep "8 11 17 21 25" mysql + +# No agent: smoke + functional on a plain deployment +./scripts/rasp-matrix.sh plain 17 mysql +``` + +Environment overrides: `AGENT_SRC`, `AGENT_DIR`, `HURL_LIBS` (dir holding +`libxml2.so.2` etc. for the `hurl` binary), `KEEP_UP=1` (leave the stack up). + +## Files + +| File | Role | +|---|---| +| `Dockerfile` | one parameterised build (5 ARGs) | +| `docker-compose.{mysql,oracle,mssql}.yml` | `build.args` wired to env vars | +| `docker-compose.rasp-agent.yml` | overlay that attaches the agent | +| `scripts/rasp-matrix.sh` | matrix + build/test/sweep driver | diff --git a/scripts/rasp-matrix.sh b/scripts/rasp-matrix.sh new file mode 100755 index 0000000..5360767 --- /dev/null +++ b/scripts/rasp-matrix.sh @@ -0,0 +1,258 @@ +#!/usr/bin/env bash +# ============================================================================= +# rasp-matrix.sh — build & RASP-test Spiracle across Java 6..25 from ONE +# Dockerfile, by resolving each Java version to a set of Docker build args. +# +# The Waratek RASP agent supports Java 6 through 25; this script lets you run +# the 440-case SQL-injection matrix (tests/hurl/rasp) against the app on any +# of those runtimes without maintaining a Dockerfile per version. +# +# COMMANDS +# matrix Print the resolved build args for a Java version. +# setup-agent Prepare the agent dir (copy + standalone config). +# build [db] Build the image for (db: mysql|oracle|mssql). +# test [db] Build, start db+app+agent, run the rasp suite, tear down. +# sweep "" [db] test each Java version in turn; print a summary. +# plain [db] Like test but NO agent (runs smoke+functional instead). +# +# ENV OVERRIDES +# AGENT_SRC source agent dir to copy (default: ../agent-test) +# AGENT_DIR prepared agent dir (mounted) (default: ../agent-run) +# HURL_LIBS dir with libxml2.so.2 etc. (default: ~/.local/hurl-libs) +# KEEP_UP=1 do not tear the stack down after test +# +# EXAMPLES +# ./scripts/rasp-matrix.sh test 17 mysql +# ./scripts/rasp-matrix.sh sweep "8 11 17 21" mysql +# ./scripts/rasp-matrix.sh sweep "8 11 17 21" oracle +# +# See docs/multi-version-testing.md for the design and the matrix rationale. +# ============================================================================= +set -euo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$REPO" + +AGENT_SRC="${AGENT_SRC:-$REPO/../agent-test}" +AGENT_DIR="${AGENT_DIR:-$REPO/../agent-run}" +HURL_LIBS="${HURL_LIBS:-$HOME/.local/hurl-libs}" + +# --------------------------------------------------------------------------- +# Version matrix: Java level -> (BUILD_JDK, VERSION_JDK, RUNTIME_BASE, +# TOMCAT_MAJOR, TOMCAT_VERSION). Emitted as KEY=VALUE lines. +# +# * BUILD_JDK bands: one JDK cannot target every source level, so pick the +# oldest LTS JDK that still supports the target (8 -> 6/7/8, 11 -> 9/10/11, +# 17 -> 12..17, 21 -> 18..21, 25 -> 22..25). +# * VERSION_JDK: 6/7/8 use the legacy 1.x spelling; 9+ are bare numbers. +# * RUNTIME_BASE: a plain JRE image; Tomcat 9 is installed from the archive. +# Eclipse Temurin publishes JRE images for 8/11/17/21 and recent (22..25). +# Non-LTS old versions (9,10,12..16,18..20) have no Temurin JRE image — they +# are marked best-effort and will need a different vendor base (set +# RUNTIME_BASE yourself, e.g. a BellSoft Liberica or SapMachine image). +# * Java 6/7: Tomcat 9 needs Java 8+, so the tail drops to Tomcat 7/8 on a +# legacy JRE 6/7 image you must supply (RUNTIME_BASE), and ojdbc8/mssql-jdbc +# (Java 8+) won't load — only MySQL works there. +# --------------------------------------------------------------------------- +matrix() { + local j="$1" build vjdk base tmaj tver note="" + case "$j" in + 6) build=8; vjdk=1.6; base="azul/zulu-openjdk:6"; tmaj=7; tver=7.0.109; note="tail: Azul Zulu JRE6 + Tomcat7; MySQL only (ojdbc8/mssql-jdbc need Java 8+)";; + 7) build=8; vjdk=1.7; base="azul/zulu-openjdk:7"; tmaj=8; tver=8.5.100; note="tail: Azul Zulu JRE7 + Tomcat8.5; MySQL only (ojdbc8/mssql-jdbc need Java 8+)";; + 8) build=8; vjdk=1.8; base="eclipse-temurin:8-jre"; tmaj=9; tver=9.0.118;; + 9) build=11; vjdk=9; base="eclipse-temurin:11-jre"; tmaj=9; tver=9.0.118; note="non-LTS: runs on JRE11 (no temurin:9-jre)";; + 10) build=11; vjdk=10; base="eclipse-temurin:11-jre"; tmaj=9; tver=9.0.118; note="non-LTS: runs on JRE11";; + 11) build=11; vjdk=11; base="eclipse-temurin:11-jre"; tmaj=9; tver=9.0.118;; + 12|13|14|15|16) build=17; vjdk="$j"; base="eclipse-temurin:17-jre"; tmaj=9; tver=9.0.118; note="non-LTS: runs on JRE17";; + 17) build=17; vjdk=17; base="eclipse-temurin:17-jre"; tmaj=9; tver=9.0.118;; + 18|19|20) build=21; vjdk="$j"; base="eclipse-temurin:21-jre"; tmaj=9; tver=9.0.118; note="non-LTS: runs on JRE21";; + 21) build=21; vjdk=21; base="eclipse-temurin:21-jre"; tmaj=9; tver=9.0.118;; + 22|23|24) build=25; vjdk="$j"; base="eclipse-temurin:${j}-jre"; tmaj=9; tver=9.0.118; note="non-LTS: temurin:${j}-jre may be unavailable";; + 25) build=25; vjdk=25; base="eclipse-temurin:25-jre"; tmaj=9; tver=9.0.118;; + *) echo "ERROR: unsupported Java version '$j' (expected 6..25)" >&2; return 1;; + esac + # JDK 16+ strongly encapsulates the JDK internals the legacy Maven plugins + # reflect into; open them so the build runs. Harmless to omit on 8/11. + local mopts="" + if [ "$build" -ge 16 ] 2>/dev/null; then + mopts="--add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.text=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.desktop/java.awt.font=ALL-UNNAMED" + fi + cat <&2 || true +} + +# --------------------------------------------------------------------------- +# Agent preparation: copy the pristine agent, write a standalone (no-controller) +# waratek.properties and a SQL-injection PROTECT rule that makes blocked queries +# return HTTP 550 (the message is hardcoded in the agent; `protect` triggers it). +# --------------------------------------------------------------------------- +setup_agent() { + [ -f "$AGENT_SRC/waratek.jar" ] || { echo "ERROR: no waratek.jar under AGENT_SRC=$AGENT_SRC" >&2; return 1; } + echo "Preparing agent: $AGENT_SRC -> $AGENT_DIR" + rm -rf "$AGENT_DIR"; mkdir -p "$AGENT_DIR" + cp -a "$AGENT_SRC/." "$AGENT_DIR/" + rm -f "$AGENT_DIR/instance.waratek.properties.lock" "$AGENT_DIR/rules.log" "$AGENT_DIR/events.log" + + cat > "$AGENT_DIR/waratek.properties" <<'PROPS' +# Standalone (headless) — no controller, local ARMR rules only. +com.waratek.ControllerPresent=false +com.waratek.ControllerUnavailableAction=ignore +com.waratek.rules.local=/opt/waratek/rules.armr +com.waratek.log.file=/opt/waratek/events.log +com.waratek.rules.autoreload=true +com.waratek.ShowStart=true +PROPS + + cat > "$AGENT_DIR/rules.armr" <<'ARMR' +app("Spiracle SQLi protect"): + requires(version: ARMR/2.12) + sql("Block SQL injection from HTTP, any vendor"): + vendor(any) + input(http) + injection(successful-attempt, failed-attempt) + protect(message: "SQL injection blocked", severity: Very-High) + endsql +endapp +ARMR + echo "Agent ready at $AGENT_DIR (ControllerPresent=false, SQLi protect rule installed)." +} + +hurl() { LD_LIBRARY_PATH="$HURL_LIBS" command hurl "$@"; } + +compose_files() { # echoes -f args for a db, optionally + agent overlay + local db="$1" agent="${2:-}" + printf -- '-f %s ' "$REPO/docker-compose.${db}.yml" + [ "$agent" = agent ] && printf -- '-f %s ' "$REPO/docker-compose.rasp-agent.yml" +} + +wait_app() { # wait for app root 200 (default 120s) + local i=0 max="${1:-40}" + until [ "$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8080/spiracle/ 2>/dev/null)" = 200 ] || [ $i -ge "$max" ]; do + i=$((i+1)); sleep 3 + done + [ "$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8080/spiracle/ 2>/dev/null)" = 200 ] +} + +build() { # build [db] + local j="$1" db="${2:-mysql}" + load_matrix "$j" + echo "==> build Java $j (BUILD_JDK=$BUILD_JDK VERSION_JDK=$VERSION_JDK RUNTIME_BASE=$RUNTIME_BASE Tomcat $TOMCAT_VERSION)" + docker compose $(compose_files "$db") build app +} + +test_version() { # test [db] — with agent + rasp suite + local j="$1" db="${2:-mysql}" + local proj="rasp${j}_$$" + load_matrix "$j" + setup_agent + echo "==> Java $j / $db : build + up (agent attached)" + AGENT_DIR="$AGENT_DIR" docker compose -p "$proj" $(compose_files "$db" agent) up -d --build + local rc=0 + if wait_app; then + echo "==> app ready; running rasp/$db" + if hurl --test --variables-file "$REPO/tests/hurl/rasp/protected.env" \ + --variable host=localhost --variable port=8080 --variable block_status=550 \ + "$REPO"/tests/hurl/rasp/${db}/*.hurl; then + echo "RESULT Java $j ($db): PASS" + else + echo "RESULT Java $j ($db): FAIL (rasp assertions)"; rc=1 + fi + else + echo "RESULT Java $j ($db): FAIL (app did not become ready)"; rc=1 + AGENT_DIR="$AGENT_DIR" docker compose -p "$proj" $(compose_files "$db" agent) logs app | tail -50 || true + fi + if [ "${KEEP_UP:-0}" = 1 ]; then + echo "KEEP_UP=1 — leaving stack '$proj' running" + else + AGENT_DIR="$AGENT_DIR" docker compose -p "$proj" $(compose_files "$db" agent) down -v >/dev/null 2>&1 || true + fi + return $rc +} + +plain_version() { # plain [db] — no agent; smoke+functional + local j="$1" db="${2:-mysql}" + local proj="plain${j}_$$" + load_matrix "$j" + echo "==> Java $j / $db : build + up (no agent)" + docker compose -p "$proj" $(compose_files "$db") up -d --build + local rc=0 + if wait_app; then + hurl --test --variables-file "$REPO/tests/hurl/smoke/local.env" \ + --variable host=localhost --variable port=8080 "$REPO"/tests/hurl/smoke/*.hurl \ + && hurl --test --variables-file "$REPO/tests/hurl/functional/local.env" \ + --variable host=localhost --variable port=8080 "$REPO"/tests/hurl/functional/*.hurl \ + && echo "RESULT Java $j ($db, plain): PASS" || { echo "RESULT Java $j ($db, plain): FAIL"; rc=1; } + else + echo "RESULT Java $j ($db, plain): FAIL (app not ready)"; rc=1 + fi + [ "${KEEP_UP:-0}" = 1 ] || docker compose -p "$proj" $(compose_files "$db") down -v >/dev/null 2>&1 || true + return $rc +} + +sweep() { # sweep "" [db] + local versions="$1" db="${2:-mysql}" v results="" + for v in $versions; do + if test_version "$v" "$db"; then results="$results\nJava $v ($db): PASS" + else results="$results\nJava $v ($db): FAIL"; fi + done + echo "==================== SWEEP SUMMARY ($db) ====================" + echo -e "$results" +} + +# Full matrix: smoke+functional + rasp/mysql on every distinct runtime band, +# plus rasp/oracle and rasp/mssql on Java 8+ (those drivers need Java 8+). The +# bands {6,7,8,11,17,21,25} cover every distinct RUNTIME_BASE/BUILD_JDK — the +# non-LTS versions in between share a neighbour's JRE. +full() { + local mysql_versions="${1:-6 7 8 11 17 21 25}" + local java8plus="${2:-8 11 17 21 25}" + local results="" v + for v in $mysql_versions; do + if plain_version "$v" mysql; then results="$results\nsmoke+functional Java $v : PASS" + else results="$results\nsmoke+functional Java $v : FAIL"; fi + done + for v in $mysql_versions; do + if test_version "$v" mysql; then results="$results\nrasp mysql Java $v : PASS" + else results="$results\nrasp mysql Java $v : FAIL"; fi + done + for v in $java8plus; do + if test_version "$v" oracle; then results="$results\nrasp oracle Java $v : PASS" + else results="$results\nrasp oracle Java $v : FAIL"; fi + done + for v in $java8plus; do + if test_version "$v" mssql; then results="$results\nrasp mssql Java $v : PASS" + else results="$results\nrasp mssql Java $v : FAIL"; fi + done + echo "==================== FULL MATRIX SUMMARY ====================" + echo -e "$results" +} + +usage() { sed -n '2,40p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; } + +cmd="${1:-}"; shift || true +case "$cmd" in + matrix) matrix "${1:?Java version}";; + setup-agent) setup_agent;; + build) build "${1:?Java version}" "${2:-mysql}";; + test) test_version "${1:?Java version}" "${2:-mysql}";; + plain) plain_version "${1:?Java version}" "${2:-mysql}";; + sweep) sweep "${1:?versions, e.g. \"8 11 17 21\"}" "${2:-mysql}";; + full) full "${1:-}" "${2:-}";; + ""|-h|--help) usage;; + *) echo "unknown command '$cmd'" >&2; usage; exit 2;; +esac diff --git a/src/main/java/com/waratek/spiracle/init/SpiracleInit.java b/src/main/java/com/waratek/spiracle/init/SpiracleInit.java index 6c44d64..fd178d5 100644 --- a/src/main/java/com/waratek/spiracle/init/SpiracleInit.java +++ b/src/main/java/com/waratek/spiracle/init/SpiracleInit.java @@ -84,9 +84,8 @@ public void contextInitialized(ServletContextEvent arg0) { Class.forName(props.getProperty(Constants.C3P0_DB2_CLASSNAME)); Class.forName(props.getProperty(Constants.C3P0_SYBASE_CLASSNAME)); Class.forName(props.getProperty(Constants.C3P0_POSTGRES_CLASSNAME)); - } catch (ClassNotFoundException e) { - logger.error("Unable to load JDBC connector classes from config."); - e.printStackTrace(); + } catch (Throwable e) { + logger.error("Unable to load one or more JDBC connector classes from config: " + e); } } 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/java/com/waratek/spiracle/sql/jndi/CreateJndiConnectionPool.java b/src/main/java/com/waratek/spiracle/sql/jndi/CreateJndiConnectionPool.java index fcf2cdd..63c64b9 100644 --- a/src/main/java/com/waratek/spiracle/sql/jndi/CreateJndiConnectionPool.java +++ b/src/main/java/com/waratek/spiracle/sql/jndi/CreateJndiConnectionPool.java @@ -26,9 +26,8 @@ public void contextInitialized(ServletContextEvent arg0) { ServletContext application = arg0.getServletContext(); application.setAttribute("jndiConnectionPool", ds); logger.info("Added jndi connection pool " + ds + " to application context."); - } catch (NamingException e) { - logger.error("JNDI reference not found."); - e.printStackTrace(); + } catch (Throwable e) { + logger.error("Optional JNDI resource jdbc/oracle not bound; continuing without it: " + e); } } } diff --git a/src/main/webapp/conf/Spiracle.properties b/src/main/webapp/conf/Spiracle.properties index 58cec1d..414546f 100644 --- a/src/main/webapp/conf/Spiracle.properties +++ b/src/main/webapp/conf/Spiracle.properties @@ -9,7 +9,7 @@ c3p0.oracle.password=test c3p0.oracle.maxPoolSize=50 c3p0.mysql.classname=com.mysql.jdbc.Driver -c3p0.mysql.url=jdbc:mysql://localhost:3306/test +c3p0.mysql.url=jdbc:mysql://localhost:3306/test?useSSL=false c3p0.mysql.username=test c3p0.mysql.password=test c3p0.mysql.maxPoolSize=50 diff --git a/src/main/webapp/conf/setupdb_mssql.sql b/src/main/webapp/conf/setupdb_mssql.sql index 14af500..409ec45 100644 --- a/src/main/webapp/conf/setupdb_mssql.sql +++ b/src/main/webapp/conf/setupdb_mssql.sql @@ -1,10 +1,13 @@ create database spiracle; +GO use spiracle; +GO -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; +GO CREATE TABLE users ( id int, @@ -27,6 +30,7 @@ CREATE TABLE TEXT_STORE ID int, DATA text ); +GO INSERT INTO users (id, name, surname, dob, credit_card, cvv) VALUES (1, 'Patrick', 'Moss', '1955-08-29', '5566 0717 3093 3773', 341); INSERT INTO users (id, name, surname, dob, credit_card, cvv) VALUES (2, 'Margaret', 'Thomas', '1959-01-15', '3461 7946 3370 838', 475); 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..a0f6c16 --- /dev/null +++ b/tests/hurl/README.md @@ -0,0 +1,124 @@ +# 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). + +--- + +## The 550 status requires the Waratek RASP agent + +The number `550` is **not** a standard HTTP status code. +`SelectUtil.verifySQLException` emits it **only** when the SQLException +message is exactly `"Attempted to execute a query with one or more bad +parameters."` — that string is produced by the **Waratek RASP agent** +intercepting the query before it reaches the database. + +**Without the Waratek agent** (e.g. plain Tomcat, CI Docker stack): + +| Payload type | Status code | +|--------------------------|-------------| +| Valid-SQL injection | **200** | +| Malformed/syntax error | **500** | +| Agent-blocked injection | **550** | + +You will **never** see 550 on a plain deployment. +The RASP suite will fail entirely without the agent — this is expected. + +--- + +## Suite layout + +`tests/hurl/` holds three suites: + +- `smoke/` and `functional/` — endpoint behaviour on a plain (no-agent) deployment. +- `rasp/` — the RASP-efficacy matrix under `mysql/` and `oracle/`; requires the Waratek agent. + +--- + +## Running the functional suite (plain Docker / CI) + +The functional suite validates endpoint behaviour without any RASP agent: + +| 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` + (documenting that injections are NOT blocked without the agent) + +```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 +``` + +--- + +## Running the RASP suite (Waratek agent required) + +```sh +# With agent attached to Tomcat: +./tests/hurl/run.sh rasp localhost 8080 + +# Override host/port: +./tests/hurl/run.sh rasp myserver.internal 9090 + +# Override expected block status (if agent uses a different code): +BLOCK_STATUS=403 ./tests/hurl/run.sh rasp localhost 8080 + +# Run a single servlet's cases: +hurl --test \ + --variables-file tests/hurl/rasp/protected.env \ + tests/hurl/rasp/mysql/get_int.hurl +``` + +Reports are written as JUnit XML to `/tmp/spiracle-{smoke,rasp}-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 == {{block_status}} +``` + +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..d9a54bb --- /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 +# Without the Waratek RASP agent 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..a3e9fd8 --- /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. +# Without a RASP agent 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..2ad1e3c --- /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 — those are agent-trigger targets, 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/rasp/mssql/get_implicit_join.hurl b/tests/hurl/rasp/mssql/get_implicit_join.hurl new file mode 100644 index 0000000..dab3d34 --- /dev/null +++ b/tests/hurl/rasp/mssql/get_implicit_join.hurl @@ -0,0 +1,179 @@ +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='2'%20OR%20'name'%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='1'%20or%20'name'%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='1'%20or%20users.id%20like%201 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='1'%20or%20'users.name'%20like'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='1'%20AND%20'users.cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='1'%20AND%20'DOB'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='1'%20AND%20'cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='1'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='1'%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=''%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=('hi')%20or%20('a'='a') + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='joe'%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=''%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id='Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=1%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=''%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=''%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=''%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_Implicit_Join?id=%27%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/mssql/get_int.hurl b/tests/hurl/rasp/mssql/get_int.hurl new file mode 100644 index 0000000..59f2033 --- /dev/null +++ b/tests/hurl/rasp/mssql/get_int.hurl @@ -0,0 +1,179 @@ +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=2'%20OR%20name%20LIKE%20'%25'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20%7C%7C%20name%20like%20'%25'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20or%20users.name%20LIKE%20'%25'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20or%20id%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20OR%20100=(SELECT%20COUNT(*)%20FROM%20users)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20OR%20users.cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20AND%20DOB%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20OR%20cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20OR%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20or%201=1%20or%20'x'='y'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id='%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=(%22hi%22)'%20or%20('a'='a')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=a'%20or%20'a'%20=%20'a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=joe'%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20UNION%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=%27%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id='%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=1'%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id=%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_int?id='%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/mssql/get_string.hurl b/tests/hurl/rasp/mssql/get_string.hurl new file mode 100644 index 0000000..f6ce144 --- /dev/null +++ b/tests/hurl/rasp/mssql/get_string.hurl @@ -0,0 +1,119 @@ +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=x'%20or%20name%20like%20'%25'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=%3C%3E%22%2527%25%3B)(%26%2B + +HTTP * +[Asserts] +status == 200 + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=x'%20AND%20100=(SELECT%20COUNT(*)%20FROM%20address)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=x'%20OR%20cvv%20IS%20NULL-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=anything'%20OR%20'x'='x + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=x'%20or%201=1%20or%20'x'='y + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name='%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name='or%201=1%20or%20''=' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=a'%20or%20'a'%20=%20'a + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name='%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name='%20UNION%20SELECT%20*%20from%20users-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=%27%20or%20%27x%27=%27x + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name='or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name='%20or%201%20--' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name='%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Get_string?name=x'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/mssql/get_union.hurl b/tests/hurl/rasp/mssql/get_union.hurl new file mode 100644 index 0000000..9b88ada --- /dev/null +++ b/tests/hurl/rasp/mssql/get_union.hurl @@ -0,0 +1,173 @@ +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='2'%20OR%20'name'%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%20'name'%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%20id%20like%201 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%20'name'%20like'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20AND%20'users.cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20AND%20'DOB'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20AND%20'cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='(%22hi%22)'%20or%20('a'='a')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='joe'%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=''%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=1%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/mssql/implicit_join_namespace.hurl b/tests/hurl/rasp/mssql/implicit_join_namespace.hurl new file mode 100644 index 0000000..9caadd3 --- /dev/null +++ b/tests/hurl/rasp/mssql/implicit_join_namespace.hurl @@ -0,0 +1,179 @@ +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='2'%20OR%20'name'%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='1'%20or%20'name'%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='1'%20or%20users.id%20like%201 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='1'%20or%20'users.name'%20like'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='1'%20AND%20'users.cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='1'%20AND%20'DOB'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='1'%20AND%20'cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='1'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='1'%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=''%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=('hi')%20or%20('a'='a') + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='joe'%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=''%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id='Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=1%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=''%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=''%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=''%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MsSql_Implicit_Join_Namespace?id=%27%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/mysql/get_implicit_join.hurl b/tests/hurl/rasp/mysql/get_implicit_join.hurl new file mode 100644 index 0000000..4e2428d --- /dev/null +++ b/tests/hurl/rasp/mysql/get_implicit_join.hurl @@ -0,0 +1,179 @@ +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='2'%20OR%20'name'%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='1'%20or%20'name'%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='1'%20or%20users.id%20like%201 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='1'%20or%20'users.name'%20like'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='1'%20AND%20'users.cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='1'%20AND%20'DOB'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='1'%20AND%20'cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='1'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='1'%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=''%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=('hi')%20or%20('a'='a') + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='joe'%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=''%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id='Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=1%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=''%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=''%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=''%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_Implicit_Join?id=%27%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/mysql/get_int.hurl b/tests/hurl/rasp/mysql/get_int.hurl new file mode 100644 index 0000000..ce71aeb --- /dev/null +++ b/tests/hurl/rasp/mysql/get_int.hurl @@ -0,0 +1,179 @@ +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=2'%20OR%20name%20LIKE%20'%25'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20%7C%7C%20name%20like%20'%25'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20or%20users.name%20LIKE%20'%25'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20or%20id%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20OR%20100=(SELECT%20COUNT(*)%20FROM%20users)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20OR%20users.cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20AND%20DOB%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20OR%20cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20OR%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20or%201=1%20or%20'x'='y'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id='%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=(%22hi%22)'%20or%20('a'='a')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=a'%20or%20'a'%20=%20'a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=joe'%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20UNION%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=%27%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id='%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=1'%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id=%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_int?id='%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/mysql/get_string.hurl b/tests/hurl/rasp/mysql/get_string.hurl new file mode 100644 index 0000000..8ab638e --- /dev/null +++ b/tests/hurl/rasp/mysql/get_string.hurl @@ -0,0 +1,119 @@ +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=x'%20or%20name%20like%20'%25'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=%3C%3E%22%2527%25%3B)(%26%2B + +HTTP * +[Asserts] +status == 200 + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=x'%20AND%20100=(SELECT%20COUNT(*)%20FROM%20address)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=x'%20OR%20cvv%20IS%20NULL-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=anything'%20OR%20'x'='x + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=x'%20or%201=1%20or%20'x'='y + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name='%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name='or%201=1%20or%20''=' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=a'%20or%20'a'%20=%20'a + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name='%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name='%20UNION%20SELECT%20*%20from%20users-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=%27%20or%20%27x%27=%27x + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name='or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name='%20or%201%20--' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name='%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Get_string?name=x'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/mysql/get_union.hurl b/tests/hurl/rasp/mysql/get_union.hurl new file mode 100644 index 0000000..9b88ada --- /dev/null +++ b/tests/hurl/rasp/mysql/get_union.hurl @@ -0,0 +1,173 @@ +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='2'%20OR%20'name'%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%20'name'%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%20id%20like%201 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%20'name'%20like'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20AND%20'users.cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20AND%20'DOB'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20AND%20'cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='(%22hi%22)'%20or%20('a'='a')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='joe'%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=''%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=1%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/mysql/implicit_join_namespace.hurl b/tests/hurl/rasp/mysql/implicit_join_namespace.hurl new file mode 100644 index 0000000..db24b55 --- /dev/null +++ b/tests/hurl/rasp/mysql/implicit_join_namespace.hurl @@ -0,0 +1,179 @@ +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='2'%20OR%20'name'%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='1'%20or%20'name'%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='1'%20or%20users.id%20like%201 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='1'%20or%20'users.name'%20like'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='1'%20AND%20'users.cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='1'%20AND%20'DOB'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='1'%20AND%20'cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='1'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='1'%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=''%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=('hi')%20or%20('a'='a') + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='joe'%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=''%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id='Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=1%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=''%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=''%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=''%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/MySql_Implicit_Join_Namespace?id=%27%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_full_outer_join.hurl b/tests/hurl/rasp/oracle/get_full_outer_join.hurl new file mode 100644 index 0000000..477e1fd --- /dev/null +++ b/tests/hurl/rasp/oracle/get_full_outer_join.hurl @@ -0,0 +1,173 @@ +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='2'%20OR%20'name'%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='1'%20or%20'name'%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='1'%20or%20users.id%20like%201 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='1'%20or%20'users.name'%20like'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='1'%20AND%20'users.cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='1'%20AND%20'DOB'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='1'%20AND%20'cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='1'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='1'%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id=''%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id=('hi')%20or%20('a'='a') + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='joe'%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id=''%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id='Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id=1%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id=''%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id=''%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id=%27%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Full_Outer_Join?id=''%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_implicit_join.hurl b/tests/hurl/rasp/oracle/get_implicit_join.hurl new file mode 100644 index 0000000..6b2df79 --- /dev/null +++ b/tests/hurl/rasp/oracle/get_implicit_join.hurl @@ -0,0 +1,173 @@ +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='2'%20OR%20'name'%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='1'%20or%20'name'%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='1'%20or%20users.id%20like%201 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='1'%20or%20'users.name'%20like'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='1'%20AND%20'users.cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='1'%20AND%20'DOB'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='1'%20AND%20'cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='1'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='1'%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id=''%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id=('hi')%20or%20('a'='a') + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='joe'%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id=''%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id='Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id=1%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id=''%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id=''%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id=''%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Implicit_Join?id=%27%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_int.hurl b/tests/hurl/rasp/oracle/get_int.hurl new file mode 100644 index 0000000..4664b88 --- /dev/null +++ b/tests/hurl/rasp/oracle/get_int.hurl @@ -0,0 +1,179 @@ +GET http://{{host}}:{{port}}/spiracle/Get_int?id=2'%20OR%20name%20LIKE%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20or%20name%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20or%20id%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id='%20or%20name%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20AND%20users.cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20AND%20DOB%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20AND%20cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20OR%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20or%201=1%20or%20'x'='y'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id='%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=(%22hi%22)'%20or%20('a'='a')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=a'%20or%20'a'%20=%20'a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=joe'%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20UNION%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id='%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=1'%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id=%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int?id='%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_int_groupby.hurl b/tests/hurl/rasp/oracle/get_int_groupby.hurl new file mode 100644 index 0000000..9225de0 --- /dev/null +++ b/tests/hurl/rasp/oracle/get_int_groupby.hurl @@ -0,0 +1,11 @@ +GET http://{{host}}:{{port}}/spiracle/Get_int_groupby?id=name%20union%20all%20select%20null,%20to_char(dob)%20from%20users + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_groupby?id=name%20union%20select%20null,%20to_char(dob)%20from%20users + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_int_having.hurl b/tests/hurl/rasp/oracle/get_int_having.hurl new file mode 100644 index 0000000..253fb73 --- /dev/null +++ b/tests/hurl/rasp/oracle/get_int_having.hurl @@ -0,0 +1,11 @@ +GET http://{{host}}:{{port}}/spiracle/Get_int_having?id=1%20union%20select%20to_char(dob)%20from%20users + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_having?id=1%20union%20all%20select%20to_char(dob)%20from%20users + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_int_inline.hurl b/tests/hurl/rasp/oracle/get_int_inline.hurl new file mode 100644 index 0000000..9983372 --- /dev/null +++ b/tests/hurl/rasp/oracle/get_int_inline.hurl @@ -0,0 +1,191 @@ +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20=%20'x'%20OR%20name%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20=%20''%20or%20name%20like%20'' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20id%20=%20''%20or%20id%20like%20'' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20=%20''%20or%20name%20like%20'' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20='x'%20AND%20users.cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20=%20'x'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20='Joe'%20AND%20DOB%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20='Joe'%20AND%20cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20='anything'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20=%20'x'%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20='Joe'%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20=%20''%20or%201=1%20or%20''='' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20=%20('hi')%20or%20('a'='a') + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20=%20'a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20=%20'joe'%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20='Joe'%20UNION%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name%20=%20(%27%27)%20or%20(%27x%27=%27x%27) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name=('')%20or%20('a'='a') + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='hi'%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name=''%20or%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='Joe'%20or%200=0%20# + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='Joe'%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='Joe'%20or%20''='' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='Joe'%20or%201=1 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='Joe'%20or%20''='' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='Joe'%20%20or%201=1 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='Joe%20%27%20or%201=1 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_inline?id=select%20*%20from%20users%20where%20name='Joe'%20or%203=3 + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_int_no_quote.hurl b/tests/hurl/rasp/oracle/get_int_no_quote.hurl new file mode 100644 index 0000000..c4d8ab6 --- /dev/null +++ b/tests/hurl/rasp/oracle/get_int_no_quote.hurl @@ -0,0 +1,197 @@ +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=2%20OR%20name%20LIKE%20'%25' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20or%20name%20like%20'%25' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20or%20id%20like%20'%25' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20or%20name%20like%20'%25' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20AND%20users.cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20AND%20DOB%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20AND%20cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20or%201=1%20or%20''='' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=''%20or%201=1%20or%20''='' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=('hi')%20or%20('a'='a') + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20UNION%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='joe'%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=(%27%27)%20or%20(%27x%27=%27x%27) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=('')%20or%20('a'='a') + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='hi'%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=''%20or%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='Joe'%20or%200=0%20# + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='Joe'%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20or%20''='' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id=1%20or%20''='' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='Joe'%20or%201=1 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='Joe'%20%20or%201=1 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='Joe%20%27%20or%201=1 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_no_quote?id='Joe'%20or%203=3 + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_int_nooutput.hurl b/tests/hurl/rasp/oracle/get_int_nooutput.hurl new file mode 100644 index 0000000..bb6e27e --- /dev/null +++ b/tests/hurl/rasp/oracle/get_int_nooutput.hurl @@ -0,0 +1,179 @@ +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=2'%20OR%20name%20LIKE%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20or%20name%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20or%20id%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id='%20or%20name%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20AND%20users.cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20AND%20DOB%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20AND%20cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20OR%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20or%201=1%20or%20'x'='y'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id='%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=(%22hi%22)'%20or%20('a'='a')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=a'%20or%20'a'%20=%20'a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=joe'%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20UNION%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id='%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id='%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1'%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id=1%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id='%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_nooutput?id='%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_int_partialunion.hurl b/tests/hurl/rasp/oracle/get_int_partialunion.hurl new file mode 100644 index 0000000..a457a3b --- /dev/null +++ b/tests/hurl/rasp/oracle/get_int_partialunion.hurl @@ -0,0 +1,179 @@ +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=2'%20OR%20name%20LIKE%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20or%20name%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20or%20id%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id='%20or%20name%20like%20'%25 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20AND%20users.cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20AND%20DOB%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20AND%20cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20OR%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20or%201=1%20or%20'x'='y'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id='%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=(%22hi%22)'%20or%20('a'='a')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=a'%20or%20'a'%20=%20'a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=joe'%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20UNION%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id='%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id='%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=1'%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id='%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id=%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_int_partialunion?id='%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_string.hurl b/tests/hurl/rasp/oracle/get_string.hurl new file mode 100644 index 0000000..b7a8263 --- /dev/null +++ b/tests/hurl/rasp/oracle/get_string.hurl @@ -0,0 +1,125 @@ +GET http://{{host}}:{{port}}/spiracle/Get_string?name=x'%20or%20name%20like%20'%25'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=t'exec%20master..xp_cmdshell%20'nslookup%20www%2egoogle%2ecom'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name='%3b%20exec%20master%2e%2exp_cmdshell%20'ping%20172%2e10%2e1%2e255'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=x'%20AND%20100=(SELECT%20COUNT(*)%20FROM%20address)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=x'%20OR%20cvv%20IS%20NULL-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=anything'%20OR%20'x'='x + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=x'%20or%201=1%20or%20'x'='y + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name='%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name='or%201=1%20or%20''=' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=a'%20or%20'a'%20=%20'a + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name='%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name='%20UNION%20SELECT%20*%20from%20users-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=%27%20or%20%27x%27=%27x + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name='or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name='%20or%201%20--' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name='%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string?name=x'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_string_no_quote.hurl b/tests/hurl/rasp/oracle/get_string_no_quote.hurl new file mode 100644 index 0000000..a7ac1d7 --- /dev/null +++ b/tests/hurl/rasp/oracle/get_string_no_quote.hurl @@ -0,0 +1,203 @@ +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='2'%20OR%20name%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='Jon'%20or%20name%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20or%20id%20like%20'2' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20or%20name%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='Joe'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users)%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20or%20name%20like%20'Sammy' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20AND%20users.cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20AND%20DOB%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20AND%20cvv%20IS%20NULL%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20or%201=1%20or%20'x'='y'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20UNION%20ALL%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name=''%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name=(1)%20or%20('a'='a')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name=1%20or%20'a'%20=%20'a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name=1%20or%20'1'='1'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='Joe'%20UNION%20SELECT%20*%20from%20users%20where%20id=1%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name=('')%20or%20('a'='a')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name=('')%20or%20('x'='x')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name=''%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name=''%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name=%27%27%20or%20%27x%27%3D%27x%27-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='Joe'%20or%200=0%20# + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='Joe'%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='1'%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='Joe'%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='Joe'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='Joe%20%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_string_no_quote?name='Joe'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/oracle/get_union.hurl b/tests/hurl/rasp/oracle/get_union.hurl new file mode 100644 index 0000000..9b88ada --- /dev/null +++ b/tests/hurl/rasp/oracle/get_union.hurl @@ -0,0 +1,173 @@ +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='2'%20OR%20'name'%20LIKE%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%20'name'%20like%20'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%20id%20like%201 + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%20'name'%20like'Joe' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20OR%20120=(SELECT%20COUNT(*)%20FROM%20users) + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20AND%20'users.cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20AND%20'DOB'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20AND%20'cvv'%20IS%20NULL + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20OR%20'x'='x' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%201=1%20or%20'x'='y' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='1'%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20or%201=1%20or%20''=''-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='(%22hi%22)'%20or%20('a'='a')-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='a'%20or%20'a'%20=%20'a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='joe'%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='hi'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='hi'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='a'%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=''%20or%20'x'='x'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=''%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='a'%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='Joe'%20or%200=0%20-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='Joe'%20or%20'a'='a'-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=1%20or%20'a'='a' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=1%20or%20'1'='1' + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id=%27%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20%20or%201=1-- + +HTTP * +[Asserts] +status == {{block_status}} + +GET http://{{host}}:{{port}}/spiracle/Get_Union?id='%20or%203=3-- + +HTTP * +[Asserts] +status == {{block_status}} diff --git a/tests/hurl/rasp/protected.env b/tests/hurl/rasp/protected.env new file mode 100644 index 0000000..b6c1f83 --- /dev/null +++ b/tests/hurl/rasp/protected.env @@ -0,0 +1,3 @@ +host=localhost +port=8080 +block_status=550 diff --git a/tests/hurl/run.sh b/tests/hurl/run.sh new file mode 100755 index 0000000..5c01368 --- /dev/null +++ b/tests/hurl/run.sh @@ -0,0 +1,77 @@ +#!/bin/sh +# run.sh — Spiracle Hurl test runner +# +# Usage: +# ./tests/hurl/run.sh smoke [host] [port] +# ./tests/hurl/run.sh functional [host] [port] +# ./tests/hurl/run.sh rasp [host] [port] +# +# Arguments: +# suite — "smoke", "functional", or "rasp" +# host — hostname/IP of Spiracle (default: localhost) +# port — TCP port (default: 8080) +# +# Environment: +# BLOCK_STATUS — expected RASP block code (default: 550) +# only used by the "rasp" suite +# +# Requirements: +# hurl v5+ at ~/.local/bin/hurl or on PATH + +set -eu + +SUITE="${1:-smoke}" +HOST="${2:-localhost}" +PORT="${3:-8080}" +BLOCK_STATUS="${BLOCK_STATUS:-550}" + +# 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}" + ;; + rasp) + VARS_FILE="$SCRIPT_DIR/rasp/protected.env" + FILES="$SCRIPT_DIR/rasp/mysql/*.hurl $SCRIPT_DIR/rasp/oracle/*.hurl $SCRIPT_DIR/rasp/mssql/*.hurl" + REPORT_DIR="${REPORT_DIR:-/tmp/spiracle-rasp-report}" + ;; + *) + echo "ERROR: unknown suite '$SUITE'. Use 'smoke', 'functional', or 'rasp'." >&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" \ + --variable block_status="$BLOCK_STATUS" \ + --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..c6fe4ac --- /dev/null +++ b/tests/hurl/smoke/smoke.hurl @@ -0,0 +1,32 @@ +# Spiracle smoke suite — runs against a PLAIN (no RASP agent) deployment. +# +# Purpose: prove the app is up, DB round-trips work, and that SQLi is +# NOT blocked without the Waratek agent. A 550 here would mean the +# agent is unexpectedly present; plain 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 ─────────────────────────── +# Without the Waratek RASP agent 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()