Hacker instalou um Backdoor secreto em servidores do Facebook para capturar senhas

Você viu essa notícia?

Hacker Installed a Secret Backdoor On Facebook Server to Steal Passwords

Resumindo, um hacker descobriu um servidor do Facebook (files.fb.com) rodando uma versão desatualizada de um software de compartilhamento de arquivos e conseguiu, através disso, fazer upload de um PHP Web Shell. Ou seja, acesso shell ao servidor.

No post original do cara que descobriu a falha você pode achar uma porção de detalhes técnicos muito interessantes.

O que é esse backdoor secreto?

Backdoor (“porta dos fundos” em inglês) é um software oculto que permite a quem o instalou acesso ao servidor. Um webshell é um backdoor que pode ser acessado em uma interface web. Existem webshells em PHP, ASP, Python, Ruby, C#, Perl e é muito fácil construir um em sua linguagem predileta.

Veja um exemplo de tela de um web shell em PHP:

Webshell em PHP

Webshell em PHP (clique para ampliar)

E seu site, é seguro?

Lição importante que você tirar desse episódio: uma corrente é tão forte quanto seu elo mais fraco. Seu servidor de controle de versão, seu software de gestão de projetos, seu webmail, todas as aplicações web acessórias ao seu site, todos os seus servidores e os computadores da sua equipe precisam estar seguros.

Por exemplo: se seu servidor git tiver o Open SSH desatualizado, se um dos programadores que desenvolve seu site instalar um software malicioso por engano ou se a sua senha do registro de domínios não é forte o suficiente, seu site estará vulnerável, não importa quão bom seja seu código.

Módulo Python: requests

Esqueça urllib e httplib: Requests resolve do jeito certo.

Você pode instalar via pip com:

pip install requests

Depois, veja como é fácil:

>>> import requests
>>> r=requests.get('http://visie.com.br')
>>> for k,v in r.headers.iteritems():print k,'=>',v
... 
content-length => 7669
content-encoding => gzip
accept-ranges => bytes
expires => Mon, 20 Jan 2014 13:18:30 GMT
vary => Accept-Encoding,Cookie
server => Apache
last-modified => Mon, 20 Jan 2014 12:38:24 GMT
cache-control => max-age=3, must-revalidate
date => Mon, 20 Jan 2014 13:18:27 GMT
content-type => text/html; charset=UTF-8
>>> r.status_code
200
>>> r.reason
'OK'
>>> r.content[:15]
'<!DOCTYPE html>'

Se você precisar fazer uma requisição HTTPS com autenticação e obter o retorno em JSON:

>>> r=requests.get('https://httpbin.org/basic-auth/user/passwd',auth=('user','passwd'))
>>> r.json()
{u'authenticated': True, u'user': u'user'}

Para fazer POST:

>>> r=requests.post('https://httpbin.org/post',data={'foo':'bar'})
>>> r.json()['form']
{u'foo': u'bar'}

Tudo muito, muito simples. E o módulo faz muito mais e está muito bem documentado. Olhe lá.

Porque você deveria aprender várias linguagens de programação

tpp_xlargecover

O programador pragmático não está preso a nenhuma tecnologia.

Há um tempo eu li “The Pragmatic Programmer“, uma espécie de livro de auto-ajuda para programadores. Não é um livro técnico, não vai te ensinar técnicas ou tecnologias, mas fala de um jeito de pensar e traz uma coleção de conselhos daquele tipo que parece óbvio mas ninguém nunca faz.

Um desses conselhos era aprender novas linguagens de programação. Os autores recomendam que você se torne proficiente em uma nova linguagem de programação por ano. O que, eu sei, é muito difícil. Eu não tenho conseguido aprender uma nova linguagem por ano. Mas isso não invalida o conselho de que você deve aprender novas linguagens de programação.

Por que aprender linguagens de programação novas?

Cada linguagem de programação traz consigo um jeito de pensar, um conjunto de soluções e uma comunidade com cultura diferente. E isso enriquece você. O bom programador tem uma visão ampla e não está “preso” a uma única tecnologia.

Por exemplo, digamos que você esteja desenvolvendo um sistema em PHP e precise, de tempos em tempos, fazer parsing de feeds RSS cuja URL foi cadastrada pelos usuários. Digamos que você queira fazer o parsing em segundo plano, a cada meia hora. Claro, você pode usar SimplePie, mas ele não é tão “Simple” assim. Dê uma olhada na documentação. SimplePie é muito poderoso, tem uma porção de recursos, mas vai dar algum trabalho para instalar direito, montar seu script, testar e automatizar.

E se você procurar soluções em outras linguagens de programação? Quanto trabalho vai ter? Vamos ver o que Python tem para nós, usando o excelente módulo feedparser. O módulo feedparser está disponível no gerenciador de pacotes do Ubuntu, e também para instalação via PIP.

import feedparser
print feedparser.parse('http://elcio.com.br/feed')

Mais uma meia dúzia de linhas para ler as URLs e salvar os resultados no banco de dados e pronto, temos um arquivo simples com excelente performance para ser colocado no cron. Bom, falando em performance, esse é o típico processamento que vai rodar muito mais rápido se feito em paralelo. Processamento em paralelo com PHP é um parto, certo? Com Python você pode usar o módulo multiprocessing e fazer isso quase que em uma linha só.

Além de ferramentas, linguagens de programação carregam jeitos de pensar

Uma vez que você já tenha resolvido um problema em uma linguagem de programação, você consegue resolver o mesmo problema em qualquer outra, certo? Bom, quando você aprende uma linguagem nova, você acaba tendo que ler um bocado de código de outras pessoas. E isso te ensina novas soluções para os seus velhos problemas.

Isso é diferente de se aprofundar no estudo de sua linguagem atual. O aprofundamento vai fazer você ler mais códigos das mesmas pessoas, da mesma comunidade, da mesma cultura. Aprender uma linguagem nova faz você ler códigos de gente nova, com outra cultura. Na prática, aprender Python vai fazer você melhor programador PHP, aprender Smalltalk vai fazer você melhor programador Java, etc.

Porque Python

De todas as linguagens de programação que você poderia escolher para começar a aprender algo novo hoje, eu recomendo que, se você ainda não sabe Python, comece por ela. Python roda no Google App Engine, no AWS Elastic Beanstalk e é a linguagem de programação por trás da maioria das ferramentas de administração do Ubuntu. Se você quer construir pequenos scripts para automatizar tarefas em seu servidor, ou quer construir grandes aplicações web para rodar em Cloud, ou se quer criar ferramentas de processamento paralelo massivo, ou interfaces gráficas multiplataforma, Python vai servir.

E é, ao mesmo tempo, uma linguagem que possui recurso fantásticos e vai te ensinar coisas incríveis, e uma das linguagens mais fáceis de aprender que eu conheço.

Que tal começar agora? Leia o excelente “Dive Into Python“, faça os exercícios, depois tente desenvolver alguma coisa na linguagem. E veja se você não vai se tornar mais eficiente em sua linguagem atual.

“Jabá”: Python é a linguagem que escolhemos para a aula de integração multi-linguagem do DevOps Heroes, treinamento da Visie que acontece a partir do dia 27 em São Paulo. Quem estiver lá vai ver isso tudo funcionando na prática. As vagas estão se esgotando.

Pare de usar FTP

Há mais de dez anos que meus processos de deploy, isto é, colocar um site ou sistema em produção, não usam FTP. Qualquer bom provedor, nacional ou internacional, oferece ferramentas muito mais eficientes para o deploy de sites e sistemas. E isso inclui desde pequenos sites em WordPress ou HTML estático até portais com milhares de acesso por hora e grandes sistemas rodando em estruturas de cloud computing elástico.

Por que você não deveria usar FTP

FTP é um protocolo muito simples de troca de arquivos, que pode ser útil para uma porção de coisas. Mas não possui os recursos necessários para o deploy e controle eficiente de aplicações web. Entre os problemas com o protocolo FTP, podemos citar:

  1. Falta de integração com controle de versão: você está fazendo uma manutenção num site, cujo diretório tem 5MB de dados. Você alterou não mais que uma dúzia de arquivos, em pastas diferentes. Arquivos texto cujos tamanhos, somados, não passam de 200KB. Como você faz o deploy por FTP? Ou sobe o site todo, “por via das dúvidas”, ou precisa pinçar os arquivos que precisa subir, um a um, certo? Algumas ferramentas de transferência, como o Filezilla, conseguem “sincronizar” as pastas, mas eles fazem isso varrendo as pastas uma por uma e comparando as datas e tamanhos dos arquivos. Leva um tempão e, se algum outro programador alterou os arquivos antes de você isso certamente vai dar problemas. O que nos leva a um segundo ponto:
  2. Falta de recursos de “auditoria” e controle de deploys: não há como obter um log ou lista de quem fez deploy, quando e o que foi feito. Um problema recorrente em ambientes em que uma equipe trabalha com FTP é a sobrescrita de alterações já publicadas. Na pior das hipóteses, gerando perda de trabalho. Mas mesmo que a equipe tenha um ambiente interno de controle de versões e a sobrescrita no FTP seja fácil de resolver, pense na dor de cabeça de ter que explicar para o cliente que o defeito que foi corrigido ontem voltou ao ar hoje, mas já estamos resolvendo.
  3. Falta de automatização: deploy por FTP é feito à mão. Um homo sapiens navega nas pastas de seu computador e do servidor e arrasta o que deve ser atualizado de um lado para outro. Num processo chato e delicado. Se ele arrasta as coisas para a pasta errada, pode ser muito difícil consertar o problema. Pode ser difícil até entender o problema. E se você coloca um homo sapiens para repetir uma mesma tarefa vinte ou trinta vezes, ele certamente vai errar alguma.
  4. Falta de recursos para rollback automatizado: você subiu a alteração. Em seguida abriu o site e viu um “erro de conexão ao banco de dados”. Percebe então que subiu a versão errada, ou no lugar errado. Como voltar atrás? Voltar atrás com FTP é um processo ainda mais manual e trabalhoso do que subir o site. Já vi casos, e não foram poucos, em que foi preciso pedir ao provedor para restaurar o backup diário. E esperar por isso, claro.

O que você deveria usar então?

SSH e Git. Há uma série de ferramentas para deploy automático, como o Capistrano ou o Jenkins. Esqueça isso tudo no começo. Aprenda SSH e Git, e construa seu processo de deploy com isso. Você vai ganhar:

  1. Deploy realmente automático. Com um único comando.
  2. Integração real com o controle de versão. Isso significa que sempre será possível rastrear cada alteração. Também significa rollback automático, o que é maravilhoso.
  3. Controle simplificado de múltiplos ambientes. Precisa fazer deploy em um ambiente de homologação, para mostrar as novidades ao cliente? Um comando. Ele aprovou as novidades, e agora é hora de fazer deploy em produção da versão que foi homologada ontem? Um comando.
  4. Preparação para o futuro. O site cresceu e você precisa agora migrar para um serviço como o AWS Elastic Beanstalk, que oferece escalabilidade “elástica” sob demanda dentro da estrutura de serviços da Amazon. O processo vai ser praticamente indolor. O cliente precisa agora de deploys com zero de indisponibilidade, e você resolveu usar a estratégia Blue Green. Já tem tudo o que precisa.

Por isso, não se conforme em usar FTP. Se precisa estudar SSH e Git, estude, vai valer a pena. Se já sabe, está esperando o quê?

“Jabá”: uma boa maneira de aprender como mudar seus processos de deploy, e muito mais, é o treinamento DevOps Heroes da Visie, que acontece daqui a duas semanas.

 

Artigo recomendado: Two Things About Conditionals in JavaScript

Detalhezinho sobre a linguagem que vale a pena conhecer, e uma boa dica de lógica sobre um erro muito cometido por iniciantes:

“We shouldn’t be fearful of writing about what we know. Even if you write from the most basic point of view, about something which has been ‘around for ages’, you’ll likely be saying something new to someone. That’s because there is no else if in JavaScript.”

Papo de Maluco

Hoje estava brincando com Requests e tive essa ideia maluca:

import requests
import re

def Ed(text):
params=dict(server=’0.0.0.0:8085′,charset_post=’utf-8′,
charset=’utf-8′,pure=1,js=0,tst=1,msg=text)
return re.sub(‘<[^>]*>’,”,re.sub(r’\n+$’,”,
requests.get(‘http://www.ed.conpet.gov.br/mod_perl/bot_gateway.cgi’,
params=params).text))

def SeteZoom(text):
params=dict(server=’127.0.0.1:8088′,pure=1,js=0,tst=1,msg=text)
return re.sub(r’\n+$’,”,
requests.get(‘http://bot.insite.com.br/cgi-bin/bot_gateway.cgi’,
params=params).text)

msg=’Oi!’
while True:
print ‘SeteZoom: %s’ % msg
msg=Ed(msg)
print ‘Ed: %s’ % msg
msg=SeteZoom(msg)

Teste aí, o resultado às vezes é mais inteligente que muito chat entre seres humanos por aí…

Pequena dica de Python: módulo webbrowser

O módulo webbrowser permite abrir uma URL no navegador do usuário. Só isso, simples assim. Por exemplo:

import webbrowser
webbrowser.open("http://visie.com.br")

E o site da Visie será aberto no navegador do usuário. Muito útil se você está fazendo um programa para desktop ou mesmo um script para o terminal. No caso de scripts para terminal, se o usuário estiver rodando o script sob uma interface gráfica o site será aberto no navegador padrão dele, já se estiver rodando via ssh ou num outro terminal sem interface gráfica, será usado um navegador de CLI (como o Lynx) se estiver disponível.

Cowsay: a vaquinha falante do Linux

Teste aí:

sudo apt-get install cowsay

Depois rode:

cowsay Funciona...

O cowsay também pode receber texto na entrada padrão:

date|cowsay

Isso permite usos razoavelmente criativos:

lynx --dump http://news.google.com.br | grep "^\[" | grep -v "»" \
| sed -e "s/.*\]//g" | sort -R | head -n 1|cowsay

Você pode colocar seu Ubuntu para te dar uma dica de Linux toda vez que você abre o terminal, assim:

sudo apt-get install fortunes-ubuntu-server

Depois edite o arquivo ~/.bashrc e inclua no final:

fortune|cowsay

E pronto! Cada vez que você abrir um terminal vai receber uma dica de Ubuntu.

API gratuita de consulta de CEP

Nosso presente de natal para os desenvolvedores do Brasil: API gratuita de consulta de CEP.

A Visie é parceira de tecnologia da Aviso Brasil. Nós fornecemos tecnologia para o Correio Control, e como parte do negócio, precisamos ter a base de endereços sempre atualizada e sincronizada com o Diretório Nacional de Endereços.

Vimos que muita gente oferece aquele cômodo recurso de auto completar o endereço pelo CEP, mas usando bases de dados desatualizadas. Existem até uns serviços pagos que oferecem esses dados.

Por isso, decidimos oferecer um serviço gratuito de consulta de endereços pelo CEP, para que você possa usar em sua aplicação. Os resultados podem ser retornados usando o modelo JSONp, de modo que o próprio navegador do usuário requisite diretamente o endereço de nossos servidores.

Aproveite!

Em tempo: se você faz software que de alguma maneira envia e controla encomendas, você precisa conhecer o Correio Control. É um software de baixo custo para usuários corporativos dos Correios que oferece o controle de faixas de registro, geração de etiquetas e AR, monitoramento e rastreamento estendido, solicitação automatizada de pedidos de informação e indenização, relatórios de status e muito mais.

 

Pequena dica de Python: as classes são dinâmicas

Veja:

>>> class Class:
...   def um(self):
...     return 1
... 
>>> c=Class()
>>> c.um()
1
>>> def dois(self):
...   return 2
... 
>>> Class.dois=dois
>>> c.dois()
2
>>> Class.tres=lambda self:3
>>> c.tres()
3
>>> Class.um=lambda self:'Um modificado.'
>>> c.um()
'Um modificado.'

As classes em Python são completamente dinâmicas. Você pode acrescentar métodos quando quiser e isso se refletirá em todos os objetos criados com aquela classe (mais ou menos como o que você faz em Javascript com prototype.)

Pequena dica de Python: leia os fontes

Python é uma linguagem open-source, com uma extensa biblioteca. E os módulos da biblioteca são escritos em Python. Alguns módulos, como pickle e StringIO, tem versões em C mais rápidas (cPickle e cStringIO) mas as versões em Python são mantidas para que você possa ler os fontes.

Veja como descobrir onde estão os fontes de um módulo qualquer:

>>> import glob
>>> glob.__file__
'/usr/lib/python2.7/glob.pyc'

O nome do arquivo tem a extensão pyc. É um compilado. Tire o último “c” e você terá o caminho do arquivo com o código fonte. Dê uma lida no conteúdo do glob.py, por exemplo, e você deve achar muito simples mas bastante interessante.

Se você está aprendendo Python agora, sempre que for resolver uma tarefa sobre determinado assunto, dê uma olhada no código dos módulos relacionados aquele assunto. Você vai ver como a comunidade Python tem abordado problemas semelhantes aos seus e com certeza vai aprender muito.

Pequena dica de Python: string formatting com locals()

Há muitas situações em que uma função faz cálculos e operações para obter valores e, ao final, deve montar uma string com esses valores. Nesta situação, muita gente monta um dicionário com os valores e usa string formatting para gerar a string a ser retornada. Por exemplo:

# -*- encoding: utf-8 -*-
import string,random

template='''Sugestões para %(nome)s:
 - login: %(login)s
 - email: %(email)s
 - site: www.%(domain)s.com
 - senha: %(passwd)s
'''

def sugere_logins(nome):
    login=nome.split(' ')[0].lower()
    domain=nome.split(' ')[-1].lower()
    email=login+'@'+domain+'.com'
    chars=string.letters+string.digits
    passwd=''.join(random.sample(chars,10))
    dados={'login':login,
           'email':email,
           'nome':nome,
           'domain':domain,
           'passwd':passwd}
    print template % dados

Você pode substituir todo o trecho em que monta o dicionário, usando o resultado da função locals(). A função locals() retorna um dicionário com todas as variáveis locais. No exemplo acima, isso ficaria assim:

# -*- encoding: utf-8 -*-
import string,random

template='''Sugestões para %(nome)s:
 - login: %(login)s
 - email: %(email)s
 - site: www.%(domain)s.com
 - senha: %(passwd)s
'''

def sugere_logins(nome):
    login=nome.split(' ')[0].lower()
    domain=nome.split(' ')[-1].lower()
    email=login+'@'+domain+'.com'
    chars=string.letters+string.digits
    passwd=''.join(random.sample(chars,10))
    print template % locals()

Uso muito esse truque ao trabalhar com web2py, fazendo com que os controllers, ao invés de retornar um dicionário montado por mim, retornem locals().

Pequena dica de Python: rot-13

A dica de hoje não é muito útil. Pelo menos eu nunca usei para nada realmente sério. Mas é bem divertida:

>>> t='All your base are belong to us.'
>>> t.encode('rot-13')
'Nyy lbhe onfr ner orybat gb hf.'

Rot-13 é um encoding comum do Python. Você pode escrever código em rot-13 também, se indicar o encoding do arquivo num cabeçalho:

# -*- encoding: rot-13 -*-
vzcbeg fgevat
sbe v va enatr(20):
    cevag fgevat.nfpvv_ybjrepnfr[:v]

Salve o conteúdo acima no arquivo rot13.py e você poderá executar:

$ python rot13.py

Divertido, não?

Pacote Ubuntu: cclive

O pacote cclive, para download de vídeos do YouTube na linha de comando, é uma reescrita do clive mais eficiente, com menor consumo de memória e menos dependências. Para instalar:

$ sudo apt-get install cclive

E para usar:

$ cclive http://www.youtube.com/watch?v=8fvTxv46ano

Isso vai baixar o vídeo na pasta atual. Simples e indolor. Mas qual a vantagem de usar a linha de comando em relação a uma extensão no navegador, onde você não precisa digitar comandos? Com a linha de comando é possível automatizar as tarefas. Criei um script que recebe um nome de usuário do YouTube e baixa os últimos 15 vídeos publicados. Chamei o arquivo de massclive. Veja o código fonte:

mkdir -p $1

lynx --dump http://www.youtube.com/user/$1/feed | \
  grep youtube.com/watch | \
  sed -e "s/.* //" | \
  sed -e "s/&.*//" | \
  sort -u | \
  while read url
  do
    cclive -c --output-dir $1 $url
  done

E você pode usar assim:

$ ./massclive maninthearenatv

Pequena dica de Python: mesclando listas

Essa é bem legal. Temos três listas:

>>> a=[1,2,3]
>>> b=[4,5,6]
>>> c=['a','b','c']

Veja:

>>> zip(a,b,c)
[(1, 4, 'a'), (2, 5, 'b'), (3, 6, 'c')]

Simples e útil, não? E se as listas tiverem tamanhos diferentes?

>>> c=['a','b']
>>> zip(a,b,c)
[(1, 4, 'a'), (2, 5, 'b')]

O resultado será truncado para o tamanho da menor lista. Se você quiser, pode obter um comportamento diferente com map, assim:

>>> map(None,a,b,c)
[(1, 4, 'a'), (2, 5, 'b'), (3, 6, None)]

Veja um truque que eu costumava usar bastante com zip:

>>> colors=['Azul','Vermelho','Amarelo','Verde','Branco']
>>> for i in zip(range(len(colors)),colors):
...   print '%i. %s' % i
... 
0. Azul
1. Vermelho
2. Amarelo
3. Verde
4. Branco

Até que eu descobri enumerate():

>>> for i in enumerate(colors):
...   print '%i. %s' % i
... 
0. Azul
1. Vermelho
2. Amarelo
3. Verde
4. Branco

HTML5: Desenvolvendo agora as aplicações web de amanhã

Boa parte das APIs do HTML5 já estão disponíveis hoje para a maioria dos navegadores e, com um pouco de conhecimento e uma pitada de javascript, é possível desenvolver hoje aplicações com geoposicionamento, funcionamento offline, conexão em tempo real com o servidor, gráficos vetoriais e todo um novo conjunto de recursos de interface.

Por que esperar?

O HTML5 foi construído de maneira modular. Não é preciso esperar que toda a documentação esteja escrita para começar a trabalhar com ele. Você pode usar agora mesmo o que já está pronto.

Pensando nisso, preparamos este Workshop sobre as APIs do HTML5 e como construir a nova geração de aplicações web. Veja o programa.