Bounty Firefox: atirar a toalha ao tapete...

08.07.07

Introdução
Construir uma dist de Linux, na CMS e no O2H Lab, é por vezes olhar um pouco mais além. É por isso que os pinguins mágicos são envolvidos e apoiados em idas a conferências, formação e desafios intelectualmente exigentes.
Lancei o desafio ao Mário Morgado de durante 3 dias olhar comigo para o bounty de 1.000 euros do Firefox.
Ao fim dos 3 dias, tínhamos evoluído bastante.
Continuei mais 5 dias a a horas desaconselháveis de madrugada e aqui fica o resultado.

O problema prendia-se com um certificado que, aparentemente bem assinado, mas que não era comido pelo Firefox apesar de ser comido pelo openssl, IE,... Refs uteis: 1,2 e 3.

Quando se acede a: https://private.eu2007.pt/, o servidor envia 3 certificados para confirmar a chain de segurança (ou seja, para validar que o site é mesmo quem diz que é...).
[CERT01] certificado do private.eu.pt assinado pela ECCE
[CERT02] certificado da ECCE assinado pela ECRaizEstado
[CERT03] certificado da ECRaizEstado assinado pela GTE CyberTrust Global Root

A GTE é uma root CA pelo que o certificado não era enviado e está obviamente built-in no browser.

Já agora, eu e o Mário utilizámos uma ferramenta que não vi ainda descrita em nenhum sitio:
nss-3.7.2/bin//ssltap -f -sx -p 2004 private.eu2007.pt

Que faz "tapping" da ligação e que depois permite ligar um browser à porta desejada (2004) e sacar os certificados enviados. Isto foi útil para logo desde início ter os certificados...
Já agora, um exemplo do início de um certificado:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
00:82:ba:51:07:ea:43:b1:46:7c:08:ce:5b:23:0a:72
Signature Algorithm: PKCS #1 SHA-1 With RSA Encryption
Issuer: CN=ECCE,OU=ECEstado,O=SCEE,C=PT
Validity:
Not Before: Fri Jun 22 17:37:18 2007
Not After: Sun Jun 22 17:37:18 2008
Subject: CN=private.eu2007.pt,OU=Missao Presidencia,O=Ministerio dos Negocios Estrangeiros,L=Lisboa,ST=Lisboa,C=PT


Identificação do problema

Após 3 dias, a comunidade não andou longe. O problema era que no certificado 2 o issuer tinha ECRaizEstado como sendo do tipo UTF8STRING mas no certificado 3 o subject ECRaizEstado estava como PRINTABLESTRING. Para isso utilizámos:
openssl asn1parse -inform DER -in cert.003

Eu e o Mário percebemos isto quando carregámos o certificado raíz no browser http://www.scee.gov.pt/ecee/certificados/ECRaizEstado.crt e passou a aceitar o site. Ou seja, a quebra na chain tinha de ser ECRaizEstado - GTE.

Podemos ter interpretado mal, mas a identificação do problema não foi totalmente bem feita até ao momento.
Não é o encoding (ou seja, o processo de codificar o campo SubjectName ou Issuer em UTF / PrintableString) que está a dar problema.
É o tipo do campo ser utilizado para a hashtable e para o seu lookup.

Comprovar o problema
O que se passa é que o Firefox utiliza o subject name+types como key para a HashTable. Mas o SubjectName utilizado é o array de bytes directamente extraído do DER.
Exemplo:
data = 0x8fdc10e "\f\004SCEE1\0250\023\006\003U\004\003\f\fECRaizEstado0\036\027\r060703142700Z\027\r180623084947Z0>1\v0\t\006\003U\004\006\023\002PT1\r0\v\006\003U\004\n\f\004SCEE1\0210\017\006\003U\004\v\f\bECEstado1\r0\v\006\003U\004\003\f\004ECCE0\202\001\"0\r\006\t*\206H\206\uffff\r\001\001\001\005", len = 6}

1.- A primeira abordagem foi tentar "martelar" na função de encoding para um determinado tipo.
Estupidos. Claro que não resultou porque depois ele ia verificar a assinatura / integridade do certificado e estava errado.

2.- A segunda foi, na função nssCertStore_FindCertByIssuerAndSerialNumberLocked(), utilizando o gdb "martelar" em memória o valor do tipo do subject para PrintableString:
set {char } 0x8fd6e2f='\023'
set {char } 0x8fd6e20='\023'


Ou seja, se virem acima, antes de ECRaizEstado existe dois bytes representandos em char como "\f\f". O primeiro deles é o tipo e '\f' é o SEC_ASN1_UTF8_STRINGE e o '\023' é o 'SEC_ASN1_PRINTABLE_STRING'.
Testando deu:


Touché.
Tínhamos a root chain completa e a possível solução.
Era então escrever umas linhas de código e ir levantar o cheque! Sim.. Sim...Estúpidos...

Solução

1.- A primeira abordagem era construir o SubjectName utilizado na hash sem o campo "tipo".
Para tal, talvez fosse possível alterar o template ASN1 no certdb.c que era utilizado para ir buscar o subject ao DER:
const SEC_ASN1Template SEC_CertSubjectTemplate[] = {
. { SEC_ASN1_SEQUENCE,
0, NULL, sizeof(SECItem) },
[snip...]
{ SEC_ASN1_SKIP }, /* validity */
{ SEC_ASN1_ANY, 0, NULL }, /* subject */
{ SEC_ASN1_SKIP_REST },
{ 0 }

Mas não foi possível porque, do nosso conhecimento, não conseguimos evitar os campos type no subject utilizando o mecanismo de templating. Mesmo com algumas tentativas com offset's (mas os campos type estão salteados dentro do subject, recordamos que existem vários subcampos no subject como CN=, OU=,O=...) ou com substructs.

2.- Mas se o openssl funcionava bem, porque não o código nss do Firefox?
Porque o openssl não guarda o campo "type" para efeitos de comparação.
A segunda abordagem passou por ir alterar o código para passar a guardar o subject apenas com o seu conteúdo (payload) em ASCII e não os bytes payload+type do subject do DER.
Mexeu-se no certdb.c, pkistore.c e stanpcertdb.c (links para patch) para passarem a criar um hash com base no payload e não no type+payload.
E funcionou... até ao certificado GTE, isto é ao que está built-in no browser.
Ou seja, os certificados pré-incluídos são guardados numa hash em cache que não é a mesma.
Era preciso que esta cache fosse criada também só com o payload....

Conclusão
Objectivamente, os patches atrás não resolvem o problema porque os certificados built-in são guardados em cache a partir do campo DER e portanto depois não fazem matching com o hash guardado apenas com o payload em ASCII.
Pode ser que alterar isto para a cache ser criada da mesma forma fosse mais 1 dia. Mas poderia ser mais 8. E também não temos a certeza que fosse aceite upstream.
Não podendo trabalhar nisto durante o dia após os 3 dias estabelecidos (sim, porque a Caixa Mágica e os projectos não param) implicou-me trabalhar à noite após os miúdos se deitarem e antes de acordarem.
Foi bom para recordar certificados x.509, ASN1, DER,...
Mas valeu mais do que pelo conhecimento gerado e o mérito vai para quem lançou a iniciativa, o Mário Valente.
As nossas instituições, e o Plano Tecnológico, por exemplo, acham que a enorme força da comunidade e indústria open source pode ser totalmente aproveitada utilizando os métodos antigos. Tal como fazer um protocolo com a MS, podia-se fazer um protocolo com o Software Aberto / Livre.
Não é assim. Tem de se compreender o ecosistema.
E quem achar que um bounty é desafiante apenas pelo dinheiro não compreende esse ecosistema. É desafiante pelo hacking. É desafiante para afirmarmos as nossas competências. É desafiante para chegar primeiro.
Um bounty é apenas a ponta do icebergue. Esta comunidade tem muito mais para dar. É apenas saber pedir.

publicado por pinguinsmagicos às 22:50editado por Fábio Teixeira em 12/10/2010 às 11:43

Firefox ganha prémio da Exame Informática...

21.05.07

O Firefox ganhou o prémio para o melhor "Software" nos prémios da Exame Informática.
Este prémio vai de encontro à subida de penetração do Firefox no mercado dos browsers.
Seria curioso traçar o gráfico do market share do Firefoz e ver que após a passagem a Open Source foi perdendo mercado, só recuperando 5 anos depois.
Conclusão: é preciso persistência...

tags: ,
publicado por pinguinsmagicos às 09:35editado por Fábio Teixeira em 12/10/2010 às 11:30

pesquisar

 

comentários recentes

  • Bueno!
  • Onde posso encontrar o Linux Caixa Magica 12 KitTe...
  • Boa noite, o Caixa Mágica 20 funciona nos process...
  • Boa tarde.Quando fazemos o registo aquando do down...
  • Á partida não, quem quiser pode instalar facilment...
  • Adorei o novo Linux Caixa Mágica está muito difere...
  • Que bacana seu blog! Gostei bastante!Se quiser dic...
  • Instalei, mas a entrada e partições dos discos, nã...
  • O software do cartão do cidadão está disponível na...
  • Foi uma apresentação bastante interessante.

mais comentados

subscrever feeds