Configuration is controlled in two files; config.py controls database connection information, whilst
levels.py acts as configuration for each level.
This file exposes 3 main symbols.
get_passwordshould return the database password for a given userdb_hostis the host on which the mysql database residesdb_setupexposes a list of known username, database, and schema file triplets- For a given setup
useris the username of a user with rights to access the databasedatabaseis the name of the database which holds the table for the given set of challengesschemais a file containing the database schema
- For a given setup
Levels contains the configurations for each level and group.
groupsexposes all the groups in the tutorial. This should be an array of objects with the propertiesname: Name of the groupdifficulty: Brief flavor text describing the difficulty of the groupflavor: Flavor text for the groupdb: An associateddb_setupobject fromconfig.py
levelscontains the specifications for each level, these contain 4 entriestype: What the type of the challenge is, this should be eithersqlor a string prefixed withsqli-group: The index of the group this challenge belongs to (index ingroups)name: Name of the challengespec: A dictionary describing the specification of a challenge. See below for more
The bulk of this file lies in the spec field. This configures the challenge. The type field will inform
the program what type the spec is. Namely a type=sql spec will be handled differently to a type=sqli spec.
A sql spec should include
question: A one-line question prompttemplate: A template for the sql that should be entered.{qN}indicates blanks the user needs to fill in.Nshould be a0indexed increasing sequence- e.g.
SELECT {q0} FROM {q1} WHERE {q2}will appear asSELECT ___ FROM ___ WHERE ___
- e.g.
match: A well-formed SQL query producing the expected result. This user's sql will be compared with the output of this query- Order matters
flag: A flag to give the user if their query matches thematchqueryerror-control: One offull,error, orblindfullerror control will return both the sql error message and the query that was execute back to the usererrorerror control will only return the sql errorblinderror control will return no feedback
A sqli spec should include
question: same assqlshow: A dictionary containing an identifier followed by place holder text that should be shown to the user- e.g.
{'q0': 'Flag Id'}will show a input with placeholderFlag Idto the user- Specifically at least the html
<input name="q0" placeholder="Flag Id">will be generated
- Specifically at least the html
- e.g.
template: A sql query with{identifier}s corresponding to the identifiers inshow. The user's inputs inshowwill be substituted here.match: same assqlflag: same assqlerror-control: same assql
- Generate a .env file with a random MYSQL_ROOT_PAASSWORD.
MYSQL_ROOT_PASSWORD=random_password
- Start up the database and app server by running
docker-compose up. - Run the database setup.
docker exec -it sqli-tutorial_app_1 /bin/sh -c 'python /app/app/_setup.py root "$MYSQL_ROOT_PASSWORD"'Ensure mysql is running (on port 3306). Once config.py is appropriately setup,
simply invoking the following from within /app will setup all appropriate
users, databases, and schemas.
python3 _setup.py <root username> <root password>
The application can be run locally with the following from within /app. This will listen on port 5001.
python3 app.py
Alternatively gunicorn can also be used to run the application. For production workloads gunicorn should be deployed with at least gevent or a reverse proxy.