CSRF on various endpoints
Pretty recently CSRF protection in calibre-web
was implemented. However, there are some state-changing endpoints that accept GET
requests instead of POST
.
The most impactful route so far, that allows to completely shutdown the server:
@admi.route("/shutdown")
@login_required
@admin_required
def shutdown():
task = int(request.args.get("parameter").strip())
showtext = {}
if task in (0, 1): # valid commandos received
# close all database connections
calibre_db.dispose()
ub.dispose()
if task == 0:
showtext['text'] = _(u'Server restarted, please reload page')
else:
showtext['text'] = _(u'Performing shutdown of server, please close window')
# stop gevent/tornado server
web_server.stop(task == 0)
return json.dumps(showtext)
if task == 2:
log.warning("reconnecting to calibre database")
calibre_db.reconnect_db(config, ub.app_DB_path)
showtext['text'] = _(u'Reconnect successful')
return json.dumps(showtext)`
And a bunch of low-impact CSRFs:
- Add a book to the shelf
@shelf.route("/shelf/add/<int:shelf_id>/<int:book_id>")
- Delete a shelf:
@shelf.route("/shelf/delete/<int:shelf_id>")
And so on, actually this file has plenty of endpoints without protection.
I’m leaving a PoC only for the first example as all payloads are almost the same:
// PoC.html
<form action="http://127.0.0.1:8083/shutdown" method="GET">
<input type="hidden" name="parameter" value="1"/>
<input type="submit" value="Shutdown"/>
</form>
All requests that somehow change server/db state must be queried using POST
method.
This vulnerability is capable of performing malicious actions in case victim visits attacker’s website.
I’m not sure that I found all vulnerable endpoints, so it’s better to check all existing routes that allow to use GET
.