Skip to content

Commit 38db8d8

Browse files
committed
- issue2550864: Potential information leakage via journal/history
Original code didn't fully implement the security checks. Users with only Edit access on a property were not able to view the journal entry for the property. This patch fixes that. Also had additional info leakage: the target object of a link or multilink must be viewable or editable in order for the journal entry to be shown. Otherwise the existance of the target is exposed via the journal while it is blocked from searches, direct access etc.
1 parent 4792d1d commit 38db8d8

File tree

2 files changed

+59
-25
lines changed

2 files changed

+59
-25
lines changed

CHANGES.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,10 @@ Features:
203203
config.ini with new options and help text. (John Rouillard)
204204
- issue2550864: Potential information leakage via journal/history
205205
Hyperdb history function now only returns properties that the user
206-
has View permissions on. Can be overridden by setting a parameter
207-
when calling the method. Also restructured code that implemented
208-
issue1714899 moving it from the templating class to the hyperdb.
209-
(John Rouillard)
206+
can View or Edit and links to objects the user can see. Can be
207+
overridden by setting a parameter when calling the method.
208+
Also restructured code that implemented issue1714899 moving it
209+
from the templating class to the hyperdb. (John Rouillard)
210210
- Improves diagnostics for mail processing: When using logging level = DEBUG,
211211
bounces and bounce problems are logged. (Bernhard Reiter)
212212

roundup/hyperdb.py

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,48 +1024,82 @@ def history(self, nodeid, enforceperm=True, skipquiet=True):
10241024

10251025
debug_logging = logger.isEnabledFor(logging.DEBUG)
10261026

1027+
uid=self.db.getuid() # id of the person requesting the history
1028+
10271029
for j in self.db.getjournal(self.classname, nodeid):
1030+
# hide/remove journal entry if:
1031+
# property is quiet
1032+
# property is not (viewable or editable)
10281033
id, evt_date, user, action, args = j
10291034
if debug_logging:
10301035
j_repr = "%s"%(j,)
10311036
else:
10321037
j_repr=''
10331038
if args and type(args) == type({}):
1034-
for k in args.keys():
1035-
if skipquiet and self.properties[k].quiet:
1036-
logger.debug("skipping quiet property %s in %s",
1037-
k, j_repr)
1038-
del j[4][k]
1039+
for key in args.keys():
1040+
if skipquiet and self.properties[key].quiet:
1041+
logger.debug("skipping quiet property"
1042+
" %s::%s in %s",
1043+
self.classname, key, j_repr)
1044+
del j[4][key]
10391045
continue
1040-
if enforceperm and not perm("View",
1041-
self.db.getuid(),
1046+
if enforceperm and not ( perm("View",
1047+
uid,
1048+
self.classname,
1049+
property=key ) or perm("Edit",
1050+
uid,
10421051
self.classname,
1043-
property=k ):
1044-
logger.debug("skipping unViewable property %s in %s",
1045-
k, j_repr)
1046-
del j[4][k]
1052+
property=key )):
1053+
logger.debug("skipping unaccessible property %s::%s seen by user%s in %s",
1054+
self.classname, key, uid, j_repr)
1055+
del j[4][key]
10471056
continue
10481057
if not args:
10491058
logger.debug("Omitting journal entry for %s%s"
1050-
" all props quiet in: %s",
1059+
" all props removed in: %s",
10511060
self.classname, nodeid, j_repr)
10521061
continue
10531062
journal.append(j)
10541063
elif action in ['link', 'unlink' ] and type(args) == type(()):
1064+
# hide/remove journal entry if:
1065+
# link property (key) is quiet
1066+
# link property is not (viewable or editable)
1067+
# id/object (linkcl, linkid) that is linked/unlinked is not
1068+
# (viewable or editable)
10551069
if len(args) == 3:
1070+
# e.g. for issue3 blockedby adds link to issue5 with:
1071+
# j = id, evt_date, user, action, args
1072+
# 3|20170528045201.484|5|link|('issue', '5', 'blockedby')
10561073
linkcl, linkid, key = args
10571074
cls = self.db.getclass(linkcl)
1058-
if skipquiet and cls.properties[key].quiet:
1059-
logger.debug("skipping quiet property %s in %s",
1060-
key, j_repr)
1075+
# is the updated property quiet?
1076+
if skipquiet and self.properties[key].quiet:
1077+
logger.debug("skipping quiet property"
1078+
" %s::%s in %s",
1079+
self.classname, key, j_repr)
10611080
continue
1062-
if enforceperm and not perm("View",
1063-
self.db.getuid(),
1081+
# property check on item we want history for
1082+
if enforceperm and not (perm("View",
1083+
uid,
1084+
self.classname,
1085+
property=key) or perm("Edit",
1086+
uid,
10641087
self.classname,
1065-
property=key):
1066-
logger.debug("skipping unViewable property %s in",
1067-
key, j_repr)
1068-
continue
1088+
property=key)):
1089+
logger.debug("skipping unaccessible property %s::%s seen by user%s in %s",
1090+
self.classname, key, uid, j_repr)
1091+
continue
1092+
# check on object linked
1093+
if enforceperm and not (perm("View",
1094+
uid,
1095+
cls.classname,
1096+
itemid=linkid) or perm("Edit",
1097+
uid,
1098+
cls.classname,
1099+
itemid=linkid)):
1100+
logger.debug("skipping unaccessible target %s%s for user%s in %s",
1101+
cls.classname, linkid, uid, j_repr)
1102+
continue
10691103
journal.append(j)
10701104
else:
10711105
logger.error("Invalid %s journal entry for %s%s: %s",

0 commit comments

Comments
 (0)