Nas últimas semanas eu me deparei com vários sites bloqueando o acesso ao devtools, ou pelo menos tentando bloquear. Já vi várias tentativas disso sendo implementadas de várias formas diferentes. Algumas são muito fáceis de contornar e apresentam falsos positivos com facilidade. Outras fazem diversas verificações e criam mecanismos para evitar diferentes tipos de contorno, o que normalmente gera uma carga extra desnecessária para a aplicação. E alguns simplesmente bloqueiam atalhos e assumem que isso resolve.
Ver todas essas tentativas me fez refletir se isso realmente tem alguma eficácia ou necessidade. Qual seria a melhor forma de proteger um sistema contra atacantes?
Proteger um sistema muitas vezes vira implantar regras a serem seguidas. Assim como na vida real implantamos leis que as pessoas devem seguir. Mas leis não são o único mecanismo que regula comportamento.
Existem países que praticamente não têm leis específicas para certas coisas simplesmente porque as pessoas não fazem aquilo. Ou pelo menos não fazem em escala suficiente para justificar uma lei. Isso normalmente não é ausência de controle, é cultura.
Um exemplo simples são leis extremamente específicas que surgem apenas depois que um comportamento começa a ser explorado. Enquanto isso não acontece, a própria norma social já regula.
Nos EUA, segundo pesquisa da Piper Sandler, cerca de 87% dos adolescentes possuem iPhone. Parte disso vem do efeito de rede do iMessage. A dinâmica das “bolhas verdes” cria pressão social indireta. Não existe proibição de Android, existe estrutura de incentivo.
Abaixo alguns links falando sobre esse efeito social:
- https://www.wsj.com/tech/why-apples-imessage-is-winning-teens-dread-the-green-text-bubble-11641618009
- https://www.loopinsight.com/2022/01/10/why-apples-imessage-is-winning-teens-dread-the-green-text-bubble/
- https://canaltech.com.br/smartphone/52-dos-usuarios-de-android-ja-foram-ridicularizados-por-quem-tem-iphone/
Trazendo isso para sistemas, bloquear devtools é tentar controlar o ambiente errado. O navegador é do usuário. Se algo pode ser explorado só porque ele abriu o devtools, é um problema de arquitetura.
Reduzindo o incentivo e projetando ao redor do atacante
Existe uma linha de pensamento em segurança que parte de uma premissa simples: você não precisa impedir todas as tentativas de ataque, você precisa tornar o ataque pouco vantajoso. Em vez de focar apenas em bloqueios técnicos, a arquitetura é desenhada para diminuir o benefício esperado da exploração.
Se explorar uma falha não gera ganho relevante, não permite escalar privilégio, não expõe dados valiosos e não traz retorno financeiro ou reputacional, o interesse naturalmente diminui. Muitos ataques acontecem porque existe recompensa clara: dados sensíveis, dinheiro, acesso privilegiado ou até reconhecimento dentro de comunidades técnicas.
Em vez de tentar travar uma guerra direta contra o usuário bloqueando ferramentas, escondendo código ou tentando “proibir” inspeção o sistema é projetado assumindo um ambiente hostil. Não se parte da ideia de que o usuário não abrirá o DevTools, parte-se da certeza de que ele pode abrir. Não se tenta impedir requisições diretas à API, assume-se que elas vão acontecer.
Incentivo, monitoramento e rastreabilidade
Quando você combina monitoramento estruturado com honeypots bem integrados, você ganha algo muito mais útil do que bloqueio: rastreabilidade.
Com logs correlacionados por requestId, userId, IP e timestamp, você consegue reconstruir o caminho de uma tentativa de ataque. É possível entender por onde o atacante passou, quais endpoints testou, quais parâmetros manipulou, que tipo de payload tentou enviar e em que momento o comportamento saiu do padrão. Também dá para identificar tentativa de escalar privilégio, enumeração de IDs ou scraping automatizado.
Isso permite identificar vulnerabilidades antes mesmo que sejam exploradas por completo. Às vezes você detecta exploração parcial de uma falha lógica antes que alguém perceba que ela é realmente explorável.
app.use((req, res, next) => {
req.context = {
requestId: crypto.randomUUID(),
startTime: Date.now()
}
next()
})
function logEvent(req, type, details = {}) {
console.log(JSON.stringify({
requestId: req.context.requestId,
userId: req.user?.id ?? null,
ip: req.ip,
path: req.path,
type,
details,
timestamp: Date.now()
}))
}
Você também pode expor um endpoint que parece interno, mas que nunca é usado pelo fluxo real, como /api/internal/report/export. Nenhuma interface legítima chama isso, mas scanners automáticos e exploração manual costumam testar rotas previsíveis como /admin, /internal, /export ou /backup.
app.get("/api/internal/report/export", async (req, res) => {
await securityEvents.create({
type: "HONEY_ENDPOINT_ACCESS",
ip: req.ip,
userId: req.user?.id ?? null,
timestamp: Date.now()
})
return res.status(404).end()
})
Se alguém acessar essa rota, já é um sinal claro de comportamento não legítimo.
Também é possível criar contas administrativas que não deveriam ser usadas. Se alguém tentar autenticar nelas, isso indica vazamento parcial de dados.
if (user.email === "backup-ops-admin@seusistema.com") {
await securityEvents.create({
type: "HONEY_ACCOUNT_LOGIN",
ip: req.ip,
userAgent: req.headers["user-agent"]
})
}
No nível de infraestrutura, pode-se rodar um serviço SSH falso em uma porta alternativa simulando um servidor vulnerável usando ferramentas como o cowrie. O atacante acredita que conseguiu acesso e começa a executar comandos. Tudo fica registrado: comandos digitados, arquivos baixados, IP de origem e ferramentas utilizadas. Isso ajuda a entender técnicas reais usadas contra você.
Grande parte das proteções feitas no frontend são superficiais, como bloquear botão direito, ofuscar HTML ou tentar impedir o uso do devtools. Scraping real acontece via requisições diretas à API, headless browsers e proxies rotativos.
O que tende a funcionar melhor é controle no backend: rate limiting, detecção de padrão não humano, limites por conta autenticada e monitoramento de volume anormal.
Não existe controle perfeito do lado do usuário. O máximo possível é dificultar, mas não impedir. E muitas vezes dificultar demais no frontend cria apenas uma sensação de desafio para quem quer ultrapassar a barreira. É mais eficiente monitorar e limitar no backend, onde o controle é real, do que bloquear no frontend e assumir que o problema foi resolvido e que algumas vezes tambem pode gerar experiencias piores para usuarios legitimos.