From 60e1d8ec30b0e488239b31f694300d4de2e7b995 Mon Sep 17 00:00:00 2001 From: b3yond Date: Sun, 27 Jan 2019 11:37:21 +0100 Subject: [PATCH 1/9] found last db.secret and fixed to use the getter --- session.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session.py b/session.py index 5d0c263..b361604 100644 --- a/session.py +++ b/session.py @@ -17,7 +17,7 @@ class SessionPlugin(object): if self.keyword in Signature.from_callable(route.callback).parameters: @wraps(callback) def wrapper(*args, **kwargs): - uid = request.get_cookie('uid', secret=db.secret) + uid = request.get_cookie('uid', secret=db.get_secret()) if uid is None: return redirect(self.loginpage) kwargs[self.keyword] = User(uid) From ddefc2aafa5571ae7517e48d27df1b49004d5eec Mon Sep 17 00:00:00 2001 From: b3yond Date: Sun, 27 Jan 2019 14:52:42 +0100 Subject: [PATCH 2/9] write and read CSRF cookie --- frontend.py | 9 +++++++++ session.py | 9 ++++++++- user.py | 4 ++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/frontend.py b/frontend.py index 452769f..53e3097 100755 --- a/frontend.py +++ b/frontend.py @@ -144,6 +144,7 @@ def settings(user): @post('/settings/markdown') +#csrf @view('template/settings.tpl') def update_markdown(user): user.set_markdown(request.forms['markdown']) @@ -151,6 +152,7 @@ def update_markdown(user): @post('/settings/mail_md') +#csrf @view('template/settings.tpl') def update_mail_md(user): user.set_mail_md(request.forms['mail_md']) @@ -158,6 +160,7 @@ def update_mail_md(user): @post('/settings/goodlist') +#csrf @view('template/settings.tpl') def update_trigger_patterns(user): user.set_trigger_words(request.forms['goodlist']) @@ -165,6 +168,7 @@ def update_trigger_patterns(user): @post('/settings/blocklist') +#csrf @view('template/settings.tpl') def update_badwords(user): user.set_badwords(request.forms['blocklist']) @@ -172,6 +176,7 @@ def update_badwords(user): @post('/settings/telegram') +#csrf def register_telegram(user): apikey = request.forms['apikey'] user.update_telegram_key(apikey) @@ -179,6 +184,7 @@ def register_telegram(user): @get('/api/state') +#csrf def api_enable(user): return user.state() @@ -198,6 +204,8 @@ def logout(): # clear auth cookie response.set_cookie('uid', '', expires=0, path="/") # :todo show info "Logout successful." + allchar = "1234567890" + response.set_cookie('csrf', '', expires=0, path="/") redirect('/') @@ -240,6 +248,7 @@ def twitter_callback(user): @post('/login/mastodon') +#csrf def login_mastodon(user): """ Mastodon OAuth authentication process. diff --git a/session.py b/session.py index b361604..f51dbce 100644 --- a/session.py +++ b/session.py @@ -1,4 +1,4 @@ -from bottle import redirect, request +from bottle import redirect, request, abort, response from db import db from functools import wraps from inspect import Signature @@ -21,6 +21,13 @@ class SessionPlugin(object): if uid is None: return redirect(self.loginpage) kwargs[self.keyword] = User(uid) + csrf = None # initialize variable + if request.method == 'POST': + csrf = request.form.get('csrf') + elif request.method == 'GET': + csrf = request.args.get('csrf') + if csrf != request.get_cookie('csrf'): + abort(400) return callback(*args, **kwargs) return wrapper diff --git a/user.py b/user.py index 92eb463..43d9050 100644 --- a/user.py +++ b/user.py @@ -4,12 +4,16 @@ from db import db import jwt from mastodon import Mastodon from pylibscrypt import scrypt_mcf, scrypt_mcf_check +from random import choice class User(object): def __init__(self, uid): # set cookie response.set_cookie('uid', uid, secret=db.get_secret(), path='/') + allchar = "1234567890" + response.set_cookie('csrf', "".join(choice(allchar) for x in [32]), + db.get_secret(), path='/') self.uid = uid def check_password(self, password): From ec68f17b320e562f161e3edfa837696fafab7c43 Mon Sep 17 00:00:00 2001 From: b3yond Date: Sun, 27 Jan 2019 14:52:42 +0100 Subject: [PATCH 3/9] write and read CSRF cookie --- frontend.py | 14 +++++++++++--- session.py | 5 ++++- template/settings.tpl | 1 + user.py | 4 ++++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/frontend.py b/frontend.py index 452769f..c6076ae 100755 --- a/frontend.py +++ b/frontend.py @@ -144,6 +144,7 @@ def settings(user): @post('/settings/markdown') +#csrf @view('template/settings.tpl') def update_markdown(user): user.set_markdown(request.forms['markdown']) @@ -151,6 +152,7 @@ def update_markdown(user): @post('/settings/mail_md') +#csrf @view('template/settings.tpl') def update_mail_md(user): user.set_mail_md(request.forms['mail_md']) @@ -158,6 +160,7 @@ def update_mail_md(user): @post('/settings/goodlist') +#csrf @view('template/settings.tpl') def update_trigger_patterns(user): user.set_trigger_words(request.forms['goodlist']) @@ -165,6 +168,7 @@ def update_trigger_patterns(user): @post('/settings/blocklist') +#csrf @view('template/settings.tpl') def update_badwords(user): user.set_badwords(request.forms['blocklist']) @@ -172,15 +176,17 @@ def update_badwords(user): @post('/settings/telegram') +#csrf def register_telegram(user): apikey = request.forms['apikey'] user.update_telegram_key(apikey) return city_page(user.get_city(), info="Thanks for registering Telegram!") -@get('/api/state') -def api_enable(user): - return user.state() +# unused afaik +#@get('/api/state') +#def api_enable(user): +# return user.state() @get('/static/') @@ -197,6 +203,7 @@ def guides(filename): def logout(): # clear auth cookie response.set_cookie('uid', '', expires=0, path="/") + response.set_cookie('csrf', '', expires=0, path="/") # :todo show info "Logout successful." redirect('/') @@ -240,6 +247,7 @@ def twitter_callback(user): @post('/login/mastodon') +#csrf def login_mastodon(user): """ Mastodon OAuth authentication process. diff --git a/session.py b/session.py index b361604..b1a0b62 100644 --- a/session.py +++ b/session.py @@ -1,4 +1,4 @@ -from bottle import redirect, request +from bottle import redirect, request, abort, response from db import db from functools import wraps from inspect import Signature @@ -21,6 +21,9 @@ class SessionPlugin(object): if uid is None: return redirect(self.loginpage) kwargs[self.keyword] = User(uid) + if request.method == 'POST': + if request.forms['csrf'] != request.get_cookie('csrf'): + abort(400) return callback(*args, **kwargs) return wrapper diff --git a/template/settings.tpl b/template/settings.tpl index dae30ce..0971d1b 100644 --- a/template/settings.tpl +++ b/template/settings.tpl @@ -106,6 +106,7 @@

+
diff --git a/user.py b/user.py index 92eb463..43d9050 100644 --- a/user.py +++ b/user.py @@ -4,12 +4,16 @@ from db import db import jwt from mastodon import Mastodon from pylibscrypt import scrypt_mcf, scrypt_mcf_check +from random import choice class User(object): def __init__(self, uid): # set cookie response.set_cookie('uid', uid, secret=db.get_secret(), path='/') + allchar = "1234567890" + response.set_cookie('csrf', "".join(choice(allchar) for x in [32]), + db.get_secret(), path='/') self.uid = uid def check_password(self, password): From cdecd170a0627d845521425a551b6bbf0f032c9c Mon Sep 17 00:00:00 2001 From: b3yond Date: Sun, 27 Jan 2019 15:56:19 +0100 Subject: [PATCH 4/9] give CSRF token to template engine --- user.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/user.py b/user.py index 43d9050..4ec7fc8 100644 --- a/user.py +++ b/user.py @@ -1,5 +1,5 @@ from config import config -from bottle import response +from bottle import response, request from db import db import jwt from mastodon import Mastodon @@ -11,10 +11,15 @@ class User(object): def __init__(self, uid): # set cookie response.set_cookie('uid', uid, secret=db.get_secret(), path='/') - allchar = "1234567890" - response.set_cookie('csrf', "".join(choice(allchar) for x in [32]), - db.get_secret(), path='/') self.uid = uid + response.set_cookie('csrf', self.get_csrf(), db.get_secret(), path='/') + + def get_csrf(self): + csrf_token = request.get_cookie('csrf') + if not csrf_token: + allchar = "1234567890" + csrf_token = "".join(choice(allchar) for x in [32]) + return csrf_token def check_password(self, password): db.execute("SELECT passhash FROM user WHERE id=?;", (self.uid,)) @@ -239,6 +244,7 @@ schlitz # - mail_md # - goodlist # - blocklist + # - csrf # - logged in with twitter? # - logged in with mastodon? # - enabled? @@ -248,7 +254,8 @@ schlitz mail_md=citydict['mail_md'], triggerwords=self.get_trigger_words(), badwords=self.get_badwords(), - enabled=self.enabled) + enabled=self.enabled, + csrf=self.get_csrf()) def save_request_token(self, token): db.execute("""INSERT INTO From 139195fd025a712035b6075d31a7a7ba875a27f5 Mon Sep 17 00:00:00 2001 From: b3yond Date: Sun, 27 Jan 2019 16:08:45 +0100 Subject: [PATCH 5/9] added CSRF token to settings template --- frontend.py | 6 ------ template/settings.tpl | 7 ++++++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/frontend.py b/frontend.py index a800191..26a6477 100755 --- a/frontend.py +++ b/frontend.py @@ -144,7 +144,6 @@ def settings(user): @post('/settings/markdown') -#csrf @view('template/settings.tpl') def update_markdown(user): user.set_markdown(request.forms['markdown']) @@ -152,7 +151,6 @@ def update_markdown(user): @post('/settings/mail_md') -#csrf @view('template/settings.tpl') def update_mail_md(user): user.set_mail_md(request.forms['mail_md']) @@ -160,7 +158,6 @@ def update_mail_md(user): @post('/settings/goodlist') -#csrf @view('template/settings.tpl') def update_trigger_patterns(user): user.set_trigger_words(request.forms['goodlist']) @@ -168,7 +165,6 @@ def update_trigger_patterns(user): @post('/settings/blocklist') -#csrf @view('template/settings.tpl') def update_badwords(user): user.set_badwords(request.forms['blocklist']) @@ -176,7 +172,6 @@ def update_badwords(user): @post('/settings/telegram') -#csrf def register_telegram(user): apikey = request.forms['apikey'] user.update_telegram_key(apikey) @@ -248,7 +243,6 @@ def twitter_callback(user): @post('/login/mastodon') -#csrf def login_mastodon(user): """ Mastodon OAuth authentication process. diff --git a/template/settings.tpl b/template/settings.tpl index 0971d1b..66cf873 100644 --- a/template/settings.tpl +++ b/template/settings.tpl @@ -61,6 +61,7 @@