Find the RCE Sink: Spotting an eval() Injection in Python

Segurança Web & API Nível 2/5 ~3 min 2026-06-27

O desafio

Esta API de 'cálculo rápido' executa tudo que você envia. Uma função nativa do Python transforma isso em execução remota de código. Leia os dois arquivos e digite o nome dessa função.

O que você vai aprender

  • Recognise eval()/exec() on untrusted input as a remote code execution sink
  • Trace request data from its entry point to a dangerous function across files
  • Tell apart code execution (eval) from safe data parsing (ast.literal_eval)
  • Read a small codebase the way a reviewer does: follow the input, find the sink

Habilidades testadas

Source code reviewPython injection sinksData-flow tracing

Pré-requisitos

  • Basic Python reading
  • Familiarity with HTTP query parameters

Como funciona

Remote code execution (RCE) is the most severe class of web vulnerability: the attacker gets the application to run code of their choosing on the server. In Python, the classic sink is eval() (and its sibling exec()). eval() takes a string and evaluates it as a Python expression - so if any part of that string comes from the user, the user can run Python.

This app exposes a 'quick math' endpoint. It reads expr from the query string and hands it directly to eval(). A normal request like ?expr=2*21 returns 42, which is exactly why this kind of bug ships - it looks like a harmless calculator. But an attacker sends ?expr=__import__('os').system('id') and the server runs a shell command. From there it is a short step to reading files, exfiltrating data, or planting a shell.

The fix is in the second file. ast.literal_eval() parses only Python literals - numbers, strings, lists, dicts - and refuses anything that would execute. That is the right tool when you need to turn text into data. The job in a review like this is to follow the untrusted value (expr) from where it enters to what consumes it, and recognise that the consumer is a code-execution primitive.

Erros comuns

  • Assuming a 'calculator' is harmless. The friendly feature name hides that eval runs arbitrary code, not just arithmetic.
  • Pointing at request.args instead of the sink. Reading input is fine; the bug is what you do with it. Name the function that executes it.
  • Confusing eval with literal_eval. They look similar but only one executes code - that difference is the whole vulnerability.

Como se proteger

Never pass untrusted input to eval() or exec(). If you need arithmetic, parse it with a real expression parser or a safe library. If you need to turn text into data, use ast.literal_eval() or json.loads().

  • Ban eval/exec on request data in code review and with a linter rule.
  • Treat every query parameter, header, and body field as attacker-controlled.
  • Prefer allow-lists and typed parsing over evaluating strings.

Solução completa

Membros Pro e Max desbloqueiam o passo a passo completo.

Assinar Pro

Estatísticas da comunidade

45 resoluções
76% taxa de sucesso
cpkakaping Primeiro sangue

Go deeper

Hacks de hoje relacionados

14.000+ Hackers 100+ Labs & Cursos Grátis
Comece Grátis