Skip to content

Commit

Permalink
Merge branch 'NeuraLegion:stable' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
TheRedHatter authored Jul 17, 2024
2 parents 6ec97a3 + 0e91835 commit f0f7156
Show file tree
Hide file tree
Showing 662 changed files with 2,603 additions and 2,921 deletions.
6 changes: 6 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ KEYCLOAK_PUBLIC_CLIENT_SECRET=4bfb5df6-4647-46dd-bad1-c8b8ffd7caf4
BRIGHT_TOKEN=
BRIGHT_CLUSTER=app.neuralegion.com
SEC_TESTER_TARGET=http://localhost:8090

CHAT_API_URL=https://api-inference.huggingface.co/v1/chat/completions
CHAT_API_MODEL=meta-llama/Meta-Llama-3-8B-Instruct
CHAT_API_MAX_TOKENS=1000
CHAT_API_TOKEN=

20 changes: 10 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches:
- stable
- development
- unstable
- experimental

jobs:
Expand All @@ -21,17 +21,17 @@ jobs:
git config --global user.email "devops@brightsec.com"
git config --global user.name "Bright Security"
- name: Change name to development
if: ${{ github.ref == 'refs/heads/development' }}
run: |
sed -i 's/brokencrystals/brokencrystals-dev/g' ./charts/brokencrystals/Chart.yaml
sed -i 's/brkn/brkn-dev/g' ./charts/brokencrystals/Chart.yaml
- name: Change name to unstable
if: ${{ github.ref == 'refs/heads/unstable' }}
run: |
sed -i 's/brokencrystals/brokencrystals-unstable/g' ./charts/brokencrystals/Chart.yaml
sed -i 's/brkn/brkn-unstbl/g' ./charts/brokencrystals/Chart.yaml
- name: Change values to development
if: ${{ github.ref == 'refs/heads/development' }}
run: |
sed -i 's/^ main:.*/ main: development/' ./charts/brokencrystals/values.yaml
sed -i 's/^ client:.*/ client: development/' ./charts/brokencrystals/values.yaml
if: ${{ github.ref == 'refs/heads/unstable' }}
run: |
sed -i 's/^ main:.*/ main: unstable/' ./charts/brokencrystals/values.yaml
sed -i 's/^ client:.*/ client: unstable/' ./charts/brokencrystals/values.yaml
- name: Release packages
uses: helm/chart-releaser-action@v1.5.0
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# compiled output
/dist
/public/build
/client/build
/node_modules

# Logs
Expand Down
62 changes: 49 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,27 +1,63 @@
FROM node:14
###################
# BUILD FOR LOCAL DEVELOPMENT
###################

WORKDIR /var/www/
FROM node:14-alpine As build

COPY package*.json ./
WORKDIR /usr/src/app

RUN npm ci -q
RUN apk add --no-cache --virtual .gyp python3 py3-pip make g++

COPY config ./config
COPY tsconfig.build.json ./
COPY tsconfig.json ./
COPY nest-cli.json ./
COPY .env ./
COPY src ./src
# Copy and build NestJS server project
COPY --chown=node:node package*.json ./
COPY --chown=node:node tsconfig.build.json ./
COPY --chown=node:node tsconfig.json ./
COPY --chown=node:node nest-cli.json ./
COPY --chown=node:node mikro-orm.config.ts ./
COPY --chown=node:node .env ./
COPY --chown=node:node config ./config
COPY --chown=node:node keycloak ./keycloak
COPY --chown=node:node src ./src

RUN npm ci
RUN npm run build
RUN npm prune --production

RUN chown -R node:node /var/www/*
# Copy and build client project
COPY --chown=node:node client/package*.json ./client/
COPY --chown=node:node client/src ./client/src
COPY --chown=node:node client/public ./client/public
COPY --chown=node:node client/typings ./client/typings
COPY --chown=node:node client/vcs ./client/vcs
COPY --chown=node:node client/tsconfig.json ./client/tsconfig.json

ENV CYPRESS_INSTALL_BINARY=0
RUN npm ci --prefix=client
RUN npm run build --prefix=client

RUN apk del .gyp

USER node

ENV NODE_ENV=production
###################
# PRODUCTION
###################

FROM node:14-alpine As production

WORKDIR /usr/src/app

COPY --chown=node:node nest-cli.json ./
COPY --chown=node:node mikro-orm.config.ts ./
COPY --chown=node:node .env ./
COPY --chown=node:node config ./config
COPY --chown=node:node keycloak ./keycloak

COPY --chown=node:node --from=build /usr/src/app/node_modules ./node_modules
COPY --chown=node:node --from=build /usr/src/app/package*.json ./
COPY --chown=node:node --from=build /usr/src/app/dist ./dist

EXPOSE 3000
COPY --chown=node:node --from=build /usr/src/app/client/build ./client/build
COPY --chown=node:node --from=build /usr/src/app/client/vcs ./client/vcs

CMD ["npm", "run", "start:prod"]
61 changes: 58 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ The application contains:
- React based web client
- FE - http://localhost:8090
- BE - http://localhost:3000
- NodeJS server - the full API documentation is available via swagger or GraphQL
- NodeJS server that serves the React client and provides both OpenAPI and GraphQL endpoints.
The full API documentation is available via swagger or GraphQL:
- Swagger UI - http://localhost:8090/swagger
- Swagger JSON file - http://localhost:8090/swagger-json
- GraphiQL UI - http://localhost:8090/graphiql
- nginx web server that serves the client and acts as a reverse proxy for the server's API requests

> **Note**
> The GraphQL API does not yet support all of the endpoints the REST API does.
Expand All @@ -22,14 +22,48 @@ The application contains:
npm ci && npm run build

# build client
npm ci --prefix public && npm run build --prefix public
npm ci --prefix client && npm run build --prefix client

#build and start dockers with Postgres DB, nginx and server
docker-compose --file=docker-compose.local.yml up -d

#rebuild dockers
docker-compose --file=docker-compose.local.yml up -d --build
```
## Running application with helm chart
Helm command example:
```bash
helm upgrade --install --namespace distributor broken \
--set snifferApiURL=https://hotel.playground.neuralegion.com \
--set snifferProjectID=ud8v8jwUaG14JiAihMQx1M \
--set snifferApiKey=6g0daym.nexp.spkuhhishhttv \
--set snifferNetworkInterface=lo0 \
--set repeaterID=5r9Kci7AKLx4bkN58yYCDz \
--set token=nptbmxr.nexp.kkaux80olef2mew3n3r3rw08tww3c4f5 \
--set cluster=hotel.playground.neuralegion.com \
--set timeout=40000 \
--set repeaterImageTag=v11.5.0-next.4 \
--set ingress.url=broken.k3s.brokencrystals.nexploit.app \
--set ingress.cert=distributorwildcard \
--set ingress.authlevel=- . --wait
```

### Arguments info

**repeaterID, token and cluster** - These argument values are required if you want to use repeater. In case you don't set any of these fields, repeater container won't be run. In that case this will be regular bc deployment. (Required arguments if repeater container is to be used).

**timeout** - this is optional argument for repeater deployment with default value 30000 if it is not set, it's only used in conjuction with main repeater options (optional argument).

**repeaterImageTag** - this argument is optional with default value latest if field is not set. Notice these are docker tags and not repeater versions. They are similar but not the same. Dockerhub tags usually have "v" in front of repeater version. this argument is only used in conjuction with main repeater options (optional argument).

**snifferApiURL, snifferProjectID and snifferApiKey** - These argument values are required if you want to use sniffer. In case you don't set any of these fields, sniffer container won't be run. In that case this will be regular bc deployment. (Required arguments if sniffer container is to be used).

**snifferNetworkInterface** - this is optional argument for sniffer deployment with default value set to **"eth0"** if it is not set explicitly, it's only used in conjuction with main sniffer options (optional argument).

**namespace** - kubernetes namespace where app will be spawned.

**ingress.url** - Domain name that will be used to access app from Internet.


## Running application with helm
Helm command example:
Expand Down Expand Up @@ -165,3 +199,24 @@ Additionally, the endpoint PUT /api/users/one/{email}/photo accepts SVG images,
2. The endpoint GET `/api/partners/searchPartners` is supposed to search partners' names by a given keyword. It's vulnerable to an XPATH injection using string detection payloads. When exploited, it can grant access to sensitive information like passwords and even lead to full data leak. You can use `')] | //password%00//` or `')] | //* | a[('` to exploit the EP.
3. The endpoint GET `/api/partners/query` is a raw XPATH injection endpoint. You can put whatever you like there. It is not referenced in the frontend, but it is an exposed API endpoint.
4. Note: All endpoints are vulnerable to error based payloads.

* **Prototype Pollution** - The `/marketplace` endpoint is vulnerable to prototype pollution using the following methods:
1. The EP GET `/marketplace?__proto__[Test]=Test` represents the client side vulnerabillity, by parsing the URI (for portfolio filtering) and converting
it's parmeters into an object. This means that a requests like `/marketplace?__proto__[TestKey]=TestValue` will lead to a creation of `Object.TestKey`.
One can test if an attack was successful by viewing the new property created in the console.
This EP also supports prototyp pollution based DOM XSS using a payload such as `__proto__[prototypePollutionDomXss]=data:,alert(1);`.
The "legitimate" code tries to use the `prototypePollutionDomXss` parameter as a source for a script tag, so if the exploit is not used via this key it won't work.
2. The EP GET `/api/email/sendSupportEmail` represents the server side vulnerabillity, by having a rookie URI parsing mistake (similiar to the client side).
This means that a request such as `/api/email/sendSupportEmail?name=Bob%20Dylan&__proto__[status]=222&to=username%40email.com&subject=Help%20Request&content=Help%20me..`
will lead to a creation of `uriParams.status`, which is a parameter used in the final JSON response.

* **Date Manipulation** - The `/api/products?date_from={df}&date_to={dt}` endpoint fetches all products that were created between the selected dates. There is no limit on the range of dates and when a user tries to query a range larger than 2 years querying takes a significant amount of time. This EP is used by the frontend in the `/marketplace` page.

* **Email Injection** - The `/api/email/sendSupportEmail` is vulnerable to email injection by supplying tempred recipients.
To exploit the EP you can dispatch a request as such `/api/email/sendSupportEmail?name=Bob&to=username%40email.com%0aCc:%20bob@domain.com&subject=Help%20Request&content=I%20would%20like%20to%20request%20help%20regarding`.
This will lead to the sending of a mail to both `username@email.com` and `bob@domain.com` (as the Cc).
Note: This EP is also vulnerable to `Server side prototype pollution`, as mentioned in this README.

* **Insecure Output Handling** - The `/chat` route is vulnerable to non-sanitized output originating from the LLM response.
Issue a `POST /api/chat` request with body payload like `[{"content": "Provide a minimal html markup for img tag with invalid source and onerror attribute with alert", "role": "user"}]`.
The response will include raw HTML code. If this output is not properly sanitized before rendering, it can trigger an alert box in the user interface.
2 changes: 1 addition & 1 deletion charts/brokencrystals/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: |
Benchmark application that uses modern technologies and implements a set of
common security vulnerabilities
type: application
version: 0.0.70
version: 0.0.71
icon: https://raw.githubusercontent.com/NeuraLegion/brokencrystals/stable/public/public/assets/img/logo.png
keywords:
- brokencrystals
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "brokencrystals.fullname" . }}-keycloak-postgres
name: {{ include "brokencrystals.fullname" . }}-kc-db
namespace: {{ .Release.Namespace }}
data:
postgresql.conf.sample: |
Expand Down
20 changes: 12 additions & 8 deletions charts/brokencrystals/templates/config-postgres.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ data:
INSERT INTO "user" (created_at, updated_at, email, password, first_name, last_name, is_admin, photo, company, card_number, phone_number, is_basic) VALUES (now(), now(), 'admin', '$2b$10$BBJjmVNNdyEgv7pV/zQR9u/ssIuwZsdDJbowW/Dgp28uws3GmO0Ky', 'admin', 'admin', true, null, 'Brightsec', '1234 5678 9012 3456', '+1 234 567 890', true);
INSERT INTO "user" (created_at, updated_at, email, password, first_name, last_name, is_admin, photo, company, card_number, phone_number, is_basic) VALUES (now(), now(), 'user', '$2b$10$edsq4aqzAHnrJu68t8GS2.v0Z7hJSstAo7wBBDmmbpjYGxMMTYpVi', 'user', 'user', false, null, 'Brightsec', '1234 5678 9012 3456', '+1 234 567 890', true);
--insert default products into the table
INSERT INTO "product" ("category", "photo_url", "name", "description") VALUES ('Healing', '/api/file?path=config/products/crystals/amethyst.jpg&type=image/jpg', 'Amethyst', 'a violet variety of quartz');
INSERT INTO "product" ("category", "photo_url", "name", "description") VALUES ('Gemstones', '/api/file?path=config/products/crystals/ruby.jpg&type=image/jpg', 'Ruby', 'an intense heart crystal');
INSERT INTO "product" ("category", "photo_url", "name", "description") VALUES ('Healing', '/api/file?path=config/products/crystals/opal.jpg&type=image/jpg', 'Opal', 'the precious stone');
INSERT INTO "product" ("category", "photo_url", "name", "description") VALUES ('Jewellery', '/api/file?path=config/products/crystals/sapphire.jpg&type=image/jpg', 'Sapphire', '');
INSERT INTO "product" ("category", "photo_url", "name", "description") VALUES ('Healing', '/api/file?path=config/products/crystals/amber.jpg&type=image/jpg', 'Amber', 'fossilized tree resin');
INSERT INTO "product" ("category", "photo_url", "name", "description") VALUES ('Jewellery', '/api/file?path=config/products/crystals/emerald.jpg&type=image/jpg', 'Emerald', 'symbol of fertility and life');
INSERT INTO "product" ("category", "photo_url", "name", "description") VALUES ('Jewellery', '/api/file?path=config/products/crystals/shattuckite.jpg&type=image/jpg', 'Shattuckite', 'mistery');
INSERT INTO "product" ("category", "photo_url", "name", "description") VALUES ('Gemstones', '/api/file?path=config/products/crystals/bismuth.jpg&type=image/jpg', 'Bismuth', 'rainbow');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES (now(), 'Healing', '/api/file?path=config/products/crystals/amethyst.jpg&type=image/jpg', 'Amethyst', 'a violet variety of quartz');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES (now(), 'Gemstones', '/api/file?path=config/products/crystals/ruby.jpg&type=image/jpg', 'Ruby', 'an intense heart crystal');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES (now(), 'Healing', '/api/file?path=config/products/crystals/opal.jpg&type=image/jpg', 'Opal', 'the precious stone');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES (now(), 'Jewellery', '/api/file?path=config/products/crystals/sapphire.jpg&type=image/jpg', 'Sapphire', '');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES (now(), 'Healing', '/api/file?path=config/products/crystals/amber.jpg&type=image/jpg', 'Amber', 'fossilized tree resin');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES (now(), 'Jewellery', '/api/file?path=config/products/crystals/emerald.jpg&type=image/jpg', 'Emerald', 'symbol of fertility and life');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES (now(), 'Jewellery', '/api/file?path=config/products/crystals/shattuckite.jpg&type=image/jpg', 'Shattuckite', 'mistery');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES (now(), 'Gemstones', '/api/file?path=config/products/crystals/bismuth.jpg&type=image/jpg', 'Bismuth', 'rainbow');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES ('2005-01-10 12:00:00', 'Gemstones', '/api/file?path=config/products/crystals/labradorite.jpg&type=image/jpg', 'Labradorite', 'rainbow');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES ('2023-12-10 12:00:00', 'Gemstones', '/api/file?path=config/products/crystals/axinite.jpg&type=image/jpg', 'Axinite', 'brown');
INSERT INTO "product" ("created_at", "category", "photo_url", "name", "description") VALUES ('2020-11-18 12:00:00', 'Gemstones', '/api/file?path=config/products/crystals/pietersite.jpg&type=image/jpg', 'Pietersite', 'blue');
CREATE INDEX IF NOT EXISTS "IDX_users_email" ON "user" ("email");
Loading

0 comments on commit f0f7156

Please sign in to comment.