Secret Experience

Secret Experience (https://secretexperience.net/index.php)
-   [L2J] Tutoriais (https://secretexperience.net/forumdisplay.php?f=39)
-   -   [GUIA] ~ Inject SQL ~ Aprenda a se proteger (https://secretexperience.net/showthread.php?t=4993)

fetish 23-02-2009 09:46 PM

[GUIA] ~ Inject SQL ~ Aprenda a se proteger
 
GUIA ~ INJECT SQL ~
Realizando e Protegendo teu servidor

nível: intermediário

Índice~
0- Código de ética.
1- O que é?
2- Localizando sites com proteção falha.
3- Protegendo-se
4- Créditos


------------
0- Código de ética.
O Inject SQL é um erro sério.
Ao ler o guia você concorda em não utilizar para destruir sites e nem invadir servidores.
Esse guia tem como objetivo explicar o que é e como funciona o Inject SQL.
Não, você não é nenhum h4x0r por saber isso pois até uma criança de 8 anos consegue dar inject SQL.


------------
1- O que é?
Inject SQL é um erro detectado recentemente que permite você logar como administrador e fazer outras coisas fodásticas!
Como a divulgação do erro foi propagada muito rápida poucos sites hoje em dia estão desprotegidos...


2- Localizando sites com proteção falha.
Simplesmente vá no google e digite:
Citação:

/admin/index.asp
/admin/login.asp
/adm/index.asp
/adm/login.asp
/admin/index.php
/admin/login.php
/adm/login.php
/adm/index.php
Procure por páginas que haja login de administrador.
Agora para ver se a proteção não está boa, digite os seguintes login e senha:


Citação:

Login: '
Senha: '='
Esse simples código não irá injetar porém é capaz de confundir MySql e irá retornar um erro do prórpio MySql.
Se não der nenhum erro de MySql então eles estão protegidos...


Se der erro então esse site é vuneravél.
Para injetar ponha ' no login e na senha tente um desses códigos:
Citação:

' or '1'='1'
' or 'a'='a'
'or''='or'1'='1
Se entrou parabéns você conseguiu!

3- Protegendo-se

Abaixo colocarei alguns scripts com a proteção anti-SQL Inject, para serem inseridos no teu website.


Criar conta

Citação:

<?php
//set host, username and password for MySQL
$dbhost = "localhost";
$dbuser = "YOURMYSQLUSERNAME";
$dbpass = "YOURMYSQLPASSEORD";

//connect to MySQL or return an error
$conn = mysql_connect("$dbhost", "$dbuser", "$dbpass")
or die('Could not connect: ' . mysql_error());

//set database name
$dbname = "l2jdb";

//select database or return an error
$dbselect = mysql_select_db("$dbname")
or die ('Could not select database');

//get username and password info from the form, protecting against SQL injection
$pass = mysql_real_escape_string($_POST["pass"]);
$confirm = mysql_real_escape_string($_POST["confirm"]);
$user = mysql_real_escape_string($_POST["name"]);

//validate user input
if(!preg_match('/^[a-zA-Z0-9]{5,20}$/',$user)) {
die ('Error: Usernames can only contain alphanumeric characters and must be between 5 and 20 characters in length.');
}

if(!preg_match('/^[a-zA-Z0-9]{5,20}$/',$pass)) {
die ('Error: Passwords can only contain alphanumeric characters and must be between 5 and 20 characters in length.');
}

if($pass != $confirm) {
die ('Error: Passwords do not match.');
}

//make sure user doesn't already exist and if it doesn't, add new record to the database
$result = mysql_query("SELECT login FROM accounts WHERE login='$user'");

if(mysql_num_rows($result)>0) {
die ('Error: Username already exists.');
}else{
mysql_query("INSERT INTO accounts (login, password, access_level) VALUES ('".$_POST['name']."', '".base64_encode(pack('H*', sha1($_POST['pass'])))."', 0)")
or die ('Error: ' . mysql_error());
}

//report successful registration
echo "Account created successfully.";

//close MySQL connection
mysql_close();

?>
salve o código como acc.php, e em seguida salve o seguinte código html para adicionar o formulario de registro em uma página html.

Citação:

<form action="acc.php" method=post>
Login: <input type="text" name="name" size=20><br><br>
Senha: <input type="password" name="pass" size=20><br><br>
Confirmar senha: <input type="password" name="confirm" size=20><br><br>
<input type=submit name="submit" value="Create"></form>

O script foi construído na proteção contra o SQL Injection, e também força o usuário a apresentar um nome de usuário e senha que estão entre os 5 e os 20 caracteres de comprimento, e limita-los a apenas caracteres alfanuméricos.

Scripts de Redefinição de senha são ainda mais sujeitos a SQL Inject , então aqui está um script para redefinição de senha:

Alterar senha
Citação:

<?php

//set host, username and password for MySQL
$dbhost = "localhost";
$dbuser = "YOURMYSQLUSERNAME";
$dbpass = "YOURMYSQLPASSEORD";

//connect to MySQL or return an error
$conn = mysql_connect("$dbhost", "$dbuser", "$dbpass")
or die('Could not connect: ' . mysql_error());

//set database name
$dbname = "l2jdb";

//select database or return an error
$dbselect = mysql_select_db("$dbname")
or die ('Could not select database');

//get username and password info from the form, protecting against SQL injection
$user = mysql_real_escape_string($_POST["name"]);
$currentpass = mysql_real_escape_string($_POST["currentpass"]);
$newpass = mysql_real_escape_string($_POST["newpass"]);
$confirm = mysql_real_escape_string($_POST["confirm"]);

//username and password should already be valid and newpass and confirm should match or this script will die
//so just validate the newpass and then check to see if newpass and confirm are the same
if(!preg_match('/^[a-zA-Z0-9]{5,20}$/',$newpass)) {
die ('Error: Passwords can only contain alphanumeric characters and must be between 5 and 20 characters in length.');
}

if($newpass != $confirm) {
die ('Error: New passwords do not match.');
}

//encrypt the passwords
$currentpass = base64_encode(pack('H*', sha1($currentpass)));
$newpass = base64_encode(pack('H*', sha1($newpass)));

//if the user input passed all the checks, make sure the account exists and then update the password
$result = mysql_query("SELECT login,password FROM accounts WHERE login='$user' AND password='$currentpass'");

if(mysql_num_rows($result)>0) {
mysql_query("UPDATE accounts SET password='$newpass' WHERE login='$user' AND password='$currentpass'");
echo "Password succesfully updated.";
}else{
die ('Error: Account does not exist or password is incorrect.');
}

//close MySQL connection
mysql_close();

?>
salve o código como changepass.php, e em seguida salve o seguinte código html para adicionar o formulario de registro em uma página html.

Citação:

<form action="changepass.php" method=post>
Login:<input type="text" name="name" size=20><br><br>
Senha: <input type="password" name="currentpass" size=20><br><br>
Nova senha: <input type="password" name="newpass" size=20><br><br>
Confirmar senha:<input type="password" name="confirm" size=20><br><br>
<input type=submit name="submit" value="Update Password">
Um simples comando chamado addslashes()
Veja esse exemplo de código:


Citação:

<?php
$user = $_POST['user'];
$pass = $_POST['pass'];
mysql_query("SELECT * FROM users WHERE user='$user' AND pass='$senha'")
?>
Ele está desprotegido e eu posso simplesmente burlar esse login...
Mas se por acaso adicionarmos umas linha:


Citação:

<?php
$user = $_POST['user'];
$pass = $_POST['pass'];
$user_escape = addslashes($user);
$pass_escape = addslashes($pass);
mysql_query("SELECT * FROM users WHERE user='$user_escape' AND pass='$senha'_escape")
?>
O que acontece no código?
O comando addslashes irá adicionar uma barra invertida "\" antes de todo ' ou "
No caso, isso irá fazer com que o interpretador ignore isso criando um erro no login.

4- Créditos

Near
e _Dudu_1533 por suas dicas.


o Changelog:
Citação:

24/02/2009
* Adicionado ao tutorial, mais algumas dicas.

_Dudu_1533 23-02-2009 10:35 PM

Bom, já que estamos falando de MySQL + PHP, vou dar meu parecer.
Hoje em dia, SQL Injection é uma questão bem discutida, mas é o tipo de assunto que o pessoal não passa soluções. É difícil você ir em algum site de Webmaster e encontrar uma solução cabível para tal problema.

Temos várias formas de proteger contra SQL Injection.

Lista de alguns:

Com esses 3 métodos básicos, que ao meu ver, todo site deve ter, você consegue proteger-se, com qualquer tipo de sistema que utilizar.

Vale lembrar, que para uso de expressões regulares, é necessário uma leitura minuciosa sobre cada propriedade. Mas a recompensa é gratificante, pois é um ótimo recurso, e proporciona muita coisa.

Mas devemos lembrar que SQL Injection não usa-se somente em formulários.
Temos que nos previnir quando usamos métodos $_GET, $_COOKIE, ou todos os tipos onde o usuário tem o poder de editar a informação.


Outro fator importante, é trabalhar com cada informação ligada às consultas.
Como nosso amigo disse, o caractere ' (aspas simples) é muito perigoso.
Por quê?
Pois é um caractere que o SQL (Todos os tipos de banco que utilizam a linguagem SQL) utiliza para caracterizar um dado como string.

Exemplo:

Código:

$string = "O Dudu é 'Bonito";
$sql = mysql_query("SELECT * FROM usuario WHERE descricao = '".$string."'") or die(mysql_error());

O Código acima retornará erro, pois possui uma aspa jogada na string ' (aspas simples), onde, ela será a limitadora, e sobrará uma, gerando erro. Como sabemos, tudo que abre, fecha. ^^

Qual a solução?
Simples, "escapar" estas aspas.

Como?
É só adicionar barra invertida \ antes de aspas simples.
A função nativa do php, addslashes(), adiciona automaticamente essa barra antes de todas as aspas simples de uma string, com isso, a aspa será considerado como um caractere, e não um limitador do SQL.

Bom, a dica está aí.
Boa leitura à todos.



Uma dica ao autor do tutorial, é que ele passe estes conceitos.
Você passou muito exemplo prático, tente colocar mais conceitos, pois existem muitos leigos no assunto.

Se quiser aproveitar este meu post, fique à vontade.

Qualquer dúvida, é só perguntar.
Até mais ^^


Horários baseados na GMT -3. Agora são 12:52 AM.

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.