Module: check_mk
Branch: master
Commit: 34f45715c2e5b4ee488ecd1cdf0d812cdd051c09
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=34f45715c2e5b4…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Thu Oct 19 15:41:40 2017 +0200
5399 SEC Fixed multiple stored XSS injections in WATO dialogs
It was possible to inject Javascript code to using configuration fields of different
objects
(users, hosts, groups, roles, timeperiods).
These issues could only be triggered by authenticated users that have permissons to use
WATO
and add/edit the objects mentioned above. Normally these are users with the roles admin
or
users.
Change-Id: I6f14aac48ea05b23508aa8d9576b012cdc7ec84a
---
.werks/5399 | 16 ++++++++++++++++
web/htdocs/valuespec.py | 2 +-
web/htdocs/wato.py | 25 ++++++++++++-------------
web/plugins/wato/builtin_attributes.py | 5 ++---
4 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/.werks/5399 b/.werks/5399
new file mode 100644
index 0000000..8c48462
--- /dev/null
+++ b/.werks/5399
@@ -0,0 +1,16 @@
+Title: Fixed multiple stored XSS injections in WATO dialogs
+Level: 1
+Component: wato
+Class: security
+Compatible: compat
+Edition: cre
+State: unknown
+Version: 1.5.0i1
+Date: 1508420225
+
+It was possible to inject Javascript code to using configuration fields of different
objects
+(users, hosts, groups, roles, timeperiods).
+
+These issues could only be triggered by authenticated users that have permissons to use
WATO
+and add/edit the objects mentioned above. Normally these are users with the roles admin
or
+users.
diff --git a/web/htdocs/valuespec.py b/web/htdocs/valuespec.py
index 2f2cb3c..762c49a 100644
--- a/web/htdocs/valuespec.py
+++ b/web/htdocs/valuespec.py
@@ -3676,7 +3676,7 @@ class ElementSelection(ValueSpec):
def value_to_text(self, value):
self.load_elements()
- return self._elements.get(value, value)
+ return html.attrencode(self._elements.get(value, value))
def from_html_vars(self, varprefix):
return html.var(varprefix)
diff --git a/web/htdocs/wato.py b/web/htdocs/wato.py
index 24cf9be..b48b260 100644
--- a/web/htdocs/wato.py
+++ b/web/htdocs/wato.py
@@ -794,7 +794,7 @@ def show_hosts(folder):
contact_group_names = userdb.load_group_information().get("contact", {})
def render_contact_group(c):
display_name = contact_group_names.get(c, {'alias': c})['alias']
- return '<a
href="wato.py?mode=edit_contact_group&edit=%s">%s</a>' % (c,
display_name)
+ return html.render_a(display_name,
"wato.py?mode=edit_contact_group&edit=%s" % c)
host_errors = folder.host_validation_errors()
rendered_hosts = []
@@ -853,7 +853,7 @@ def show_hosts(folder):
else:
tdclass, tdcontent = attr.paint(effective.get(attrname), hostname)
tdclass += " inherited"
- table.cell(attr.title(), tdcontent, css=tdclass)
+ table.cell(attr.title(), html.attrencode(tdcontent), css=tdclass)
# Am I authorized?
reason = host.reason_why_may_not("read")
@@ -868,8 +868,8 @@ def show_hosts(folder):
# Permissions and Contact groups - through complete recursion and inhertance
permitted_groups, host_contact_groups, use_for_services = host.groups()
- table.cell(_("Permissions"), ",
".join(map(render_contact_group, permitted_groups)))
- table.cell(_("Contact Groups"), ",
".join(map(render_contact_group, host_contact_groups)))
+ table.cell(_("Permissions"), HTML(",
").join(map(render_contact_group, permitted_groups)))
+ table.cell(_("Contact Groups"), HTML(",
").join(map(render_contact_group, host_contact_groups)))
if not config.wato_hide_hosttags:
# Raw tags
@@ -7212,8 +7212,8 @@ class ModeGroups(WatoMode):
html.icon_button(clone_url, _("Create a copy of this group"),
"clone")
html.icon_button(delete_url, _("Delete"), "delete")
- table.cell(_("Name"), name)
- table.cell(_("Alias"), group['alias'])
+ table.cell(_("Name"), html.attrencode(name))
+ table.cell(_("Alias"), html.attrencode(group['alias']))
def page(self):
@@ -8894,8 +8894,8 @@ def mode_timeperiods(phase):
html.icon_button(edit_url, _("Properties"), "edit")
html.icon_button(delete_url, _("Delete"), "delete")
- table.cell(_("Name"), name)
- table.cell(_("Alias"), timeperiod.get("alias",
""))
+ table.cell(_("Name"), html.attrencode(name))
+ table.cell(_("Alias"),
html.attrencode(timeperiod.get("alias", "")))
table.end()
@@ -10499,7 +10499,7 @@ def mode_users(phase):
html.icon(_('Notifications are disabled'), 'notif_disabled')
# Full name / Alias
- table.cell(_("Alias"), user.get("alias", ""))
+ table.cell(_("Alias"), html.attrencode(user.get("alias",
"")))
# Email
table.cell(_("Email"), user.get("email", ""))
@@ -11254,10 +11254,10 @@ def mode_roles(phase):
html.icon_button(delete_url, _("Delete this role"),
"delete")
# ID
- table.cell(_("Name"), id)
+ table.cell(_("Name"), html.attrencode(id))
# Alias
- table.cell(_("Alias"), role["alias"])
+ table.cell(_("Alias"), html.attrencode(role["alias"]))
# Type
table.cell(_("Type"), _("builtin") if
role.get("builtin") else _("custom"))
@@ -11268,8 +11268,7 @@ def mode_roles(phase):
# Users
table.cell(_("Users"),
- ", ".join([ '<a href="%s">%s</a>' %
(folder_preserving_link([("mode", "edit_user"), ("edit",
user_id)]),
- user.get("alias", user_id))
+ HTML(", ").join([ html.render_a(user.get("alias", user_id),
folder_preserving_link([("mode", "edit_user"), ("edit",
user_id)]))
for (user_id, user) in users.items() if (id in user["roles"])]))
diff --git a/web/plugins/wato/builtin_attributes.py
b/web/plugins/wato/builtin_attributes.py
index 2b371da..03d91a5 100644
--- a/web/plugins/wato/builtin_attributes.py
+++ b/web/plugins/wato/builtin_attributes.py
@@ -220,10 +220,9 @@ class ParentsAttribute(ValueSpecAttribute):
return "parents"
def paint(self, value, hostname):
- parts = [ '<a href="%s">%s</a>' % (
- "wato.py?" + html.urlencode_vars([("mode",
"edit_host"), ("host", hn)]), hn)
+ parts = [ html.render_a(hn, "wato.py?" +
html.urlencode_vars([("mode", "edit_host"), ("host", hn)]))
for hn in value ]
- return "", ", ".join(parts)
+ return "", HTML(", ").join(parts)
declare_host_attribute(ParentsAttribute(),