SQL InjectionSQL Injection é um ataque que consiste na inserção (conhecido como injeção) de uma query via aplicação web. A Locaweb sempre toma todas as precauções em relação a atualizações para evitar quaisquer brechas de segurança nos sites hospedados.Entretanto às vezes surgem vulnerabilidades que são exploradas através de programação, de nada adiantando as precauções que tomamos. Tais vulnerabilidades estão presentes em códigos (ASP, PHP, etc.) colocados pelos próprios clientes. Este é o caso da "SQL Injection", brecha através da qual um invasor pode executar queries ou statements arbitrários numa base relacional via "injeção" de comandos em campos de formulários. Atualmente existem 5 tipos de SQLi (injeção de sql)Abaixo segue detalhes sobre cada uma:- Poorly Filtered Strings Ataques de SQLi baseado em strings mal-filtradas, são causados quando a entrada que o usuário faz ao sistema não é escapada. Isto significa que um usuário pode inserir uma variável que pode ser transmitida com uma instrução SQL, resultando em manipulação de entrada de dados pelo usuário final (através do navegador). Exemplo: $pass = $_GET['pass']; $password = mysql_query("SELECT password FROM users WHERE password = '". $pass . "';"); ' OR 1 = 1 /* Segue o resultado: SELECT password FROM users WHERE password = '' OR 1 = 1 /* - Incorrect type handling Manipulação de tipo incorreto, ocorre quando uma entrada não é verificada para restrições desse tipo. Um exemplo é quando o campo ID é númerico, mas não há nenhuma filtragem para validar estes input, is_numeric() onde deve sempre ser utilizado quando for explicitamente um número. Este exemplo não esta vulnerável a este tipo de ataque: (is_numeric($_GET['id'])) ? $id = $_GET['id'] : $id = 1; $news = mysql_query( "SELECT * FROM `news` WHERE `id` = $id ORDER BY `id` DESC LIMIT 0,3" ); - Signature Evasion Muitas injeções de SQL serão bloqueadas por sistemas de detecção de intrusão e prevencão de intrusos (chamados de IDS/IPS), usando regras para detectá-los. Os mais conhecidos são "Mod_Security" e o "Snort", onde existem muitos métodos de bypassar estas proteções. Segue descrição de algumas delas abaixo: Different Encondig Codificação diferente pode ser facilmente explorada usando o próprio enconding da URL: NULL OR 1 = 1/* Seria mascarada como: NULL+OR+1%3D1%2F%2A Assim, o sistema de detecção de intruso (IDS) não pode registrar este ataque, e então iremos bypassar esta assinatura. White Space Multiplicity, ou multiplicidade de espaços em branco. É comum alguns bancos de dados checar algumas strings como "OR" (OR seguido por um espaço), podemos bypassar estas assinaturas utilizando técnicas de espaçamento diferente do padrão ou adicionando uma nova linha seguida de espaço, como no exemplo abaixo: NULL OR 'value'='value'/* O espaço em branco dentro da injeção será substituída por uma nova linha: NULL%0aOR%0a'value'='value'/* NULL OR 'value'='value'/* No MySQL os comentários podem ser inseridos em uma consulta usando sintaxe de C /* para iniciar o comentário e */ para encerrá-lo. Podemos usar estes comentários para evitar a detecção das assinaturas. Este exemplo pode ser facilmente detectado pelo IPS (Sistema de Prevenção de Invasão). NULL UNION ALL SELECT user,pass, FROM user_db WHERE user LIKE '%admin%/* NULL/**/UNION/**/ALL/**/SELECT/**/user,pass,/**/FROM/**/user_db/**/WHERE/**/uid/**/=/*evade*/'1'// - Filter Bypassing Em alguns casos, filtros como addslashes() e magic_quotes_gpc podem ser bypassado quando o servidor de SQL vulnerável usa um determinado conjunto de caracteres GBK (caracteres usado pela população da República da China). Neste charset o valor hex de 0xbf27 não é um multi-byte caracter, entretanto o valor é 0xbf5c. Se os caracteres são construídos como caracteres de byte unico 0xbf5c é 0xbf (¿) seguido por 0x5c ( / ); ¿\. E 0xbf27 é 0x27 ('), onde teremos um 0xbf(¿); ¿', ou seja - acontece quando a aspas simples é escapada com uma barra invertida(). <?php $url = "http://www.victimsite.com/login.php"; $ref = "http://www.victimsite.com/index.php"; $session = "PHPSESSID=abcdef01234567890abcdef01"; $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $url ); curl_setopt( $ch, CURLOPT_REFERER, $ref ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, TRUE ); curl_setopt( $ch, CURLOPT_COOKIE, $session ); curl_setopt( $ch, CURLOPT_POST, TRUE ); curl_setopt( $ch, CURLOPT_POSTFIELDS, "username=" . chr(0xbf) . chr(0x27) . "OR 1=1/*&submit=1" ); $data = curl_exec( $ch ); print( $data ); curl_close( $ch ); ?> - Blind SQL Injection: Grande maioria dos ambientes seguros de SQL não permitem que você veja a saída na forma de mensagens de erros , ou seja a aplicação web é vulnerável a uma injeção de SQL, mas os resultados não são visíveis para o atacante. Exemplo: SELECT booktitle FROM booklist WHERE bookId = 'OOk14cd' AND '1'='1'; Vai resultar em uma página normal: SELECT booktitle FROM booklist WHERE bookId = 'OOk14cd' AND '1'='2'; Agora teremos o resultado diferente e podemos manipular qualquer resultado quando: SELECT 1/0 FROM users WHERE username='ooo'; Se a página for vulnerável, teremos uma resposta diferente e o ataque pode começar a ser construído. 3. Impacto do SQL Injection: Esse tipo de ataque pode comprometer toda a estrutura do banco, se não for contido antes da publicação da aplicação ou quando atualizado, se for feita uma checagem se existe ou não algum tipo de vulnerabilidade SQLi. Um ponto extremamente crítico é quando o usuário é atacado através de SQLi onde no local é usado privilégios administrador. 4. Prevenção: Como se proteger?De acordo com a OWASP as melhores práticas para se previnir de um ataque de SQLi são: Parametrização das consultas
Usar "stored procedures"
Escapar toda entrada fornecida pelo usuário
Limitar privilégios aos acessos
Usando a função addslashes() tem o mesmo efeito que habilitar magic quotes, porém só aplica onde for conveniente.
O que ela faz é colocar um caracter de escapa antes das aspas simples ou dupla, antes da barra invertida e do caracter NULL.
Usar 'prepared statements' ao invés do próprio código SQL atribuíndo todas as outras medidas de prevenção usar esta, nos daria mais performace e segurança, além de ser mais simples de ler e escrever. Porem só pode ser usado em SELECT, INSERT, UPDATE, REPLACE, DELETE e CREATE TABLE. $login = $_GET['login'] $query = "SELECT * FROM registos WHERE login = '$login'"; Ficaria assim: $query = "SELECT * FROM registos WHERE login = OR 1"; Recomendamos Limitar Privilégios das contas com acesso ao DB. É importante manter apenas os privilégios e acessos necessários. É comum muitas permissões serem dadas para resolver problemas de funcionalidade, muito parecido ao chmod 777 no linux. Escapar toda entrada fornecida pelo usuario
Escapar toda entrada fornecida pelo usuário antes de colocá-la em uma consulta.
Todo DMBS (database management system) suporta escapar caracteres.
Para se proteger do SQL Injection verifique se todo parâmetro passado para o site é tratado antes que seja concatenado na query. Por exemplo, nunca faça simplesmente: // ASP consulta = "DELETE FROM tabela WHERE id_tabela = " & Request.Form("id") // PHP $consulta = "DELETE FROM tabela WHERE id_tabela = " . $_POST[id]; Em vez disso, trate primeiro o Request.Form("id") ou $_POST[id], como neste exemplo: //ASP If IsNumeric(Request.Form("id")) Then consulta = "DELETE FROM tabela WHERE id_tabela = " & Request.Form("id") Else Response.Write "Dados Inválidos" Response.End End If //PHP if (is_numeric($_POST[id])) { $consulta = "DELETE FROM tabela WHERE id_tabela = " . $_POST[id]; } else { die("Dados inválidos"); } No ASP poderíamos ter especificado simplesmente o Request("id"), entretanto este não valida se os dados foram passados pelo método GET (parâmetro especificado na URL) ou POST (dados enviados por formulário que não aparecem na URL), então a pessoa mal-intencionada poderia passar o "id" pela URL. Ao invés disso use: Request.QueryString("id") -> se o "id" tiver que ser passado via GET Request.Form("id") -> se o "id" tiver que ser passado via POST No PHP faça a mesma coisa, ao invés de simplesmente validar $id, valide: $_GET[id] -> se o "id" tiver que ser passado via GET $_POST[id] -> se o "id" tiver que ser passado via POST Para campos com strings é aconselhável checar pelos caracteres: " (aspas duplas) ' (aspas simples) (espaços) ; (ponto e vírgula) = (sinal de igual) < (sinal de menor que) > (sinal de maior que) ! (ponto de exclamação) -- (dois hifens, indica início de comentário em alguns bancos) # (sustenido ou jogo-da-velha, indica início de comentário em alguns bancos) // (duas barras, indica início de comentário em alguns bancos) - SELECT - INSERT - UPDATE - DELETE - WHERE - JOIN - LEFT - INNER - NOT - IN - LIKE - TRUNCATE - DROP - CREATE - ALTER - DELIMITER OBS: O código de programação mencionado acima é uma sugestão, portanto é aconselhável um tratamento mais sofisticado que pode ser encontrado fácilmente pela Internet. Contamos com sua compreensão para o fato de que a Locaweb não pode se responsabilizar por apresentar mais detalhes a respeito de sua implementação e utilização. Para mais informações, sugerimos que entre em contato com o seu desenvolvedor, pois tal conhecimento é aberto e de domínio de profissionais técnicos. |
http://www.youtube.com/watch?feature=player_embedded&v=fiy7WvyIGds
Fora de tópico Mostrar Código Esconder Código Mostrar EmoticonEsconder Emoticon