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.

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.

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.

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.

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 frente — round_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.



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.