Sophie

Sophie

distrib > Mandriva > 2008.1 > i586 > by-pkgid > 703d980c580707c382b4e43e25965bc5 > files > 12141

php-manual-pt_BR-5.2.4-1mdv2008.1.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML
><HEAD
><TITLE
>Injeção de SQL</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK
REL="HOME"
TITLE="Manual do PHP"
HREF="index.html"><LINK
REL="UP"
TITLE="Segurança de Bancos de Dados"
HREF="security.database.html"><LINK
REL="PREVIOUS"
TITLE="Modelo de Armazenamento Criptografado"
HREF="security.database.storage.html"><LINK
REL="NEXT"
TITLE="Relatando Erros"
HREF="security.errors.html"><META
HTTP-EQUIV="Content-type"
CONTENT="text/html; charset=UTF-8"></HEAD
><BODY
CLASS="sect1"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Manual do PHP</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="security.database.storage.html"
ACCESSKEY="P"
>Anterior</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>Capítulo 27. Segurança de Bancos de Dados</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="security.errors.html"
ACCESSKEY="N"
>Próxima</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="sect1"
><H1
CLASS="sect1"
><A
NAME="security.database.sql-injection"
>Injeção de SQL</A
></H1
><P
>&#13;     Muitos desenvolvedores web não sabem de como consultas SQL podem ser manipuladas,
     e presumem que uma consulta de SQL é um comando confiável. Significa que consultas
     SQL são capazes de passar indetectado por controles de acesso, portanto desviando
     da autenticação padrão e teestes de autorização, e algumas vezes consultas SQL podem
     permitir acesso à comando em nível do sistema operacional do servidor.
    </P
><P
>&#13;     Injeção direta de comandos SQL é uma técnica onde um atacante cria ou
     alterar comandos SQL existentes para expor dados escondidos, ou sobrescrever
     dados valiosos, ou ainda executar comandos de sistema perigosos no servidor.
     Isso é possível se a aplicação pegar a entrada do usuário e combinar
     com parâmetros estáticos para montar uma consulta SQL. Os exemplos
     a seguir são baseados em estórias verdadeiras, infelizmente.
    </P
><P
>&#13;     Devido a faulta de validação de entrada e conectar ao banco de dados
     usando o super-usuário ou um usuário que pode criar usuário, o atacante
     pode criar um super-usuário no seu banco de dados.
     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN6467"
></A
><P
><B
>Exemplo 27-2. 
       Dividinto o result set em páginas ... e criando super-usuários
       (PostgreSQL)
      </B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /><br />$offset </font><font color="#007700">= </font><font color="#0000BB">$argv</font><font color="#007700">[</font><font color="#0000BB">0</font><font color="#007700">]; </font><font color="#FF8000">// Cuidado, sem validação de entrada!<br /></font><font color="#0000BB">$query&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#DD0000">"SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;"</font><font color="#007700">;<br /></font><font color="#0000BB">$result </font><font color="#007700">= </font><font color="#0000BB">pg_query</font><font color="#007700">(</font><font color="#0000BB">$conn</font><font color="#007700">, </font><font color="#0000BB">$query</font><font color="#007700">);<br /><br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
      Usuário normais clicam nos links 'próxima' e 'anterior' onde <CODE
CLASS="varname"
>$offset</CODE
>
      é codificado na URL. O script espera que o valor de
      <CODE
CLASS="varname"
>$offset</CODE
> seja um número decimal. No entanto, e se alguém tentar
      invadir acrescentando a forma codificada por <A
HREF="function.urlencode.html"
><B
CLASS="function"
>urlencode()</B
></A
> da
      URL seguinte:
      <DIV
CLASS="informalexample"
><P
></P
><A
NAME="AEN6473"
></A
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="sql"
>0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
    select 'crack', usesysid, 't','t','crack'
    from pg_shadow where usename='postgres';
--</PRE
></TD
></TR
></TABLE
><P
></P
></DIV
>
      Se isso acontecesse, então o script daria de presente acesso de super-usuário ao
      atacante. Pareceba que <TT
CLASS="literal"
>0;</TT
> é para fornecer uma deslocamento válido
      para a consulta original e terminá-la.
    </P
><DIV
CLASS="note"
><BLOCKQUOTE
CLASS="note"
><P
><B
>Nota: </B
>
      É uma técnica comum forçar o avaliador de SQL ignorar o resto da consulta
      escrita pelo desenvolvedor com <TT
CLASS="literal"
>--</TT
>, que é o sinal de
      comentário no SQL.
     </P
></BLOCKQUOTE
></DIV
><P
>&#13;     Uma maneira de ganhar senha é desviar suas páginas de resultado de busca.
     A única coisa que o atacante precisa fazer é ver se alguma variável enviada
     é usada em um comando SQL que não é tratado corretamente. Esses filtros podem ser
     configurados de forma a personalizar cláusulas <TT
CLASS="literal"
>WHERE, ORDER BY,
     LIMIT</TT
> e <TT
CLASS="literal"
>OFFSET</TT
> em comandos <TT
CLASS="literal"
>SELECT</TT
>
     Se seu banco de dados suporta a funcionalidade <TT
CLASS="literal"
>UNION</TT
>,
     o atacante pode tentar adicionar uma consulta inteira à consulta original para
     listar senhas de uma tabela arbitrária. Uso de campos de senha criptografados é
     fortemente incentivado.
     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN6484"
></A
><P
><B
>Exemplo 27-3. 
       Listando artigos ... e algumas senhas (qualquer banco de dados)
      </B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /><br />$query&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#DD0000">"SELECT id, name, inserted, size FROM products<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHERE size = '$size'<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ORDER BY $order LIMIT $limit, $offset;"</font><font color="#007700">;<br /></font><font color="#0000BB">$result </font><font color="#007700">= </font><font color="#0000BB">odbc_exec</font><font color="#007700">(</font><font color="#0000BB">$conn</font><font color="#007700">, </font><font color="#0000BB">$query</font><font color="#007700">);<br /><br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
     A parte estática da consulta pode ser combinada com outro comando
     <TT
CLASS="literal"
>SELECT</TT
> que revela todas as senhas:
     <DIV
CLASS="informalexample"
><P
></P
><A
NAME="AEN6488"
></A
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><PRE
CLASS="sql"
>'
union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable;
--</PRE
></TD
></TR
></TABLE
><P
></P
></DIV
>
     Se essa consulta (brincando com <TT
CLASS="literal"
>'</TT
> e
     <TT
CLASS="literal"
>--</TT
>) for atribuída para uma das variáveis usadas em
     <CODE
CLASS="varname"
>$query</CODE
>, a besta da consulta acorda.
    </P
><P
>&#13;     Comandos de UPDATE também são suscetíveis à ataques. Essas consultas também
     são ameaçadas por cortes e acréscimos de uma nova consulta. Mas o
     atacante pode brincar com a cláusula <TT
CLASS="literal"
>SET</TT
>. Nesse caso
     ele precisa estar de posse de alguma informação sobre o esquema para manipular a
     consulta com sucesso. Isso pode ser conseguido examinando so nomes das variáveis do
     formulário, ou simplesmente por força bruta. Não existem muitas convensões para
     campos guardando senhas ou nomes de usuários.
     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN6495"
></A
><P
><B
>Exemplo 27-4. 
      De reinicializando uma senha ... para ganhando mais privilégios (qualquer banco de dados)
     </B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br />$query </font><font color="#007700">= </font><font color="#DD0000">"UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';"</font><font color="#007700">;<br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
     Mas um usuário malicioso envia o valor
     <TT
CLASS="literal"
>' or uid like'%admin%'; --</TT
> para <CODE
CLASS="varname"
>$uid</CODE
> para
     mudar a senha do administrador, ou simplesmente configura <CODE
CLASS="varname"
>$pwd</CODE
> para
     <TT
CLASS="literal"
>"hehehe', admin='yes', trusted=100 "</TT
> (com um espaço
     sobrando) para ganha mais privilégios. Então, a consulta ficará torta:
     <DIV
CLASS="informalexample"
><P
></P
><A
NAME="AEN6502"
></A
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /><br /></font><font color="#FF8000">// $uid == ' or uid like'%admin%'; --<br /></font><font color="#0000BB">$query </font><font color="#007700">= </font><font color="#DD0000">"UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --"</font><font color="#007700">;<br /><br /></font><font color="#FF8000">// $pwd == "hehehe', admin='yes', trusted=100 "<br /></font><font color="#0000BB">$query </font><font color="#007700">= </font><font color="#DD0000">"UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE<br />...;"</font><font color="#007700">;<br /><br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
><P
></P
></DIV
>
    </P
><P
>&#13;     Um exemplo assustado de como comandos do sistema operacional podem ser acessados
     em alguns bancos de dados.
     <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN6505"
></A
><P
><B
>Exemplo 27-5. Atacando o sistema operacional do servidor (MSSQL Server)</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /><br />$query&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#DD0000">"SELECT * FROM products WHERE id LIKE '%$prod%'"</font><font color="#007700">;<br /></font><font color="#0000BB">$result </font><font color="#007700">= </font><font color="#0000BB">mssql_query</font><font color="#007700">(</font><font color="#0000BB">$query</font><font color="#007700">);<br /><br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
     Se o atacante enviar o valor
     <TT
CLASS="literal"
>a%' exec master..xp_cmdshell 'net user test testpass /ADD' --</TT
>
     para <CODE
CLASS="varname"
>$prod</CODE
>, então <CODE
CLASS="varname"
>$query</CODE
> terá o valor:
     <DIV
CLASS="informalexample"
><P
></P
><A
NAME="AEN6511"
></A
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /><br />$query&nbsp;&nbsp;</font><font color="#007700">= </font><font color="#DD0000">"SELECT * FROM products<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHERE id LIKE '%a%'<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec master..xp_cmdshell 'net user test testpass /ADD'--"</font><font color="#007700">;<br /></font><font color="#0000BB">$result </font><font color="#007700">= </font><font color="#0000BB">mssql_query</font><font color="#007700">(</font><font color="#0000BB">$query</font><font color="#007700">);<br /><br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
><P
></P
></DIV
>
     MSSQL Server executa os comandos SQL em um em um lote, incluindo um comando
     para adicionar um novo usuário para o banco de dados de contas locais. Se essa aplicação
     estiver sendo executada como <TT
CLASS="literal"
>sa</TT
> e o serviço MSSQLSERVER estiver
     sendo executado com privilégios suficientes, o atacante teria agora uma
     conta com a qual poderia acessar essa máquina.
    </P
><DIV
CLASS="note"
><BLOCKQUOTE
CLASS="note"
><P
><B
>Nota: </B
>
      Alguns dos exemplos acima estão ligados à bancos específicos. Isso não
      significa que um ataque similar é impossível contra outros produtos.
      Seu servidor de banco de dados pode ter uma vulnerabilidade similar de outa maneira.
     </P
></BLOCKQUOTE
></DIV
><DIV
CLASS="sect2"
><H2
CLASS="sect2"
><A
NAME="security.database.avoiding"
>Técnicas para Evitar Ataques</A
></H2
><P
>&#13;      Você pode dizer que o atacante precisa possuir um pouco de informação
      sobre o esquema de banco de dados na maioria dos exemplo. Você tem razão, mas
      você nunca sabe quando e como isso pode ser obtido e, se acontecer, seu
      banco de dados pode ficar exposto. Se você estiver usando um pacote
      open source publicamente disponível para lidar com banco de deados, que pode pertencer
      a um sistema de controle de conteúdo ou forum, os invasores facilmente produzem
      uma cópia de parte de seu código. Também pode ser um risco de segurança se
      este for for mal desenhado.
     </P
><P
>&#13;      Esses ataques se baseam principalmente em explorar falhas no código escrito
      sem se preocupar com segurança. Nunca confie em nenhum tipo de entrada, especialmente
      aquela que vem do lado do cliente, mesmo que venha de um combobox,
      um campo de entrada escondido (hidden) ou um cookie. O primeiro exemplo mostra
      como uma consulta inocente pode causar desastres.
     </P
><P
></P
><UL
><LI
><P
>&#13;        Nunca conecte ao banco de dados como um super-usuário ou como o dono do banco
        de dados. Sem use usuários personalidados com privilégios bem limitados.
       </P
></LI
><LI
><P
>&#13;        Verifique se uma entrada qualquer tem o tipo de dados experado. O PHP tem
        um grande número de funções de validação de entrada, desde as mais simples
        encontrada em <A
HREF="missing-stuff.html#ref.var"
>Funções de Variáveis</A
> e
        em <A
HREF="ref.ctype.html"
>Funções de Tipo de Caracteres</A
>
        (ex.: <A
HREF="function.is-numeric.html"
><B
CLASS="function"
>is_numeric()</B
></A
>, <A
HREF="function.ctype-digit.html"
><B
CLASS="function"
>ctype_digit()</B
></A
>
        respectivamente) além de usar
        o suporte à
        <A
HREF="ref.pcre.html"
>Expressões Regulares Compatível com Perl</A
>.
       </P
></LI
><LI
><P
>&#13;        Se a aplicação espera por entradas numéricas, considere verificar os dados
        com a função <A
HREF="function.is-numeric.html"
><B
CLASS="function"
>is_numeric()</B
></A
>, ou silenciosamente mudar o seu
        tipo usando <A
HREF="function.settype.html"
><B
CLASS="function"
>settype()</B
></A
>, ou usar a representação númeria
        usando a função <A
HREF="function.sprintf.html"
><B
CLASS="function"
>sprintf()</B
></A
>.
        <TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
CLASS="EXAMPLE"
><TR
><TD
><DIV
CLASS="example"
><A
NAME="AEN6535"
></A
><P
><B
>Exemplo 27-6. Uma maneira mais segura para compor consultas de paginação</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
CELLPADDING="5"
><TR
><TD
><code><font color="#000000">
<font color="#0000BB">&lt;?php<br /><br />settype</font><font color="#007700">(</font><font color="#0000BB">$offset</font><font color="#007700">, </font><font color="#DD0000">'integer'</font><font color="#007700">);<br /></font><font color="#0000BB">$query </font><font color="#007700">= </font><font color="#DD0000">"SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;"</font><font color="#007700">;<br /><br /></font><font color="#FF8000">// por favor perceba o %d na string de formato, usando %s seria inútil<br /></font><font color="#0000BB">$query </font><font color="#007700">= </font><font color="#0000BB">sprintf</font><font color="#007700">(</font><font color="#DD0000">"SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;"</font><font color="#007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#0000BB">$offset</font><font color="#007700">);<br /><br /></font><font color="#0000BB">?&gt;</font>
</font>
</code></TD
></TR
></TABLE
></DIV
></TD
></TR
></TABLE
>
       </P
></LI
><LI
><P
>&#13;        Adicione aspas para cada valor não numérico especificado pelo usuário que
        será passado para o banco de dados com as funções de caracteres de escape (ex.:
        <A
HREF="function.mysql-escape-string.html"
><B
CLASS="function"
>mysql_escape_string()</B
></A
>,
        <B
CLASS="function"
>sql_escape_string()</B
>, etc.). Se um mecanismo de
        escape de caracter específico par ao seu banco de dados não for disponível, as
        funções <A
HREF="function.addslashes.html"
><B
CLASS="function"
>addslashes()</B
></A
> e <A
HREF="function.str-replace.html"
><B
CLASS="function"
>str_replace()</B
></A
>
        podem ser úteis (dependendo do tipo de banco de dados).
        Veja o <A
HREF="security.database.storage.html"
>o primeiro exemplo</A
>.
        Como o exemplo mostra, adicionar aspas para a parte estática da consulta
        não é suficiente, fazendo com que a consulta seja facilmente atacada.
       </P
></LI
><LI
><P
>&#13;        Não imprima qualquer informação específica do banco de dados, especialmente
        sobre o esquema, custe o que custar. Veja também <A
HREF="security.errors.html"
>Relatório de Erros</A
> e <A
HREF="ref.errorfunc.html"
>Funções de Tratamento e Relatório de Erros</A
>.
       </P
></LI
><LI
><P
>&#13;        Você pode usar stored procedures e cursores previamente definidas para abstrair
        acesso aos dados para que os usuário não acessem tabelas ou view diretamente, mas
        essa solução pode ter outros impactos.
       </P
></LI
></UL
><P
>&#13;      Além disso, você ganha em relatar consultas ou dentro do script
      ou no próprio banco de dados, se esse suportar. Obviamente, o relatório é
      para previnir qualquer tentativa danosa, mas pode ser útil para ajudar a rastrar
      qual aplicação foi atacada. O resitro não é útil em si, mas
      atráves da informação que ele contem. Mais detalhes geralmente é melhor que menos.
     </P
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="security.database.storage.html"
ACCESSKEY="P"
>Anterior</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>Principal</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="security.errors.html"
ACCESSKEY="N"
>Próxima</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Modelo de Armazenamento Criptografado</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="security.database.html"
ACCESSKEY="U"
>Acima</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Relatando Erros</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>