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 @@