mirror of
https://github.com/kakwa/ldapcherry
synced 2024-11-22 09:24:21 +01:00
Protect against XSS vulnerabilities in URL redirection
- Switch from base64 to URL encoding for the passing the URL, using the built-in Mako filtering - Apply HTML filtering to Mako output by default - Disable HTML filtering for nested templates in adduser, modify, and selfmodify
This commit is contained in:
parent
1ed654c91b
commit
6f98076281
@ -15,7 +15,7 @@ import logging
|
|||||||
import logging.handlers
|
import logging.handlers
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from socket import error as socket_error
|
from socket import error as socket_error
|
||||||
import base64
|
import urllib
|
||||||
import cgi
|
import cgi
|
||||||
|
|
||||||
from exceptions import *
|
from exceptions import *
|
||||||
@ -387,7 +387,8 @@ class LdapCherry(object):
|
|||||||
)
|
)
|
||||||
# preload templates
|
# preload templates
|
||||||
self.temp_lookup = lookup.TemplateLookup(
|
self.temp_lookup = lookup.TemplateLookup(
|
||||||
directories=self.template_dir, input_encoding='utf-8'
|
directories=self.template_dir, input_encoding='utf-8',
|
||||||
|
default_filters=['unicode', 'h']
|
||||||
)
|
)
|
||||||
# load each template
|
# load each template
|
||||||
self.temp = {}
|
self.temp = {}
|
||||||
@ -573,7 +574,7 @@ class LdapCherry(object):
|
|||||||
|
|
||||||
def _check_auth(self, must_admin, redir_login=True):
|
def _check_auth(self, must_admin, redir_login=True):
|
||||||
""" check if a user is autheticated and, optionnaly an administrator
|
""" check if a user is autheticated and, optionnaly an administrator
|
||||||
if user not authentifaced -> redirection to login page (with base64
|
if user not authenticated -> redirect to login page (with escaped URL
|
||||||
of the originaly requested page (redirection after login)
|
of the originaly requested page (redirection after login)
|
||||||
if user authenticated, not admin and must_admin enabled -> 403 error
|
if user authenticated, not admin and must_admin enabled -> 403 error
|
||||||
@boolean must_admin: flag "user must be an administrator to access
|
@boolean must_admin: flag "user must be an administrator to access
|
||||||
@ -588,13 +589,13 @@ class LdapCherry(object):
|
|||||||
qs = ''
|
qs = ''
|
||||||
else:
|
else:
|
||||||
qs = '?' + cherrypy.request.query_string
|
qs = '?' + cherrypy.request.query_string
|
||||||
# base64 of the requested URL
|
# Escaped version of the requested URL
|
||||||
b64requrl = base64.b64encode(cherrypy.url() + qs)
|
quoted_requrl = urllib.quote_plus(cherrypy.url() + qs)
|
||||||
if not username:
|
if not username:
|
||||||
# return to login page (with base64 of the url in query string
|
# return to login page (with quoted url in query string)
|
||||||
if redir_login:
|
if redir_login:
|
||||||
raise cherrypy.HTTPRedirect(
|
raise cherrypy.HTTPRedirect(
|
||||||
"/signin?url=%(url)s" % {'url': b64requrl},
|
"/signin?url=%(url)s" % {'url': quoted_requrl},
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise cherrypy.HTTPError(
|
raise cherrypy.HTTPError(
|
||||||
@ -606,7 +607,7 @@ class LdapCherry(object):
|
|||||||
or not cherrypy.session['connected']:
|
or not cherrypy.session['connected']:
|
||||||
if redir_login:
|
if redir_login:
|
||||||
raise cherrypy.HTTPRedirect(
|
raise cherrypy.HTTPRedirect(
|
||||||
"/signin?url=%(url)s" % {'url': b64requrl},
|
"/signin?url=%(url)s" % {'url': quoted_requrl},
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise cherrypy.HTTPError(
|
raise cherrypy.HTTPError(
|
||||||
@ -631,7 +632,7 @@ class LdapCherry(object):
|
|||||||
else:
|
else:
|
||||||
if redir_login:
|
if redir_login:
|
||||||
raise cherrypy.HTTPRedirect(
|
raise cherrypy.HTTPRedirect(
|
||||||
"/signin?url=%(url)s" % {'url': b64requrl},
|
"/signin?url=%(url)s" % {'url': quoted_requrl},
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise cherrypy.HTTPError(
|
raise cherrypy.HTTPError(
|
||||||
@ -919,7 +920,7 @@ class LdapCherry(object):
|
|||||||
if url is None:
|
if url is None:
|
||||||
redirect = "/"
|
redirect = "/"
|
||||||
else:
|
else:
|
||||||
redirect = base64.b64decode(url)
|
redirect = url
|
||||||
raise cherrypy.HTTPRedirect(redirect)
|
raise cherrypy.HTTPRedirect(redirect)
|
||||||
else:
|
else:
|
||||||
message = "login failed for user '%(user)s'" % {
|
message = "login failed for user '%(user)s'" % {
|
||||||
@ -932,7 +933,7 @@ class LdapCherry(object):
|
|||||||
if url is None:
|
if url is None:
|
||||||
qs = ''
|
qs = ''
|
||||||
else:
|
else:
|
||||||
qs = '?url=' + url
|
qs = '?url=' + urllib.quote_plus(url)
|
||||||
raise cherrypy.HTTPRedirect("/signin" + qs)
|
raise cherrypy.HTTPRedirect("/signin" + qs)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
<form method='POST' autocomplete="off" action='/adduser' role="form" class="form-signin" id=form>
|
<form method='POST' autocomplete="off" action='/adduser' role="form" class="form-signin" id=form>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Fill new user's attributes:</legend>
|
<legend>Fill new user's attributes:</legend>
|
||||||
${form}
|
${form | n}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Enable/Disable user's roles:</legend>
|
<legend>Enable/Disable user's roles:</legend>
|
||||||
${roles}
|
${roles | n}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
<div class="row clearfix" style="margin-top:30px">
|
<div class="row clearfix" style="margin-top:30px">
|
||||||
<div class="col-md-4 column"></div>
|
<div class="col-md-4 column"></div>
|
||||||
<div class="col-md-4 column well">
|
<div class="col-md-4 column well">
|
||||||
<%
|
<form method='POST' role="form" class="form-signin"
|
||||||
if url is None:
|
% if url:
|
||||||
qs=''
|
action='login?url=${url | u}'
|
||||||
else:
|
% else:
|
||||||
qs='?url=' + url
|
action='login'
|
||||||
%>
|
% endif
|
||||||
<form method='POST' action='/login${qs}' role="form" class="form-signin">
|
>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<h2 class="form-signin-heading">Please sign in</h2>
|
<h2 class="form-signin-heading">Please sign in</h2>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
<form method='POST' action='/modify' role="form" class="form-signin" id="form">
|
<form method='POST' action='/modify' role="form" class="form-signin" id="form">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Modify user's attributes:</legend>
|
<legend>Modify user's attributes:</legend>
|
||||||
${form}
|
${form | n}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Enable/Disable user's roles:</legend>
|
<legend>Enable/Disable user's roles:</legend>
|
||||||
${roles}
|
${roles | n}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
% if len(standalone_groups) != 0:
|
% if len(standalone_groups) != 0:
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<div class="well well-sm">
|
<div class="well well-sm">
|
||||||
<form method='POST' action='/selfmodify' autocomplete="off" role="form" class="form-signin" id="form">
|
<form method='POST' action='/selfmodify' autocomplete="off" role="form" class="form-signin" id="form">
|
||||||
<legend>Modify your attributes:</legend>
|
<legend>Modify your attributes:</legend>
|
||||||
${form}
|
${form | n}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
|
Loading…
Reference in New Issue
Block a user