Protegendo binários do Oracle Database de alterações maliciosas

This post is also available in: English

Introdução

Em minhas apresentações sobre segurança e vulnerabilidades de Oracle Database, eu sempre menciono os rootkits ou malwares que podem atacar um Banco de Dados por dentro (através de SQL Injection, alteração de códigos PL/SQL, leaks de Java, etc) ou por fora (através de alteração de arquivos do usuário oracle, tais como binários / libs / crontab / etc).

Para chegar a estas duas formas de ataques, um hacker costuma utilizar o que eu chamo de escada da alegria:

Normalmente um invasor começa o escalonamento de privilégios partir de um usuário com baixas permissões, muitas vezes apenas com o grant de CREATE SESSION, e tenta diversas técnicas para subir a escada, como SQL Injection, Java Vulnerabilities, Buffer Overflow, etc. Uma vez como SYSDBA ou DBA, é trivial o caminho para alcançar o usuário oracle de SO, responsável pelos binários do BD.

O objetivo deste artigo é apresentar como proteger os arquivos do usuário Oracle Home contra alterações indevidas e evitar assim a implantação de rootkits ou malwares.

OBS: Note que algumas etapas deste artigo não são documentadas ou suportadas pela Oracle. Portanto, faça por sua conta e risco.

Começando

No Oracle 18c foi introduzida uma nova funcionalidade chamada Read-Only Oracle Home (ou ROOH) e em cima deste novo recurso que iremos implementar esta proteção extra. Para BDs pre-18c, há uma sessão exclusiva neste tutorial.

Dentre os objetivos do ROOH estão:

• Remover do Oracle Home arquivos mutáveis.
• Consolidar estes arquivos em uma pasta separada.
• Facilitar a migração / clonagem de ambientes.
• Facilitar a utilização de Docker / compartilhamento de Oracle Homes via NFS / etc.

No entanto, o ROOH apenas garante que nenhum processo irá criar ou alterar arquivos no ORACLE_HOME, mas não torna impossível ao usuário oracle de implementar qualquer tipo de alteração em seus próprios arquivos. Uma vez como proprietário dos mesmos, ele obviamente ainda é capaz de alterá-los. Portanto, esses arquivos ainda não estão protegidos contra mudanças maliciosas.

O que faremos então, uma vez ativado o ROOH e tendo a certeza que o usuário oracle não precisará mais modificar qualquer arquivo dentro desta raiz (salvo em casos de aplicação de patches), será proteger os binários com as seguintes etapas:

  1. Salve os atuais proprietários e privilégios de todos os arquivos presentes ORACLE_HOME.
  2. Altere o atual proprietário de todos os arquivos do ORACLE_HOME para root.

O objetivo da Etapa 1 é ter uma forma de retornar ao proprietário e privilégios anteriores em caso de necessidade de aplicação de um patch ou qualquer outro tipo de alteração do ORACLE_HOME pelo usuário oracle.

O objetivo da Etapa 2 é proteger de fato o ORACLE_HOME de alterações indevidas, uma vez que o usuário oracle não será mais proprietário dos arquivos (parecido com o que ocorre hoje com o GRID_HOME, cujo proprietário é o root e não o grid).

Antes de começar

Certifique-se que:

  • O ROOH está ativo para o seu ORACLE_HOME (veja esse doc para saber como).
  • Nenhum processo está executando com o usuário proprietário do ORACLE_HOME (normalmente oracle).

1. Salvando as permissões e proprietários atuais

A primeira etapa é efetuar um backup dos privilégios e permissões.

Isso pode ser feito através do comando abaixo como oracle:

$ ORACLE_HOME=/u01/app/oracle/product/18.0.0/dbhome_1
$ cd $ORACLE_HOME
$ find -depth -printf '%m:%u:%g:%p\0' |
awk -v RS='\0' -F: '
BEGIN {
    print "#!/bin/sh";
    print "set -e";
    q = "\047";
}
{
    gsub(q, q q "\\" q);
    f = $0;
    sub(/^[^:]*:[^:]*:[^:]*:/, "", f);
    print "chown --", q $2 ":" $3 q, q f q;
    print "chmod", $1, q f q;
}' > original-permissions.sh

O comando find e awk acima irão gerar dentro do ORACLE_HOME o arquivo original-permissions.sh. Este shellscript possui comandos chown e chmod atuais para todos os arquivos existentes.

$ head original-permissions.sh
#!/bin/sh
set -e
chown -- 'oracle:oinstall' './bin/lxegen'
chmod 755 './bin/lxegen'
chown -- 'oracle:oinstall' './bin/sqlldr'
chmod 751 './bin/sqlldr'
chown -- 'oracle:oinstall' './bin/lsnrctl'
chmod 751 './bin/lsnrctl'
chown -- 'oracle:oinstall' './bin/ore_srcexport.pl'
chmod 644 './bin/ore_srcexport.pl'

2. Alterar o atual proprietário de todos os arquivos do ORACLE_HOME para root

Antes de mudar o atual proprietário dos arquivos para root, é preciso garantir algumas coisas, uma vez que os privilégios para o usuário oracle ler (r) e executá-los (x) se dará através do grupo do arquivo (normalmente oinstall):

  1. Se o proprietário do arquivo tinha poder de execução (x), o grupo precisará ter poder de execução.
  2. Se o proprietário do arquivo tinha poder de leitura (r), o grupo precisará ter poder de leitura.
  3. Grupo e others não poderão ter privilégios de alteração (w).

Isso pode ser feito através dos comandos abaixo, executados como root:

# ORACLE_HOME=/u01/app/oracle/product/18.0.0/dbhome_1
# cd $ORACLE_HOME
# pwd
/u01/app/oracle/product/18.0.0/dbhome_1
# find ./ -perm -u+x ! -perm -g+x -exec chmod g=u-w {} +
# find ./ -perm -u+r ! -perm -g+r -exec chmod g=u-w {} +
# find ./ -perm -g+w ! -type l -exec chmod g-w {} +
# find ./ -perm -o+w ! -type l -exec chmod o-w {} +
# chown -R root ./*

Pronto! Agora pode iniciar a sua instância com garantia que um ataque não conseguirá afetar os binários do BD.

OBS: Lembrando de que nada adianta esse tipo de proteção caso o usuário oracle consiga executar um su ou sudo para o usuário root.

Rollback

Sempre antes de aplicar um patch ou caso queira desfazer a alteração de proprietário e permissões, execute o arquivo original-permissions.sh (gerado na etapa 1) como root:

# ORACLE_HOME=/u01/app/oracle/product/18.0.0/dbhome_1
# cd $ORACLE_HOME
# sh original-permissions.sh

OBS: Lembre-se de reexecutar a Etapa 1 após a execução de alterações no Oracle Home, a fim de garantir que permissões e proprietários de novos arquivos sejam inclusos no shellscript.

O meu Oracle Home está realmente protegido?

Como usuário oracle, eu posso agora verificar se a Oracle Home está realmente blindada. Como?

Tentarei remover todos os arquivos recursivamente como oracle.

JAMAIS TENTE ISSO EM SEU SERVIDOR.

$ cd $ORACLE_HOME
$ pwd
/u01/app/oracle/product/18.0.0/dbhome_1
$ find ./ | wc -l
42098
$ rm -rf ./* ./.* 2>&-
$ find ./ | wc -l
42098

Como é possível ver do resultado acima, o usuário oracle não foi capaz de remover um sequer arquivo.

Banco de Dados Pré-18c

Em ambientes 12c ou anteriores, esse tipo de abordagem de proteção também funcionaria. No entanto, para evitar problemas é necessário mapear TODOS os arquivos que são mutáveis dentro do ORACLE_HOME (algo inexistente no 18c com ROOH) e mantê-los com as permissões originais do usuário oracle.

Como essa é uma tarefa muito difícil pois não é possível controlar os diretórios em que uma versão pré-18c gera arquivos, recomendo uma "abordagem inclusiva", com a proteção apenas de arquivos nas seguintes pastas para evitar impactos nos ambientes:

  • ./bin/
  • ./ctx/lib/
  • ./hs/lib/
  • ./javavm/admin/
  • ./ldap/lib/
  • ./lib/
  • ./network/lib/
  • ./odbc/lib/
  • ./owb/wf/lib/
  • ./plsql/lib/
  • ./precomp/lib/
  • ./racg/lib/
  • ./rdbms/admin/
  • ./rdbms/lib/
  • ./sqlplus/lib/
  • ./srvm/lib/
  • ./sysman/lib/
  • ./xdk/lib/

Isso pode ser feito através dos comandos abaixo como root (lembre-se de salvar as permissões atuais antes, conforme descrito no item 1):

# ORACLE_HOME=/u01/app/oracle/product/12.1.0/dbhome_1
# cd $ORACLE_HOME
# pwd
/u01/app/oracle/product/12.1.0/dbhome_1
# cat protected_folders.txt
./bin/
./ctx/lib/
./hs/lib/
./javavm/admin/
./ldap/lib/
./lib/
./network/lib/
./odbc/lib/
./owb/wf/lib/
./plsql/lib/
./precomp/lib/
./racg/lib/
./rdbms/admin/
./rdbms/lib/
./sqlplus/lib/
./srvm/lib/
./sysman/lib/
./xdk/lib/
# find $(cat protected_folders.txt) -perm -u+x ! -perm -g+x -exec chmod g=u-w {} +
# find $(cat protected_folders.txt) -perm -u+r ! -perm -g+r -exec chmod g=u-w {} +
# find $(cat protected_folders.txt) -perm -g+w ! -type l -exec chmod g-w {} +
# find $(cat protected_folders.txt) -perm -o+w ! -type l -exec chmod o-w {} +
# chown -R root $(cat protected_folders.txt)

OBS: Você pode adicionar ou removes pastas da lista acima, a seu próprio risco, para aumentar ou diminuir a proteção.

Conclusão

Escalação de privilégios ( Usuário DBA no BD -> Usuário oracle no SO ), apesar de não apresentado por estar fora do escopo deste artigo, é algo realmente trivial e o principal objetivo final dos invasores. Portanto, dificultar a implantação de qualquer tipo de código malicioso nos binários é uma preocupação real que deve ser levantada em todos os tipos de ambientes, principalmente no de Produção.

Gostou? Não deixe de comentar ou deixar um 👍!

Deixe um comentário

Seu e-mail não será publicado.