Neste artigo demonstro como criar uma solução de melhoria de segurança no acesso a serviços remotos como FTP e SSH usando Apache/PHP e Perl. Tal solução foi implementada na empresa onde trabalho e funciona perfeitamente.
Uma dos maiores prós da Internet é permitir o uso de ferramentas de acesso
remoto para se trabalhar de qualquer lugar. Eu mesmo não saberia viver sem
o SSH. O risco reside no fato de não vivermos num mundo perfeito, onde todas
as pessoas são felizes, sempre existem pessoas interessadas em jogar areia
no seu arroz.
SSH e FTP são dois grandes alvos de tentativas de invasão. Recentemente, ao
analisar o log do meu SSHD, descobri que um lammer chinês estava tentando fazer
milhares de tentativas de quebra de senha através de um desses
"scripts kiddie" de "brute force attack". Aquilo me incomodou bastante e fui
obrigado a mudar a porta do meu server tirando do padrão 22 (aliás o que
é extremamente recomendado). Mas isso não me fez dormir mais seguro naquela
noite. Fiz algumas considerações:
Um sistema remoto é sempre alvo de possíveis ataques;
Mesmo mudando a porta de determinado serviço, ela pode ser descoberta através
de um paciente "portscan";
Preciso prover acesso remoto para meus clientes e nem todos estarão afim de reconfigurar seus clientes de acesso toda a semana;
Pode ser que um dia eu saia da empresa e é sempre positivo para seu currículo que um sistema que você configurou permaneça seguro mesmo você não estando mais lá para administrar;
Não dava pra restringir acesso remoto para apenas alguns IPs cadastrados, pois clientes ADSL mudam de IP o tempo todo.
[2] Comentário enviado por tiagoalgodas em 30/03/2006 - 17:45h
Olá amigo. Parabéns pelo artigo, é de extrema importancia esses aspectos levantados por você sobre segurança. Apenas uma coisa, me corrija se estiver errado, por padrão na filtragem de pacotes, os pacotes direcionados a porta correpsondente ao ssh devem ser "DROPADOS" confere ? abraço e parabéns.
[4] Comentário enviado por agk em 30/03/2006 - 20:19h
Parabéns, muito bom.
Isso já ajuda a impedir os ataques de brute force e no caso de alguém descobrir que tem que entrar na página X, essa página poderia ter algum código especifico que só o cliente saiba para poder liberar o acesso para ele.
O iptables também um módulo que ajuda a aumentar a segurança, chama-se port-knock-out, tem uma dica ou artigo aqui no VOL que fala sobre isso.
[ ]'s.
[6] Comentário enviado por davidsonbhz em 31/03/2006 - 09:31h
Opas! Viajei no nome do campo expira_em, deve ter sido empolgacao. Em relacao a pergunta do tiagoalgodas sobre os pacotes serem dropados por padrao, seria uma coisa do tipo:
iptables -I INPUT -p tcp --dport 22 -j DROP
colocando isso na primeira linha do script de firewall impede qualquer tentativa de conexao na porta 22, em seguida eu acrescento
isso permite que apenas os caras autenticados acessem a porta 22. Lembrando que o parametro -I do input insere a regra no topo da cadeia do iptables empurrando as outras pra baixo.
[8] Comentário enviado por removido em 31/03/2006 - 13:15h
Só uma coisa que não ficou clara para mim...
Em que momento está ocorrendo a exclusão do redirecionamento do IpTables?
Entendi todo o resto do sistema, só não localizei essa parte...
[9] Comentário enviado por jov em 31/03/2006 - 14:50h
Achei excelente a idéia, mas acho que tem um porém,o ideal não seria colocar uma rotina no script perl que quando expirasse o tempo dropasse as regras que foram incluídas?
[10] Comentário enviado por davidsonbhz em 31/03/2006 - 17:26h
Boa ideia Jov, seria algo mais ou menos do tipo:
Acrescentamos na tabelas de autenticados um campo char para indicar a validade da sessao.
mysql> alter table acesso_autenticado add expirout char default 'N'
Depois criamos um script para verificar a validade das sessoes
#!/usr/bin/perl
$agora = time;
my $db = DBI->connect("DBI:mysql:banco_de_dados:$server",$user,$pass) or die $DBI::errstr;
my $cursor = $db->prepare("select login,ip from acesso_autenticado where expira <= $agora and expirou='N'");
$cursor->execute;
#depois que a gente removeu os expirados do iptables, marcamos eles como expirados na tabela
my $cursor = $db->prepare("update acesso_autenticado set expirou='S' where expira <= $agora and expirou='N'");
$cursor->execute;
[14] Comentário enviado por prota em 04/04/2006 - 01:57h
Muito boa sua idéia cara, parabéns. O único problema é que se voce entrar com anything' OR 'x'='x nos campos usuario e senha, o acesso sera liberado da mesma forma.
[15] Comentário enviado por davidsonbhz em 05/04/2006 - 09:40h
Isso que o prota falou eh verdade! Eh muito importante que quando se implementar o esquema, eh necessario tratar os campos de usuario e senha pra evitar o famoso "sql injection".
Algumas precaucoes simples podem ajudar nisso como remover os espacos em branco, aspas e coisas que podem comprometer. Limitar o tamanho dos campos de usuario e senha tambem ajuda!
[17] Comentário enviado por pitombera em 07/04/2006 - 09:48h
Estáis de parabéns pelo artigo, mas não entendo bem... teria cm gerenciar a questão de ip's pelo php com sessions ( creio eu ), assim o clinte teria q estar logado na página e ao dar um logout ele rodaria um outro perl semelhante ou o msm só q fazendo o inverso, retirando a regra :
iptables -D INPUT -s ip_do_cara_autenticado1 -p tcp --dpor 22 -j ACCEPT
Achei mto interessante e curti pacas seu script mas achei falho a questão da retirada de ips, mais por estética e talz... mas não gosto de um INPUT cheio de regras .. mas ai fica minha opinião e não tenho certeza se é a mais correta mas... comentem ai x)
[19] Comentário enviado por davidsonbhz em 07/04/2006 - 15:27h
Interessante o que o pitombera disse. Esse método de validação de ips pode ser implementado de diversas maneiras. Estarei trabalhando em outro artigo que mostrará a solução completa do sistema, por enquanto eu quis apenas expor a idéia! Pelo que estou percebendo um projeto pode nascer aqui, mandem suas sugestões!
[20] Comentário enviado por kadu em 10/09/2007 - 09:49h
Uma dica, não sei se vulnerável, mas seria eficiente colocar o PHP pra rodar o script perl, pois assim seria adicionada a regra em tempo real e não rodaria o mesmo quando desnecessário.
Pensei em faze-lo com o sudo da seguinte forma:
---------------
~# visudo
---------------
No PHP acrescentar após a inserção dos dados no banco MySQL a linha:
system("sudo /local/do/script.pl");
---------------
Está aí a dica !!!
Obs: não testei mas acredito que funciona perfeitamente, pois uso algo parecido num gerenciador de emails para criar a pasta do usuário, mudar a permissão da pasta, e adicionar as pastas padrões com maildirmake.
Mas creio não ser uma coisa muito pratica para quando tratamos de acessos remotos feito por usuários finais. Pois normalmente preferem algo mais pratico e de facil manuseio.