Setup of forcAD done, now services

main
Gasper Spagnolo 2022-10-28 23:18:10 +02:00
parent f8a9e46491
commit 3ced1d8807
44 changed files with 1998 additions and 13 deletions

View File

@ -27,3 +27,9 @@ Ansible:
## Start
You shuold firstly specify server in the `invenvtory` file. Then start the root of repo and execute ` ansible-playbook -i inventory deploy_forcad.yml` command.
## Todo:
- create N teams
- fix docker installation
- VPN
- test

View File

@ -1,6 +1,6 @@
---
- name: Setup ForcAD infra
hosts: faust_ad
hosts: forc_ad
become: true
tasks:
@ -8,3 +8,8 @@
include_role:
name: docker
tasks_from: main
- name: Install and setup forcAD
include_role:
name: forcad
tasks_from: main

View File

@ -1,2 +1,2 @@
[faust_ad]
ubuntu.vic ansible_connection=ssh
[forc_ad]
192.168.88.130 ansible_connection=ssh ansible_user=root ansible_ssh_pass=root

View File

@ -10,15 +10,16 @@
- python3-setuptools
update_cache: true
- name: Add Docker GPG apt Key
apt_key:
url: 'https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg'
state: present
- name: Add Docker Repository
apt_repository:
repo: 'deb https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable'
state: present
##### WARNING OUTDATED!!! NEED FIX ASAP
#- name: Add Docker GPG apt Key
# apt_key:
# url: 'https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg'
# state: present
#
#- name: Add Docker Repository
# apt_repository:
# repo: 'deb https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable'
# state: present
- name: Install Docker
apt:
@ -29,7 +30,7 @@
- docker-compose-plugin
update_cache: true
- name: Install Docker Module for Python
- name: Install docker-compose
pip:
name:
- docker

View File

@ -0,0 +1,38 @@
admin:
password: 4206942069
username: forcad
game:
mode: classic
round_time: 20
start_time: 2019-11-30 15:30:00
timezone: Europe/Ljubljana
default_score: 2500
flag_lifetime: 5
game_hardness: 10.0
inflation: true
tasks:
- checker: test_service/checker.py
checker_timeout: 10
checker_type: hackerdom
gets: 2
name: test_basic_service
places: 5
puts: 2
- checker: test_service/gevent_checker.py
checker_timeout: 10
checker_type: gevent
gets: 2
name: test_gevent_service_1
places: 5
puts: 2
teams:
- ip: 192.168.1.2
name: "Team 1"
- ip: 192.168.1.3
name: "Team 2 (highlighted)"
highlighted: true

View File

@ -0,0 +1,44 @@
- name: Create forcAD directory
ansible.builtin.file:
path: "{{ forc_ad_directory }}"
state: directory
mode: '0755'
- name: Download forcAD files
ansible.builtin.get_url:
url: "{{ forc_ad_link }}"
dest: "{{ forc_ad_directory }}"
- name: Unzip forcAD files
ansible.builtin.unarchive:
src: "{{ forc_ad_directory}}/{{ forc_ad_zipfile }}"
dest: "{{ forc_ad_directory }}"
remote_src: true
- name: Set unzipped directory
ansible.builtin.set_fact:
forc_ad_directory: "{{ forc_ad_directory }}/{{ forc_ad_zipfile.split('.z')[0] }}"
- name: Make sure python and python-venv are installed
ansible.builtin.apt:
pkg:
- python3
- python3-venv
- name: Create venv
ansible.builtin.pip:
requirements: "{{ item }}"
virtualenv: "{{ forc_ad_directory }}//.venv"
virtualenv_python: python3
with_items:
- "{{ forc_ad_directory }}/cli/requirements.txt"
- "{{ forc_ad_directory }}/checkers/requirements.txt"
- name: Copy forcAD config
ansible.builtin.copy:
src: "config.yml"
dest: "{{ forc_ad_directory }}"
- name: Setup forcAD
ansible.builtin.command:
cmd: "{{ forc_ad_directory }}/.venv/bin/python3 {{ forc_ad_directory }}/control.py setup"

View File

@ -0,0 +1,9 @@
---
# Default directory for forcAD files
forc_ad_directory: '/forc_ad'
# forcAD download link
forc_ad_link: 'https://github.com/pomo-mondreganto/ForcAD/releases/download/v1.4.0/ForcAD_v1.4.0.zip'
# forcAd zipfile
forc_ad_zipfile: 'ForcAD_v1.4.0.zip'

View File

@ -0,0 +1,50 @@
#!/usr/bin/env python3
# Author: Angelo Delicato
# Description: Just a checker for the BabySql ForcAD Vulnbox
# Note: Use this file inside the checker folder in ForcAD
import sys
from pathlib import Path
BASE_DIR = Path(__file__).absolute().resolve().parent
sys.path.insert(0, str(BASE_DIR))
from service_lib import *
class Checker(BaseChecker):
def __init__(self, *args, **kwargs):
super(Checker, self).__init__(*args, **kwargs)
self.mch = CheckMachine(self)
def action(self, action, *args, **kwargs):
try:
super(Checker, self).action(action, *args, **kwargs)
except requests.exceptions.ConnectionError:
self.cquit(
Status.DOWN,
'Connection error',
'Got requests connection error',
)
def check(self):
self.mch.ping()
self.cquit(Status.OK)
def put(self, flag_id, flag, vuln):
new_id = self.mch.put_flag(flag, vuln)
self.cquit(Status.OK, new_id)
def get(self, flag_id, flag, vuln):
got_flag = self.mch.get_flag(flag_id, vuln)
self.assert_eq(got_flag, flag, 'Could not get flag', status=Status.CORRUPT)
self.cquit(Status.OK)
if __name__ == '__main__':
c = Checker(sys.argv[2])
try:
c.action(sys.argv[1], *sys.argv[3:])
except c.get_check_finished_exception():
cquit(Status(c.status), c.public, c.private)

View File

@ -0,0 +1,46 @@
import requests
from checklib import *
PORT = 5005
class CheckMachine:
def __init__(self, checker):
self.checker = checker
def ping(self):
r = requests.get(f'http://{self.checker.host}:{PORT}/ping/', timeout=2)
self.checker.check_response(r, 'Check failed')
def put_flag(self, flag, vuln):
new_id = rnd_string(10)
r = requests.post(
f'http://{self.checker.host}:{PORT}/put/',
json={
'id': new_id,
'vuln': vuln,
'flag': flag,
},
timeout=2,
)
self.checker.check_response(r, 'Could not put flag')
return new_id
def get_flag(self, flag_id, vuln):
r = requests.get(
f'http://{self.checker.host}:{PORT}/get/',
params={
'id': flag_id,
'vuln': vuln,
},
timeout=2,
)
self.checker.check_response(r, 'Could not get flag')
data = self.checker.get_json(r, 'Invalid response from /get/')
self.checker.assert_in(
'flag', data,
'Could not get flag',
status=Status.CORRUPT,
)
return data['flag']

View File

@ -0,0 +1,9 @@
FROM mysql:5.7
ARG DEBIAN_FRONTEND=noninteractive
ENV MYSQL_ROOT_PASSWORD=root
ENV MYSQL_USER=baby
ENV MYSQL_PASSWORD=sql
ENV MYSQL_DATABASE=babysql
COPY default-users.sql /docker-entrypoint-initdb.d

View File

@ -0,0 +1,2 @@
CREATE TABLE `babysql`.`users` (`id` INT NOT NULL , `username` VARCHAR(255) NOT NULL , `pwd` VARCHAR(255) NOT NULL ) ENGINE = InnoDB;
INSERT INTO `users` (`id`, `username`, `pwd`) VALUES ('1', 'admin', 'CCIT{D3f4ult}');

View File

@ -0,0 +1,56 @@
version: '3.9'
services:
db:
build:
context: ./db
ports:
- 3306:3306
restart: always
phpmyadmin:
image: phpmyadmin/phpmyadmin:5.2.0
restart: always
ports:
- 5004:80
links:
- db
environment:
- PMA_HOST=db
- PMA_PORT=3306
- PMA_ARBITRARY=1
depends_on:
- db
web:
build:
context: ./web
restart: always
environment:
- DBHOST=db
- DBUSER=baby
- DBPASS=sql
- DBSCHEMA=babysql
links:
- db
ports:
- 5003:80
depends_on:
- db
# Do not tamper this!
flag_manager:
build:
context: ./flag_manager
restart: always
links:
- db
environment:
- DBHOST=db
- DBUSER=baby
- DBPASS=sql
- DBSCHEMA=babysql
ports:
- 5005:5005
depends_on:
- db

View File

@ -0,0 +1,163 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Flags file
flags.json

View File

@ -0,0 +1,9 @@
FROM python:3.9.13-slim
WORKDIR /usr/src/app
COPY api.py flags.py main.py requirements.txt ./
RUN pip install -r requirements.txt
EXPOSE 5005
CMD ["python", "main.py"]

View File

@ -0,0 +1,31 @@
import flags
from flask import Blueprint, jsonify, make_response, request
rest_api = Blueprint('api', __name__)
@rest_api.route('/ping/', methods = ['GET'])
def ping():
return make_response("I am alive!")
@rest_api.route('/get/', methods = ['GET'])
def get_flag():
try:
args = request.args
id = args['id']
vuln = args['vuln']
flag = flags.Singleton().get_flag(id, vuln)
return make_response(jsonify({'flag': flag}))
except Exception as e:
return make_response(str(e))
@rest_api.route('/put/', methods = ['POST'])
def set_flag():
try:
body = request.get_json()
id = body['id']
vuln = body['vuln']
flag = body['flag']
flags.Singleton().set_flag(id, vuln, flag)
return make_response('Flag correctly set')
except Exception as e:
return make_response(str(e))

View File

@ -0,0 +1,44 @@
import os
import peewee
import json
dbschema = os.getenv('DBSCHEMA', default=None)
dbuser = os.getenv('DBUSER', default=None)
dbpwd = os.getenv('DBPASS', default=None)
dbhost = os.getenv('DBHOST', default=None)
database = peewee.MySQLDatabase(dbschema, user=dbuser, password=dbpwd, host=dbhost, port=3306)
class Singleton():
flags = []
"""Implement it as a Singleton"""
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance
def get_flag(self, id, vuln):
is_correct_flag = lambda f: f['id'] == id and f['vuln'] == vuln
flag = next(filter(is_correct_flag, self.flags), None)['flag']
return flag
def set_flag(self, id, vuln, flag):
new_flag = {'id': id, 'vuln': vuln, 'flag': flag}
self.flags.append(new_flag)
with open('flags.json', 'w') as outfile:
json.dump(self.flags, outfile, sort_keys=True, indent=4, separators=(',', ': '))
database.connect()
query = Users.update({Users.pwd:flag}).where(Users.username == "admin")
query.execute()
database.close()
class BaseModel(peewee.Model):
class Meta:
database = database
class Users(BaseModel):
id = peewee.IntegerField(unique=True)
username = peewee.CharField()
pwd = peewee.CharField()
base = BaseModel()

View File

@ -0,0 +1,20 @@
import flask
import flags
from api import rest_api
PORT = 5005
def main():
app = flask.Flask(__name__)
app.register_blueprint(rest_api)
# Instantiate Flags Singleton
flags.Singleton()
# Load server
print(f"BabySql Flag Manager running on port {PORT}")
app.run(host='0.0.0.0', port=PORT)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,9 @@
click==8.1.3
Flask==2.1.2
inputimeout==1.0.4
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.1
peewee==3.15.0
PyMySQL==1.0.2
Werkzeug==2.1.2

View File

@ -0,0 +1,7 @@
FROM php:7.2-apache
RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli
COPY index.php /var/www/html/index.php
EXPOSE 80
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

View File

@ -0,0 +1,101 @@
<?php
error_reporting(0);
if(isset($_GET['source'])){
highlight_file(__FILE__);
die();
}
function do_query($query){
$servername = getenv('DBHOST');
$username = getenv('DBUSER');
$password = getenv('DBPASS');
$dbschema = getenv('DBSCHEMA');
$conn = new mysqli($servername, $username, $password, $dbschema, 3306);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$result = $conn->query($query);
if ($result->num_rows > 0) {
return $result->fetch_assoc();
}
else{
return false;
}
}
if(isset($_POST['password'])){
#$password = addslashes($_POST['password']);
$password = $_POST['password'];
$query = "SELECT * FROM users WHERE pwd=('$password') AND username=('admin')";
if (preg_match('/INSERT|UPDATE|DELETE|CREATE|ALTER|DROP/i', $query)) {
die("Sorry! You cannot do that.");
}
$res = do_query($query);
if(isset($res['username'])){
$name = $res['username'];
}
}
?>
<html>
<head>
<title></title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</head>
<body>
<div class="main">
<div class="container">
<div class="row">
<h1>BabySql</h1>
</div>
<div class="row">
<p class="lead">
Welcome to BabySql! If you want you can view the source code <a href="?source">here</a>. Happy Injection:)
</p>
</div>
</div>
<div class="container">
<div class="row">
<form class="form form-inline" method='POST'>
<input class="form-control" name='password' class='form-control' type='password' value='' placeholder='Password'>
<input class="form-control btn btn-default" name="submit" value='Go' type='submit'>
</form>
</div>
<div class="row">
<p class="lead">
<?php
if($name){?>
Logged as <?= htmlspecialchars($name) ?>
<?php }; ?>
</p>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,50 @@
#!/usr/bin/env python3
# Author: Angelo Delicato
# Description: Just a dummy checker for the Dummy ForcAD Vulnbox
# Note: Use this file inside the checker folder in ForcAD
import sys
from pathlib import Path
BASE_DIR = Path(__file__).absolute().resolve().parent
sys.path.insert(0, str(BASE_DIR))
from service_lib import *
class Checker(BaseChecker):
def __init__(self, *args, **kwargs):
super(Checker, self).__init__(*args, **kwargs)
self.mch = CheckMachine(self)
def action(self, action, *args, **kwargs):
try:
super(Checker, self).action(action, *args, **kwargs)
except requests.exceptions.ConnectionError:
self.cquit(
Status.DOWN,
'Connection error',
'Got requests connection error',
)
def check(self):
self.mch.ping()
self.cquit(Status.OK)
def put(self, flag_id, flag, vuln):
new_id = self.mch.put_flag(flag, vuln)
self.cquit(Status.OK, new_id)
def get(self, flag_id, flag, vuln):
got_flag = self.mch.get_flag(flag_id, vuln)
self.assert_eq(got_flag, flag, 'Could not get flag', status=Status.CORRUPT)
self.cquit(Status.OK)
if __name__ == '__main__':
c = Checker(sys.argv[2])
try:
c.action(sys.argv[1], *sys.argv[3:])
except c.get_check_finished_exception():
cquit(Status(c.status), c.public, c.private)

View File

@ -0,0 +1,46 @@
import requests
from checklib import *
PORT = 5001
class CheckMachine:
def __init__(self, checker):
self.checker = checker
def ping(self):
r = requests.get(f'http://{self.checker.host}:{PORT}/ping', timeout=2)
self.checker.check_response(r, 'Check failed')
def put_flag(self, flag, vuln):
new_id = rnd_string(10)
r = requests.post(
f'http://{self.checker.host}:{PORT}/put',
json={
'id': new_id,
'vuln': vuln,
'flag': flag,
},
timeout=2,
)
self.checker.check_response(r, 'Could not put flag')
return new_id
def get_flag(self, flag_id, vuln):
r = requests.get(
f'http://{self.checker.host}:{PORT}/get',
params={
'id': flag_id,
'vuln': vuln,
},
timeout=2,
)
self.checker.check_response(r, 'Could not get flag')
data = self.checker.get_json(r, 'Invalid response from /get')
self.checker.assert_in(
'flag', data,
'Could not get flag',
status=Status.CORRUPT,
)
return data['flag']

View File

@ -0,0 +1,130 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

View File

@ -0,0 +1,10 @@
FROM node:alpine3.16
WORKDIR /usr/src/app
COPY package.json yarn.lock ./
COPY src ./src
RUN yarn install
EXPOSE 5001
CMD ["node", "src/server.js"]

View File

@ -0,0 +1,6 @@
version: "3.9"
services:
dummy:
build: .
ports:
- "5001:5001"

View File

@ -0,0 +1,10 @@
{
"name": "Dummy-ForcAD-Vulnbox",
"version": "1.0.0",
"main": "src/server.js",
"license": "MIT",
"dependencies": {
"body-parser": "^1.20.0",
"express": "^4.18.1"
}
}

View File

@ -0,0 +1,21 @@
class FlagService {
constructor() {
this.flags = []
}
getFlag(id, vuln) {
return this.flags.find((f) => f.id === id && f.vuln === vuln).flag
}
setFlag(id, vuln, flag) {
const newFlag = {id, vuln, flag}
this.flags.push(newFlag);
}
getLastFlag() {
const index = this.flags.length-1
return this.flags[index].flag
}
}
module.exports = new FlagService();

View File

@ -0,0 +1,65 @@
const express = require('express')
const bodyParser = require('body-parser')
const flagService = require('./flag')
const app = express()
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.json());
PORT = 5001;
const log = (msg) => {
const currentDate = new Date().toUTCString();
console.log(`[${currentDate}] ${msg}`)
}
app.get('/', (_req, res) => {
log("GET on /")
res.send('I am just a dummy Vulnbox')
})
app.get('/ping', (_req, res) => {
log("GET on /ping")
res.send('I am just a dummy Vulnbox')
})
app.get('/get', (req, res) => {
log("GET on /get")
if (req.query && req.query.id && req.query.vuln) {
log(`Received id: ${req.query.id} - vuln: ${req.query.vuln}`)
const id = req.query.id
const vuln = req.query.vuln
res.json({flag:flagService.getFlag(id, vuln)})
}
else {
res.send("ERROR: flag not set")
}
})
app.post('/put', (req, res) => {
log("POST on /put")
if (req.body && req.body.id && req.body.vuln && req.body.flag) {
log(`Received body with id: ${req.body.id} - vuln: ${req.body.vuln} - flag: ${req.body.flag}`)
const id = req.body.id
const vuln = req.body.vuln
const flag = req.body.flag
flagService.setFlag(id, vuln, flag)
res.send("Flag correctly set")
}
else {
res.send("ERROR: flag not set")
}
})
app.get('/hackme', (_req, res) => {
log("GET on /hackme")
res.json({flag: flagService.getLastFlag()})
})
log(`Starting Dummy ForcAD Vulnbox on port ${PORT}`)
app.listen(PORT)

View File

@ -0,0 +1,405 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
accepts@~1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
dependencies:
mime-types "~2.1.34"
negotiator "0.6.3"
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
body-parser@1.20.0, body-parser@^1.20.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5"
integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==
dependencies:
bytes "3.1.2"
content-type "~1.0.4"
debug "2.6.9"
depd "2.0.0"
destroy "1.2.0"
http-errors "2.0.0"
iconv-lite "0.4.24"
on-finished "2.4.1"
qs "6.10.3"
raw-body "2.5.1"
type-is "~1.6.18"
unpipe "1.0.0"
bytes@3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
call-bind@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
dependencies:
function-bind "^1.1.1"
get-intrinsic "^1.0.2"
content-disposition@0.5.4:
version "0.5.4"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
dependencies:
safe-buffer "5.2.1"
content-type@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
cookie-signature@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
cookie@0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
debug@2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
dependencies:
ms "2.0.0"
depd@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
destroy@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
etag@~1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
express@^4.18.1:
version "4.18.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
body-parser "1.20.0"
content-disposition "0.5.4"
content-type "~1.0.4"
cookie "0.5.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "2.0.0"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
finalhandler "1.2.0"
fresh "0.5.2"
http-errors "2.0.0"
merge-descriptors "1.0.1"
methods "~1.1.2"
on-finished "2.4.1"
parseurl "~1.3.3"
path-to-regexp "0.1.7"
proxy-addr "~2.0.7"
qs "6.10.3"
range-parser "~1.2.1"
safe-buffer "5.2.1"
send "0.18.0"
serve-static "1.15.0"
setprototypeof "1.2.0"
statuses "2.0.1"
type-is "~1.6.18"
utils-merge "1.0.1"
vary "~1.1.2"
finalhandler@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
dependencies:
debug "2.6.9"
encodeurl "~1.0.2"
escape-html "~1.0.3"
on-finished "2.4.1"
parseurl "~1.3.3"
statuses "2.0.1"
unpipe "~1.0.0"
forwarded@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
fresh@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
get-intrinsic@^1.0.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598"
integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==
dependencies:
function-bind "^1.1.1"
has "^1.0.3"
has-symbols "^1.0.3"
has-symbols@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
http-errors@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
dependencies:
depd "2.0.0"
inherits "2.0.4"
setprototypeof "1.2.0"
statuses "2.0.1"
toidentifier "1.0.1"
iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
dependencies:
safer-buffer ">= 2.1.2 < 3"
inherits@2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
ipaddr.js@1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
merge-descriptors@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@~2.1.24, mime-types@~2.1.34:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
dependencies:
mime-db "1.52.0"
mime@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
ms@2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
negotiator@0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
object-inspect@^1.9.0:
version "1.12.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
on-finished@2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
dependencies:
ee-first "1.1.1"
parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
proxy-addr@~2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
dependencies:
forwarded "0.2.0"
ipaddr.js "1.9.1"
qs@6.10.3:
version "6.10.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
dependencies:
side-channel "^1.0.4"
range-parser@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
raw-body@2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
dependencies:
bytes "3.1.2"
http-errors "2.0.0"
iconv-lite "0.4.24"
unpipe "1.0.0"
safe-buffer@5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
"safer-buffer@>= 2.1.2 < 3":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
send@0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
dependencies:
debug "2.6.9"
depd "2.0.0"
destroy "1.2.0"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
fresh "0.5.2"
http-errors "2.0.0"
mime "1.6.0"
ms "2.1.3"
on-finished "2.4.1"
range-parser "~1.2.1"
statuses "2.0.1"
serve-static@1.15.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
dependencies:
encodeurl "~1.0.2"
escape-html "~1.0.3"
parseurl "~1.3.3"
send "0.18.0"
setprototypeof@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
side-channel@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
dependencies:
call-bind "^1.0.0"
get-intrinsic "^1.0.2"
object-inspect "^1.9.0"
statuses@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
toidentifier@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
type-is@~1.6.18:
version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
dependencies:
media-typer "0.3.0"
mime-types "~2.1.24"
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
utils-merge@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==

View File

@ -0,0 +1,50 @@
#!/usr/bin/env python3
# Author: Angelo Delicato
# Description: Just a checker for the HashMePlease ForcAD Vulnbox
# Note: Use this file inside the checker folder in ForcAD
import sys
from pathlib import Path
BASE_DIR = Path(__file__).absolute().resolve().parent
sys.path.insert(0, str(BASE_DIR))
from service_lib import *
class Checker(BaseChecker):
def __init__(self, *args, **kwargs):
super(Checker, self).__init__(*args, **kwargs)
self.mch = CheckMachine(self)
def action(self, action, *args, **kwargs):
try:
super(Checker, self).action(action, *args, **kwargs)
except requests.exceptions.ConnectionError:
self.cquit(
Status.DOWN,
'Connection error',
'Got requests connection error',
)
def check(self):
self.mch.ping()
self.cquit(Status.OK)
def put(self, flag_id, flag, vuln):
new_id = self.mch.put_flag(flag, vuln)
self.cquit(Status.OK, new_id)
def get(self, flag_id, flag, vuln):
got_flag = self.mch.get_flag(flag_id, vuln)
self.assert_eq(got_flag, flag, 'Could not get flag', status=Status.CORRUPT)
self.cquit(Status.OK)
if __name__ == '__main__':
c = Checker(sys.argv[2])
try:
c.action(sys.argv[1], *sys.argv[3:])
except c.get_check_finished_exception():
cquit(Status(c.status), c.public, c.private)

View File

@ -0,0 +1,46 @@
import requests
from checklib import *
PORT = 5002
class CheckMachine:
def __init__(self, checker):
self.checker = checker
def ping(self):
r = requests.get(f'http://{self.checker.host}:{PORT}/ping/', timeout=2)
self.checker.check_response(r, 'Check failed')
def put_flag(self, flag, vuln):
new_id = rnd_string(10)
r = requests.post(
f'http://{self.checker.host}:{PORT}/put/',
json={
'id': new_id,
'vuln': vuln,
'flag': flag,
},
timeout=2,
)
self.checker.check_response(r, 'Could not put flag')
return new_id
def get_flag(self, flag_id, vuln):
r = requests.get(
f'http://{self.checker.host}:{PORT}/get/',
params={
'id': flag_id,
'vuln': vuln,
},
timeout=2,
)
self.checker.check_response(r, 'Could not get flag')
data = self.checker.get_json(r, 'Invalid response from /get/')
self.checker.assert_in(
'flag', data,
'Could not get flag',
status=Status.CORRUPT,
)
return data['flag']

View File

@ -0,0 +1 @@
This folder will contain the flags.json file

View File

@ -0,0 +1,19 @@
version: "3.9"
services:
netcat:
build:
context: ./netcat
ports:
- "9600:9600"
volumes:
- ./:/data
# Do not tamper with this!
flag_manager:
build:
context: ./flag_manager
restart: always
ports:
- "5002:5002"
volumes:
- ./:/data

View File

@ -0,0 +1,163 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Flags file
flags.json

View File

@ -0,0 +1,9 @@
FROM python:3.9.13-slim
WORKDIR /usr/src/app
COPY api.py flags.py main.py requirements.txt ./
RUN pip install -r requirements.txt
EXPOSE 5002
CMD ["python", "main.py"]

View File

@ -0,0 +1,31 @@
import flags
from flask import Blueprint, jsonify, make_response, request
rest_api = Blueprint('api', __name__)
@rest_api.route('/ping/', methods = ['GET'])
def ping():
return make_response("I am alive!")
@rest_api.route('/get/', methods = ['GET'])
def get_flag():
try:
args = request.args
id = args['id']
vuln = args['vuln']
flag = flags.Singleton().get_flag(id, vuln)
return make_response(jsonify({'flag': flag}))
except Exception as e:
return make_response(str(e))
@rest_api.route('/put/', methods = ['POST'])
def set_flag():
try:
body = request.get_json()
id = body['id']
vuln = body['vuln']
flag = body['flag']
flags.Singleton().set_flag(id, vuln, flag)
return make_response('Flag correctly set')
except Exception as e:
return make_response(str(e))

View File

@ -0,0 +1,23 @@
import json
DATA_FOLDER = "/data"
class Singleton():
flags = []
"""Implement it as a Singleton"""
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance
def get_flag(self, id, vuln):
is_correct_flag = lambda f: f['id'] == id and f['vuln'] == vuln
flag = next(filter(is_correct_flag, self.flags), None)['flag']
return flag
def set_flag(self, id, vuln, flag):
new_flag = {'id': id, 'vuln': vuln, 'flag': flag}
self.flags.append(new_flag)
with open(f"{DATA_FOLDER}/flags.json", 'w') as outfile:
json.dump(self.flags, outfile, sort_keys=True, indent=4, separators=(',', ': '))

View File

@ -0,0 +1,20 @@
import flask
import flags
from api import rest_api
PORT = 5002
def main():
app = flask.Flask(__name__)
app.register_blueprint(rest_api)
# Instantiate Flags Singleton
flags.Singleton()
# Load server
print(f"HashMePlease Flag Manager running on port {PORT}")
app.run(host='0.0.0.0', port=PORT)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,6 @@
click==8.1.3
Flask==2.1.2
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.1
Werkzeug==2.1.2

View File

@ -0,0 +1,163 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Flags file
flags.json

View File

@ -0,0 +1,9 @@
FROM alpine/socat:1.7.4.3-r0
WORKDIR /usr/src/app
COPY hashme.py requirements.txt ./
RUN apk update && apk add python3 py3-pip && pip install -r requirements.txt
EXPOSE 9600
ENTRYPOINT ["socat", "TCP-LISTEN:9600,fork", "EXEC:'python3 hashme.py'"]

View File

@ -0,0 +1,49 @@
import signal
import sys
import string
import random
import json
import hashlib
from inputimeout import inputimeout, TimeoutOccurred
DATA_FOLDER = "/data"
TIMEOUT = 300
BANNER = "Welcome to Hash Me Please!"
BYEBYE_MSG = "Unfortunately the hash is not correct. Byeeee!"
def get_last_flag():
try:
with open(f"{DATA_FOLDER}/flags.json") as json_file:
data = json.load(json_file)
return data[-1]['flag']
except:
print("An error occured, it's not your fault!")
def hash_me():
random_value = ''.join(random.sample(string.ascii_lowercase,15))
correct_hash = hashlib.sha512(random_value.encode()).hexdigest()
print(f"If you hash me I'll give you a gift: {random_value}")
try:
user_hash = inputimeout(prompt='>>', timeout=5)
if user_hash == correct_hash:
print(f"Here is your flag: {get_last_flag()}")
else:
print(BYEBYE_MSG)
except TimeoutOccurred:
print(BYEBYE_MSG)
def handle():
print(BANNER)
print("What do you want to do?")
print("1. Hash me")
print("0. Exit")
ch = int(input("> "))
if ch == 1:
hash_me()
else:
sys.exit(1)
if __name__ == "__main__":
signal.alarm(TIMEOUT)
handle()

View File

@ -0,0 +1 @@
inputimeout==1.0.4

View File

@ -0,0 +1,2 @@
---
- name: Todo