thinking outside the [sand]box

25
Thinking Outside the [Sand]Box

Upload: michael-genkin

Post on 03-Jul-2015

159 views

Category:

Technology


2 download

DESCRIPTION

A 40 minute talk about sandboxes, Python, creating Python in process sandboxes, and defeating them. (Based in part on PySandbox).

TRANSCRIPT

Page 1: Thinking Outside The [Sand]Box

Thinking Outside the [Sand]Box

Page 2: Thinking Outside The [Sand]Box

>>> dir(self)

• Michael Genkin

• A computer engineer

• A researcher• A jack of many trades

• And a master of some

• Prefers Python [2.7] to your favorite programming language since 2008.• Isn’t afraid of the

bytecode.

Page 3: Thinking Outside The [Sand]Box

Outline

• Sandboxes – how & why?

• A bit of Python• Code execution

• __builtins__

• Python Sandbox – HowTo & Examples• Blacklisting

• Whitelisting

• Modifying __builtins__

• If time allows• CPython implementation details

• Code objects

Page 4: Thinking Outside The [Sand]Box

What’s a Sandbox?

“A security mechanism for separating running programs. It is often used to execute untested code, or untrusted programs from unverified third parties, suppliers, untrusted users and untrusted websites.The sandbox typically provides a tightly controlled set of resources for guest programs to run in…” [Wikipedia]

Page 5: Thinking Outside The [Sand]Box

Why a Sandbox?

• UNTRUSTED CODE? Why we’d ever want to execute untrusted code?• Learning platform

• A certain challenge site

• Development environment as a Service

Page 6: Thinking Outside The [Sand]Box

How to Sandbox?

OS Level

• Linux seccomp

• PyPy Sandboxing

Language Level/In-Process*

• PySandbox

• rexec

Don’t use those examples @Home/Production

Page 7: Thinking Outside The [Sand]Box

A Bit of Python…Quick detour

Page 8: Thinking Outside The [Sand]Box

Code Execution in Python

• How does one execute untrusted code?• Or simply dynamically generated code…

• A few ways…• exec(file) – compile & execute a statement (or a file).

• eval – compile & execute an expression.• if you really need eval – try using ast.literal_eval()

• os.exec* – create & execute a new shell• subprocess...

• pickle – a minefield

• Don’t do this at home..!• Really. Don’t. Ever.

Page 9: Thinking Outside The [Sand]Box

Shit Can Happen…

• Resource exhaustion – DoS

• Information disclosure

• Server takeover

Page 10: Thinking Outside The [Sand]Box

Tools of Chaos

• file/open• Though we might need those…

• eval/exec(file)

• exit/quit

• pickle/os/subprocess• We might need those as well

Page 11: Thinking Outside The [Sand]Box

Nice to Meet You __builtins__>>> print dir(__builtins__)['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']

Page 12: Thinking Outside The [Sand]Box

We Need a Sandbox…A Builder & Breaker How-To

Page 13: Thinking Outside The [Sand]Box

An Optimal [Python] Sandbox

• How does this *black magic* really looks like?

class Sandbox(object):def __make_secure(self, unsafecode):

""" Black Magic """return safecode

def execute(self, code):exec self.__make_secure(code)

if __name__ == '__main__':s = Sandbox()s.execute("print 'Hello World!'") # Hello World!s.execute("*bad stuff*") # RuntimeException

Page 14: Thinking Outside The [Sand]Box

Blacklisting __builtins__

def __make_secure(self, unsafecode):keyword_blacklist = ["file", "quit", "eval", "exec",

"execfile", "exit"]for keyword in keyword_blacklist:

if keyword in unsafecode:raise ValueError("Blacklisted")

return unsafecode

Page 15: Thinking Outside The [Sand]Box

Circumventing a Blacklist

• The problem with blacklist is that they’re always incomplete…• What isn’t in the blacklist?

• Lesson learned…• If we can get a reference to

something – we caninvoke it.

s.execute("""__builtins__.__dict__["ZXZhbA==".decode("base64")](*bad stuff*)

""")

Page 16: Thinking Outside The [Sand]Box

Whitelisting __builtins__

import sysdef __make_secure(self, unsafecode):

# Blacklisting codemain = sys.modules["__main__"].__dict__orig_builtins = main["__builtins__"].__dict__builtins_whitelist = set((

'ArithmeticError', 'AssertionError', 'AttributeError', ... # Exceptions'False', 'None', 'True', ... # Constants'basestring', 'bytearray', 'bytes', 'complex', 'dict', ... # Types'__import__', 'abs', 'all', 'any', 'apply', 'bin', 'bool', ... # Functions

# Block: eval, execfile, file, quit, exit, reload, etc.))

for builtin in orig_builtins.keys():if builtin not in builtins_whitelist:

del orig_builtins[builtin]

return unsafecode # No way to do bad stuff now...

s.execute('__builtins__.__dict__["ZXZhbA==".decode("base64")](*bad stuff*)') # NameError

Page 17: Thinking Outside The [Sand]Box

I brought This Little Something…

• The whitelist insures we don’t have anything useful in scope…• But, can we bring more stuff into the scope?

• Lesson learned…• Whitelisting __builtins__

isn’t enough if the attacker canjust import stuff

s.execute("""import osos.exec("python -c '*something bad*'")""")

Page 18: Thinking Outside The [Sand]Box

Whitelisting Imports

• Ever wondered how do Python imports work?

• And how to roll your own?

importer = __builtins__.__dict__.get('__import__')os = importer('os')

Page 19: Thinking Outside The [Sand]Box

Whitelisting Imports

def safe_importer(module_name, globals={}, locals={}, fromlist=[], level=-1):print "You can't import anything bad now..."good_modules = ['string', 're', ...]# Doesn't include os, subprocess, or pickle!

if module_name in good_modules:return __import__(module_name, globals, locals, fromlist, level)

else:raise ImportError('You can\'t import this!')

def __make_secure(self, unsafecode):# Blacklisting code# Whitelisting codeorig_builtins['__import__'] = safe_importer

s.execute("""import osos.exec("python -c '*something bad*'")

""") # ImportError

Page 20: Thinking Outside The [Sand]Box

I Know I Left This Somewhere…

• What do we have left?

• Do we have anything useful left?• We have some types… let’s check them out

• If we have a class – why not have a metaclass as well?• PEP 0253 - __bases__ & __subclasses__()

Page 21: Thinking Outside The [Sand]Box

I Know I Left This Somewhere…

Page 22: Thinking Outside The [Sand]Box

If We Have a Reference…

s.execute("""__builtins__.__dict__['__import__'] = ().__class__.__bases__[0].__subclasses__()[59]()._module.__builtins__['__import__']import osos.exec("python -c '*something bad*'")

""")

Page 23: Thinking Outside The [Sand]Box
Page 24: Thinking Outside The [Sand]Box

Questions Time!How many interactive Python interpreters were harmed while preparing this talk?

Page 25: Thinking Outside The [Sand]Box

Thanks for [email protected]