Como andar de táxi às custas de outra pessoa - vulnerabilidades no exemplo de um serviço

Depois de encontrar vulnerabilidades no banco móvel de um banco ucraniano ( post ), eu queria mudar um pouco de direção e mudar de serviços financeiros para outros.

Um artigo de publicidade sobre o aplicativo de táxi móvel atualizado chamou minha atenção e eu o escolhi como experimental.

Aqui as ferramentas são as mesmas: PC, Fiddler, Android-smartphone - instale o aplicativo e acompanhe seus pedidos.

Especificamente, não considerei solicitações e respostas ao registrar ou fazer login (por exemplo, não verifiquei a possibilidade de senha de força bruta), mas mudei para as funções disponíveis após o registro.

Como eu não tinha um histórico de viagens usando esse serviço e não queria realizar uma viagem real para testes, precisava de dados de um dos outros clientes. Decidi pedir aos amigos uma conta no serviço. Entre os conhecidos, havia clientes deste táxi, mas eles o chamavam à moda antiga - com a ajuda de uma ligação.

Então comecei a procurar números de telefone entre as informações publicamente disponíveis na Internet - por exemplo, no site oficial e entre as resenhas nas redes sociais ( geralmente clientes insatisfeitos, descrevendo reclamações, os deixamos nos comentários para exibição pública, em vez de enviar a empresa ao seu MP pessoal ). Como resultado, encontrei alguns telefones em um dos sites de busca de emprego. Substituí um deles em solicitações subsequentes e recebi informações que não deveriam estar acessíveis a ninguém de fora.



Estes foram os seguintes problemas:

1. Obtemos a identificação do cliente, seu nome, telefone, e-mail e cidade (o táxi funciona em várias cidades).

Quando o aplicativo carrega o perfil, a seguinte solicitação POST é executada:

https://sometaxi/mobile3/templateAll.php?PHPSESSID=4cmdlokh4luo209d88kv6uh7 Content-Type: application/x-www-form-urlencoded charset: utf-8 User-Agent: User Host: sometaxi Connection: Keep-Alive Accept-Encoding: gzip Content-Length: 37 func=loadMyInfo&phone=%2B380671234567 

Substituindo o número de telefone de outra pessoa na função loadMyInfo&phone , em resposta, recebi a identificação do cliente, seu nome completo, telefone, email e cidade:

 [{"id":14014,"varFirstName":" ","varLastName":"","varSurName":" ","varTel":"+380671234567","varTel2":"","varEmail":"Sergey_ivan@some.mail","city":1,"cityName":""}] 


2) Informações sobre cartões de pagamento de clientes

Na segunda solicitação, consegui obter informações sobre os cartões de pagamento adicionados pelo cliente à minha conta pessoal:

 https://sometaxi/mobile3/ClientCard.php?PHPSESSID=4cmdlokh4luo209d88kv6uh7 HTTP/1.1 Content-Type: application/x-www-form-urlencoded charset: utf-8 User-Agent: User Host: sometaxi Connection: Keep-Alive Accept-Encoding: gzip Content-Length: 58 data={"Task":"GetClientCardsData","phone":"+380671234567"} 

A resposta é:

 {"data":[{"masked_card":"512345XXXXXX6789","rectoken":"ccaffe873a0e88caf49bc65bbef2390329","card_type":"MASTERCARD","default":true,"card_name":""}]} 

Aqui estavam disponíveis: um número de cartão truncado, algum tipo de token, tipo de cartão, se o cartão está instalado por padrão e seu nome.

3) Obter informações sobre as viagens do cliente

A terceira solicitação - loadHistory - provavelmente me forneceu a maior e mais importante (como eu pensava então) quantidade de informações:

 https://sometaxi/mobile3/templateAll.php?PHPSESSID=4cmdlokh4luo209d88kv6uh7 HTTP/1.1 Content-Type: application/x-www-form-urlencoded charset: utf-8 User-Agent: User Host: sometaxi Connection: Keep-Alive Accept-Encoding: gzip Content-Length: 38 func=loadHistory&phone=%2B380671234567 

Parte da resposta (como antes, os dados foram alterados) :

 {"id":454875,"From":"- ., 1","To":"і ., 13","When":"10-01-2019 15:55","WhenDate":1569942900,"Price":"160","Rate":0,"preorder":0,"status":1,"orderid":"11174445","additionalServices":"[]","classAvto":2,"callsignid":6426,"Car":"  ,Toyota Corolla,, 3733 ","city":1,"cityName":"ї","distance":"0.00"} {"id":408880,"From":"  ., 2","To":"- ., 1","When":"25-12-2018 03:44","WhenDate":1545709440,"Price":"79","Rate":0,"preorder":0,"status":1,"orderid":"10966503","additionalServices":"[]","classAvto":2,"callsignid":4545,"Car":"  ,Toyota Corolla,, 0415 ","city":null,"cityName":null,"distance":"0.00"} 

Aqui estão disponíveis: Endereço de partida, Endereço de destino, Data e hora da viagem, Custo, bem como Nome completo do motorista, tipo, cor e número do seu carro.

Total: com um par de solicitações, por número de telefone, você pode descobrir tudo sobre o cliente deste serviço, incluindo alguns detalhes de sua vida pessoal (por exemplo, uma viagem ao Ano Novo às 2 da manhã de um endereço para outro).

Certamente havia outros lugares no aplicativo onde outras informações poderiam ser obtidas. Mas já foi encontrado o suficiente para informar os desenvolvedores sobre isso, o que fiz imediatamente para direcionar os endereços de trabalho.

Nós nos correspondemos por um mês e depois eles me pagaram uma taxa.



E então este post pode terminar, mas decidi verificar novamente se todos os erros foram corrigidos.

Sim, dois dos três pedidos não me forneceram mais informações de outras pessoas, mas um ainda era válido.

Os cartões de pagamento são adicionados a esse aplicativo da mesma maneira que em qualquer outro: primeiro, em uma página especial, o cliente indica o número completo, a data de validade e os cartões CVV. Em seguida, vem a verificação baixando 1 UAH. e confirmação do cliente de tal operação usando 3-D Secure / LookUp. Essa é uma prática normal, o número completo e outros detalhes de pagamento dos cartões de clientes não estavam nas solicitações.

Mas como vi que meu cartão adicionado foi excluído por uma solicitação do formulário data={"Task":"DeleteClientCardsData", "rectoken":"bc65bbef2390329ccaffe873a0e88caf49" } , decidi verificar: o que acontecerá se você especificar a retomada de outro cliente.

4) Removendo o cartão de outra pessoa por token

Eu executo a solicitação com outro token:

 https://sometaxi/mobile3/ClientCard.php?PHPSESSID=5n4tim74asve7uefdf3hvd6c3 HTTP/1.1 Content-Type: application/x-www-form-urlencoded charset: utf-8 User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; SM-G925F) Host: sometaxi Connection: Keep-Alive Accept-Encoding: gzip Content-Length: 86 data={"Task":"DeleteClientCardsData","rectoken":"ccaffe873a0e88caf49bc65bbef2390329"} 

E a carta alienígena se foi!

Além disso, verifiquei isso com a mesma consulta nº 2 - foi apenas uma resposta visual {"status":"Success"."err":""} ou o cartão foi realmente excluído do cliente.

O mapa foi realmente excluído.

Imediatamente escrevi uma segunda carta pedindo desculpas, mas decidi experimentar ainda mais criando uma outra conta para mim: se o cartão pode ser excluído pelo token - talvez ele possa ser vinculado pelo mesmo token e estar ligado a si mesmo?

5) Adicionando o cartão de outra pessoa por token à sua conta

Sim, não vou definhar - o cartão de outra pessoa pode estar vinculado a si próprio. O principal é saber o que é retomado (e você pode obtê-lo graças ao problema aberto nº 2).

Na solicitação POST, foi possível especificar quaisquer dados - os primeiros 6 e os 4 últimos dígitos do número do cartão, pelo menos 500.000 **** 1111 - o cartão estava associado visualmente a esses dados e o token era de outro cliente e era válido.

 POST https://sometaxi/mobile3/ClientCard.php?PHPSESSID=5n4tim74asve7uefdf3hvd6c3 HTTP/1.1 Content-Type: application/x-www-form-urlencoded charset: utf-8 User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; SM-G925F) Host: sometaxi Connection: Keep-Alive Accept-Encoding: gzip Content-Length: 221 data={"Task":"ClientCardData","default":false,"phone":"+380991234567","masked_card":"500000XXXXXX1111","card_name":"Test","card_type":"MASTERCARD","rectoken":"4f6d228517f2d45690670aba78013a0408"} 

O que isso significa: devido à possibilidade de vincular o token à minha conta, eu poderia fazer uma viagem às custas de outra pessoa sem conhecer todos os detalhes do cartão e sem nenhuma verificação adicional - afinal, o cartão já foi adicionado pelo cliente e foi verificado com êxito pelo serviço de pagamento.

Explicação sobre a capacidade de pagar com o cartão de outra pessoa:
Para simplificar a entrada de detalhes de pagamento para pagamentos, é usado o pagamento com um clique com base em tokens. Na primeira compra, o cliente insere os dados do pagamento, com pagamentos subseqüentes ao cliente, basta clicar no botão "pagar".

Um token é um número exclusivo atribuído a um conjunto de parâmetros do cartão no sistema. Esse token pode ser usado para pagamento direto sem entrar no CVV e sem autenticação 3-D Secure.

Opcional
Criar um token é um processo de pagamento / bloqueio bem-sucedido de fundos no cartão de um cliente, inserindo todos os detalhes do cliente (número do cartão, data de validade, CVV). Você pode criar um token da seguinte maneira:

  1. Aceitar pagamento (compra) - pagamento bem-sucedido pelo cliente com a introdução de detalhes completos do cartão. O cartão recebe um recToken e é transmitido na resposta.
  2. Verificação do cartão / recebimento de um token (Verify) - verificação bem-sucedida do cartão, bloqueando fundos no cartão do cliente. O cartão recebe um recToken e é transmitido na resposta.


Baixa por token - a operação de debitar / bloquear fundos no cartão, sem a participação do cliente, transferindo o token do comerciante.

Um exemplo de explicação é retirado daqui .

Os desenvolvedores pediram para demonstrar a possibilidade de transferir o token de sua conta para a minha e pedir um táxi - eles precisavam garantir que a dedução do token realmente acontecesse. Obviamente, o pedido foi aprovado, o dinheiro foi debitado ( não entrei no carro ). Mais tarde, eles me pagaram um pouco mais de dinheiro.



Como você pode ver neste e em artigos anteriores, às vezes PHPSESSID, Authorization ou SecurityToken não é suficiente.

Se você é um desenvolvedor, siga o que você dá quando pede. Se você é um testador, pesquise e encontre, mas não deixe de informar os desenvolvedores sobre isso. As vulnerabilidades estão cheias aqui e ali, portanto, seja um hacker branco.

Source: https://habr.com/ru/post/pt443928/


All Articles