Калькулятор для платёжной системы

  • Автор темы Автор темы Koloboking
  • Дата начала Дата начала

Koloboking

Grey Team
12.01.2017
196
83
господа, кто хочет поломать голову?)
Разработчик делает калькулятор с поддержкой выражений, чтобы пользователи могли задавать скидки и правила округления в виде формул:
Python:
import ast
import operator
import math

class SafeMathEvaluator:
    allowed_names = {
        "abs": abs,
        "round": round,
        "min": min,
        "max": max,
        "pow": pow,
        "floor": math.floor,
        "ceil": math.ceil,
        "pi": math.pi,
        "e": math.e,
    }

    allowed_ops = {
        ast.Add: operator.add,
        ast.Sub: operator.sub,
        ast.Mult: operator.mul,
        ast.Div: operator.truediv,
        ast.Pow: operator.pow,
        ast.USub: operator.neg,
    }

    def eval_expr(self, expr):
        tree = ast.parse(expr, mode="eval")
        return self._eval(tree.body)

    def _eval(self, node):
        if isinstance(node, ast.Constant):
            return node.value
        elif isinstance(node, ast.BinOp):
            if type(node.op) not in self.allowed_ops:
                raise ValueError("Operator not allowed")
            return self.allowed_ops[type(node.op)](
                self._eval(node.left),
                self._eval(node.right)
            )
        elif isinstance(node, ast.UnaryOp):
            if type(node.op) not in self.allowed_ops:
                raise ValueError("Unary operator not allowed")
            return self.allowed_ops[type(node.op)](self._eval(node.operand))
        elif isinstance(node, ast.Call):
            if isinstance(node.func, ast.Name) and node.func.id in self.allowed_names:
                func = self.allowed_names[node.func.id]
                args = [self._eval(arg) for arg in node.args]
                return func(*args)
            raise ValueError("Function not allowed")
        elif isinstance(node, ast.Name):
            if node.id in self.allowed_names:
                return self.allowed_names[node.id]
            raise ValueError("Unknown identifier")
        else:
            raise TypeError("Unsupported expression node")
Задача
Пользователь может передать любую строку выражения в eval_expr(expr).
Нельзя использовать eval, exec, import, os, sys и т.п.
Вроде бы всё безопасно — только математика.
Но — есть способ заставить этот код “провалиться” и вытащить из него данные или вызвать нестандартное поведение.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab