[Tutor] best way to dynamically set class variables?
Steven D'Aprano
steve at pearwood.info
Fri Nov 9 19:03:20 EST 2018
On Thu, Nov 08, 2018 at 11:34:35AM -0500, Avi Gross wrote:
> An interesting discussion that is outside the scope of a group like this is
> HOW malicious things can be done and perhaps how to avoid them.
>
> Obviously some contexts are totally uncontrolled. If you write a
> "calculator" that asks the user to type in an arbitrary string like
> "2*(3+5)" or "sin(30)" and execute that string and show the result, then
> they can slip in anything like a shell command to reformat the hard disk.
If they want to reformat their own hard disk, there are much easier ways
than slipping a shell command into a Python calculator.
The risk, tiny as it is, is that something which starts life as a
desktop application running on the user's own computer gets extracted
out into a library used in a web application running on somebody else's
server. So in that sense, it is better to avoid eval/exec even on
locally-run desktop applications.
But it is *critical* to avoid eval or exec on untrusted input running on
a server.
> What can you do to minimize risks in such situations?
(1) Don't use eval or exec.
(2) If you must use eval or exec, consider allowing only a whitelist of
allowed commands. You can do that by specifying the global and local
namespace arguments:
ns = {'round': round, 'sin': math.sin, '__builtins__': None}
eval(command, ns, ns)
You must set __builtins__ to something, if it is missing, the
interpreter will set it to the real builtins module and open the doors
wide open.
(3) Don't use eval or exec.
(4) But even with a whitelist, it is remarkably easy to break out of the
sandbox. Most(?) tricks for doing so involve using dunder (Double
UNDERscore) attributes, so a quick palliative for this is to disallow
any command that includes an underscore:
if '_' in command:
raise InvalidCommand('syntax error: no underscores allowed')
else:
eval(command, ns, ns)
(5) Its okay to use eval and exec for your own use, at the interactive
interpreter, or in quick scripts you use in a trusted environment.
(6) But even if you successfully block all the escape tricks, the user
can trivially DOS (Denial Of Service) your calculator web app:
command = '(2**1000)**(2**1000)**(2**1000)'
so you need to run it in an environment where evaluation will timeout
after a certain amount of time, without using up all the memory on your
server.
(7) For experts, its okay to use eval or exec. Maybe.
For a good use of exec, see the source code to namedtuple in the
collections module. Or this:
http://code.activestate.com/recipes/578918-yet-another-namedtuple/
--
Steve
More information about the Tutor
mailing list