Carregando
0x70Lição 8 de 15

Reconheça os riscos comuns na web

Mantenha os dados separados do código: consultas parametrizadas, codificação da saída e allowlists.

22 min Questionário com 7 perguntas 1 exercício de código
Ao final desta lição, você saberá
  • Explicar por que misturar dados não confiáveis ao código causa injection
  • Usar consultas parametrizadas e allowlists
  • Codificar a saída para o contexto em que ela aparece

As aplicações web cruzam fronteiras de confiança o tempo todo: um texto digitado num navegador viaja até um servidor, entra numa consulta ao banco de dados e volta para uma página HTML. A raiz de toda uma família de bugs - injection (OWASP A05:2025) e cross-site scripting - é a mesma: dados não confiáveis são tratados como código.

Se um programa monta uma consulta ao banco colando a entrada do usuário no texto SQL, uma entrada bem escolhida pode mudar o significado da consulta, e não só os valores dela. A correção é nunca misturar os dois: mande a consulta e os valores separadamente.

Unsafe and safe queries
1# Unsafe: the input becomes part of the SQL text
2cursor.execute("SELECT * FROM users WHERE name = '" + name + "'")
3
4# Safe: the query and the value travel separately
5cursor.execute("SELECT * FROM users WHERE name = ?", (name,))

Com uma consulta parametrizada (também chamada de prepared statement), o banco de dados recebe o SQL com marcadores (?, %s ou :name) e os valores à parte. Um valor pode conter aspas, palavras-chave ou qualquer outra coisa - ele só vai ser comparado como dado. Toda biblioteca de banco de dados popular suporta isso; os ORMs fazem isso por você.

Algumas partes de uma consulta não podem ser parâmetros - nomes de tabelas, nomes de colunas, direção da ordenação. Para essas, use uma allowlist (lista de permissões): aceite só valores de uma lista fixa escrita por você e, caso contrário, use um padrão seguro.

Prática: ataque um formulário de login

Experimente

Até 15 XP

Invada um aplicativo simulado com SQL injection

Veja a consulta mudar enquanto você digita. Primeiro, entre normalmente com o usuário ana e a senha blue-kettle-42. Depois experimente uma aspa simples no nome de usuário e veja o que o erro conta para um atacante.

Agora cumpra os objetivos. Use as dicas se travar.

Uma simulação: nenhum banco de dados ou rede real está envolvido.

Entrar na Acme Store
SELECT * FROM users WHERE username = '' AND password = ''
  • Entrar como admin sem a senha
  • Fazer a consulta encontrar todos os usuários
  • Ativar os parâmetros e ver um ataque falhar

Experimente

Até 15 XP

Seguro ou inseguro?

Decida se cada trecho mantém os dados não confiáveis separados do código.

0 de 6 classificadosPontuação 0/0
  • “cursor.execute("SELECT * FROM users WHERE email = %s", (email,))”

  • “cursor.execute(f"SELECT * FROM users WHERE email = '{email}'")”

  • “order = sort if sort in {"name", "price"} else "name"”

  • “os.system("convert " + uploaded_filename + " out.png")”

  • “subprocess.run(["convert", uploaded_filename, "out.png"])”

  • “element.innerHTML = "Hello " + username”

Codificando a saída

A mesma ideia vale ao mostrar dados numa página: para exibir um comentário como texto, os caracteres que significam algo em HTML (<, >, &, aspas) precisam ser convertidos em entidades como &lt;. Motores de template como Jinja, React e a maioria dos outros fazem isso automaticamente - o perigo vem de desligar isso (|safe, dangerouslySetInnerHTML, innerHTML).

Principais conclusões

  • O injection acontece quando dados não confiáveis são interpretados como código.

  • Use consultas parametrizadas, listas de argumentos e allowlists para manter o código e os dados separados.

  • Codifique a saída para o contexto dela; mantenha ligada a codificação automática do framework.

Quiz da aula

7 perguntas · aprovação com 5 acertos · até 50 XP

Ao passar, você conclui a aula e mantém sua sequência. As perguntas erradas voltarão em sessões de revisão.

Pratique: escreva código em Python

Escreva código Python no editor e execute os testes com exemplos. O Python roda localmente no navegador usando WebAssembly.

Exercício 1

Use uma allowlist para a coluna de ordenação

+25 XP

Nomes de colunas não podem ser parâmetros da consulta. Cada linha da entrada é column direction, pedida por um usuário. Imprima ORDER BY COLUMN DIRECTION, em que a coluna precisa ser name, price ou created_at (caso contrário, use created_at) e a direção ASC ou DESC, sem diferenciar maiúsculas de minúsculas (caso contrário, DESC).

  • Pedidos válidos e inválidos
main.py
Carregando editor…

O Python é executado em um ambiente isolado no navegador, com limite de 60 segundos. O runtime é carregado pelo CDN do Pyodide; seu código permanece neste navegador.

Dúvidas sobre esta lição

Travou em algum ponto? Pergunte. Descobriu algo? Compartilhe. Explicar também é uma ótima forma de aprender.

Carregando publicações…