You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

475 lines
16 KiB

4 years ago
  1. # -*- coding: utf-8 -*-
  2. """
  3. jinja2.sandbox
  4. ~~~~~~~~~~~~~~
  5. Adds a sandbox layer to Jinja as it was the default behavior in the old
  6. Jinja 1 releases. This sandbox is slightly different from Jinja 1 as the
  7. default behavior is easier to use.
  8. The behavior can be changed by subclassing the environment.
  9. :copyright: (c) 2017 by the Jinja Team.
  10. :license: BSD.
  11. """
  12. import types
  13. import operator
  14. from collections import Mapping
  15. from jinja2.environment import Environment
  16. from jinja2.exceptions import SecurityError
  17. from jinja2._compat import string_types, PY2
  18. from jinja2.utils import Markup
  19. from markupsafe import EscapeFormatter
  20. from string import Formatter
  21. #: maximum number of items a range may produce
  22. MAX_RANGE = 100000
  23. #: attributes of function objects that are considered unsafe.
  24. if PY2:
  25. UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
  26. 'func_defaults', 'func_globals'])
  27. else:
  28. # On versions > python 2 the special attributes on functions are gone,
  29. # but they remain on methods and generators for whatever reason.
  30. UNSAFE_FUNCTION_ATTRIBUTES = set()
  31. #: unsafe method attributes. function attributes are unsafe for methods too
  32. UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
  33. #: unsafe generator attirbutes.
  34. UNSAFE_GENERATOR_ATTRIBUTES = set(['gi_frame', 'gi_code'])
  35. #: unsafe attributes on coroutines
  36. UNSAFE_COROUTINE_ATTRIBUTES = set(['cr_frame', 'cr_code'])
  37. #: unsafe attributes on async generators
  38. UNSAFE_ASYNC_GENERATOR_ATTRIBUTES = set(['ag_code', 'ag_frame'])
  39. import warnings
  40. # make sure we don't warn in python 2.6 about stuff we don't care about
  41. warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
  42. module='jinja2.sandbox')
  43. from collections import deque
  44. _mutable_set_types = (set,)
  45. _mutable_mapping_types = (dict,)
  46. _mutable_sequence_types = (list,)
  47. # on python 2.x we can register the user collection types
  48. try:
  49. from UserDict import UserDict, DictMixin
  50. from UserList import UserList
  51. _mutable_mapping_types += (UserDict, DictMixin)
  52. _mutable_set_types += (UserList,)
  53. except ImportError:
  54. pass
  55. # if sets is still available, register the mutable set from there as well
  56. try:
  57. from sets import Set
  58. _mutable_set_types += (Set,)
  59. except ImportError:
  60. pass
  61. #: register Python 2.6 abstract base classes
  62. from collections import MutableSet, MutableMapping, MutableSequence
  63. _mutable_set_types += (MutableSet,)
  64. _mutable_mapping_types += (MutableMapping,)
  65. _mutable_sequence_types += (MutableSequence,)
  66. _mutable_spec = (
  67. (_mutable_set_types, frozenset([
  68. 'add', 'clear', 'difference_update', 'discard', 'pop', 'remove',
  69. 'symmetric_difference_update', 'update'
  70. ])),
  71. (_mutable_mapping_types, frozenset([
  72. 'clear', 'pop', 'popitem', 'setdefault', 'update'
  73. ])),
  74. (_mutable_sequence_types, frozenset([
  75. 'append', 'reverse', 'insert', 'sort', 'extend', 'remove'
  76. ])),
  77. (deque, frozenset([
  78. 'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop',
  79. 'popleft', 'remove', 'rotate'
  80. ]))
  81. )
  82. class _MagicFormatMapping(Mapping):
  83. """This class implements a dummy wrapper to fix a bug in the Python
  84. standard library for string formatting.
  85. See https://bugs.python.org/issue13598 for information about why
  86. this is necessary.
  87. """
  88. def __init__(self, args, kwargs):
  89. self._args = args
  90. self._kwargs = kwargs
  91. self._last_index = 0
  92. def __getitem__(self, key):
  93. if key == '':
  94. idx = self._last_index
  95. self._last_index += 1
  96. try:
  97. return self._args[idx]
  98. except LookupError:
  99. pass
  100. key = str(idx)
  101. return self._kwargs[key]
  102. def __iter__(self):
  103. return iter(self._kwargs)
  104. def __len__(self):
  105. return len(self._kwargs)
  106. def inspect_format_method(callable):
  107. if not isinstance(callable, (types.MethodType,
  108. types.BuiltinMethodType)) or \
  109. callable.__name__ != 'format':
  110. return None
  111. obj = callable.__self__
  112. if isinstance(obj, string_types):
  113. return obj
  114. def safe_range(*args):
  115. """A range that can't generate ranges with a length of more than
  116. MAX_RANGE items.
  117. """
  118. rng = range(*args)
  119. if len(rng) > MAX_RANGE:
  120. raise OverflowError('range too big, maximum size for range is %d' %
  121. MAX_RANGE)
  122. return rng
  123. def unsafe(f):
  124. """Marks a function or method as unsafe.
  125. ::
  126. @unsafe
  127. def delete(self):
  128. pass
  129. """
  130. f.unsafe_callable = True
  131. return f
  132. def is_internal_attribute(obj, attr):
  133. """Test if the attribute given is an internal python attribute. For
  134. example this function returns `True` for the `func_code` attribute of
  135. python objects. This is useful if the environment method
  136. :meth:`~SandboxedEnvironment.is_safe_attribute` is overridden.
  137. >>> from jinja2.sandbox import is_internal_attribute
  138. >>> is_internal_attribute(str, "mro")
  139. True
  140. >>> is_internal_attribute(str, "upper")
  141. False
  142. """
  143. if isinstance(obj, types.FunctionType):
  144. if attr in UNSAFE_FUNCTION_ATTRIBUTES:
  145. return True
  146. elif isinstance(obj, types.MethodType):
  147. if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
  148. attr in UNSAFE_METHOD_ATTRIBUTES:
  149. return True
  150. elif isinstance(obj, type):
  151. if attr == 'mro':
  152. return True
  153. elif isinstance(obj, (types.CodeType, types.TracebackType, types.FrameType)):
  154. return True
  155. elif isinstance(obj, types.GeneratorType):
  156. if attr in UNSAFE_GENERATOR_ATTRIBUTES:
  157. return True
  158. elif hasattr(types, 'CoroutineType') and isinstance(obj, types.CoroutineType):
  159. if attr in UNSAFE_COROUTINE_ATTRIBUTES:
  160. return True
  161. elif hasattr(types, 'AsyncGeneratorType') and isinstance(obj, types.AsyncGeneratorType):
  162. if attr in UNSAFE_ASYNC_GENERATOR_ATTRIBUTES:
  163. return True
  164. return attr.startswith('__')
  165. def modifies_known_mutable(obj, attr):
  166. """This function checks if an attribute on a builtin mutable object
  167. (list, dict, set or deque) would modify it if called. It also supports
  168. the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
  169. with Python 2.6 onwards the abstract base classes `MutableSet`,
  170. `MutableMapping`, and `MutableSequence`.
  171. >>> modifies_known_mutable({}, "clear")
  172. True
  173. >>> modifies_known_mutable({}, "keys")
  174. False
  175. >>> modifies_known_mutable([], "append")
  176. True
  177. >>> modifies_known_mutable([], "index")
  178. False
  179. If called with an unsupported object (such as unicode) `False` is
  180. returned.
  181. >>> modifies_known_mutable("foo", "upper")
  182. False
  183. """
  184. for typespec, unsafe in _mutable_spec:
  185. if isinstance(obj, typespec):
  186. return attr in unsafe
  187. return False
  188. class SandboxedEnvironment(Environment):
  189. """The sandboxed environment. It works like the regular environment but
  190. tells the compiler to generate sandboxed code. Additionally subclasses of
  191. this environment may override the methods that tell the runtime what
  192. attributes or functions are safe to access.
  193. If the template tries to access insecure code a :exc:`SecurityError` is
  194. raised. However also other exceptions may occur during the rendering so
  195. the caller has to ensure that all exceptions are caught.
  196. """
  197. sandboxed = True
  198. #: default callback table for the binary operators. A copy of this is
  199. #: available on each instance of a sandboxed environment as
  200. #: :attr:`binop_table`
  201. default_binop_table = {
  202. '+': operator.add,
  203. '-': operator.sub,
  204. '*': operator.mul,
  205. '/': operator.truediv,
  206. '//': operator.floordiv,
  207. '**': operator.pow,
  208. '%': operator.mod
  209. }
  210. #: default callback table for the unary operators. A copy of this is
  211. #: available on each instance of a sandboxed environment as
  212. #: :attr:`unop_table`
  213. default_unop_table = {
  214. '+': operator.pos,
  215. '-': operator.neg
  216. }
  217. #: a set of binary operators that should be intercepted. Each operator
  218. #: that is added to this set (empty by default) is delegated to the
  219. #: :meth:`call_binop` method that will perform the operator. The default
  220. #: operator callback is specified by :attr:`binop_table`.
  221. #:
  222. #: The following binary operators are interceptable:
  223. #: ``//``, ``%``, ``+``, ``*``, ``-``, ``/``, and ``**``
  224. #:
  225. #: The default operation form the operator table corresponds to the
  226. #: builtin function. Intercepted calls are always slower than the native
  227. #: operator call, so make sure only to intercept the ones you are
  228. #: interested in.
  229. #:
  230. #: .. versionadded:: 2.6
  231. intercepted_binops = frozenset()
  232. #: a set of unary operators that should be intercepted. Each operator
  233. #: that is added to this set (empty by default) is delegated to the
  234. #: :meth:`call_unop` method that will perform the operator. The default
  235. #: operator callback is specified by :attr:`unop_table`.
  236. #:
  237. #: The following unary operators are interceptable: ``+``, ``-``
  238. #:
  239. #: The default operation form the operator table corresponds to the
  240. #: builtin function. Intercepted calls are always slower than the native
  241. #: operator call, so make sure only to intercept the ones you are
  242. #: interested in.
  243. #:
  244. #: .. versionadded:: 2.6
  245. intercepted_unops = frozenset()
  246. def intercept_unop(self, operator):
  247. """Called during template compilation with the name of a unary
  248. operator to check if it should be intercepted at runtime. If this
  249. method returns `True`, :meth:`call_unop` is excuted for this unary
  250. operator. The default implementation of :meth:`call_unop` will use
  251. the :attr:`unop_table` dictionary to perform the operator with the
  252. same logic as the builtin one.
  253. The following unary operators are interceptable: ``+`` and ``-``
  254. Intercepted calls are always slower than the native operator call,
  255. so make sure only to intercept the ones you are interested in.
  256. .. versionadded:: 2.6
  257. """
  258. return False
  259. def __init__(self, *args, **kwargs):
  260. Environment.__init__(self, *args, **kwargs)
  261. self.globals['range'] = safe_range
  262. self.binop_table = self.default_binop_table.copy()
  263. self.unop_table = self.default_unop_table.copy()
  264. def is_safe_attribute(self, obj, attr, value):
  265. """The sandboxed environment will call this method to check if the
  266. attribute of an object is safe to access. Per default all attributes
  267. starting with an underscore are considered private as well as the
  268. special attributes of internal python objects as returned by the
  269. :func:`is_internal_attribute` function.
  270. """
  271. return not (attr.startswith('_') or is_internal_attribute(obj, attr))
  272. def is_safe_callable(self, obj):
  273. """Check if an object is safely callable. Per default a function is
  274. considered safe unless the `unsafe_callable` attribute exists and is
  275. True. Override this method to alter the behavior, but this won't
  276. affect the `unsafe` decorator from this module.
  277. """
  278. return not (getattr(obj, 'unsafe_callable', False) or
  279. getattr(obj, 'alters_data', False))
  280. def call_binop(self, context, operator, left, right):
  281. """For intercepted binary operator calls (:meth:`intercepted_binops`)
  282. this function is executed instead of the builtin operator. This can
  283. be used to fine tune the behavior of certain operators.
  284. .. versionadded:: 2.6
  285. """
  286. return self.binop_table[operator](left, right)
  287. def call_unop(self, context, operator, arg):
  288. """For intercepted unary operator calls (:meth:`intercepted_unops`)
  289. this function is executed instead of the builtin operator. This can
  290. be used to fine tune the behavior of certain operators.
  291. .. versionadded:: 2.6
  292. """
  293. return self.unop_table[operator](arg)
  294. def getitem(self, obj, argument):
  295. """Subscribe an object from sandboxed code."""
  296. try:
  297. return obj[argument]
  298. except (TypeError, LookupError):
  299. if isinstance(argument, string_types):
  300. try:
  301. attr = str(argument)
  302. except Exception:
  303. pass
  304. else:
  305. try:
  306. value = getattr(obj, attr)
  307. except AttributeError:
  308. pass
  309. else:
  310. if self.is_safe_attribute(obj, argument, value):
  311. return value
  312. return self.unsafe_undefined(obj, argument)
  313. return self.undefined(obj=obj, name=argument)
  314. def getattr(self, obj, attribute):
  315. """Subscribe an object from sandboxed code and prefer the
  316. attribute. The attribute passed *must* be a bytestring.
  317. """
  318. try:
  319. value = getattr(obj, attribute)
  320. except AttributeError:
  321. try:
  322. return obj[attribute]
  323. except (TypeError, LookupError):
  324. pass
  325. else:
  326. if self.is_safe_attribute(obj, attribute, value):
  327. return value
  328. return self.unsafe_undefined(obj, attribute)
  329. return self.undefined(obj=obj, name=attribute)
  330. def unsafe_undefined(self, obj, attribute):
  331. """Return an undefined object for unsafe attributes."""
  332. return self.undefined('access to attribute %r of %r '
  333. 'object is unsafe.' % (
  334. attribute,
  335. obj.__class__.__name__
  336. ), name=attribute, obj=obj, exc=SecurityError)
  337. def format_string(self, s, args, kwargs):
  338. """If a format call is detected, then this is routed through this
  339. method so that our safety sandbox can be used for it.
  340. """
  341. if isinstance(s, Markup):
  342. formatter = SandboxedEscapeFormatter(self, s.escape)
  343. else:
  344. formatter = SandboxedFormatter(self)
  345. kwargs = _MagicFormatMapping(args, kwargs)
  346. rv = formatter.vformat(s, args, kwargs)
  347. return type(s)(rv)
  348. def call(__self, __context, __obj, *args, **kwargs):
  349. """Call an object from sandboxed code."""
  350. fmt = inspect_format_method(__obj)
  351. if fmt is not None:
  352. return __self.format_string(fmt, args, kwargs)
  353. # the double prefixes are to avoid double keyword argument
  354. # errors when proxying the call.
  355. if not __self.is_safe_callable(__obj):
  356. raise SecurityError('%r is not safely callable' % (__obj,))
  357. return __context.call(__obj, *args, **kwargs)
  358. class ImmutableSandboxedEnvironment(SandboxedEnvironment):
  359. """Works exactly like the regular `SandboxedEnvironment` but does not
  360. permit modifications on the builtin mutable objects `list`, `set`, and
  361. `dict` by using the :func:`modifies_known_mutable` function.
  362. """
  363. def is_safe_attribute(self, obj, attr, value):
  364. if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
  365. return False
  366. return not modifies_known_mutable(obj, attr)
  367. # This really is not a public API apparenlty.
  368. try:
  369. from _string import formatter_field_name_split
  370. except ImportError:
  371. def formatter_field_name_split(field_name):
  372. return field_name._formatter_field_name_split()
  373. class SandboxedFormatterMixin(object):
  374. def __init__(self, env):
  375. self._env = env
  376. def get_field(self, field_name, args, kwargs):
  377. first, rest = formatter_field_name_split(field_name)
  378. obj = self.get_value(first, args, kwargs)
  379. for is_attr, i in rest:
  380. if is_attr:
  381. obj = self._env.getattr(obj, i)
  382. else:
  383. obj = self._env.getitem(obj, i)
  384. return obj, first
  385. class SandboxedFormatter(SandboxedFormatterMixin, Formatter):
  386. def __init__(self, env):
  387. SandboxedFormatterMixin.__init__(self, env)
  388. Formatter.__init__(self)
  389. class SandboxedEscapeFormatter(SandboxedFormatterMixin, EscapeFormatter):
  390. def __init__(self, env, escape):
  391. SandboxedFormatterMixin.__init__(self, env)
  392. EscapeFormatter.__init__(self, escape)