<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es">
	<id>https://manuais.iessanclemente.net/index.php?action=history&amp;feed=atom&amp;title=Curso_POO_PHP_Inxecci%C3%B3n_SQL</id>
	<title>Curso POO PHP Inxección SQL - Historial de revisiones</title>
	<link rel="self" type="application/atom+xml" href="https://manuais.iessanclemente.net/index.php?action=history&amp;feed=atom&amp;title=Curso_POO_PHP_Inxecci%C3%B3n_SQL"/>
	<link rel="alternate" type="text/html" href="https://manuais.iessanclemente.net/index.php?title=Curso_POO_PHP_Inxecci%C3%B3n_SQL&amp;action=history"/>
	<updated>2026-10-23T22:15:12Z</updated>
	<subtitle>Historial de revisiones de esta página en la wiki</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://manuais.iessanclemente.net/index.php?title=Curso_POO_PHP_Inxecci%C3%B3n_SQL&amp;diff=36522&amp;oldid=prev</id>
		<title>Vlourido: /* Validar os datos introducidos polos usuarios */</title>
		<link rel="alternate" type="text/html" href="https://manuais.iessanclemente.net/index.php?title=Curso_POO_PHP_Inxecci%C3%B3n_SQL&amp;diff=36522&amp;oldid=prev"/>
		<updated>2013-07-22T23:26:42Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Validar os datos introducidos polos usuarios&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Página nueva&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Inxección SQL ==&lt;br /&gt;
&lt;br /&gt;
Un dos problemas de seguridade máis habituais é a vulnerabilidade fronte a inxeccións SQL. Unha &amp;#039;&amp;#039;&amp;#039;[http://php.net/manual/es/security.database.sql-injection.php inxección SQL]&amp;#039;&amp;#039;&amp;#039; consiste en introducir xunto cos datos (por exemplo nos formularios) código que ten por obxecto modificar as consultas que se realizan sobre a base de datos.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, vexamos o seguinte código PHP, que recibe o nome e o contrasinal introducidos nun formulario HTML de &amp;#039;&amp;#039;login&amp;#039;&amp;#039; (nótese que é un exemplo ficticio; na realidade é recomendable empregar unha función de hash como [http://www.php.net/manual/es/function.md5.php md5] para almacenar as contrasinais dos usuarios):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$consulta = &amp;quot;SELECT * FROM usuarios WHERE nome=&amp;#039;&amp;quot; . $_REQUEST[&amp;quot;nome&amp;quot;] . &amp;quot;&amp;#039; AND contrasinal=&amp;#039;&amp;quot; . $_REQUEST[&amp;quot;contrasinal&amp;quot;] . &amp;quot;&amp;#039;&amp;quot;;&lt;br /&gt;
$resultado = $db-&amp;gt;query($consulta);&lt;br /&gt;
if($resultado) {&lt;br /&gt;
   $usuario = $resultado-&amp;gt;fetch_array(); // Obtemos o primeiro rexistro&lt;br /&gt;
   $nome = $usuario[&amp;#039;nome&amp;#039;];&lt;br /&gt;
   $contrasinal = $usuario[&amp;#039;contrasinal&amp;#039;];&lt;br /&gt;
   ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A función do código anterior é comprobar se existe na base de datos un usuario con ese nome e contrasinal. Se existe, suponse que é único e colle os datos do primeiro rexistro devolto pola consulta.&lt;br /&gt;
&lt;br /&gt;
Se o usuario introducise o seguinte texto no campo &amp;quot;contrasinal&amp;quot; do formulario anterior: &amp;quot;&amp;#039;&amp;#039;&amp;#039;&amp;#039; OR 1;&amp;#039;&amp;#039;&amp;#039;&amp;quot; (notar a primeira comiña simple de peche no texto), a consulta que executaría PHP sería a seguinte e devolvería a lista completa de usuarios:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT * FROM usuarios WHERE nome=&amp;#039;xxx&amp;#039; AND contrasinal=&amp;#039;&amp;#039; OR 1;&amp;#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Isto é, daríamos ao usuario por válido coa identidade do primeiro usuario da táboa. &lt;br /&gt;
&lt;br /&gt;
Imos ver distintos métodos que podemos aplicar nos nosos scripts PHP para evitar a inxección SQL.&lt;br /&gt;
&lt;br /&gt;
=== Empregar consultas preparadas ===&lt;br /&gt;
&lt;br /&gt;
As consultas preparadas non se ven afectadas polas técnicas de inxección SQL. Os valores que reciben dos parámetros non se poden extender a outras partes da consulta.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$consulta = $db-&amp;gt;prepare(&amp;#039;SELECT * FROM usuarios WHERE nome=:nome AND contrasinal=:contrasinal&amp;#039;);&lt;br /&gt;
$consulta-&amp;gt;bind_param(&amp;quot;:nome&amp;quot;, $_REQUEST[&amp;quot;nome&amp;quot;]);&lt;br /&gt;
$consulta-&amp;gt;bind_param(&amp;quot;:contrasinal&amp;quot;, $_REQUEST[&amp;quot;contrasinal&amp;quot;]);&lt;br /&gt;
$consulta-&amp;gt;execute();&lt;br /&gt;
if($rexistro = $consulta-&amp;gt;fetch(PDO::FETCH_OBJ)) {&lt;br /&gt;
   $nome = $rexistro-&amp;gt;nome;&lt;br /&gt;
   $contrasinal = $rexistro-&amp;gt;contrasinal;&lt;br /&gt;
   ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O problema das consultas preparadas é que os parámetros non se poden empregar en algúns casos, por exemplo:&lt;br /&gt;
&lt;br /&gt;
* Para substituir listas de valores (como na clausula IN de SQL).&lt;br /&gt;
* Para facer referencia ao nome dunha táboa ou dun campo da táboa.&lt;br /&gt;
* Como parte da sintaxe da sentenza SQL (por exemplo, para facer un UPDATE ou un DELETE en función da entrada do usuario).&lt;br /&gt;
&lt;br /&gt;
Se é o caso, teremos que empregar consultas interpoladas e apoiarnos noutras técnicas para protexernos fronte a inxección SQL.&lt;br /&gt;
&lt;br /&gt;
=== Validar os datos introducidos polos usuarios ===&lt;br /&gt;
&lt;br /&gt;
Consiste en comprobar que os datos que introducen os usuarios se axustan aos requisitos necesarios para o campo concreto. Por exemplo, que o valor da idade dunha persoa é numérico positivo, ou que a dirección de correo electrónico é válida.&lt;br /&gt;
&lt;br /&gt;
A validación pode facerse de varias formas:&lt;br /&gt;
&lt;br /&gt;
* Comprobando o tipo de datos coas funcións &amp;#039;&amp;#039;&amp;#039;is_int&amp;#039;&amp;#039;&amp;#039;, &amp;#039;&amp;#039;&amp;#039;is_string&amp;#039;&amp;#039;&amp;#039;, &amp;#039;&amp;#039;&amp;#039;is_bool&amp;#039;&amp;#039;&amp;#039;, ..., ou con &amp;#039;&amp;#039;&amp;#039;gettype&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 2em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$idade = ($_REQUEST[&amp;quot;idade&amp;quot;];&lt;br /&gt;
if(!is_int($idade)) exit(&amp;quot;$idade é un valor inválido para a idade!&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
: Ou directamente forzando o tipo de datos.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 2em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$idade = (int) $_REQUEST[&amp;quot;idade&amp;quot;];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Comprobando a lonxitude dos datos introducidos, para evitar desbordamento de buffer e ataques DOS.&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 2em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$nome = (int) $_REQUEST[&amp;quot;nome&amp;quot;];&lt;br /&gt;
if (strlen($nome) &amp;gt; 255) exit(&amp;quot;O nome NON é válido&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Empregando expresións regulares.&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 2em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$expreg = &amp;#039;/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/&amp;#039;; &lt;br /&gt;
if (!preg_match($expreg, $email)) exit(&amp;quot;A dirección de email NON é válida&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Empregando a extensión &amp;#039;&amp;#039;&amp;#039;[http://docs.php.net/manual/es/book.filter.php Filter]&amp;#039;&amp;#039;&amp;#039;, que ven activa por defecto dende PHP 5.2, xunto cun [http://www.php.net/manual/es/filter.filters.validate.php filtro de validación] axeitado.&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-left: 2em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) exit(&amp;quot;A dirección de email NON é válida&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sanear os datos introducidos polos usuarios ===&lt;br /&gt;
&lt;br /&gt;
A validación das entradas dos usuarios é un procedimento que convén levar a cabo de forma xeralizada para calquera información nova que deba introducir o usuario. O saneamento dos datos consiste en verificar que é seguro a súa utilización en certo contexto; no noso caso deberemos sanear os datos para asegurarnos de que podemos empregarlos como parte dunha consulta SQL.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, a cadea que introduce o usuario como contrasinal no exemplo inicial, &amp;#039;&amp;#039;&amp;#039;&amp;amp;apos; OR 1;&amp;#039;&amp;#039;&amp;#039; non é segura. Deberemos transformala para poder empregala como parte dunha consulta. Os caracteres que non poden ser admitidos nas consultas como parte dos valores introducidos polos usuarios son principalmente a comiña simple (&amp;#039;&amp;#039;&amp;#039;&amp;amp;apos;&amp;#039;&amp;#039;&amp;#039;), a comiña dobre (&amp;#039;&amp;#039;&amp;#039;&amp;quot;&amp;#039;&amp;#039;&amp;#039;), o punto e coma (&amp;#039;&amp;#039;&amp;#039;;&amp;#039;&amp;#039;&amp;#039;) e a barra inversa (&amp;#039;&amp;#039;&amp;#039;\&amp;#039;&amp;#039;&amp;#039;), aínda que poden variar según o SXBD empregado. Normalmente cada extensión asociada a un SXBD prové unha función axustada aos seus requerimentos para sanear estes valores.&lt;br /&gt;
&lt;br /&gt;
Na extensión MySQLi temos a función &amp;#039;&amp;#039;&amp;#039;[http://www.php.net/manual/es/mysqli.real-escape-string.php mysqli_real_escape_string]&amp;#039;&amp;#039;&amp;#039; (correspondente ao método [http://www.php.net/manual/es/mysqli.real-escape-string.php real_escape_string] da clase mysqli).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$db = new mysqli(&amp;#039;localhost&amp;#039;, &amp;#039;usuario&amp;#039;, &amp;#039;abc123.&amp;#039;, &amp;#039;platega&amp;#039;);&lt;br /&gt;
$nome = $db-&amp;gt;real_escape_string($_REQUEST[&amp;quot;nome&amp;quot;]);&lt;br /&gt;
$contrasinal = $db-&amp;gt;real_escape_string($_REQUEST[&amp;quot;contrasinal&amp;quot;]);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na extensión PDO temos o método &amp;#039;&amp;#039;&amp;#039;[http://es1.php.net/manual/es/pdo.quote.php quote]&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$db = new PDO(&amp;quot;mysql:host=localhost;dbname=platega&amp;quot;, &amp;quot;usuario&amp;quot;, &amp;quot;abc123.&amp;quot;);&lt;br /&gt;
$nome = $db-&amp;gt;quote($_REQUEST[&amp;quot;nome&amp;quot;]);&lt;br /&gt;
$contrasinal = $db-&amp;gt;quote($_REQUEST[&amp;quot;contrasinal&amp;quot;]);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nalgúns casos pode suceder que a extensión do SXBD que empreguemos non implemente unha función ou método adecuado para sanear a información que introduza o usuario. Por exemplo, o controlador ODBC de PDO non o contempla. Unha alternativa é empregar un [http://docs.php.net/manual/es/filter.filters.sanitize.php filtro de saneamento] proporcionado pola extensión [http://docs.php.net/manual/es/book.filter.php Filter] da que falamos antes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$nome = filter_var($_REQUEST[&amp;quot;nome&amp;quot;], FILTER_SANITIZE_MAGIC_QUOTES);&lt;br /&gt;
$contrasinal = filter_var($_REQUEST[&amp;quot;contrasinal&amp;quot;], FILTER_SANITIZE_MAGIC_QUOTES);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Empregar &amp;quot;listas brancas&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Cando os valores que introducen os usuarios deben limitarse a un grupo de opcións, é mellor asegurarse de que a súa entrada se corresponde con un dos valores válidos.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, se a táboa sobre a que imos facer a consulta pode ser, en función dun valor aportado polo usuario, &amp;quot;Empregados&amp;quot; ou &amp;quot;Clientes&amp;quot;, poderíamos facer algo como o seguinte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$taboas = array(&amp;quot;empregados&amp;quot; =&amp;gt; &amp;quot;Empregados&amp;quot;,&lt;br /&gt;
                &amp;quot;persoal&amp;quot; =&amp;gt; &amp;quot;Empregados&amp;quot;,&lt;br /&gt;
                &amp;quot;clientes&amp;quot; =&amp;gt; &amp;quot;Clientes&amp;quot;,&lt;br /&gt;
                &amp;quot;persoas&amp;quot; =&amp;gt; &amp;quot;Clientes&amp;quot;,&lt;br /&gt;
                &amp;quot;por_defecto&amp;quot; =&amp;gt; &amp;quot;Clientes&amp;quot;);&lt;br /&gt;
if(isset($taboas[$_REQUEST[&amp;quot;taboa&amp;quot;]]) $taboa = $taboas[$_REQUEST[&amp;quot;taboa&amp;quot;]];&lt;br /&gt;
else $taboa = $taboas[&amp;quot;por_defecto&amp;quot;];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Empregando o operador &amp;#039;&amp;#039;&amp;#039;?&amp;#039;&amp;#039;&amp;#039;, pode simplificarse a expresión condicional anterior.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$taboas = array(&amp;quot;empregados&amp;quot; =&amp;gt; &amp;quot;Empregados&amp;quot;,&lt;br /&gt;
                &amp;quot;persoal&amp;quot; =&amp;gt; &amp;quot;Empregados&amp;quot;,&lt;br /&gt;
                &amp;quot;clientes&amp;quot; =&amp;gt; &amp;quot;Clientes&amp;quot;,&lt;br /&gt;
                &amp;quot;persoas&amp;quot; =&amp;gt; &amp;quot;Clientes&amp;quot;,&lt;br /&gt;
                &amp;quot;por_defecto&amp;quot; =&amp;gt; &amp;quot;Clientes&amp;quot;);&lt;br /&gt;
$taboa = $taboas[$_REQUEST[&amp;quot;taboa&amp;quot;]] ?: $taboas[&amp;quot;por_defecto&amp;quot;];&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--[[Usuario:Vlourido|Víctor Lourido]] 21:26 18 jul 2013 (CEST)&lt;/div&gt;</summary>
		<author><name>Vlourido</name></author>
	</entry>
</feed>