samuca Posted January 19, 2007 at 11:58 PM Report #77366 Posted January 19, 2007 at 11:58 PM Boas... Ando a fazer um site para uma loja e estou a fazer um sistema de login. o sistema já está a funcionar bem, mas gostava de saber se tem algum problema de segurança, pois é uma das minhas preocupações. //recebe a página escolhida pelo utilizador $pagina = $_GET['pagina']; //Recebe os dados do login $username= $_POST['username']; $password= $_POST['password']; //recebe o tempo actual $time=time(); //Define os parâmetros da sessão $tempo = 1600; //tempo da sessão em segundos session_set_cookie_params($tempo, "/"); session_name("Loja"); session_start(); if ($pagina=="logout"){ session_unset(); session_destroy(); include'pages/inicio.php'; } //Verifica se os dados do login estão correctos if ($username && $password) { $password = md5($password); $consulta = "select * from users where nome='$username' and password='$password'"; $result = mysql_query($consulta, $conexao); $rows = mysql_num_rows($result); if ($rows == 1) { $_SESSION['username']=$username; } else{ $login_error = true; } }code] Este código guarda o nome do utilizador numa variavel de sessão, não seria melhor guardar somente a ID da sessão e guardar o utilizador a que corresponde este id numa tabela da base de dados? Alguém me pode dizer como posso melhorar a segurança deste pequeno script? Obrigado samuca.freehostia.com
shumy Posted January 20, 2007 at 12:24 AM Report #77375 Posted January 20, 2007 at 12:24 AM 1º Esse md5 não está ai a fazer nada. 2º Validar os dados para não sofrer com um SQL Injection. Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!
samuca Posted January 20, 2007 at 12:42 AM Author Report #77381 Posted January 20, 2007 at 12:42 AM 1º Esse md5 não está ai a fazer nada. 2º Validar os dados para não sofrer com um SQL Injection. 1º Esse md5 é necessário ali porque a password já está encriptada na base de dados, e para poder comparar preciso de encriptar a password que recebi do formulário de login. 2º Validar os dados? Como? Não percebi muito bem samuca.freehostia.com
shumy Posted January 20, 2007 at 01:02 AM Report #77382 Posted January 20, 2007 at 01:02 AM Imagina que o user introduz o $username vaiporcima'# Se a BD for MySQL qual é o resultado? Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!
Rui Carlos Posted January 20, 2007 at 01:14 AM Report #77383 Posted January 20, 2007 at 01:14 AM Imagina que o user introduz o $username vaiporcima'# Se a BD for MySQL qual é o resultado? o mais provável é que o php fizesse escape do caracter ', por isso não devia ser muito problemático. Rui Carlos Gonçalves
shumy Posted January 20, 2007 at 01:32 AM Report #77386 Posted January 20, 2007 at 01:32 AM Pode estar activo as Magic Quotes, ou não! Na minha opinião estragam mais do que ajudam. Mas é uma hipotese para quem não pretende fazer mais nada. Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!
Bruno Posted January 20, 2007 at 01:50 AM Report #77391 Posted January 20, 2007 at 01:50 AM Bem, 1º o md5 é preciso e está correctamente aplicado! Falta apenas fazeres, como o shunny disse, o escape a mysql injections. Usa o mysql_real_escape_string(); Eu uso esta função que vi no php.net: //Evita o mysql injection function escape($value) { // Stripslashes if (get_magic_quotes_gpc()) { $value = stripslashes($value); } // Quote if not a number or a numeric string if (!is_numeric($value)) { $value = "'" . mysql_real_escape_string($value) . "'"; } return $value; }
shumy Posted January 20, 2007 at 01:57 AM Report #77392 Posted January 20, 2007 at 01:57 AM Campos que serão colocados na BD e que posteriormente serão apresentados na página também têm de ser validados contra HTML e JavaScript. Não faço ideia se o get_magic_quotes_gpc faz isso. Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!
kingless Posted January 20, 2007 at 11:46 AM Report #77404 Posted January 20, 2007 at 11:46 AM @shumy Acho que estas a falar de XSS se for isso então esse código resolve... <?php function xss_protect( $data ) { $desinfectar = array(''); $Limpo = array(); $XSS = array( '/<[^>]*script*\"?[^>]*>/i', '/<[^>]*object*\"?[^>]*>/i', '/<[^>]*iframe*\"?[^>]*>/i', '/<[^>]*applet*\"?[^>]*>/i', '/<[^>]*meta*\"?[^>]*>/i', '/<[^>]*style*\"?[^>]*>/i', '/<[^>]*form*\"?[^>]*>/i' ); $Limpar = preg_replace( $XSS , $desinfectar, $data ); array_push( $Limpo, $Limpar ); return $Limpo[0]; } echo xss_protect( $_REQUEST['varN'] ); //$_POST, $_GET, $_COOKIE... ?>
samuca Posted January 20, 2007 at 03:00 PM Author Report #77438 Posted January 20, 2007 at 03:00 PM Bem, 1º o md5 é preciso e está correctamente aplicado! Falta apenas fazeres, como o shunny disse, o escape a mysql injections. Usa o mysql_real_escape_string(); Eu uso esta função que vi no php.net: //Evita o mysql injection function escape($value) { // Stripslashes if (get_magic_quotes_gpc()) { $value = stripslashes($value); } // Quote if not a number or a numeric string if (!is_numeric($value)) { $value = "'" . mysql_real_escape_string($value) . "'"; } return $value; } Estive a pesquisar sobre MySQL injection e resolvi aplicar a função que o Bruno colocou. Quanto a isso já está protegido. Obrigado Agora a minha dúvida está na seguinte linha: $_SESSION['username']=$username; Eu guardo o username na sessão. Não seria guardar apenas um ID na sessão e o username numa tabela da BD que guarda os utilizadores online? Ou não faz diferenças a nível de segurança? samuca.freehostia.com
samuca Posted January 29, 2007 at 11:34 AM Author Report #79163 Posted January 29, 2007 at 11:34 AM Depois de fazer o sistema todo com a vossa ajuda apareceu-me outro problema. Eu tenho uma função que serve para validar se o utilizador é administrador ou não, e se este não for administrador redirecciona-o para a página index.php. function validar($us) { //Verifica se o utilizador que está a aceder a uma página privada é administrador ou não //Se o utilizador não for administrador ou não estiver registado, é redireccionado para a página index.php $consulta = "Select * from users where nome = '$us' and nivel='1'"; $result = mysql_query($consulta, $conexao); if(mysql_num_rows($result)==0){ header("Location: index.php"); } } Mas esta função dá-me o seguinte erro: Warning: mysql_query(): supplied argument is not a valid MySQL-Link resource in C:\Programas\xampp\htdocs\projecto\admin.php on line 19Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in C:\Programas\xampp\htdocs\projecto\admin.php on line 21 Warning: Cannot modify header information - headers already sent by (output started at C:\Programas\xampp\htdocs\projecto\admin.php:19) in C:\Programas\xampp\htdocs\projecto\admin.php on line 22 Mas o que é mais estúpido é que se eu meter o código que está dentro da função, fora da função já não dá erro nenhum e funciona na perfeição. Alguém me explica qual é o problema? samuca.freehostia.com
shumy Posted January 29, 2007 at 11:50 AM Report #79166 Posted January 29, 2007 at 11:50 AM Verifica qual é o conteudo dessa $conexao. Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!
samuca Posted January 29, 2007 at 11:55 AM Author Report #79168 Posted January 29, 2007 at 11:55 AM Verifica qual é o conteudo dessa $conexao. A variavel $conexao é o resultado da conexão ao servidor mysql. //conectar ao servidor MySQL $conexao = mysql_connect("localhost","teste","teste"); if (!$conexao) { die('Erro de conexão: ' . mysql_error()); } //escolhe a base de dados mysql_select_db("loja",$conexao); Porque é que este código só dá warning se estiver dentro da função? samuca.freehostia.com
shumy Posted January 29, 2007 at 12:02 PM Report #79169 Posted January 29, 2007 at 12:02 PM OK, eu sei. Mas essa variavel provavelmente tem local scope, e não tem o link de ligação MySql Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!
samuca Posted January 29, 2007 at 01:57 PM Author Report #79187 Posted January 29, 2007 at 01:57 PM OK, eu sei. Mas essa variavel provavelmente tem local scope, e não tem o link de ligação MySql Pois, deve ser esse o problema. Não sabia que o PHP era diferente neste pormenor. Para resolver o problema é só adicionar esta linha dentro da função? global $conexao; Ou é preferível passar a variável por referência? samuca.freehostia.com
shumy Posted January 29, 2007 at 02:02 PM Report #79189 Posted January 29, 2007 at 02:02 PM Eu em geral não gosto de variaveis globais. Não que dizer que não possam existir excepções. Neste caso até nem parece mal ser global. Mas se estiveres a programar no paradigma OOP, é preferivel ser uma variavel da classe. Ou melhor... ter uma classe que te prepara a conexão e trata os erros. Aqui há coisa de 2 anos fazia umas malhas de croché, depois fartei-me e fui para informática!
deathseeker25 Posted January 30, 2007 at 05:38 PM Report #79456 Posted January 30, 2007 at 05:38 PM Boas, Para não estar a abrir um novo tópico, vou escrever a minha dúvida já aqui. Neste momento tenho um formulário com a seguinte estrutura: <form action="login.php" id="login" name="login"> <input type="text" name="username" id="username"> <div class="nav-body-login">Password:</div> <div id="form2"> <input type="password" id="password" name="password"> </div> <div id="submit_form"> <input type="submit" id="submit" name="submit" value="Login"> </form> E o ficheiro que valida o formulário é o ficheiro login.php, com o seguinte código: <?php //Evita o mysql injection function escape($value) { // Stripslashes if (get_magic_quotes_gpc()) { $value = stripslashes($value); } // Quote if not a number or a numeric string if (!is_numeric($value)) { $value = "'" . mysql_real_escape_string($value) . "'"; } return $value; } session_start(); $time = time(); error_reporting(E_ALL); $script_base = dirname($_SERVER['SCRIPT_FILENAME']); //define o root do ficheiro... define('SCRIPT_BASE', $script_base); include SCRIPT_BASE.'/includes/mysql.class.php'; include 'config.php'; //inclui o ficheiro de instalacao $ligacao = new MySQL_DB_Connector; //faz a ligacao a classe que esta no ficheiro mysql.class.php $ligacao->connect($host, $username, $password); //os valores $host, $username e $password estão no ficheiro config.php mysql_select_db($database) or die("ERRO: Impossível escolher a base de dados: ".mysql_error()); if(isset($username) and isset($password)) //se tiverem sido introduzidos password e username... { $username = $_POST['username']; $password = $_POST['password']; //escape($password); //faz uso da função que escrevi acima, que evita o mysql injection //$password = md5($password); //encripta a password $query = "SELECT * FROM utilizador WHERE nome = '$username' AND password = '$password'"; $resultado = mysql_query ($query); $array = mysql_fetch_array($resultado, MYSQL_ASSOC); $id = $array["id"]; $email = $array["email"]; $permissao = $array["permissao"]; $rows = mysql_num_rows($resultado); if($rows == 1) //se devolver resultado... { $_SESSION['username'] = $username; $_SESSION['password'] = $password; $_SESSION['id'] = $id; $_SESSION['email'] = $email; $_SESSION['permissao'] = $permissao; ?><script language="JavaScript"> window.location = "admin/admin.php"; </script><?php } if($rows == 0) { ?> <script language="JavaScript"> window.location = "index.php"; </script> <?php $erro = array(); $erro [] = 'Impossivel fazer login !'; return $erro; } } ?> Ando aqui às voltas e ainda não consegui detectar qual o erro que está a fazer com que a página volte sempre ao index.php. Alguém me pode ajudar? 😛
djthyrax Posted January 30, 2007 at 07:46 PM Report #79474 Posted January 30, 2007 at 07:46 PM Tenta passar if($rows == 1) //se devolver resultado... para: if($rows != 0) //se devolver resultado... Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!
deathseeker25 Posted January 30, 2007 at 07:58 PM Report #79479 Posted January 30, 2007 at 07:58 PM Tenta passar if($rows == 1) //se devolver resultado... para: if($rows != 0) //se devolver resultado... Continua a não dar. Mais uma vez, verifiquei se os dados que estava a introduzir no form eram os mesmos que estão na tabela e estes realmente correspondem. Não percebo, portanto, de onde provém este problema. 😛
Triton Posted January 30, 2007 at 10:24 PM Report #79498 Posted January 30, 2007 at 10:24 PM Assim à primeira vista, falta-te fechar um <div> no formulário. Quanto ao código, não uses JavaScript para redireccionar uma página... 😛 <3 life
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now