Aprenda PHP Intermediário

  • Página Inicial
  • Contato!
  • Tudo sobre PHP Intermediário Parte 1!
  • Tudo sobre PHP Intermediário Parte 2!
  • Tudo sobre PHP Intermediário Parte 3!
  • Tudo sobre PHP Intermediário Parte 4!
  • Tudo sobre PHP Intermediário Parte 5!
  • Tudo sobre PHP Intermediário Parte 6!
  • Tudo sobre PHP Intermediário Parte 7!
  • SQL Injection

    SQL Injection via URL

    Primeiro, teremos que usar um site vulnerável, veja alguns permitidos para testes: https://www.checkmarx.com/2015/04/16/15-vulnerable-sites-to-legally-practice-your-hacking-skills/

    Se o site, ao ter um parâmetro como ?id=2 e ao tirar o número dê algum erro, ou colocar uma aspas simples, é sinal que ele está desprotegido

    Coloque na URL algo assim: id=-1 union select 1, 2, 3, 4, 5, 6, 7, 8;--, pra tentar descobrir os nomes das tabelas. Enquanto der erro, tire ou adicione números.

    Coloque um comando completo, com um suposto nome de login, tipo: -1 union select 1, 2, 3, 4, 5, 6, 7, 8 from login;--. (o union une resultados de duas ou mais querys em um único result set, no caso, ele unirá o select do servidor com o inserido na injeção).

    Uma dica é fazermos tabelas com nomes diferenciados, pois os invasores procuram nomes comuns como login, contato e etc.

    Para descobrir os dados após descobrir a tabela, aparecerão os parâmetros passados em algum lugar do site.

    Se aparecer algo tipo 4 e 6, podemos fazer: id=-1 union select 1, 2, 3, user, 5, senha, 7, 8;--.

    Nesse ponto, podemos já ter descoberto a senha, e podemos entrar no admin do site.

    Solução do Problema SQL Injection via URL

    Para isso, procute a variável onde se passa o parâmetro da URL. Onde for número inteiro, bloqueie a passagem de parâmetros strings, e números serão convertidos para inteiro, com algo tipo assim:

    
    isset($_GET["id"]) ? (int)$_GET["id"] : 0;
    
    

    Faça isso em todos que tiverem declarações inteiras (só que deixe ele por último, fora de qualquer método como htmlspecialchars()).

    Solução Completa do Problema SQL Injection via URL

    Quando um parâmetro é número, a solução acima funciona, mas quando é string, é mais complicado, podemos usar uma função tipo essa:

    
    function anti_injection($sql) {  
        $lista = array("select", "update", "drop", "insert", "delete", "alter", "from", "where", "table", "tables", "database", ";", "--", "#", "%", "&", "'", "\"", "(", ")", "<", ">", "[", "]", ":", "?", "`", "|", "*");
        $sql = strip_tags($sql); 
        $sql = str_ireplace($lista, "", $sql); 
        $sql = htmlspecialchars($sql, ENT_QUOTES); 
        $sql = trim($sql);
        
        return $sql;
    }
    
    

    E por um include, chame o arquivo com o código acima.

    E faça o ID (o que está sendo passado pela url), assim:

    
    $id = anti_injection(filter_input(INPUT_GET, "id"));
    
    

    PS: O filter_input() funciona como os métodos get e post, só que com uma filtragem básica. O que vai nos parênteses é o name do parâmetro HTML a ser recebido.

    A função strip_tags() protege contra ataques XSS, pelo menos esse precisa estar na função anti injection.

    SQL Injection via Formulário

    Um macete muito comum é colocar nos formulários algo tipo 'or''=' (atenção, tem duas aspas simples sequenciais) no login, e o mesmo na senha, e tentar logar.

    Para evitar isso, inclua o arquivo anti injection que criamos anteriormente. e da mesma forma, faça isso:

    
    $login = anti_injection(filter_input(INPUT_GET, "login"));
    $senha = anti_injection(filter_input(INPUT_GET, "senha"));
    
    

    PS: Coloque o método htmlspecialchars() por fora da invocação da função, para prevenção de algum caractere especial não ter sido colocado no filtro, já o filter_input() vai dentro de tudo, pois ele substituí os métodos $_GET[], $_POST[] e outros do tipo, se forçar conversão pra número, deixe o typecast fora de todos os métodos.

    Veja alguns dos métodos usados para SQL Injection em PHP onde o esperado é select * from tabela where login = '$campoLogin' and senha = '$campoSenha':

    O que Digitar no Login Resultado Funcionamento
    login'; -- select * from tabela where login = 'login';-- and senha = ''; Sabendo o login, tudo após o ponto e vírgula, virará comentário (ou seja, a parte de senha).
    'or '1 = 1 select * from tabela where login = '' or '1 = 1' and senha = ''; Não precisa saber o login nem a senha, condição sempre será satisfatória
    123'; drop table tabela; -- select * from tabela where login = '123'; drop table tabela; --and senha = ''; O login não faz diferença, o objetivo era só apagar a tabela.

    PS: Pode ser preciso retirar os últimos ponto e vírgula dos comandos antes dos comentários, ficando login' --, ' or '1 = 1 -- ou 123'; truncate table users --.

    Esse site também tem algumas dicas: https://juancarloscunha.wordpress.com/2009/08/19/tutorial-como-invadir-com-sql-injection-mysql-sql-injection-por-method-_get-e-_post-programa-para-sqlinjection/

    E aqui temos outras dicas de como evitar ataques: https://eufacoprogramas.com/net-como-evitar-sql-injection/