RC
webservice retornando todos os registro do banco
Bom dia a toda comunidade,
preparei um webservice pra retornar dados de um determinado registro da tabela Atendimento,
para isso deve-se passar o protocolo de atendimento.
Segue a chamada no WS:
O protocolo consultado que está na string é o 191-TKI3-854
Esse é o protocolo exatamente igual ao que está registrado no banco e manda o retorno:
Entretanto, se eu coloco um ponto em qualquer lugar do protocolo 19.1-TKI3-854 (tentativa de burlar o sistema), retorna-se todos os registros do banco, como pode se ver a seguir:
Tal comportamento É TOTALMENTE INDESEJADO.
Segue o código do serviço WS que construi:
preparei um webservice pra retornar dados de um determinado registro da tabela Atendimento,
para isso deve-se passar o protocolo de atendimento.
Segue a chamada no WS:
http://localhost/isonomicus_1.2/14476001000111/pagamento/191-TKI3-854/informarPagamento?prefeitura_cnpj=92923578000100&chave_acesso=202cb962ac59075b964b07152d234b70
O protocolo consultado que está na string é o 191-TKI3-854
Esse é o protocolo exatamente igual ao que está registrado no banco e manda o retorno:
{
"status": "success",
"data":
"{
"atendimento_id":702,
"system_user_id":"2",
"registrado":"2019-08-13 11:43:25"
}"
}
Entretanto, se eu coloco um ponto em qualquer lugar do protocolo 19.1-TKI3-854 (tentativa de burlar o sistema), retorna-se todos os registros do banco, como pode se ver a seguir:
//query de WS
http://localhost/isonomicus_1.2/14476001000111/pagamento/19.1-TKI3-854/informarPagamento?prefeitura_cnpj=92923578000100&chave_acesso=202cb962ac59075b964b07152d234b70
//retorno do WS
{
"status": "success",
"data": [
{
"id": 1,
"atendimento_id": 272,
"forma_pagamento_id": 3,
"system_user_id": 2,
"registrado": "2018-08-21 13:38:02",
"valor_operacao": "470.43",
"hash": "UEN25TMI1LIq713ZYV6500br",
"email_enviado": null,
"valor_parcela": "497.15",
"qtd_parcelas": 2,
"percentual_juros": "1.14"
},
{
"id": 2,
"atendimento_id": 241,
"forma_pagamento_id": 3,
"system_user_id": 2,
"registrado": "2019-01-03 18:07:01",
"valor_operacao": "662.59",
"hash": "YJW17AOT4YYx841SOW1333kf",
"email_enviado": null,
"valor_parcela": "324.49",
"qtd_parcelas": 4,
"percentual_juros": "7.8"
},
{
"id": 3,
"atendimento_id": 387,
"forma_pagamento_id": 3,
"system_user_id": 2,
"registrado": "2018-07-31 23:07:51",
"valor_operacao": "420.66",
"hash": "YZZ63CAE6PLw639SRK0062qq",
"email_enviado": null,
"valor_parcela": "108.95",
"qtd_parcelas": 10,
"percentual_juros": "0.59"
},
{
"id": 4,
"atendimento_id": 697,
"forma_pagamento_id": 3,
"system_user_id": 2,
"registrado": "2019-08-27 13:59:15",
"valor_operacao": "573.46",
"hash": "KWU08BLL2PLe818EDF8782rv",
"email_enviado": null,
"valor_parcela": "257.47",
"qtd_parcelas": 7,
"percentual_juros": "2.46"
},
{
"id": 5,
"atendimento_id": 234,
"forma_pagamento_id": 2,
"system_user_id": 1,
"registrado": "2019-11-07 02:01:55",
"valor_operacao": "408.84",
"hash": "XVO59PYN3RRh946LHZ3215qf",
"email_enviado": null,
"valor_parcela": "179.69",
"qtd_parcelas": 2,
"percentual_juros": "7.29"
},
{
"id": 6,
"atendimento_id": 375,
"forma_pagamento_id": 2,
"system_user_id": 2,
"registrado": "2018-09-13 23:11:54",
"valor_operacao": "369.49",
"hash": "FAT91LRV1EQw289TGV5671qw",
"email_enviado": null,
"valor_parcela": "252.62",
"qtd_parcelas": 1,
"percentual_juros": "5.7"
},
{
"id": 7,
"atendimento_id": 583,
"forma_pagamento_id": 1,
"system_user_id": 1,
"registrado": "2018-09-11 09:34:10",
"valor_operacao": "495.84",
"hash": "ARV91VGN2RQb732CCR2784vk",
"email_enviado": null,
"valor_parcela": "437.97",
"qtd_parcelas": 6,
"percentual_juros": "2.84"
},
{
"id": 8,
"atendimento_id": 300,
"forma_pagamento_id": 1,
"system_user_id": 2,
"registrado": "2019-05-25 02:23:58",
"valor_operacao": "798.02",
"hash": "SNN56NEU5UOj751KLR4106dt",
"email_enviado": null,
"valor_parcela": "339.5",
"qtd_parcelas": 2,
"percentual_juros": "5.09"
},
{
"id": 9,
"atendimento_id": 551,
"forma_pagamento_id": 3,
"system_user_id": 1,
"registrado": "2020-04-10 07:01:17",
"valor_operacao": "624.84",
"hash": "QOX16JAE0IHu263NDD4806gp",
"email_enviado": null,
"valor_parcela": "482.84",
"qtd_parcelas": 3,
"percentual_juros": "0.45"
},
{
"id": 10,
"atendimento_id": 692,
"forma_pagamento_id": 3,
"system_user_id": 1,
"registrado": "2020-02-19 05:26:46",
"valor_operacao": "410.77",
"hash": "AHP09TKN4QIg255UWE7234qo",
"email_enviado": null,
"valor_parcela": "330.27",
"qtd_parcelas": 8,
"percentual_juros": "8.92"
},
{
"id": 11,
"atendimento_id": 555,
"forma_pagamento_id": 3,
"system_user_id": 2,
"registrado": "2019-05-05 02:15:48",
"valor_operacao": "832.33",
"hash": "FMV72YLN1OLt431GXJ9074jc",
"email_enviado": null,
"valor_parcela": "181.69",
"qtd_parcelas": 9,
"percentual_juros": "7.4"
}
}
Tal comportamento É TOTALMENTE INDESEJADO.
Segue o código do serviço WS que construi:
- <?php
- /**
- * PagamentoService REST service
- */
- class PagamentoService extends AdiantiRecordService
- {
- const DATABASE = 'sistema';
- const ACTIVE_RECORD = 'Pagamento';
- /**
- * informarPagamento($param)
- *
- * informa o pagamento realizado para o Atendimento anteriormente gerado,
- * isto só é possível se o Atendimento estiver EM ABERTO
- *
- * @param $param['id'] protocolo do Atendimento
- * @return TRUE or FALSE
- */
- public function informarPagamento($param)
- {
- TTransaction::open(self::DATABASE);
- //checa permissao do acesso ao webservice
- if( WebserviceLog::checarPermissao($param) )
- {
- //pega a prefeitura que se quer consultar os dados
- $pref = Prefeitura::loadByCNPJ($param['prefeitura_cnpj']);
- //pega o credenciado que esta consumindo o webservice
- $dados = explode('/', $_SERVER['REQUEST_URI']);
- $cred = Credenciado::loadByCNPJ($dados[2]);
- //grava o log do webservice
- WebserviceLog::registrar($pref->id, $cred->id);
- //checa o protocolo do Atendimento
- if( empty($param['id']) )
- {
- throw new Exception('Informe o protocolo do Atendimento');
- }
- //checa se existe Atendimento em aberto pelo protocolo informado
- $atend = Atendimento::where('protocolo', '=', $param['id'])
- ->where('atendimento_status_id', '=', AtendimentoStatus::ABERTO)
- ->load();
- //Notifica o atendimento (caso exista) para o Contribuinte de Credenciado diferente daquele do protocolo gerado
- if( isset($atend[0]) and ($atend[0]->credenciado_id != $cred->id))
- {
- //gera notificação para o administrador do sistema
- SystemNotification::register( 1, 'Pagamento realizado por Credenciado diferente',
- $cred->razao_social . ' informou Pagamento para o protocolo ' . $atend[0]->protocolo .
- ', mas este Atendimento está vinculado ao Credenciado ' . $atend[0]->credenciado->razao_social,
- 'class=AtendimentoFormView&method=onShow&key=' . $atend[0]->id,
- 'Consultar Atendimento', 'fa fa-search #478fca' );
- }
- //throw new Exception(print_r($atend));
- //salva o Pagamento
- $object = new Pagamento();
- $object->atendimento_id = $atend[0]->id;
- $object->system_user_id = SystemUsers::ISONOMICUS;
- $object->registrado = date('Y-m-d H:i:s');
- /*
- $object->forma_pagamento_id = ;
- $object->valor_operacao = ;
- $object->valor_parcela = ;
- $object->qtd_parcelas = ;
- $object->percentual_juros = ;
- $object-> = ;
- $object->gerarHash();
- $object->store(); // save the object
- */
- TTransaction::close();
- return $object->toJson();
- }
- }
- /**
- * delete($param)
- *
- * Delete an Active Records by its ID
- *
- * @return The Operation result
- * @param $param['id'] Object ID
- */
- public function delete($param)
- {
- throw new Exception('Função não permitida!');
- }
- /**
- * store($param)
- *
- * Save an Active Records
- *
- * @return The Operation result
- * @param $param['data'] Associative array with object data
- */
- public function store($param)
- {
- throw new Exception('Função não permitida!');
- }
- /**
- * loadall($param)
- *
- * List the Active Records by the filter
- *
- * @return Array of records
- * @param $param['offset'] Query offset
- * $param['limit'] Query limit
- * $param['order'] Query order by
- * $param['direction'] Query order direction (asc, desc)
- * $param['filters'] Query filters (array with field,operator,field)
- */
- public function loadall($param)
- {
- throw new Exception('Função não permitida!');
- }
- /**
- * deleteAll($param)
- *
- * Delete the Active Records by the filter
- *
- * @return Array of records
- * @param $param['filters'] Query filters (array with field,operator,field)
- */
- public function deleteAll($param)
- {
- throw new Exception('Função não permitida!');
- }
- }
- ?>
Se alguém conseguir identificar o problema avise, esta falha na segurança pode estar acontecendo em outros sistemas.
Ricardo,
Para melhorar ainda mais a segurança use sempre POST no lugar de GET nas chamadas
Crie um token de segurança para checar quem está solicitando algum serviço, enviando ele pelo header.
Outro detalhe que faço em meus serviços, eu faço o tratamento do dado enviado, principalmente se for alguma chave. No seu caso, verifique a estrutura do Protocolo antes de continuar a execução do serviço.
Se o protocolo tem esta estrutura AAA-AAA-AAA, então antes de buscar, retire todos os outros caracteres que possa ser indesejados usando expressões regulares ou até mesmo um str_replace.
Olá Marcelo Gomes,
eu tratei o parâmetro enviado com str_replace como havia sugerido.
Entretanto o erro continua.
Eu já utilizo token de segurança com jwt token.
Estou tentando tratar as requisições mesmo com GET para evitar que clientes mal intencionados tenham acesso indevido ao banco.
A requisição GET está assim:
Esta outra classe de serviço ficou assim:
Imagino que o problema não esteja na função getPrefeitura, visto que ela sempre retorna um único objeto, independente do parâmetro passado.
Provavelmente é o mapeamento da rota no htaccess que tá fazendo com que seja chamada a função loadAll.
Olá Nataniel,
obrigado pela ajuda.
A função getPrefeitura retorna apenas um objeto, quando o parâmetro está correto.
Entretanto, todas as funções retornam todos os registro do banco se houver um ponto "." dentro do parâmetro.
Mesmo tentando retirar o ponto, como fiz na linha 24 da classe PrefeituraService, o erro persiste.
$param['id'] = str_replace('.', '', $param['id']);
Com relação ao htaccess, vou postá-lo aqui:
Vou postar novamente, pois ficou mal formatado.
Parâmetros quando digitado o ponto:
Parâmetros sem ponto:
Note que quando há ponto, method = handle e a chave "id" não é setada. E não havendo "id", a função handle chama loadAll.
Isso acontece porque no htaccess "[A-Za-z-_0-9]" não considera nada além de letras e números, com isso o ponto faz com que seja utilizada a última regra, que usa a função handle.
Perfeito Nataniel,
segue suas orientações e o erro foi corrigido.
Meu htaccess ficou assim
Então quando coloco o ponto na requisição o webservice retorna:
Muito obrigado pela ajuda.