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.
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()).
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.
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/