Merge pull request #82 from ticketfrei/csrf

Building in CSRF prevention
This commit is contained in:
b3yond 2019-01-27 17:56:53 +01:00 committed by GitHub
commit eb2bf5a063
4 changed files with 29 additions and 7 deletions

View file

@ -178,9 +178,10 @@ def register_telegram(user):
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/<filename:path>')
@ -197,6 +198,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('/')

View file

@ -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
@ -17,10 +17,14 @@ 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)
if request.method == 'POST':
if request.forms['csrf'] != request.get_cookie('csrf',
secret=db.get_secret()):
abort(400)
return callback(*args, **kwargs)
return wrapper

View file

@ -61,6 +61,7 @@
<option value='octodon.social'>
<option value='soc.ialis.me'>
</datalist>
<input name='csrf' value='{{csrf}}' type='hidden' />
<input name='confirm' value='Log in' type='submit'/>
</form>
</section>
@ -82,6 +83,7 @@
</p>
<form action="/settings/telegram" method="post">
<input type="text" name="apikey" placeholder="Telegram bot API key" id="apikey">
<input name='csrf' value='{{csrf}}' type='hidden' />
<input name='confirm' value='Login with Telegram' type='submit'/>
</form>
</div>
@ -106,6 +108,7 @@
</p>
<form action="/settings/markdown" method="post">
<textarea id="markdown" rows="20" cols="70" name="markdown" wrap="physical">{{markdown}}</textarea>
<input name='csrf' value='{{csrf}}' type='hidden' />
<input name='confirm' value='Save' type='submit'/>
</form>
</div>
@ -123,6 +126,7 @@
</p>
<form action="/settings/mail_md" method="post">
<textarea id="mail_md" rows="20" cols="70" name="mail_md" wrap="physical">{{mail_md}}</textarea>
<input name='csrf' value='{{csrf}}' type='hidden' />
<input name='confirm' value='Save' type='submit'/>
</form>
</div>
@ -137,6 +141,7 @@
</p>
<form action="/settings/goodlist" method="post">
<textarea id="goodlist" rows="8" cols="70" name="goodlist" wrap="physical">{{triggerwords}}</textarea>
<input name='csrf' value='{{csrf}}' type='hidden' />
<input name='confirm' value='Submit' type='submit'/>
</form>
</div>
@ -151,6 +156,7 @@
</p>
<form action="/settings/blocklist" method="post">
<textarea id="blocklist" rows="8" cols="70" name="blocklist" wrap="physical">{{badwords}}</textarea>
<input name='csrf' value='{{csrf}}' type='hidden' />
<input name='confirm' value='Submit' type='submit'/>
</form>
</div>

14
user.py
View file

@ -1,9 +1,10 @@
from config import config
from bottle import response
from bottle import response, request
from db import db
import jwt
from mastodon import Mastodon
from pylibscrypt import scrypt_mcf, scrypt_mcf_check
from os import urandom
class User(object):
@ -11,6 +12,13 @@ class User(object):
# set cookie
response.set_cookie('uid', uid, secret=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', secret=db.get_secret())
if not csrf_token:
csrf_token = str(urandom(32))
return csrf_token
def check_password(self, password):
db.execute("SELECT passhash FROM user WHERE id=?;", (self.uid,))
@ -235,6 +243,7 @@ schlitz
# - mail_md
# - goodlist
# - blocklist
# - csrf
# - logged in with twitter?
# - logged in with mastodon?
# - enabled?
@ -244,7 +253,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