Montamos um Caça-Níquel Viciado e Desafiamos o Hacker Summer Camp a Quebrá-lo

A banca sempre ganha. Era essa a proposta na tela do nosso estande durante o Hacker Summer Camp — DEF CON, Black Hat e BSides Las Vegas. Escolha um apelido — sem e-mail, sem cadastro — ganhe cinco créditos e puxe a alavanca de um caça-níquel “777” em neon. Os rolos giram, param numa caveira, e o feed do crupiê imprime paid=false. Puxe de novo. Caveira. De novo. Caveira.

Dez prêmios por evento, quatro deles reservados para quem quebrasse o bug mais difícil, e um contador no topo caindo ao vivo. O e-mail só era pedido depois que alguém ganhava de verdade.

A máquina é viciada. A gente avisou, ali no rodapé: esta máquina é viciada de propósito. É esse o ponto. O cliente nunca ganha. Mas a máquina está conversando com um servidor, e o servidor é desleixado. Leia a máquina, quebre a máquina, e o prêmio de verdade eram até três meses de Tandera, de graça.

A tela inicial do 777: Jackpot or Jail

Por baixo do neon era um CTF web de quatro flags, cada uma um bug que a gente vê no mundo real — em especial no canto pouco regulado dos jogos de “cassino social” online. Aqui vai o tour, agora que os códigos já foram resgatados.

Flag 1 — o cliente é mentiroso

Cada giro envia um pedacinho de telemetria ao servidor: client_outcome, os rolos que o navegador acha que mostrou. O cliente honesto reporta o que sorteou. O detalhe é que o servidor decide o resultado e ignora o seu relato por completo — os rolos nunca são seus para declarar.

E se você declarar mesmo assim? Abra a aba de rede, repita o giro com client_outcome valendo uma trinca vencedora, e o servidor responde:

nice try — the client cannot authorize a payout. the house signs its own outcomes.

O feed do crupiê com o giro adulterado e a captura da flag 1

Essa é a flag um, valendo 100 pontos de consolação e nenhum prêmio. A lição é a mais antiga da segurança web: o cliente é controlado pelo atacante. Um número assustador de front-ends reais de apostas decide a vitória em JavaScript e simplesmente confia que o navegador vai reportá-la de volta. O nosso não confia — mas te entrega uma flag por provar que você entende por que isso importa.

Flag 2 — XOR não é criptografia

Quando você senta, /api/hsc/start devolve um vault: um blob base64 que a máquina chama de “criptografado”. Não é. É um JSON passado por um XOR de chave curta repetida — ofuscação disfarçada de cadeado.

XOR cai com um crib de texto conhecido. Você sabe que o blob é JSON, então sabe que ele começa com {"flag":". Faça o XOR do texto cifrado contra esse prefixo conhecido e a chave repetida aparece na hora; aplique no resto e o vault volta em texto claro, incluindo uma chave de assinatura por sessão e, de brinde, a receita de como usá-la. Envie a chave recuperada e você leva a flag dois: 250 pontos e um mês de Tandera.

Enviar o token recuperado do vault leva a flag 2

O ponto não é que o XOR é fraco — é que um segredo que você entrega ao cliente não é um segredo. Toda chave que chega ao navegador pode ser recuperada do navegador. A gente já abriu respostas de API “criptografadas” exatamente assim em engajamentos reais, e a criptografia era exatamente fina assim.

Flag 3 — o pagamento em dobro

Existe um botão de “resgatar bônus” que vale cinco créditos grátis, uma vez por sessão. O servidor verifica se você já resgatou e então concede os créditos. Leia de novo devagar: ele verifica e depois age, e não há nada de atômico entre as duas coisas.

Essa brecha é um TOCTOU — time-of-check to time-of-use. Clique no botão e você recebe seus cinco créditos como um bom cidadão. Um duplo-clique preguiçoso não resolve; dispare uma rajada de verdade ao mesmo tempo e várias delas leem “ainda não resgatado” antes de qualquer uma terminar de escrever “resgatado”. O bônus é pago de novo e de novo. O servidor percebe que pagou várias vezes e te entrega a flag três — 500 pontos, dois meses.

A rajada dispensa o bônus várias vezes e entrega a flag 3

Essa é a corrida clássica por trás de todo incidente de “saquei meu saldo duas vezes”: uma trava correta isoladamente e inútil sob concorrência. Um servidor de dev serializado esconde isso por completo; a produção, com workers realmente paralelos batendo numa única linha compartilhada, não.

Flag 4 — provavelmente injusto

O grande prêmio se esconde atrás do recurso de que a máquina mais se orgulha: ela é provably fair (comprovadamente justa). Quando você senta, o /start se compromete com uma server seed publicando o hash dela. O resultado de cada giro é v = int(sha256(round_seed : client_seed : nonce)[:8], 16), e um giro é jackpot quando v % 20000 == 7770 — cerca de um em vinte mil, então você nunca vai comprar seu caminho até lá com cinco créditos. Cada giro ainda te devolve o próprio round_seed para você conferir que a máquina não te trapaceou.

Essa transparência é o bug. As round seeds são uma cadeia para frenteround_seed[n+1] = sha256(round_seed[n]) — e a máquina revela cada uma conforme você joga. Revele uma única seed e você consegue avançar o hash para computar toda rodada futura: cada seed, cada resultado, até onde quiser olhar. Então você gira uma vez, pega a seed revelada e mói sha256 para frente até achar o nonce cujo resultado dá o jackpot. Aí você reivindica — POST /api/hsc/jackpot {nonce, seed} — nomeando a rodada exata em que a máquina vai pagar, e anexando a seed daquela rodada para provar que sabe computá-la. Chute uma seed errada e a reivindicação é rejeitada; não há o que forçar. Você cantou o jackpot antes de ele acontecer. Essa é a flag quatro — 1000 pontos e os três meses completos.

Cassinos provably fair de verdade se comprometem com a seed e a revelam depois, na direção segura. Erre a direção e a prova de justiça vira uma bola de cristal.

Cantar a rodada do jackpot antes de acontecer leva a flag 4

As quatro flags capturadas, com o prêmio pronto para resgatar

O ranking High Rollers

Por que um cassino?

Porque o código de cassino é onde esses bugs sustentam o negócio e, com frequência demais, estão em produção. Resultados decididos no cliente, “criptografia” caseira, atualizações de saldo não-atômicas e esquemas provably-fair que vazam o futuro não são exóticos — são os achados do dia a dia de teste de aplicação web, e o dinheiro os torna caros. Envolvê-los num caça-níquel só deixou o risco legível.

E é para isso que a Tandera existe. Construímos a plataforma que times de segurança ofensiva usam para encontrar exatamente esses problemas e transformá-los em relatórios limpos, padronizados e white-label — da descoberta de ativos aos findings até a entrega. O caça-níquel era um brinquedo. A metodologia por trás de achar seus quatro bugs é o trabalho de verdade.

A todos que leram a máquina em vez de puxar a alavanca: o ranking era de vocês, e os meses também. Até o próximo camp.

acesso antecipado

Garanta a Tandera antes do próximo engagement.

Entre na waitlist para acesso antecipado. Estamos integrando times de pentest em ondas.

Onboarding prioritário para times de pentest.
Linha direta com quem está construindo.
Preço de acesso antecipado, garantido.

Sem spam, sem cartão. Cancele quando quiser.

enespt-br