List comprehension - NameError: name '_[1]' is not defined ?

mario ruggier mario.ruggier at gmail.com
Sat Jan 17 08:09:13 EST 2009


On Jan 17, 12:04 am, ajaksu <aja... at gmail.com> wrote:
> On Jan 16, 3:45 pm, mario ruggier <mario.rugg... at gmail.com> wrote:
>
> > > '(x for x in ()).throw("bork")'
>
> > What is the potential security risk with this one?
>
> I don't see a concrete issue, just found it tempting... raising hand-
> crafted objects :)

OK, I can think of no good reson why anyone would want to do that from
within a temlate, so I'd be fine with blocking out any attribute whose
name starts with "throw" to block this out.

> > All the above attempts will be blocked this way. Any other disallow-
> > sub-strings to add to the list above?
>
> None that I know of, but I suggest testing with dir, globals, locals
> and '__' enabled (which I haven't done yet), as spotting possible
> flaws should be easier. If you can get BOM+encoded garbage tested (seehttp://tinyurl.com/72d98y), it might be worth it too.

The BOM stuff is interesting... from that discussion, I think it would
be also a good idea to blacklist "object" out of the restricted
builtins. I played with this, and prepared a file template as well as
a little script to run it... see below.

To tweak any disallwoed builtins back into the restricted namespace
for testing, you can just do something like:

d.set_on_globals("dir", dir)

for each name you'd like to add, when setting up the domain (see
script below).

To re-enable "__" lookups, you'd need to tweak the regexp above, in
the RestrictedEvaluator class.

> This one fails in lots of interesting ways when you juggle keyword-
> args around:
> exprs = [
>     'evoque("hmm", filters=[unicode.upper ] ,src="/etc/python2.5/
> site.py")',
> ]

Not sure what you mean... it just renders that source code file
uppercased (if it finds it as per the domain setup) ?!?


Here's (a) a mini testing py2-py3 script, similar to previous one
above but to read a template from a file (there may be additional
tricks possible that way), and (b) a sample companion test template.

evoque_restricted_file_test.py
----
# in lieu of print, py2/py3
import sys
def pr(*args):
    sys.stdout.write(" ".join([str(arg) for arg in args])+'\n')
#
from os.path import abspath, join, dirname
from evoque import domain, template

# set the base for for the defualt collection
DEFAULT_DIR = abspath((dirname(__file__)))

# a restricted domain instance
d = domain.Domain(DEFAULT_DIR, restricted=True, errors=3,
quoting='str')
# errors: 3 -> renders, 4 -> raises any evaluation errors,
# see: http://evoque.gizmojo.org/usage/errors/

# Tweak domain.globals to add specific callables for testing:
d.set_on_globals("dir", dir)
d.set_on_globals("gobals", globals)
d.set_on_globals("locals", locals)

pr("domain", d.default_collection.dir,
    d.restricted and "RESTRICTED" or "*** unrestricted ***")

t = d.get_template(restricted_exprs.txt)
pr(t.evoque())
----

restricted_exprs.txt
----
#[
    BOM + encoded trickery

    Note:
    when evaluated in python interpreter:
    >>> eval("# coding: utf7\n
+AG8AYgBqAGUAYwB0AC4AXwBfAHMAdQBiAGMAbABhAHMAcwBlAHMAXwBf-")
    <built-in method __subclasses__ of type object at 0x1f1860>

    but when specified within a template here as:
    ${# coding: utf7\n
+AG8AYgBqAGUAYwB0AC4AXwBfAHMAdQBiAGMAbABhAHMAcwBlAHMAXwBf-}
    gives **pre-evaluation**:
    SyntaxError: unknown encoding: utf7
]#
${"# coding: utf7\n
+AG8AYgBqAGUAYwB0AC4AXwBfAHMAdQBiAGMAbABhAHMAcwBlAHMAXwBf-"},


#[
    Attempt to subversively build string expressions
]#
Explicitly written target expression: ().__class__.mro()
[1].__subclasses__()
    evaluates: ${().__class__.mro()[1].__subclasses__()}

Subversive variation: "()."+"_"*2+"class"+"_"*2+".mro()
[1]."+"_"*2+"subclasses"+"_"*2+"()"
    evaluates (to just the str!): ${"()."+"_"*2+"class"+"_"*2+".mro()
[1]."+"_"*2+"subclasses"+"_"*2+"()"}

Attempt to "set" same subsersively built expr to a loop variable
and then "evaluate" that variable:
$for{
    expr in [
        str("()."+"_"*2+"class"+"_"*2+".mro()
[1]."+"_"*2+"subclasses"+"_"*2+"()")
            ] }
    evaluates (to just the str!): ${expr}
    attempt eval(...): ${eval(expr)}
$rof
(Note: evoque does not explicitly allow arbitrary setting of
variables, except within for loops.)
----


mario



More information about the Python-list mailing list