DEV Community

Cover image for 13 findings no Juice Shop. Nenhuma virou issue.
Tiago Vilas Boas (Montanha)
Tiago Vilas Boas (Montanha)

Posted on Edited on

13 findings no Juice Shop. Nenhuma virou issue.

Pessoal, eu ia colar o Juice Shop na tabela do post das três portas.

Tinha 13 findings com requisito ASVS e arquivo:linha. SQL concatenado, eval no username, CORS *, cesto de outro usuário. O modelo tinha trabalhado. A tabela ia ficar "mais completa".

Aí li o package.json: probably the most modern and sophisticated insecure web application. Não é gap. É o produto.

O que você leva daqui: lab de propósito inseguro calibra o procedimento. Não entra nas três portas. Silêncio aqui não é "invariante manteve". É não abrir issue no scoreboard dos outros.


Tabela de Conteúdo


1. A tabela errada

O post pai é sobre OSS que alguém usa de verdade. Formbricks, Dub, Cal.com, Magnitude. Issue de hardening, e-mail quando for exploitable, nada quando o denominador fecha.

Juice Shop e WebGoat não são essa classe. O README do WebGoat avisa: a máquina fica vulnerável de propósito; o default escuta em localhost. O SECURITY.md do Juice Shop pede contato só para o que não faz parte de nenhum hacking challenge. O resto já está no placar.

Somar 13 linhas naquela tabela seria o mesmo reflexo dos 23 findings que eu quase mandei. Volume. A pergunta de segurança some: disto aqui, o que vira issue?

Nada. Porque o sink já tem nome de challenge.


2. Lab vs OSS real: a porta não é a mesma

Antes de rodar qualquer scan, a primeira pergunta é: isso é lab ou produto?

Critério Lab (Juice Shop, WebGoat, DVWA) OSS real (Formbricks, Cal.com, Dub)
Propósito Ensinar vulnerabilidades Resolver problema de usuário
Vulnerabilidades Intencionais, documentadas Acidentais, não documentadas
O que fazer com finding Validar procedimento, não reportar Avaliar porta, reportar se aplicável
SECURITY.md "Não reporte o que é challenge" "Reporte via email/HackerOne"
Você ganha Prática, calibração Contribuição, CVE, bounty

Se o README tem "intentionally insecure", "vulnerable by design", ou "hacking challenge", a porta é treino. Não é issue tracker.


3. O que a varredura achou no Juice Shop

Estático. Sem PoC. Sem tráfego. Fatia estreita, não o monorepo. YAML de challenges depois, só pra recall. Issue: nenhuma.

Juice Shop v20.2.0. 13 findings (10 L1, 3 L2). 10 chaves do catálogo bateram depois, de 116.

# Problema ASVS Onde
1 Busca concatena q em SQL V1.2.4 routes/search.ts
2 Login concatena email em SQL V1.2.4 routes/login.ts
3 Username via eval V1.3.2 routes/userProfile.ts
4 Search query com bypassSecurityTrustHtml V3.2.2 search-result.component.ts
5 Description HTML sem encoding V3.2.2 search-result.component.ts
6 CORS default * V3.4.2 server.ts
7 Cesto por id sem dono V8.2.2 routes/basket.ts
8 Senha em MD5 V11.4.1 lib/insecurity.ts
9 Admin seed admin123 V6.3.2 data/static/users.yml
10 FTP: allowlist de extensão depois null-byte V5.3.2 routes/fileServer.ts
11 fetch(imageUrl) sem allowlist V1.3.6 routes/profileImageUrlUpload.ts
12 Redirect com url.includes V3.7.2 lib/insecurity.ts
13 Chave RSA do JWT no source V13.3.1 lib/insecurity.ts

4. O que a varredura achou no WebGoat

WebGoat. 11 findings. Uma lição de SSRF não abre URL: não entrei como SSRF.

# Problema ASVS Onde
1 SQL concatena params V1.2.4 SqlInjectionLesson5a.java
2 XML parser com entidade externa V1.5.1 CommentsCache.java
3 Upload usa fullName no path V5.3.2 ProfileUploadBase.java
4 XSS refletido em HTML V1.2.1 CrossSiteScriptingLesson5a.java
5 Comment stored sem encoding V3.2.2 StoredXssComments.java
6 Profile por userId sem dono V8.2.2 IDORViewOtherProfile.java
7 JWT jku busca chave na URL do token V9.1.3 JWTHeaderJKUEndpoint.java
8 Default admin / admin V6.3.2 DefaultCredentialsTask.java
9 Lista de users sem role V8.2.1 MissingFunctionACUsers.java
10 redirect: sem allowlist V3.7.2 OpenRedirectRealRedirect.java
11 HMAC JWT com palavra do source V13.3.1 JWTSecretKeyEndpoint.java

Round 1 responde se inventa ID, inventa finding ou vaza PoC. Não responde se cobriu o placar.


5. Como usar lab pra treinar o olho

Lab não é pra gerar issue. É pra calibrar o procedimento antes de ir pro código que paga boleto.

Fluxo de treino

1. Roda a varredura no lab (Juice Shop, WebGoat, DVWA)
2. Mapeia findings → ASVS
3. Confere contra o catálogo de challenges
4. Mede recall: quantos challenges a varredura achou?
5. Mede precisão: quantos findings eram challenge de verdade?
6. Ajusta o procedimento (prompt, scope, threshold)
7. Só então vai pro OSS real
Enter fullscreen mode Exit fullscreen mode

O que o lab ensina

Lição O que você aprende
SQLi no search Como o modelo descreve concatenação vs prepared statement
eval no username Se o modelo diferencia eval de JSON.parse
CORS * Se o finding tem contexto (API pública vs admin)
IDOR no basket Se o modelo pede ownership check ou só descreve o sintoma
JWT no source Se diferencia chave de teste de chave de produção

Recall no Juice Shop

O catálogo tem 116 challenges. A varredura achou 13 findings. 10 bateram com challenges conhecidos.

Recall: ~8.6% (10/116). Baixo? Sim. Mas a varredura era estática, sem runtime, sem fuzzing. O ponto não é cobrir 100%. É saber o que a ferramenta vê e o que não vê.


6. O checklist de lab vs produto

Antes de abrir issue, passa por isso:

1. O README tem "intentionally insecure", "vulnerable by design",
   ou "hacking challenge"?
   → Sim: é lab. Não reporta.

2. O SECURITY.md diz "não reporte challenges"?
   → Sim: confere se o finding é challenge conhecido.

3. O finding tem nome de challenge no catálogo?
   → Sim: é lab. Calibra o procedimento, não abre issue.

4. O código é de lição/lesson/exercise?
   → Sim: é lab.

5. Passou por 1-4 e ainda parece real?
   → Aí sim: avalia a porta (hardening, exploitable, ou silêncio).
Enter fullscreen mode Exit fullscreen mode

O checklist completo está no gist.


7. A pessoa que segura a mão do time

Essa tabela não é troféu. É o Juice Shop fazendo o trabalho que a OWASP se propôs: um lugar onde a gente pode errar de propósito, ver o sink com nome, e voltar pro código que paga boleto com o olho mais treinado.

Quem mantém isso (e o WebGoat no mesmo espírito) está doando academia pra uma indústria que, no dia a dia, mistura pressão de entrega com risco de verdade. Sem esse tipo de lab, o atalho vira "rodei o scanner, achei 23 coisas, mandei pro tracker". Com ele, dá pra ensaiar o reflexo certo: isto aqui é aula. Aquilo ali é produto. A porta não é a mesma.

Ferramenta ajuda. Prompt ajuda. Modelo de raciocínio alto ajuda. Nada disso substitui a pessoa no time que já viu o suficiente de segurança pra não confundir volume com cuidado.

O profissional avançado em AppSec não é o que gera a lista mais longa. É o que segura a mão do time quando a lista pede 13 issues num CTF. É o que olha um eval no username e pergunta: isso é challenge ou é o checkout de amanhã? É o que sabe que silêncio também é ofício. Não o silêncio de quem não olhou. O de quem olhou e escolheu não fazer barulho no lugar errado.

Time sem essa voz vira fábrica de card. Time com essa voz usa o Juice Shop como aquecimento e reserva o tracker pra quem realmente vai ler a issue no sábado.


Takeaway: 13 sinks, zero issues, porque academia não se reporta como incidente. O que se leva pro time é o julgamento.

O post das três portas continua sendo o mapa quando o alvo é OSS de verdade.

No seu time, quem é a pessoa que olha uma tabela dessas e pergunta a porta, em vez de abrir treze cards?

Top comments (0)