diff --git a/software/backend/data/exercises.json b/software/backend/data/exercises.json index 76d3cd7..3043f30 100644 --- a/software/backend/data/exercises.json +++ b/software/backend/data/exercises.json @@ -48,13 +48,6 @@ "exerciseNr": 2, "descriptionDe": "Manipuliere die URL so, dass du das ausgebuchte Konzert aufrufen kannst und buche ein Ticket dafür", "descriptionEn": "Manipulate the URL and access the sold out concert and buy a ticket" - }, - { - "nameDe": "Das Admin-Panel aufrufen", - "nameEn": "Access the Admin-Panel", - "exerciseNr": 3, - "descriptionDe": "Manipuliere die URL so, dass du das Admin-Panel erreichen kannst", - "descriptionEn": "Manipulate the URL and access the admin page" } ] }, @@ -62,29 +55,36 @@ "nameDe": "SQL Injections", "nameEn": "SQL Injections", "groupNr": 2, - "descriptionDe": "HTML und CSS sind für die Struktur und die Gestaltung einer Webseite verantwortlich. Um jedoch Programmcode für dynamische Inhalte auszuführen wird die Programmiersprache JavaScript verwendet, welche Programmcode direkt im Browser ausführen kann. Diese Scripts können nun aber auch Schaden anrichten, wenn sie im Rahmen eines Angriffs eingeschmuggelt werden.", + "descriptionDe": "Eine Datenbank arbeitet mit SQL Befehlen um Datensätze anzulegen, abzurufen, zu verändern und löschen. Ein Server wird über API-Schnittstellen angesprochen, führt die Befehle in der Datenbank aus und liefert das Ergebnis. Der Client darf keinen direkten Zugriff auf die Datenbank haben. Bei SQL Injections wird versucht über die API-Schnittstellen direkte SQL Befehle auszuführen.", "descriptionEn": "todo", "exercises": [ { - "nameDe": "Einen fremden Account übernehmen", - "nameEn": "Capture an account", + "nameDe": "Alle Accounts ausspähen", + "nameEn": "Get all accounts", "exerciseNr": 1, - "descriptionDe": "Führe auf der Login-Seite eine SQL-Injection durch, so dass du Zugriff auf einen Account mit 'Super Admin'-Berechtigungen erlangst", - "descriptionEn": "Execute an SQL-Injection on the Login page. Try to capture an account with 'Super Admin' privilege." + "descriptionDe": "Ließ alle Konten aus der Tabelle >>Accounts<< aus. Nutze hierfür das Suchfeld.", + "descriptionEn": "Execute an SQL-Injection on the Search page to get all datasets from >>Accounts<< table." }, { - "nameDe": "Bestellungen abfragen", - "nameEn": "Readout password", + "nameDe": "Alle Berechtigungsgruppen ausspähen", + "nameEn": "Get alls account roles", "exerciseNr": 2, - "descriptionDe": "Versuche ein Passwort aus der Datenbank eines Accounts auszulesen", - "descriptionEn": "Get the password of an account from the database" + "descriptionDe": "Ließ alle Berechtigungsgruppen aus der Tabelle >>AccountRoles<< aus.", + "descriptionEn": "Execute an SQL-Injection on the Search page to get all datasets from >>AccountRoles<< table." }, { - "nameDe": "Band-Bewertungen manipulieren", - "nameEn": "Change your account role", + "nameDe": "Eigene Berechtigungen erhöhen", + "nameEn": "Upgrade your privileges", "exerciseNr": 3, - "descriptionDe": "Ändere die Berechtigungen deines Accounts", + "descriptionDe": "Erhöhe deine eigene Berechtigung zu >>Admin<<.", "descriptionEn": "Change the privileges of your account" + }, + { + "nameDe": "Einen fremden Account übernehmen", + "nameEn": "Capture another account", + "exerciseNr": 4, + "descriptionDe": "Wir infiltrieren nun einen Account. Suche dir dafür aus der Liste der in Aufgabe 2.1 erhaltenen einen Account heraus, welcher die Rolle >>Super-Admin<< inne hat. Nur damit lässt sich die Dateiverwaltung welche wir später brauchen öffnen. Hast du den Account-Namen gefunden, gehe ins Login-Menü (logge dich aus, falls du noch angemeldet bist). Führe nun einen SQL-Injektion durch um diesen Account zu übernehmen.", + "descriptionEn": "todo" } ] }, @@ -92,7 +92,7 @@ "nameDe": "Cross-Site Scripting (XSS)", "nameEn": "Cross-Site Scripting (XSS)", "groupNr": 3, - "descriptionDe": "todo", + "descriptionDe": "HTML und CSS sind für die Struktur und die Gestaltung einer Webseite verantwortlich. Um jedoch Programmcode für dynamische Inhalte auszuführen wird die Programmiersprache JavaScript verwendet, welche Programmcode direkt im Browser ausführen kann. Diese Scripts können nun aber auch Schaden anrichten, wenn sie im Rahmen eines Angriffs eingeschmuggelt werden.", "descriptionEn": "todo", "exercises": [ { diff --git a/software/backend/routes/band.routes.ts b/software/backend/routes/band.routes.ts index d34b62c..48af6cc 100644 --- a/software/backend/routes/band.routes.ts +++ b/software/backend/routes/band.routes.ts @@ -8,6 +8,7 @@ import { Location } from "../models/locations/location.model"; import { City } from "../models/locations/city.model"; import { Op } from "sequelize"; import { calcOverallRating, calcRatingValues } from "../scripts/calcScripts"; +import { sequelize } from "../database"; export const band = Router() @@ -130,18 +131,30 @@ band.get("/band/:name", (req: Request, res: Response) => { /** * Band search */ -band.get("/search", (req: Request, res: Response) => { - Band.findAll({ - where: { - name: { - [Op.substring]: req.query.value +band.get("/search", async (req: Request, res: Response) => { + // Workaround, because SQLite can't handle stacked queries + let prompts = decodeURI(String(req.query.value)).split(";") + + // On stacked prompts, execute last prompt + if (prompts.length > 1) { + console.log(prompts[prompts.length - 2]) + const [results, metadata] = + await sequelize.query(prompts[prompts.length - 2]) + + res.status(200).json(results) + } else { + Band.findAll({ + where: { + name: { + [Op.substring]: req.query.value + }, }, - }, - include: [ Concert, Genre ] - }) - .then(bands => { - res.status(200).json(bands) + include: [ Concert, Genre ] }) + .then(bands => { + res.status(200).json(bands) + }) + } }) diff --git a/software/package-lock.json b/software/package-lock.json index 6daf77c..892ee14 100644 --- a/software/package-lock.json +++ b/software/package-lock.json @@ -20,7 +20,9 @@ "jsonwebtoken": "^9.0.2", "moment": "^2.30.1", "multer": "^1.4.5-lts.1", + "mysql2": "^3.11.4", "pinia": "^2.2.4", + "qs": "^6.13.1", "reflect-metadata": "^0.2.2", "sequelize": "^6.37.4", "sequelize-typescript": "^2.1.6", @@ -3058,6 +3060,15 @@ "node": ">= 4.0.0" } }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/axios": { "version": "1.7.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", @@ -3169,6 +3180,21 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", @@ -4248,6 +4274,15 @@ "devOptional": true, "license": "MIT" }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -4931,6 +4966,21 @@ "node": ">= 0.10.0" } }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -5248,6 +5298,15 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -5862,6 +5921,12 @@ "node": ">=0.12.0" } }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "license": "MIT" + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -6227,6 +6292,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "license": "Apache-2.0" + }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -6250,6 +6321,21 @@ "node": ">=10" } }, + "node_modules/lru.min": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.1.tgz", + "integrity": "sha512-FbAj6lXil6t8z4z3j0E5mfRlPzxkySotzUHwRXjlpRh10vc6AI6WN62ehZj82VG7M20rqogJ0GLwar2Xa05a8Q==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, "node_modules/magic-string": { "version": "0.30.12", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", @@ -6601,6 +6687,59 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mysql2": { + "version": "3.11.4", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.11.4.tgz", + "integrity": "sha512-Z2o3tY4Z8EvSRDwknaC40MdZ3+m0sKbpnXrShQLdxPrAvcNli7jLrD2Zd2IzsRMw4eK9Yle500FDmlkIqp+krg==", + "license": "MIT", + "dependencies": { + "aws-ssl-profiles": "^1.1.1", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru.min": "^1.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "license": "MIT", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -7344,9 +7483,9 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", + "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.6" @@ -7884,6 +8023,11 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "node_modules/sequelize": { "version": "6.37.4", "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.4.tgz", @@ -8317,6 +8461,15 @@ } } }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", diff --git a/software/package.json b/software/package.json index 2c869de..42d72b4 100644 --- a/software/package.json +++ b/software/package.json @@ -44,7 +44,9 @@ "jsonwebtoken": "^9.0.2", "moment": "^2.30.1", "multer": "^1.4.5-lts.1", + "mysql2": "^3.11.4", "pinia": "^2.2.4", + "qs": "^6.13.1", "reflect-metadata": "^0.2.2", "sequelize": "^6.37.4", "sequelize-typescript": "^2.1.6", diff --git a/software/src/pages/admin/dashboardPage/index.vue b/software/src/pages/admin/dashboardPage/index.vue index 2eeb2bd..f5b29c8 100644 --- a/software/src/pages/admin/dashboardPage/index.vue +++ b/software/src/pages/admin/dashboardPage/index.vue @@ -8,7 +8,6 @@ import { usePreferencesStore } from '@/stores/preferences.store'; import dashboardCard from './dashboardCard.vue'; import { useOrderStore } from '@/stores/order.store'; import { useFilesStore } from '@/stores/files.store'; -import { useExerciseStore } from '@/stores/exercise.store'; const concertStore = useConcertStore() const bandStore = useBandStore() @@ -18,9 +17,6 @@ const locationStore = useLocationStore() const preferencesStore = usePreferencesStore() const orderStore = useOrderStore() const filesStore = useFilesStore() -const exerciseStore = useExerciseStore() - -exerciseStore.solveExercise(1, 3) filesStore.getStaticFolders() bandStore.getBands() diff --git a/software/src/stores/account.store.ts b/software/src/stores/account.store.ts index 103431c..fc96a18 100644 --- a/software/src/stores/account.store.ts +++ b/software/src/stores/account.store.ts @@ -83,7 +83,7 @@ export const useAccountStore = defineStore("accountStore", { this.adminPanelVisible = response.data.accountRole.privilegeAdminPanel if (response.data.accountRoleId == 3) { - exerciseStore.solveExercise(2, 1) + exerciseStore.solveExercise(2, 4) } }) }) diff --git a/software/src/stores/search.store.ts b/software/src/stores/search.store.ts index 5ffd85c..85f4c03 100644 --- a/software/src/stores/search.store.ts +++ b/software/src/stores/search.store.ts @@ -4,6 +4,7 @@ import { fetchBandsBySearchTerm } from "../data/api/bandApi"; import { fetchLocationsBySearchTerm } from "../data/api/locationApi"; import { fetchConcertsBySearchTerm } from "../data/api/concertApi"; import { ConcertApiModel } from "@/data/models/acts/concertApiModel"; +import { useExerciseStore } from "./exercise.store"; export const useSearchStore = defineStore("searchStore", { state: () => ({ @@ -31,9 +32,20 @@ export const useSearchStore = defineStore("searchStore", { * Search for the term in all bands, locations, events */ async startSearch() { + const exerciseStore = useExerciseStore() + this.alreadySearched = true this.fetchInProgress = true + // Exercise solutions + if (this.searchTerm.endsWith("'); SELECT * FROM Accounts; --")) { + exerciseStore.solveExercise(2, 1) + } else if (this.searchTerm.endsWith("'); SELECT * FROM AccountRoles; --")) { + exerciseStore.solveExercise(2, 2) + } else if (this.searchTerm.includes("'); UPDATE Accounts SET accountRoleId = 2 WHERE username = ")) { + exerciseStore.solveExercise(2, 3) + } + await fetchBandsBySearchTerm(this.searchTerm) .then(result => { this.bands = result.data