Protegendo seu código WordPress de Sql Injection Parte 1

Introdução:

Há algum tempo atrás tenho dedicado à pesquisar sobre segurança e vulnerabilidades de plugins WordPress. E o resultado como podemos ver a seguir, esta sendo muito satisfatório. Tenho publicado e ajudado a comunidade a ficar um pouco mais segura.

  1. WpVull, site que lista vulnerabilidades com foco em WordPress
  2. Exploit-db, Site que lista 0days de todos os tipos.

Interessante dessa pesquisa não é apenas o resultado, mas as inúmeras peculiaridades de cada código, como são abordados questões complicadas de segurança e como existe inúmeras soluções para o mesmo problema. O resultado dessas observações pretendo publicar em forma sequencial em meu site.

O primeiro dela é sobre a quantidade enorme de  formas que podemos usar para nos proteger de um Sql Injection.

Mas o que é um Sql Injection?

Sql Injection é um tipo de ataque que visa enviar comandos de SQL, através de campos de formulários ( POST ) ou através de URLs ( GET). O sucesso do ataque normalmente causa roubo de dados sensíveis como uma base de dados que contenham dados de acesso, como login e senha, mas dependendo do ataque  pode até realizar um drop da base de dados.

Exemplo simples:

Recebemos uma query com login e senha para acesso com dados vindo do formulário de login:

$username = $_POST['username'];
$password = $_POST['password'];
SELECT * FROM Users WHERE Username='$username' AND Password='$password'

Se passarmos o parâmetro da seguinte forma…

$username = 1' or '1' = '1
$password = 1' or '1' = '1

A query vai ficar assim ...
SELECT * FROM Users WHERE Username='1' OR '1' = '1' AND Password='1' OR '1' = '1'

Resultado que dessa forma a pesquisa será positiva e terá acesso ao sistema.

Exemplo com Plugin WordPress.

Um exemplo verídico com Plugin WordPress retirado de outro post:

Despois de um acesso a parte administrativa com o plugin dsubscribers com  a versão vulnerável irei inserir a seguinte url:

 http://target/wp-admin/admin.php?page=dsubscribers&action=edit&dsubscribers=0 UNION SELECT 1,2,CONCAT(user_login,char(58),user_pass) FROM wp_users WHERE ID=1

A query com problema era:

$id = $_GET['dsubscribers'];
...
$wpdb->get_row("SELECT * FROM $table_name WHERE id=$id");

O resultado será esse:

O login e senha foi impresso no campo que era para trazer o email.
  • Observações
    • Não irei falar sobre qual é o melhor forma para implementação.

-Cenário será:

Mais comum possível, será plugin instalado que cria novas tabelas e precisa de um select com passagem de parâmetro via GET para retornar informações específicas.

Testes :

I Exemplo:

Tipo : $wpdb->prepare.

Query:

$query=$wpdb->get_row( $wpdb->prepare("SELECT * FROM ".$wpdb->prefix."spidercatalog_product_categories WHERE id=%d",$_GET['id']) );

Motivo: O que salva o Sql Injection nessa situação será o método $wpdb->prepare que serve justamente para poder tratar e filtrar. Leia Mais…

II Exemplo: ✅

 

Tipo : Usando (int).

Query:

$pppm_phid = (int) $_POST['pppm_phrase_filter'];
$pppm_res = $wpdb->get_row( "SELECT `phrase`,`replace` FROM `".$wpdb->prefix."pppm_filter` WHERE `id` = $pppm_phid ", ARRAY_A );

Motivo: O que salva o Sql Injection nessa situação é o validação do inteiro na query (int) na primeira linha. Isso vale para PHP em geral. Lei Mais…

Observação: Outros servem para algo semelhante a essa tipificação como:

  • $pppm_phid = (integer) $_POST[‘pppm_phrase_filter’];
  • $pppm_phid = intval($_POST[‘pppm_phrase_filter’]);
  • $pppm_phid = (float)$_POST[‘pppm_phrase_filter’]);

 

tem mais, aguardem …

One Comment

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *