Proteja o servidor web e o banco de dados com mod_selinux e SEPostgreSQL REDES Um muro para a Web O módulo mod_selinux do Apache ajuda a tapar os buracos que vão além do controle do firewall. por Thorsten Scherf A plicativos web são um vetor de ataque popular na invasão de sistemas (figura 1). Sistemas de firewall tradicionais não conseguem proteger contra ataques de injeção SQL e cross-site scripting, o que significa que um erro em um aplicativo web pode ter consequências fatais. Por um lado, os aplicativos web são extremamente dinâmicos e complexos; por outro lado, o desenvolvedor de um aplicativo web não pode adivinhar o futuro para antecipar e eliminar perigos em potencial antes que eles ocorram. 64 ModSecurity O módulo ModSecurity do Apache [1], que usa regras para filtrar conteúdo suspeito nos dados recebidos, tornou-se uma ferramenta popular para impedir a entrada de intrusos. Pacotes de dados que não correspondem aos padrões permitidos são descartados. Essa abordagem consegue barrar uma grande porcentagem de pacotes maliciosos antes que cheguem ao aplicativo web, mas o que acontece com aqueles que conseguem passar? Sistemas que dependem de casamento de padrões detectam apenas os padrões conhecidos e, portanto, falham ao encontrar algo desconhecido. Além disso, uma vez que o intruso já tenha entrado, as possibilidades de estender o ataque são infinitas. Com relação ao sistema operacional, os administradores conseguem resolver esse problema com a introdução de um esquema MAC (Mandatory Access Control – Controle Obrigatório de Acesso), que permite o ajuste das permissões empregadas a recursos específicos. Nos últimos http://www.linuxmagazine.com.br mod_selinux | SEGURANÇA Site Outros 7% 47% 33% 67% 53% 93% 2006 2007 2008 Figura 1A porcentagem de ataques de rede direcionados a servidores web aumenta a cada ano. (Fonte: Little Earth Corporation) anos, o SELinux estabeleceu-se como uma importante ferramenta para implantar MACs em ambientes de alta segurança, mas o problema é que o SE apenas restringe o acesso aos recursos do sistema. Os novos ataques concentram-se em servidores de aplicativos web e bancos de dados. O SEPostgreSQL (Security Enhanced PostgreSQL) [2] e o mod_selinux [3] ampliam a proteção oferecida pelo SELinux a objetos de bancos de dados e aplicativos web. Como funciona O SEPostgreSQL é uma extensão do popular sistema de banco de dados PostgreSQL que suporta a atribuição de um contexto de segurança SELinux a objetos individuais. Em um banco de dados PostgreSQL clássico, o usuário se conecta usando um nome de usuário e uma senha. Com isso, ele tem acesso a todos os objetos disponíveis para sua conta. Com o SEPostgreSQL, o socket do cliente recebe um contexto de segurança que pode ser de um usuário buscando acesso ou o contexto do processo que o está acessando. O administrador do SEPostgreSQL pode atribuir rótulos de segurança a tabelas individuais e a qualquer objeto que elas contenham e, por isso, as regras centralizadas do SELinux Linux Magazine #63 | Fevereiro de 2010 definem qual usuário ou processo pode ou não acessar cada um dos objetos do banco de dados. Como no caso típico do SELinux, dois controles de acesso devem ser negociados antes que o usuário ou o processo tenha acesso ao objeto solicitado. Primeiro, as credenciais são verificadas pelo sistema de autenticação do banco de dados; em um segundo passo, o sistema verifica se o rótulo de segurança do socket de acesso possui privilégios suficientes para o objeto requisitado. Esses dois testes precisam ser efetuados com sucesso para que o banco de dados sirva o objeto requisitado. O administrador do banco de dados também só pode acessar um objeto específico caso o administrador de segurança tenha dado autorização explícita a esse acesso por meio de uma regra do SELinux. Diferentemente de objetos de sistema tradicionais, tais como arquivos e diretórios, onde o contexto de segurança é armazenado em seus atributos, o SEPostgreSQL armazena o contexto de segurança de um objeto do banco de dados em um catálogo de sistema especial. Catálogos de sistema de bancos de dados relacio- Listagem 1: Arquivo /etc/httpd/conf.d/mod_selinux.conf 01 02 03 04 05 06 07 <Directory “/var/www/html”> # HTTP Basic Authentication AuthType Basic AuthName “Secret Zone” AuthUserFile /var/www/htpasswd Require valid-user </Directory> Listagem 2: Arquivo /etc/httpd/conf.d/mod_selinux.conf 01 02 03 04 05 06 07 ### O mod_selinux.conf pode acessar um ### arquivo local para mapear usuários ### a contextos de segurança selinuxDomainMap /var/www/mod_selinux.map selinuxDomainVal anon_webapp_t:s0 selinuxDomainEnv SELINUX_DOMAIN 65 SEGURANÇA | mod_selinux Listagem 3: Arquivo /var/www/mod_selinux.map 01 02 03 04 foo bar _anonymous__ * *:s0:c0 *:s0:c1 anon_webapp_t:s0 user_webapp_t:s0 Listagem 4: Comando chcat 01 # chcat -L 02 s0 03 s0-s0:c0.c255 SystemLow-SystemHigh 04 s0:c0.c255 SystemHigh 05 s0:c1 Marketing 06 s0:c2 Payroll 07 s0:c3 IT 08 09 chcat +IT /var/www/virtual/www1/index.html 10 ls -lZ /var/www/virtual/www1/index.html 11 -rw-rw-r-- root apache root:object_r:httpd_sys_content_t:IT /var /www/virtual/www1/index.html nais geralmente incluem dados de esquema e outras metainformações. O SEPostgreSQL introduz um outro catálogo intitulado sg_security e o usa para armazenar o mapeamento entre o contexto de segurança de um objeto e o OID (Object Identifier – Identificador do Objeto) correspondente. Quando um novo objeto é criado no banco de dados, ele recebe um OID numérico. O próprio banco de dados faz a resolução do OID para uma string convencional necessária ao contexto de segurança. Módulo mod_selinux O módulo mod_selinux do Apache permite que o administrador inicie diferentes instâncias do servidor web com um contextos de segurança individuais em vez de usar o mesmo contexto para vários processos. O contexto de segurança designado a uma instância de um servidor web depende do usuário que a acessa. O método é semelhante ao login tradicional pelo shell. Após uma autenticação bem-sucedida pelo login ou ssh, o usuário do shell recebe um contexto de segurança. Com isso, ele pode trabalhar no sistema dentro das restrições de segurança desse contexto. Caso o usuário tente fazer algo que não seja permitido pelo contexto, o SELinux impedirá que isso aconteça. No caso do mod_selinux, é o Apache que age como agente ou proxy de um usuário. Se um usuário se conecta à sua conta, o processo do servidor web aplicará o contexto do usuário. Para ver os direitos concedidos a um processo, é possível consultar o servidor de segurança embutido no kernel para conferir os objetos que o usuário pode e não pode acessar. Quando o SEPostgreSQL é usado como back-end de um aplicativo web, os controles de acesso se estendem a objetos individuais dentro do banco de dados. Configuração do mod_selinux Antes de começar a configuração, é necessário instalar o pacote do mod_selinux, já presente nos repositórios da maioria das distribuições GNU/Linux; se sua distribuição não contém uma versão do módulo, é possível baixá-lo do repositório do Projeto Fedora [3]. Depois de terminar a instalação em um sistema Fedora 11, o arquivo mod_selinux.conf estará no diretório /etc/ httpd/conf.d. Contexto Após a instalação do mod_selinux, a próxima pergunta é: “como os usuários receberão o contexto de segurança para um aplicativo web?”. O mod_selinux pode atribuir um contexto de várias maneiras, todas descritas no seu arquivo de configuração. Em primeiro lugar, é preciso informar ao Apache qual o diretório ou local onde a autenticação do usuário é necessária. A listagem 1 mostra um exemplo de autenticação que utiliza um arquivo local com os nomes de usuários e hashes MD5 de suas senhas. Listagem 5: sesearch 01 02 03 04 05 06 07 08 66 # sesearch --allow -s user_webapp_t Found 120 semantic av rules: allow user_webapp_t public_content_t : file { ioctl read getattr lock open} ; allow user_webapp_t public_content_t : dir { ioctl read getattr lock search open } ; allow user_webapp_t public_content_t : lnk_file { read getattr } ; allow user_webapp_t sysctl_kernel_t : file { ioctl read getattr lock open } ; allow user_webapp_t sysctl_kernel_t : dir { ioctl read getattr lock search open } ; ... http://www.linuxmagazine.com.br mod_selinux | SEGURANÇA O comando a seguir adiciona um usuário ao arquivo de senhas: # htpasswd -m /var/www/htpasswd foo A listagem 2 contém mais configurações. A instrução selinuxDomainMap especifica um arquivo local que atribui um contexto de segurança para cada usuário; como alternativa, pode-se usar selinuxDomainVal para estabelecer um contexto padrão. Um arquivo de mapeamento seria semelhante à listagem 3. Após a autenticação, os processos do servidor web para as duas requisições do usuário encontram-se no domínio do SELinux user_webapp_t , com a MLS (Multi-Level Security – Segurança Multi-Nível) do SELinux com sensibilidade de nível s0 e categorias c0 (foo) e c1 (bar) na MCS (Multi-Category Security – Segurança Multi-Categoria). O arquivo dá acesso a objetos que pertencem a essas categorias e que podem acessar o domínio user_webapp_t. As categorias MCS dos objetos de arquivos são determinadas pela ferramenta chcat (listagem 4). Se um usuário não estiver listado no arquivo de mapeamento, só poderá ter acesso por meio do domínio user_webapp_t, a menos que a categoria MCS esteja definida. A ferramenta sesearch informa se o acesso a objetos no domínio user_webapp_t é permitido (listagem 5). Essas regras são adicionadas à política do SELinux através do pacote mod_selinux. pp. Esse pacote é automaticamente carregado após a instalação do mod_ selinux, como confirma a chamada ao semodule: # semodule -l |grep mod_selinux mod_selinux 2.2 Logicamente, é possível adicionar suas próprias regras à política, mas elas precisam estar reunidas em um pacote. Qualquer acesso não autenti- Linux Magazine #63 | Fevereiro de 2010 Listagem 6: Tabela uaccount 01 # su sepgsql 02 # createdb web 03 # psql web 04 ... 05 06 web=# CREATE TABLE uaccount ( 07 web(# uname TEXT PRIMARY KEY, 08 web(# upass TEXT, 09 web(# udomain TEXT 10 web(# ); 11 12 web=# INSERT INTO uaccount VALUES (‘foo’, ‘pass’, ‘user_ webapp_t:s0:c0’); 13 web=# INSERT INTO uaccount VALUES (‘bar’, ‘pass’, ‘user_ webapp_t:s0:c1’); cado ao servidor web é roteado para o domínio anon_webapp_t do SELinux, como especificado no arquivo de mapeamento. Configurando o SEPostgreSQL Na autenticação de usuários em domínios maiores, é preferível armazenar os usuários em um banco de dados, principalmente se o sistema de banco de dados for necessário para hospe- dar seu aplicativo web. O exemplo a seguir usa o SEPostgreSQL como banco de dados. A vantagem é que o administrador pode mapear todos os objetos desse banco de dados para um contexto de segurança, o que não seria possível com outros sistemas de bancos relacionais. Na maioria das distribuições GNU/Linux, é possível usar o repositório de software padrão para a instalação; caso não seja possível, Listagem 7: Arquivo /etc/httpd/conf.d/mod_selinux.conf 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 LoadModule dbd_module modules/mod_dbd.so LoadModule authn_dbd_module modules/mod_authn_dbd.so # Parâmetros para conexão ao banco de dados DBDriver pgsql DBDParams “dbname=web user=apache” # Autenticação por digest <Directory “/var/www/html”> AuthType Digest AuthName “Secret Zone” AuthDigestProvider dbd AuthDBDUserRealmQuery \ “SELECT md5(uname || ‘:’ || $2 || ‘:’ || upass), udomain, \ %s=%s as dummy FROM uaccount WHERE uname = $1” # Mapeamento de contexto do SELinux selinuxDomainEnv AUTHENTICATE_UDOMAIN selinuxDomainVal anon_webapp_t:s0 </Directory> 67 SEGURANÇA | mod_selinux o código-fonte está disponível no Google Code [4]. Após a instalação, é necessário inicializar o banco de dados com os comandos abaixo: # /etc/init.d/sepostgresql initdb # /etc/init.d/sepostgresql start O acesso administrativo ao banco é feito por meio de uma conta padrão (sepgsql) criada pelos comandos acima. Ela permite que o administrador crie um banco de dados inicial para armazenar os objetos do usuário (listagem 6). Com isso, é possível usar o arquivo de configuração mod_selinux.conf para acessar esses objetos na autenticação de usuários pelo aplicativo web. O contexto de segurança correspondente a cada objeto usuário já existe no banco de dados, o que elimina a necessidade de mapeamento. Os comandos necessários para configurar o mod_selinux estão na listagem 7. Em primeiro lugar, é preciso carregar os módulos do Apache neces- Listagem 8: Contexto de Segurança para entradas de bancos de dados 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # su sepgsql # createdb footballdb # psql footballdb Welcome to psql 8.3.7, the PostgreSQL interactive terminal. Type: \copyright for distribution terms \h for help with SQL commands \? for help with psql commands \g or terminate with semicolon to execute query \q to quit footballdb=# footballdb(# footballdb(# footballdb(# footballdb(# footballdb(# CREATE TABLE clubs ( id integer primary key, nome varchar(32), ranking integer, pontos integer ); footballdb=# INSERT INTO clubs (id, nome, ranking, pontos) footballdb-# VALUES (1, ‘Manchester United’, 1, 72); footballdb=# SELECT security_context, * FROM clubs; security_context | id | nome | ranking | pontos ––––––––––––----–+–---+––---–+––-------+––----unconfined_u:object_r:sepgsql_table_t:s0 | 1 | Manchester United | 1 | 72 27 (1 row) 28 29 footballdb=# UPDATE clubs SET security_context = ‘system_u:object_r:public_content_t:s0’ WHERE nome=’Manchester United’; 30 31 footballdb=# SELECT security_context, * FROM clubs; 32 33 security_context | id | nome | ranking | pontos 34 –––––––––––----––+–---+–---––+–------–-+––----35 system_u:object_r:public_content_t:s0 | 1 | Manchester United | 1 | 72 36 (1 row) 68 sários para acessar o banco de dados. Depois, os próximos dois parâmetros especificam os nomes do driver e as credenciais exigidas para acessar o PostgreSQL. Esses parâmetros são seguidos da autenticação do usuário, onde a variável AUTHENTICATE_UDOMAIN é usada para passar os dados de autenticação para o mod_selinux. O usuário que não conseguir se conectar ainda pode usar o contexto de segurança anon_webapp_t como segunda opção. SEPostgreSQL com MAC Como exemplo, as seções a seguir descrevem a configuração do SELinux em um sistema gerenciador de banco de dados relacional usando SEPostgreSQL. A listagem 8 mostra o fluxo esquematizado. Em primeiro lugar, é necessário conectar-se ao SGBD com privilégios de administrador e criar um novo banco de dados – footballdb, neste caso. Depois, use o aplicativo cliente Psql para se conectar ao banco de dados e criar uma nova tabela – clubs neste exemplo. Em seguida, é adicionar uma única entrada à tabela. A primeira declaração SELECT gera essa entrada. Como se pode ver, já há um contexto de segurança. O tipo deste contexto de segurança padrão é sepgsql_table_t para o acesso a partir do domínio unconfined_t. Apenas uma declaração de atualização é necessária para mudar o contexto. O último comando SELECT verifica se a entrada possui agora um novo contexto de segurança. O contexto pode ser aplicado individualmente a colunas, assim como a registros no banco de dados (listagem 9). A listagem 9 mostra uma tabela com dados de funcionários; a ideia é aplicar o contexto de segurança sepgsql_secret_table_t a essa coluna. Os usuários comuns no domínio de usuários do SELinux não têm per- http://www.linuxmagazine.com.br mod_selinux | SEGURANÇA missão para acessá-lo, como confirmam as duas declarações SELECT. O comando SELECT sepgsql_getcon() retorna o contexto de segurança do socket de acesso; neste caso, o domínio de usuário user_t. O último SELECT tenta acessar todas as colunas da tabela de funcionários. Isso causa um erro no SELinux, pois o acesso ao tipo de objeto de banco de dados sepgsql_secret_table_t não é permitido ao domínio user_t. As regras para isso foram acrescentadas ao pacote de políticas sepostgresql-devel.pp, que contém a regra global do SELinux para instalar o SEPostgreSQL. Assim como no mod_selinux, é possível acrescentar suas próprias regras. A página de manual do sepostgresql lista todos os tipos do SELinux suportados e suas respectivas permissões. Para decidir sobre o acesso a objetos no banco de dados, o SEPostgreSQL sempre usa o contexto do socket utilizado pelo cliente para acessá-lo. Esse contexto pode ser o de segurança do processo usado para o acesso (por exemplo, httpd_t) ou o contexto do shell do usuário (user_t, por exemplo). O psql usa uma declaração SELECT sepgsql_getcon() para exibir o contexto do socket que o está acessando. Se o acesso for originado em um servidor Apache ou em outra máquina, em vez da máquina local, o SEPostgreSQL obviamente enxergará somente o contexto do socket de rede usado para acessá-lo. Porém, o uso de rótulos na rede é uma solução elegante, pois suporta túneis IPSec arbitrários entre vários sistemas para estender o contexto de segurança de um processo além das fronteiras da rede. Conclusões Graças ao mod_selinux, agora é possível iniciar processos individuais do servidor web (ou threads individuais, para ser mais exato) com um contexto de segurança individual. Com isso, o administrador pode usar as regras do SELinux para definir os objetos Linux Magazine #63 | Fevereiro de 2010 Listagem 9: Contexto de segurança para colunas 01 foo=# CREATE TABLE employee ( 02 foo(# mid integer primary key, 03 foo(# mname varchar(32), 04 foo(# esalary varchar(32) CONTEXT = ‘system_u:object_r:sepgsql _secret_table_t:s0’ 05 foo(# ); 06 07 foo=# GRANT ALL ON employee TO PUBLIC; 08 09 foo=# SELECT sepgsql_getcon(); 10 sepgsql_getcon 11 ––––––––12 user_u:user_r:user_t:s0 13 (1 row) 14 15 foo=# SELECT * FROM employee; 16 ERROR: SELinux: denied { select } \ 17 scontext=user_u:user_r:user_t:s0 \ 18 tcontext=system_u:object_r:sepgsql_secret_table_t:s0 \ 19 tclass=db_column name=employee.esalary que têm permissão de acesso a essas threads individuais. Examinando mais atentamente a documentação, notase que há muitas outras aplicações para isso. Por exemplo, é possível usar o mod_selinux para iniciar hosts virtuais individuais do Apache com seus próprios contextos de segurança, ou definir um contexto com base no endereço IP da máquina que está acessando o servidor. O mod_selinux oferece uma abordagem mais granular do que nunca para acessar objetos do SELinux. Apesar do AppArmor oferecer uma solução similar, ele requer um servidor Apache especial, o que não acontece com o mod_selinux. E, caso o SEPostgreSQL seja usado como banco de dados, o controle obrigatório de acesso pode ser estendido aos objetos do banco de dados. Uma combinação dos dois sistemas promete grandes benefícios de segurança no uso de aplicativos web. n Mais informações [1]Módulo ModSecurity: http://www.modsecurity.org/ [2]SEPostgreSQL: http://wiki.postgresql.org/wiki/SEPostgreSQL [3]Pacote do mod_selinux para Fedora: https://admin.fedoraproject.org/pkgdb/packages/name/mod_selinux [4]Download do SEPostgreSQL: http://code.google.com/p/sepgsql/ Gostou do artigo? Queremos ouvir sua opinião. Fale conosco em [email protected] Este artigo no nosso site: http://lnm.com.br/article/3278 69