[Zope-Coders] Minor vulnerability in page templates

Shane Hathaway shane@zope.com
Thu, 24 Oct 2002 13:22:01 -0400 (EDT)


I just ran across a minor vulnerability in Zope page templates.  I'm going
to disclose this anyway before having a fix so we can take the opportunity
to talk about it and the surrounding issues.

The "macros" computed attribute of page templates is a simple dictionary
that is stored as a volatile attribute.  This means that untrusted scripts
can temporarily change the macros for a page template.  The changes do not
get written to the database, but it does allow a partially trusted user
(someone who has the authority to write scripts) to deface a site that
uses page templates.  I don't know of a way for the public to exploit it.

My first thought was to either wrap the macros dictionary in something
that only permits reads, but never writes, or just make a copy of the
dictionary.  The wrapper sounds less expensive on the surface until you
consider that you'd have to construct a class instance, create an instance
dictionary, and put an attribute in it.  The dictionary copy is much
simpler.

This solved the problem at first, until I realized there was another way
to exploit this.  Macros in a template are Python list objects, which are
also mutable by untrusted code.  So instead of changing the dictionary,
exploit code can just change the contents of the list objects.  Even if
you add some code to protect the lists, the lists contain other lists.
Exploit code can still change the contained lists.  deepcopy() would be a
performance hit.

So now we have a few things to consider.

1) What is the right fix?  We could make TAL generate tuples instead of
lists.  Or maybe the macros need to be wrapped in something that allows no
introspection by untrusted code, and TAL has to unwrap the macros before
using them.  I'm leaning toward the second option.

2) Will Zope 3's "checkers" provide a good answer for this?  Do the
default checkers for dictionaries and lists allow mutation?  If they
don't, then Zope 3 automatically prevents this situation.

3) If we released a "hotfix" for this, the masses would think Zope has a
major vulnerability, even if we explicitly stated it does not.  This is
minor, but Zope 2.6, 2.5, and maybe even 2.4 need to be fixed.  If we
don't keep older maintenance branches in a squeaky clean state, we're
forced to release hotfixes.  Therefore add only *essential* bugfixes to
older maintenance branches like 2_5.

Shane