Fórum OpenCart Brasil

Por um e-commerce livre, confiável e profissional

Suporte geral sobre problemas técnicos para OpenCart v3.x.
#92015
Olá pessoal! Tudo joia?

Em minha loja virtual tenho habilitado o recaptcha no cadastro e apliquei todas as configurações de segurança no arquivo .htaccess conforme recomendações aqui do forum, no entanto notei que há alguns meses algum "cliente" tem feito o cadastro utilizando uma tentativa de Cross Site Scripting (XSS) onde nos campos de texto ele adiciona, com algumas variações, códigos para inserção de script, que basicamente começam com
'"><
que são os caracteres: aspa simples, aspas duplas, maior que e menor que.
--> Caracteres responsáveis pela interrupção do código, em seguida o código prossegue conforme o link que ele adiciona à frente destes caracteres.

Os IPs de origem destes cadastros são variáveis e são do BR, então não posso bloquear os ranges de IPs senão perco clientes.

Meu pedido de ajuda é: existe alguma forma de fazer com que o formulário de cadastro de clientes e de endereço trate os campos de texto (todos de uma vez ou um por um) através de uma função PHP que substitua pelo menos os caracteres "<" e ">" por interrogação (?) ou apagando tais caracteres e assim mitigar o risco de execução de tais scripts, aumentando a segurança e eventualmente reduzindo um possível consumo de servidor causado por tais scripts?

Encontrei este tópico que MUITO provavelmente responde minha pergunta, mas me falta um conhecimento técnico maior para que eu consiga implantar a solução em minha loja:
https://forum.opencart.com/viewtopic.php?t=214273
--> por exemplo ao invés da função "noSpecialCharacters" seria uma função "replaceChar" onde ela substituiria os caracteres "<" e ">" por "?" ou simplesmente apagaria tais caracteres antes de eles serem processados pelo backend.

Será que conseguimos melhorar a segurança de todos? Não parece ser algo de extrema dificuldade, só precisamos de direcionamento.

Desde já muito obrigado!
#92016
Para excluir os caracteres < e > é só utilizar o método abaixo, que fiz alteração; Mas te informo que o correto é fazer uma verificação nos formulários e não aceitar inserir tags html;
Código: Selecionar todos
private function noSpecialCharacters($str) {
    return preg_replace('/[^A-Za-z0-9\-<>]/', '', $str);
}
#92017
Oi @veteranodf, obrigado pelo retorno. Farei testes utilizando o código que você atualizou.
Não sei exatamente onde realizar tal alteração, mas bora testar em alguns formulários de cadastro e qualquer coisa volto aqui pedindo socorro novamente.

Saberia dizer se há alguma extensão disponível que faça a verificação nos formulários e não aceite a inserção de tags html nos formulários do OpenCart?

Uso o OC Versão 3.0.2.0

Agradeço antecipadamente por utilizar seu tempo auxiliando a comunidade.
#92020
Ola pessoa, basicamente precisa criar uma função no model antes de salvar os dados para ele limpar os campos.
Acho que algo como aqui
-> catalog/model/account/customer.php

// Permitir apenas letras e números
Coloque esse bloco antes da última }
Código: Selecionar todos
private function replaces($str) {
       $str = preg_replace('/[^A-Za-z0-9\-]/', ' ', $str);
}
Agora encontre esse linha:
Código: Selecionar todos
$this->db->query("INSERT INTO " . DB_PREFIX . "customer SET customer_group_id = '" . (int)$customer_group_id . "', store_id = '" . (int)$this->config->get('config_store_id') . "', language_id = '" . (int)$this->config->get('config_language_id') . "', firstname = '" . $this->db->escape($data['firstname']) . "', lastname = '" . $this->db->escape($data['lastname']) . "', email = '" . $this->db->escape($data['email']) . "', telephone = '" . $this->db->escape($data['telephone']) . "', custom_field = '" . $this->db->escape(isset($data['custom_field']['account']) ? json_encode($data['custom_field']['account']) : '') . "', salt = '" . $this->db->escape($salt = token(9)) . "', password = '" . $this->db->escape(sha1($salt . sha1($salt . sha1($data['password'])))) . "', newsletter = '" . (isset($data['newsletter']) ? (int)$data['newsletter'] : 0) . "', ip = '" . $this->db->escape($this->request->server['REMOTE_ADDR']) . "', status = '" . (int)!$customer_group_info['approval'] . "', date_added = NOW()");
Adicione o filtro nos campos desejáveis, assim como eu fiz no exemplo abaixo:
Código: Selecionar todos
$this->db->query("INSERT INTO " . DB_PREFIX . "customer SET customer_group_id = '" . (int)$customer_group_id . "', store_id = '" . (int)$this->config->get('config_store_id') . "', language_id = '" . (int)$this->config->get('config_language_id') . "', firstname = '" . $this->replaces($this->db->escape($data['firstname'])) . "', lastname = '" . $this->replaces($this->db->escape($data['lastname'])) . "', email = '" . $this->db->escape($data['email']) . "', telephone = '" . $this->db->escape($data['telephone']) . "', custom_field = '" . $this->db->escape(isset($data['custom_field']['account']) ? json_encode($data['custom_field']['account']) : '') . "', salt = '" . $this->db->escape($salt = token(9)) . "', password = '" . $this->db->escape(sha1($salt . sha1($salt . sha1($data['password'])))) . "', newsletter = '" . (isset($data['newsletter']) ? (int)$data['newsletter'] : 0) . "', ip = '" . $this->db->escape($this->request->server['REMOTE_ADDR']) . "', status = '" . (int)!$customer_group_info['approval'] . "', date_added = NOW()");
PRECISA TESTAR ,

Veja se isso ajuda.
;)
Henrique Lacerda gostou disso
#92021
Henrique Lacerda escreveu: 15 Out 2024, 13:17 Oi @veteranodf, obrigado pelo retorno. Farei testes utilizando o código que você atualizou.
Não sei exatamente onde realizar tal alteração, mas bora testar em alguns formulários de cadastro e qualquer coisa volto aqui pedindo socorro novamente.

Saberia dizer se há alguma extensão disponível que faça a verificação nos formulários e não aceite a inserção de tags html nos formulários do OpenCart?

Uso o OC Versão 3.0.2.0

Agradeço antecipadamente por utilizar seu tempo auxiliando a comunidade.
A pouco tempo fiz um serviço em um site para impedir inserir javascript no formulário de cadastro, tinha vários cadastros com código javasript com link externo para o endereço "https://xss.rep......", Como o cadastro caia na admin e em pedidos é bem provável que o ataque xss desejava roubar cookies e até a sessão do administrador da loja; Caso precisar de um suporte comercial para esse problema pode me chamar no link https://www.bestcode.dev/contato
#92022
reds escreveu: 16 Out 2024, 08:36 Ola pessoa, basicamente precisa criar uma função no model antes de salvar os dados para ele limpar os campos.
Acho que algo como aqui
-> catalog/model/account/customer.php

// Permitir apenas letras e números
Coloque esse bloco antes da última }
Código: Selecionar todos
private function replaces($str) {
       $str = preg_replace('/[^A-Za-z0-9\-]/', ' ', $str);
}
Agora encontre esse linha:
Código: Selecionar todos
$this->db->query("INSERT INTO " . DB_PREFIX . "customer SET customer_group_id = '" . (int)$customer_group_id . "', store_id = '" . (int)$this->config->get('config_store_id') . "', language_id = '" . (int)$this->config->get('config_language_id') . "', firstname = '" . $this->db->escape($data['firstname']) . "', lastname = '" . $this->db->escape($data['lastname']) . "', email = '" . $this->db->escape($data['email']) . "', telephone = '" . $this->db->escape($data['telephone']) . "', custom_field = '" . $this->db->escape(isset($data['custom_field']['account']) ? json_encode($data['custom_field']['account']) : '') . "', salt = '" . $this->db->escape($salt = token(9)) . "', password = '" . $this->db->escape(sha1($salt . sha1($salt . sha1($data['password'])))) . "', newsletter = '" . (isset($data['newsletter']) ? (int)$data['newsletter'] : 0) . "', ip = '" . $this->db->escape($this->request->server['REMOTE_ADDR']) . "', status = '" . (int)!$customer_group_info['approval'] . "', date_added = NOW()");
Adicione o filtro nos campos desejáveis, assim como eu fiz no exemplo abaixo:
Código: Selecionar todos
$this->db->query("INSERT INTO " . DB_PREFIX . "customer SET customer_group_id = '" . (int)$customer_group_id . "', store_id = '" . (int)$this->config->get('config_store_id') . "', language_id = '" . (int)$this->config->get('config_language_id') . "', firstname = '" . $this->replaces($this->db->escape($data['firstname'])) . "', lastname = '" . $this->replaces($this->db->escape($data['lastname'])) . "', email = '" . $this->db->escape($data['email']) . "', telephone = '" . $this->db->escape($data['telephone']) . "', custom_field = '" . $this->db->escape(isset($data['custom_field']['account']) ? json_encode($data['custom_field']['account']) : '') . "', salt = '" . $this->db->escape($salt = token(9)) . "', password = '" . $this->db->escape(sha1($salt . sha1($salt . sha1($data['password'])))) . "', newsletter = '" . (isset($data['newsletter']) ? (int)$data['newsletter'] : 0) . "', ip = '" . $this->db->escape($this->request->server['REMOTE_ADDR']) . "', status = '" . (int)!$customer_group_info['approval'] . "', date_added = NOW()");
PRECISA TESTAR ,

Veja se isso ajuda.
;)
Oi @reds ! Obrigado pelo retorno. Fiz alguns testes e não funcionou. Comparei com outras funções e testei com diferentes formas de escrever a função, mas ainda assim nada aconteceu.
Notei que na postagem deste link (https://forum.opencart.com/viewtopic.php?t=214273) o pessoal sugeriu a inserção da função "preg_replace" num arquivo php que era responsável pelo método $POST (última resposta do link), então acredito que sua sugestão não tenha dado certo pq (1) muito provavelmente fiz algo errado rsrsss ou (2) não é no arquivo catalog/model/account/customer.php e sim em algum outro arquivo que seja responsável pelo envio das informações
#92023
veteranodf escreveu: 16 Out 2024, 13:29 A pouco tempo fiz um serviço em um site para impedir inserir javascript no formulário de cadastro, tinha vários cadastros com código javasript com link externo para o endereço "https://xss.rep......", Como o cadastro caia na admin e em pedidos é bem provável que o ataque xss desejava roubar cookies e até a sessão do administrador da loja; Caso precisar de um suporte comercial para esse problema pode me chamar no link https://www.bestcode.dev/contato
Oi @veteranodf , obrigado pelo retorno.

Meu caso é BASTANTE similar ao que você teve contato. Do lado de cá tomei outras providências no endpoint, visando não permitir a conexão aos links contidos no script. Além disso, como recebo a notificação do pedido via email, na hora percebi se tratar de XSS e sequer abri o pedido em meu navegador padrão, prefiro abrir num navegador onde bloqueio a execução de javascript e assim corre-se menos risco.

Vou continuar testando do lado de cá e buscando maneiras de substituir/apagar os caracteres especiais nos campos de texto do método post.
#92024
Oi pessoal! Continuando minha busca por formas de aplicar a limpeza de caracteres especiais (basicamente os caracteres "aspa simples", "aspas duplas", "maior que", "menor que" e "&") visando minimizar o risco de XSS me deparei com esta postagem do @reds e do @Manoel Vidal onde é declarada a função "replace_accents" no controller:
viewtopic.php?t=17314
Posteriormente o @reds na mesma postagem informa que utilizou a função no Model ao invés de ser no Controller e funcionou.

Caso essa postagem ilumine a mente dos usuários do forum podemos testar de outras formas e, quem sabe posteriormente, solicitar a implantação deste tipo de proteção em novas versões do OC, uma vez que ataques do tipo XSS são muitas vezes focadas no navegador e, pelo que percebi, as informações são salvas no DB de maneira "convertida", mas ao recuperar as informações do DB elas são reconstituídas e acredito que seja aí que mora o perigo, pois como citou @veteranodf os códigos "reconstituídos" podem ser utilizados para explorar falhas de quem utiliza a parte Administrativa do OpenCart.
#92026
Ola @Henrique Lacerda
Na verdade eu uso ate hoje o padrão mostrado nesse post, no mais seria ajustar ao desejável, como exemplo vou deixar abaixo como eu faço hoje.
Código: Selecionar todos
private function replaceAcents($str) {
		// $this->replaces()
		// strtolower() input email
		if($str !== mb_convert_encoding(mb_convert_encoding($str, 'UTF-32', 'UTF-8'), 'UTF-8', 'UTF-32'))

		$str = mb_convert_encoding($str, 'UTF-8', mb_detect_encoding($str));
		$str = htmlentities($str, ENT_NOQUOTES, 'UTF-8');
		$str = preg_replace('`&([a-z]{1,2})(acute|uml|circ|grave|ring|cedil|slash|tilde|caron|lig);`i', '\1', $str);
		$str = html_entity_decode($str, ENT_NOQUOTES, 'UTF-8');
		$str = preg_replace('/[^A-Za-z0-9\-]/', ' ', $str);
		//$str = preg_replace('/[^A-Za-z0-9\-<>]/', ' ', $str);
		//$str = preg_replace('/( ){2,}/', '$1', $str);
		$str = strtoupper(trim($str));
		//$str = ucwords($str); 
		
		return $str;
	}
Lembrando que você precisa implementar nas entradas do cadastro de pessoas
  • catalog/model/account/customer.php
  • catalog/model/account/address.php
  • admin/model/customer/customer.php
Adicione o filtros nos campos desejáveis para cada entrada ou atualização de dados.
;)
Henrique Lacerda gostou disso