it-swarm-pt.tech

Exploração do atraso quando um ingresso para o festival é digitalizado

Como um sistema de ticket funciona

Um sistema de tickets - que você vê em festivais - funciona assim: quando um usuário paga pelo ingresso, uma linha é adicionada ao banco de dados com uma coluna chamada is_scanned, cujo valor padrão é definido como false.

Assim que um guarda do festival escaneia o código de barras (contendo um ID e um hash exclusivo) com o dispositivo, uma solicitação é enviada ao banco de dados para verificar se:

  1. o usuário que corresponde ao ID e hash pagou e
  2. se o valor da coluna is_scanned ainda está definido como false.

Se ambas as condições forem atendidas, ele definirá o valor is_scanned a true, para impedir que outra pessoa que copie o ticket/código de barras entre.

O problema da vulnerabilidade

O problema aqui é o tempo entre a solicitação ser enviada pelo dispositivo de digitalização e o valor is_scanned sendo alternado de false para true.

Considere o seguinte cenário: Alice possui um ticket válido pelo qual pagou, mas ela permite que Eve copie seu código de barras e altere o nome visível no ticket falso de Alice para Eve. Então agora temos dois ingressos. Um válido e um fraudulento, mas ambos têm o mesmo código de barras, a única diferença é o nome.

E se o ingresso de Alice e Eve for digitalizado exatamente ao mesmo tempo em que entram no festival? O sistema de ingressos não alternaria is_scanned a true a tempo de garantir que Eve não pudesse entrar com o mesmo código de barras que Alice. Isso resulta em ambos os tickets (válidos e fraudulentos) sendo mostrados como "válidos" para os guardas.

Soluções possíveis

Claro, esse tipo de exploração realmente depende de muita sorte e, embora seja possível em teoria ... em um cenário real, isso provavelmente falharia.

No entanto, como podemos derrotar esse tipo de exploração também na teoria?

Identificação

Eu já levei essa exploração em consideração usando o seguinte método: Quando um código de barras é lido, eu mostro não apenas se o ticket é válido (satisfaz as condições declaradas anteriormente), mas também o nome no banco de dados. Se o nome não corresponder ao nome do ticket, sabemos que o ticket é manipulado de alguma forma. Além disso, se o nome que aparece no dispositivo de varredura não corresponder ao nome no ID (que todo mundo precisa mostrar de qualquer maneira para provar a idade), a entrada também não será permitida.

A única maneira de contornar essa solução é a fraude de identidade, e é claro que está além da responsabilidade do sistema de tickets verificar.

Demora

Outra maneira de resolver isso, em teoria, é adicionar um tempo aleatório de atraso entre cada solicitação feita à API de banco de dados/validação. Dessa forma, ninguém seria capaz de verificar seu ticket ao mesmo tempo ... porque o tempo de validação é adiado cada vez com uma quantidade aleatória de milissegundos.

Eu não sou fã disso, porque:

  1. torna tudo mais lento na entrada
  2. não é eficaz se não for atrasado o suficiente. Porque se leva 50 ms para o banco de dados atualizar is_scanned de false para true, a única solução seria atrasá-lo com um intervalo mínimo de 50 ms por vez.

Outras soluções?

Em que outras soluções você pensa para resolver essa exploração?

42
O'Niel

A vulnerabilidade que você está descrevendo é um condição de corrida .

Existem várias maneiras de lidar com isso, mas eu usaria um SELECT ... FOR UPDATE Consulta SQL, que bloqueia as linhas selecionadas para impedir novas gravações até que a transação atual seja confirmada.

Verifique sua documentação do RDBMS para verificar como implementá-la corretamente:

154
Benoit Esnard

A outra solução aqui é absolutamente correta e faz sentido para sistemas maiores, onde não é tão fácil.

Com os dados que você possui, isso é relativamente simples, você pode optar por uma opção sem bloqueio:

UPDATE [FESTIVAL_TICKET] 
  SET IS_SCANNED = TRUE
WHERE TICKET_ID = @ScannedKey 
  AND IS_SCANNED = FALSE

Agora, esta é uma operação atômica. Dois usuários do banco de dados não podem emitir isso e para atualizar a linha. A pessoa que recebe "1 linha afetada" retornada (obviamente existe uma maneira de descobrir isso no código, não analisa o texto para isso) pode entrar. Todo mundo terá zero linhas afetadas pela instrução. Se você deseja ser amigável, agora pode verificar por que não foi encontrado, se era o ID errado ou se já foi verificado.

Mas o detalhe importante é que a afirmação é atômica. Apenas um vencerá, não importa quão próximos estejam da diferença de tempo zero. Porque você não tem mais uma leitura e e depois uma gravação. Você tem a leitura e gravação em uma operação atômica.

87
nvoigt

A desvantagem disso parece ser que uma pessoa pode entrar para grátis (com um bilhete copiado).

Para pequenos eventos que provavelmente estão corretos.
No entanto, se você adicionar muito atraso, por qualquer motivo, corre o risco de mais do que uma pessoa entrar.
Os scanners de tickets apenas permitirão que algumas pessoas passem se seus dispositivos atolarem ou estiverem muito lentos ... porque, diabos, a maioria deles provavelmente possui tickets válidos, certo?

Eu assisti isso acontecer em um grande evento deste ano, com a participação de milhares de fãs de músicos que muitos pessoas já ouviram falar.
A empresa de ingressos era uma das principais empresas (talvez a empresa para quem você trabalha?) E estava em um site personalizado para a compra de ingressos.
Minha festa foi uma das que deixaram passar sem uma verificação (e sim ... eu tinha um bilhete válido/legal).
Eu tive que ficar lá e assistir os compradores de ingressos alguns minutos antes de descobrir por que isso aconteceu.

TL; DR;
Não codifique para todas as eventualidades quando há pessoas envolvidas.
Faça dois ou três noves (99% -99,9%) e encerre o dia.
Guarde o nick picking para quando apenas máquinas estiverem envolvidas ... é quando você pode obter um monte de 9.

15
J. Chris Compton

Essa resposta já tem uma resposta ótima e barata, no entanto, eu adicionaria minha própria resposta do ponto de vista deengenharia de softwaree de segurança. Isso pode ser útil para futuras perguntas semelhantes sobreexplorações improváveis ​​.

e enquanto isso é possível em teoria ... Em um cenário real, isso provavelmente falharia.

E então, qual é o dano potencial comparado ao custo? Vou provar que gastar esforços e dores de cabeça com segurança adicional não valem o risco.

Agora, a solução já proposta e aceita para lidar adequadamente com as condições de corrida com transações SQL, transferindo a responsabilidade/custo para o banco de dados, é a melhor solução, padrão do setor e mais barata. Pode ser o fim do caso, já que a resposta foi de fatoaceito.

Como já foi mencionado, o evento em que os dois participantes são examinados no exato momento e acionam a exploração da condição de corrida pode ser estimado em chances de milhões, se não bilhõesde magnitude. Para lhe dar umaqualitativaideia de probabilidades bilionárias, leia este artigo sobre loterias e descubra que jogar para esse SuperEnalotto no topo da segunda lista pode seja um jogo fácil /comparado a verificar dois tíquetes, e a recompensa é definitivamente consistente. As probabilidades representam oexplorabilidadede uma vulnerabilidade e isso normalmente é qualificado em níveis discretos ([muito] improvável, [muito] provável). Eu sempre comparo eventos não determinísticos relacionados à segurança à loteria para fornecer uma comparação mais familiar.

Para esclarecimentos adicionais, as probabilidades são influenciadas por:

  • A capacidade de os dois sincronizarem suas movimentações pelas filas e entregarem o bilhete ao guarda ao mesmo tempo. Isso implica que os dois têm comunicação constante e se treinaram, sem mencionar a sorte (chances!) De que suas linhas se movem em velocidades previsíveis
  • O movimento físico dos guardas. Nem todos os guardas levam o tempo exato em milis para escanear os bilhetes, eles movem os braços em velocidades diferentes. Um dos bilhetes pode cair das mãos do guarda, um guarda pode segurar o bilhete ao contrário. Um guarda pode se virar para verificar se a linha não está encravada atrás deles. Em outras palavras, há entropia excessiva para planejar um ataque
    • Máquinas de verificação de tickets não tripuladospodemnão serem afetadas por esse fator
  • O tempo que leva para o sistema do computadorverificar o ticket, para que as duas verificações caiam no mesmo intervalo de tempo e a vulnerabilidade seja explorada.

Então, aqui está a consideração de engenharia de software.

O bilhete tem um preço, portanto vale X $. Eu estimo a magnitude de X pode estar na ordem de 50 a 100. Para cada pessoa que explora a vulnerabilidade e entra na instalação de maneira fraudulenta, aplica-se uma perda de $ X.

Implementar verificações mais complexas (por exemplo, controle de nome de passaporte) é caroambosnos termos do código exigido na fase de desenvolvimento do software e no tempo necessário para as pessoas entrarem a facilidade. Os seguranças são pagos a cada hora. Implementar um exame de segurança no estilo Ben-Gurion * é muito mais caro e penoso para os honestos.

Agora, você quer dormir melhor, com a certeza de que ninguém pode explorar seu sistema. Quanto custa isso? Depois que você pagou uma quantia exorbitante de dinheiro para proteger seu sistema, você pode descobrir que seu concorrente, executando um sistema "desprotegido", está tolerando uma perda de US $ 80 com as probabilidades de mais de um milhão de magnitude. É difícil quantificar essa probabilidade. Como você tem mais chances de ganhar na loteria mais difícil do mundo, é melhor você apostar em deixar seu emprego para sempre!

Conclusão: em nossa profissão, as chances de ganhar são o nosso melhor parceiro para dormir!

Conclusão 2: os ataques às condições de corrida podem provavelmenteserem explorados em sistemas de rede automatizados, onde os atacantes podem obviamentesincronizar-seno microssegundo !! ! Isso também poderiamultiplicaro dano, então seja bem-vindo às melhores medidas de segurança!

Conclusão 3: se o sistema já estiver em execução, o esforço de corrigi-lo com a resposta aceita (design, desenvolvimento, teste, UAT, lançamento, PMO ...)émais caro que o dano potencial. Por favor, comente abaixo

* Citei isso como exemplo, porque as linhas de segurança aeroportuária em Israel são lendariamente longas e completas

12
usr-local-ΕΨΗΕΛΩΝ

Já existem boas respostas que cobriram grande parte das explorações de parte do banco de dados. Mas eu queria acrescentar minha experiência na vida real , tendo trabalhado no campo do evento (festival ao ar livre) e criando o sistema de validação de ingressos e aplicativos.

Um dos grandes desafios é a estabilidade da rede, porque a suposição de que todos os dispositivos de digitalização têm capacidade de rede o tempo todo está completamente errada. Pode haver atrasos, interrupções ou indisponibilidade a qualquer momento durante o processo de digitalização e isso não deve atrasar as entradas dos clientes no evento (pelo menos em nosso ponto de vista, outros eventos podem exigir uma validação mais rigorosa).

Em nosso aplicativo, os tickets foram validados usando uma assinatura, mas foram sincronizados e confirmados no banco de dados somente quando a rede estava ativa. O aplicativo armazenou os tickets validados/a serem confirmados em um bucket e tentou confirmar o máximo possível de tickets assim que a rede estivesse disponível. Também evita fazer um INSERT por tickets.

Na parte mais distante da entrada do evento, o wifi não chegava. Para reduzir o custo de ter outro roteador com apenas 10 metros a mais de cobertura, os dispositivos de digitalização poderiam se comunicar entre eles e compartilhar suas conexões. Significando que se apenas um dos dispositivos tivesse acesso ao wifi, os outros poderiam teoricamente enviar seus baldes para ele ou para o dispositivo mais próximo do alcance que o encaminharia.

A vida real nos mostrou que a maioria dos dispositivos de digitalização perdia a conexão pelo menos uma vez em um minuto.

Portanto, teoricamente, um ticket pode ser verificado pelo dispositivo não conectado que ele desejar, mas apenas uma vez por dispositivo. Esta é uma condição de corrida , mas muito mais trivial de explorar do que as outras respostas mencionadas.


Uma palavra no How to prevent it?:

Você pode impedir a condição de corrida removendo o paralelismo, que é o que uma trava faz. Ele apresentará latências, já que você basicamente reduz a capacidade do banco de dados para aceitar gravações simultâneas.

A questão então se torna: vale a pena? Podemos aceitar mais atraso até a validação para garantir a autenticação correta? Isso impedirá que as pessoas encontrem uma porta aberta ou pulem uma cerca?

4
Cyrbil

Uma boa solução pode ser usar uma fila de mensagens em vez de atrasar. O ticket digitalizado não é processado imediatamente, aguarda até que todos os tickets enviados sejam processados. E o sistema não retorna uma resposta, a menos que o ticket tenha saído da fila e tenha sido processado corretamente. Um argumento seria que poderia ser lento, porque todo mundo tem que esperar que os outros terminem. mas você pode dividir logicamente os IDs de ticket, por exemplo: 2 filas, 1 para tickets numerados ímpares e 1 para tickets numerados pares. ou simplesmente coloque números de grupo no próprio ID.

2
paolord