CTFd / CTFd/CTFd

Creating a dynamic challenge creates two

Open
#1,666 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
6.8k
Forks
2.8k
Avg merge
1d 6h
Merged PRs (30d)
5

Description

**Environment**:

- CTFd Version/Commit: Tested on 3.1.0 and 3.1.1
- Operating System: Ubuntu LTS 20.04
- Web Browser and Version: Firefox 80.0.1 on Manjaro Linux

**What happened?**
On creating a dynamic challenge, two copies of the same challenge is made. And then unable to delete either due to foreign key constraint. Stack trace below.

**What did you expect to happen?**
Creating a dynamic challenge would create only one dynamic challenge.

**How to reproduce your issue**
This issue doesn't show up immediately. I run the docker version of CTFd, and upon creating a few dynamic challenges in the beginning, there don't seem to be any problems. However, after some hours, this challenge duplication error occurs.

**Any associated stack traces or error logs**
Stack trace for creating challenge, then trying to delete the duplicated challenge.
```
162.158.165.184 - - [25/Sep/2020:17:20:40 +0000] "GET /admin/challenges HTTP/1.1" 200 9634 "https://ctfdomainredacted.com/admin/config" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.165.184 - - [25/Sep/2020:17:20:42 +0000] "GET /admin/challenges/new HTTP/1.1" 200 7776 "https://ctfdomainredacted.com/admin/challenges" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0
"
162.158.165.184 - - [25/Sep/2020:17:20:43 +0000] "GET /api/v1/challenges/types HTTP/1.1" 200 5101 "https://ctfdomainredacted.com/admin/challenges/new" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firef
ox/80.0"
162.158.166.117 - - [25/Sep/2020:17:20:44 +0000] "GET /plugins/challenges/assets/view.js?_=1601054443211 HTTP/1.1" 200 0 "https://ctfdomainredacted.com/admin/challenges/new" "Mozilla/5.0 (X11; Linux x86_64; rv:80.
0) Gecko/20100101 Firefox/80.0"
172.68.146.160 - - [25/Sep/2020:17:20:44 +0000] "GET /plugins/dynamic_challenges/assets/view.js?_=1601054443212 HTTP/1.1" 200 0 "https://ctfdomainredacted.com/admin/challenges/new" "Mozilla/5.0 (X11; Linux x86_64;
rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.166.227 - - [25/Sep/2020:17:20:44 +0000] "GET /themes/core/static/fonts/lato-latin-400.woff2 HTTP/1.1" 200 0 "https://ctfdomainredacted.com/themes/core/static/css/fonts.min.css?d=e54f98c3" "Mozilla/5.0 (X1
1; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.165.28 - - [25/Sep/2020:17:20:44 +0000] "GET /plugins/challenges/assets/create.js?_=1601054443213 HTTP/1.1" 200 0 "https://ctfdomainredacted.com/admin/challenges/new" "Mozilla/5.0 (X11; Linux x86_64; rv:80
.0) Gecko/20100101 Firefox/80.0"
162.158.166.115 - - [25/Sep/2020:17:20:45 +0000] "GET /plugins/dynamic_challenges/assets/create.js?_=1601054443214 HTTP/1.1" 200 0 "https://ctfdomainredacted.com/admin/challenges/new" "Mozilla/5.0 (X11; Linux x86_
64; rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.165.184 - - [25/Sep/2020:17:24:15 +0000] "POST /api/v1/challenges HTTP/1.1" 200 840 "https://ctfdomainredacted.com/admin/challenges/new" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.
0"
162.158.165.184 - - [25/Sep/2020:17:24:15 +0000] "POST /api/v1/challenges HTTP/1.1" 200 840 "https://ctfdomainredacted.com/admin/challenges/new" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.
0"
/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/mapper.py:1693: SAWarning: Flushing object with incompatible polymorphic identity 'static'; the object may not refresh and/or
load correctly (this warning may be suppressed after 10 occurrences)
(state_str(state), dict_[polymorphic_key]),
162.158.165.184 - - [25/Sep/2020:17:25:02 +0000] "POST /api/v1/flags HTTP/1.1" 200 162 "https://ctfdomainredacted.com/admin/challenges/new" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.165.184 - - [25/Sep/2020:17:25:02 +0000] "PATCH /api/v1/challenges/6 HTTP/1.1" 200 840 "https://ctfdomainredacted.com/admin/challenges/new" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/
80.0"
162.158.165.184 - - [25/Sep/2020:17:25:03 +0000] "GET /admin/challenges/6 HTTP/1.1" 200 16531 "https://ctfdomainredacted.com/admin/challenges/new" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/8
0.0"
162.158.166.227 - - [25/Sep/2020:17:25:04 +0000] "GET /plugins/dynamic_challenges/assets/update.js HTTP/1.1" 200 0 "https://ctfdomainredacted.com/admin/challenges/6" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko
/20100101 Firefox/80.0"
162.158.165.184 - - [25/Sep/2020:17:25:04 +0000] "GET /api/v1/comments?challenge_id=6&page=1&per_page=10 HTTP/1.1" 200 135 "https://ctfdomainredacted.com/admin/challenges/6" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.165.184 - - [25/Sep/2020:17:25:04 +0000] "GET /api/v1/challenges/types HTTP/1.1" 200 5101 "https://ctfdomainredacted.com/admin/challenges/6" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.166.177 - - [25/Sep/2020:17:25:05 +0000] "GET /plugins/challenges/assets/view.js?_=1601054704059 HTTP/1.1" 200 0 "https://ctfdomainredacted.com/admin/challenges/6" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.166.153 - - [25/Sep/2020:17:25:05 +0000] "GET /plugins/challenges/assets/create.js?_=1601054704060 HTTP/1.1" 200 0 "https://ctfdomainredacted.com/admin/challenges/6" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.165.184 - - [25/Sep/2020:17:25:09 +0000] "GET /admin/challenges HTTP/1.1" 200 11186 "https://ctfdomainredacted.com/admin/challenges/6" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.165.184 - - [25/Sep/2020:17:33:04 +0000] "GET /admin/challenges HTTP/1.1" 200 11186 "https://ctfdomainredacted.com/admin/challenges/6" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"
162.158.166.41 - - [25/Sep/2020:17:33:04 +0000] "GET /themes/admin/static/js/pages/challenges.min.js?d=e54f98c3 HTTP/1.1" 200 0 "https://ctfdomainredacted.com/admin/challenges" "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0"

ERROR [CTFd] Exception on /api/v1/challenges/6 [DELETE]
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1284, in _execute_context
cursor, statement, parameters, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 590, in do_execute
cursor.execute(statement, parameters)
sqlite3.IntegrityError: FOREIGN KEY constraint failed

The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/usr/local/lib/python3.7/site-packages/flask_restx/api.py", line 375, in wrapper
resp = resource(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/flask/views.py", line 89, in view
return self.dispatch_request(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/flask_restx/resource.py", line 44, in dispatch_request
resp = meth(*args, **kwargs)
File "/opt/CTFd/CTFd/utils/decorators/__init__.py", line 110, in admins_only_wrapper
return f(*args, **kwargs)
File "/opt/CTFd/CTFd/api/v1/challenges.py", line 444, in delete
chal_class.delete(challenge)
File "/opt/CTFd/CTFd/plugins/challenges/__init__.py", line 103, in delete
Challenges.query.filter_by(id=challenge.id).delete()
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3872, in delete
delete_op.exec_()
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/persistence.py", line 1697, in exec_
self._do_exec()
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/persistence.py", line 1928, in _do_exec
self._execute_stmt(delete_stmt)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/persistence.py", line 1702, in _execute_stmt
self.result = self.query._execute_crud(stmt, self.mapper)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3514, in _execute_crud
return conn.execute(stmt, self._params)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1020, in execute
return meth(self, multiparams, params)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 298, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1139, in _execute_clauseelement
distilled_params,
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1324, in _execute_context
e, statement, parameters, cursor, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1518, in _handle_dbapi_exception
sqlalchemy_exception, with_traceback=exc_info[2], from_=e
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 178, in raise_
raise exception
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1284, in _execute_context
cursor, statement, parameters, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 590, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) FOREIGN KEY constraint failed
[SQL: DELETE FROM challenges WHERE challenges.id = ?]
[parameters: (6,)]
(Background on this error at: http://sqlalche.me/e/gkpj)
```

Contributor guide

Open the contributing guide

Research direction

Start with the duplicate POST /api/v1/challenges requests in the report, then read CTFd/api/v1/challenges.py and CTFd/plugins/challenges/__init__.py around challenge creation and deletion. Inspect the dynamic_challenges/assets/create.js entry point and reproduce the delayed duplication if possible. Done means one dynamic challenge is created per request and the resulting challenge can be deleted without a foreign-key error.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, flask, python, sqlalchemy, sqlite
Domain
api, backend, database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.