Contornando a Camada Zero
Desde o início do L2BEAT, nos esforçamos muito para analisar e entender os riscos associados aos protocolos L2. Fazemos o possível para ser um cão de guarda imparcial e independente, agindo no melhor interesse dos usuários e do ecossistema. Não deixamos que nossas preferências pessoais pelo projeto ou pela equipe envolvida atrapalhem. Por isso é comum precisarmos ativar alertas vermelhos ou apontar nossas preocupações em diversos protocolos, ainda que valorizemos o tempo e o trabalho das equipes específicas em seus projetos. Ter discussões relacionadas à segurança desde o início permite que todo o ecossistema se prepare melhor para riscos potenciais e reaja mais cedo a qualquer comportamento suspeito.
Hoje gostaríamos de abrir um debate sobre modelos de segurança compartilhada de aplicativos cross-chain. Atualmente, existem duas abordagens: segurança compartilhada versus segurança por aplicativo. A primeira, segurança compartilhada, é utilizada, por exemplo, por todos os rollups. A segunda, a segurança por aplicação, é utilizada por projetos “omnichain”. O principal exemplo de tal projeto é o LayerZero.
Segurança compartilhada versus segurança isolada
Por segurança compartilhada, queremos dizer que tokens ou aplicativos específicos executados em uma determinada infraestrutura não escolhem livremente seu modelo de segurança. Em vez disso, eles precisam obedecer a quaisquer requisitos de segurança impostos pela infraestrutura. Por exemplo, rollups otimistas geralmente impõem uma janela de finalização de 7 dias — os aplicativos executados nesses rollups não podem simplesmente ignorar ou encurtar esse período. Pode parecer um obstáculo, mas é um obstáculo colocado por um motivo. Ele permite fornecer aos usuários uma garantia de segurança que eles podem esperar ser mantida por qualquer aplicativo que estejam usando nesse rollup, independentemente da política de segurança interna dos aplicativos. O aplicativo pode apenas fortalecer a política de rollups, não enfraquecê-la.
Por segurança isolada, queremos dizer que cada app é responsável por definir sua segurança, não sendo de forma alguma restringida pela infraestrutura. A princípio, pode parecer uma boa ideia. Afinal, os desenvolvedores de aplicativos sabem melhor quais medidas de segurança o aplicativo pode precisar. Mas, ao mesmo tempo, transfere a responsabilidade de avaliar os riscos associados à política de segurança de cada aplicativo para o usuário final. Além disso, se os desenvolvedores de aplicativos são livres para escolher sua política de aplicativos, eles também podem optar por alterá-la quando quiserem. Portanto, não basta avaliar os riscos uma vez para cada aplicativo, eles devem ser avaliados sempre que a política dos aplicativos mudar.
O problema
Acreditamos que o modelo de segurança isolado, em que cada aplicativo pode definir livremente sua política de segurança, apresenta sérias preocupações de segurança. Em primeiro lugar, aumenta os riscos para os usuários finais, pois eles precisam validar separadamente os riscos associados a cada aplicativo que pretendem usar.
Também aumenta o risco para os aplicativos que usam esse modelo. A segurança isolada adiciona riscos adicionais em relação à mudança da política de segurança — se o invasor conseguir alterar o modelo de segurança do aplicativo, ele pode simplesmente desativá-lo, oferecendo a possibilidade de drenar os fundos ou usá-los indevidamente de qualquer outra forma. Não há nenhuma camada de segurança adicional sobre o aplicativo que proteja contra uso indevido.
Além disso, com as políticas de segurança que podem mudar instantaneamente a qualquer momento, torna-se praticamente impossível monitorar aplicativos diariamente e informar os usuários sobre os riscos.
Achamos isso semelhante à capacidade de atualização de contratos inteligentes. Já alertamos contra isso no L2BEAT . Informamos os usuários sobre rollups e pontes que possuem mecanismos de atualização em seus contratos inteligentes, bem como o mecanismo exato que rege a capacidade de atualização em cada caso. Isso já é bem complexo e com um modelo de segurança isolado, isso se multiplica para cada app, tornando quase impossível rastrear de forma eficaz.
É por isso que consideramos um modelo de segurança isolado como um risco de segurança em si e postulamos tratar todos os aplicativos que usam esse modelo como arriscados por padrão até prova em contrário.
O plano
Decidimos testar nossas suposições no mundo real, na rede principal. A estrutura LayerZero foi escolhida para o experimento porque é uma das soluções mais populares usando segurança isolada em seu núcleo. Implantamos um token omnichain que era seguro e, posteriormente, a configuração de segurança foi atualizada, o que permitiu a retirada de tokens maliciosos. O código do token é baseado nos exemplos fornecidos pelo LayerZero e é muito semelhante ou idêntico a muitos outros tokens omnichain e aplicativos implantados na produção.
Mas antes de nos aprofundarmos nos detalhes, vamos dar uma breve olhada na aparência do modelo de segurança LayerZero.
Como afirma claramente o white paper do LayerZero, sua “comunicação entre cadeias sem confiança” depende de dois atores independentes (o oráculo e o retransmissor) atuando juntos para garantir a segurança do protocolo.
Como afirma o LayerZero em seu site, seu conceito principal é que é um “endpoint on-chain configurável pelo aplicativo do usuário que executa um ULN (UltraLightNode)”. Os componentes on-chain do LayerZero dependem de duas partes externas fora da cadeia para retransmitir mensagens entre as cadeias - o Oracle e o Relayer.
Sempre que qualquer mensagem M é enviada da cadeia A para a cadeia B, as duas ações a seguir ocorrem:
- primeiro, o Oracle espera até que a transação que envia a mensagem M na cadeia A seja finalizada e depois escreve na cadeia B o compromisso para o pacote de mensagens, por exemplo, o hash do cabeçalho do bloco (o formato exato pode variar entre diferentes cadeias/oráculos) na cadeia A contendo aquela mensagem M
- então o Relayer envia para a cadeia B uma “prova” (por exemplo, uma Prova Merkle) de que o cabeçalho armazenado contém a mensagem M
LayerZero afirma que “o design do LayerZero elimina a possibilidade de conluio”. Mas, na verdade, essa afirmação não é verdadeira (o que provamos no experimento apresentado abaixo), pois cada aplicativo de usuário pode definir seu próprio Relayer e Oracle. LayerZero não garante por design que esses componentes sejam independentes e que não possam ser coniventes. Cabe ao aplicativo do usuário fornecer essas garantias. E se o aplicativo decidir quebrá-los, não há nada na mecânica do LayerZero que possa impedi-lo de fazê-lo.
Além disso, por padrão, todos os aplicativos do usuário podem alterar o Relayer e o Oracle a qualquer momento, redefinindo completamente as suposições de segurança. Portanto, não basta verificar a segurança do aplicativo fornecido uma vez, pois ele pode ter mudado a qualquer momento após a verificação, como mostraremos em nosso experimento.
O experimento
Em nosso experimento, decidimos criar um token omnichain simples, CarpetMoon, funcionando tanto no Ethereum quanto no Optimism, usando ZeroLayer para comunicação entre as duas chains.
Nosso token inicialmente usa o modelo de segurança padrão fornecido pelo LayerZero, portanto, parece o mesmo que a maioria (se não todos) dos aplicativos LayerZero implantados atualmente. Assim, geralmente é tão seguro quanto qualquer outro token usando LayerZero.
Primeiro, implantamos nossos contratos de token no Ethereum e no Optimism:
https://ethtx.info/mainnet/0xf4d1cdabb6927c363bb30e7e65febad8b9c0f6f76f1984cd74c7f364e3ab7ca9/
https://optimistic.etherscan.io/tx/0xf41389d71fa3942de5225efb067072728c6c6de56c241574187781db7c73d221
E configuramos o roteamento para que o LayerZero saiba qual contrato corresponde a qual em ambas as chains:
https://ethtx.info/mainnet/0x19d78abb03179969d6404a7bd503148b4ac14d711f503752495339c96a7776e9/
https://optimistic.etherscan.io/tx/0x037b1bad33faa5607bb5835460a1d5caaf3a147dc3a09762ac7703befcdb3c3c
Assim que o token estiver configurado, ele se parece exatamente com todos os outros tokens omnichain usando LayerZero, com configuração padrão, nada suspeito.
Fornecemos ao nosso usuário de teste, vamos chamá-la de Alice, com tokens de teste, então Alice tem tokens 1B CarpetMoon no Ethereum:
https://ethtx.info/mainnet/0x7e2faa8426dacae92830efbf356ca2da760833eca28e652ff9261fc03042b313/
Agora Alice conecta esses tokens ao Optimism usando LayerZero.
Bloqueamos os tokens em um depósito no Ethereum:
https://ethtx.info/mainnet/0xe4dc3757b86bfda8e7baddc088fb1a599e083ed77034c29e5dd8bd11f1e17771/
A mensagem com a transação está sendo entregue ao Optimism através do LayerZero:
https://layerzeroscan.com/101/address/0xc6005ccc1de4b300d538903b74848bff881d5dc5/message/111/address/0x201fe0d843b546f2e24d4c8444318d1c71b7d10d/nonce/1
E tokens interligados estão sendo cunhados no Optimism, Alice agora tem 1B MoonCarpet tokens no Optimism:
https://optimistic.etherscan.io/tx/0x5388ced88cf562acafff82d6798f791b0b38b90ee106df9bf91c0d86306ec302
Ok, então tudo funcionou como esperado, Alice conectou seus tokens e viu que há 1B de tokens MoonCarpet no escrow no Ethereum e 1B de tokens MoonCarpet em sua conta no Optimism. Mas, para garantir que tudo funcione corretamente, ela transfere metade dos tokens (500M MoonCarpet) de volta para a Ethereum.
Então começamos com a transação queimando tokens de 500M no Optimism:
https://optimistic.etherscan.io/tx/0x118a57106488ad0bae1f3b920b1fd98b187752ad966f3a901fc53cff47f2097f
As informações sobre essa transação são passadas para a Ethereum:
https://layerzeroscan.com/111/address/0x201fe0d843b546f2e24d4c8444318d1c71b7d10d/message/101/address/0xc6005ccc1de4b300d538903b74848bff881d5dc5/nonce/1
E, como esperado, 500 milhões de tokens MoonCarpet são devolvidos ao endereço de Alice pelo depósito:
https://etherscan.io/tx/0x27702e07a65a9c6a7d1917222799ddb13bb3d05159d33bbeff2ca1ed414f6a18
Até agora, tudo funciona bem, exatamente como assumido. Alice verificou se ela pode transferir tokens de Ethereum para Optimism e vice-versa, ela não tem motivos para ter medo de seus tokens MoonCarpet.
Mas digamos que algo dê errado — por exemplo, a equipe por trás do nosso token foi comprometida e o mal-intencionado Bob obteve acesso à configuração do LayerZero para nosso aplicativo.
Com esse acesso, Bob pode alterar o Oracle e o Relayer de padrão para aqueles sob seu controle.
Lembre-se de que este é um mecanismo fornecido para todos os aplicativos que usam o LayerZero, arraigado na arquitetura do LayerZero, não é nenhum tipo de backdoor, mas sim um mecanismo padrão.
Então Bob muda o Oracle para um EOA sob seu controle:
https://ethtx.info/mainnet/0x4dc84726da6ca7d750eef3d33710b5f63bf73cbe03746f88dd8375c3f4672f2f/
E faz o mesmo com o Relayer:
https://ethtx.info/mainnet/0xc1d7ba5032af2817e95ee943018393622bf54eb87e6ff414136f5f7c48c6d19a/
E agora coisas estranhas acontecem. Com Oracle e Relayer agora sob controle total de Bob, ele é capaz de roubar os tokens de Alice. Mesmo que nenhuma ação ocorra no Optimism (os tokens MoonCarpet ainda estão na carteira de Alice lá), Bob é capaz de convencer o contrato inteligente MoonCarpet no Ethereum (usando mecanismos LayerZero) de que ele queimou tokens em outra cadeia e pode retirar os tokens MoonCarpet no Ethereum.
Primeiro, ele atualiza o blockhash no Ethereum usando o Oracle desonesto:
https://ethtx.info/0xde2edee2cc7f070120e96c9df90d86696970befcfc221e18c6ac4168bb5b1d92/
E agora ele pode retirar os tokens restantes do depósito:
https://ethtx.info/0xda695f374b375d5372efeca37aae4c5a17f114d5a76db1e86edebb0924bcdcc7/
O resultado
Alice nem saberá por que e quando algo de errado aconteceu. De repente, seus tokens MoonCarpet no Optimism não são mais apoiados por tokens no Ethereum.
Os contratos inteligentes não podem ser atualizados e estão funcionando conforme o esperado. A única atividade suspeita é a mudança de Oracle e Relayer, mas este é um mecanismo regular embutido no LayerZero, então Alice não pode nem saber se essa mudança foi intencional ou não. E mesmo que Alice soubesse dessa mudança, já seria tarde demais - o invasor é capaz de drenar os fundos antes mesmo que ela possa reagir.
E o LayerZero também não poderia ajudar aqui - todas essas foram execuções válidas de seus mecanismos, que eles não podem mais controlar. Teoricamente, o próprio aplicativo pode se impedir de alterar o Oracle e o Relayer, mas, até onde sabemos, nenhum dos aplicativos já implantados o fez.
Fizemos esse experimento para verificar se alguém notou, mas, como esperávamos, ninguém notou. É praticamente impossível monitorar efetivamente todas as aplicações construídas com LayerZero para verificar se sua política de segurança não mudou e avisar os usuários se isso acontecer.
Mesmo que alguém consiga perceber que o Oracle e o Relayer mudaram de uma forma que representa riscos à segurança, quando isso acontece, já é tarde demais. Como o novo Oracle e Relayer agora podem escolher livremente censurar ou simplesmente desabilitar a comunicação entre as cadeias, os usuários geralmente não podem fazer nada a respeito. Isso é claramente mostrado em nosso experimento, pois mesmo que Alice perceba a mudança na configuração do aplicativo, ela não pode fazer muito com seus tokens em ponte — o novo Oracle e o Relayer não escutam mais na cadeia original, então eles não retransmitem o mensagens de volta para Ethereum.
Conclusões e CTA
Como pudemos ver acima, mesmo que nosso token tenha sido construído usando LayerZero e tenha usado sua mecânica conforme pretendido, conseguimos roubar fundos do depósito de tokens. Claro que foi uma falha do aplicativo (token CarpetMoon no nosso caso) e não do próprio LayerZero, mas isso prova que o LayerZero por si só não oferece nenhuma garantia de segurança .
Quando o LayerZero descreve seu modelo de segurança em relação ao Oracle e ao Relayer, eles assumem que os proprietários de aplicativos (ou alguém em posse de suas chaves privadas) não farão nada irracional. Mas essa suposição é incorreta em um ambiente adversário. Além disso, exige que os usuários confiem nos proprietários do aplicativo como terceiros confiáveis.
Na prática, como resultado disso, não se pode fazer suposições sobre a segurança dos aplicativos construídos com o LayerZero — cada aplicativo deve ser considerado arriscado até que se prove o contrário.
Na verdade, toda a história começou para nós com um PR com o qual planejamos incluir todos os tokens omnichain no site L2BEAT - tivemos dificuldade em descobrir como avaliar seus riscos. Ao analisar os vetores de risco, tivemos a ideia de nosso experimento.
Para o L2BEAT, as consequências são que temos que colocar alertas no topo de cada aplicativo construído usando o LayerZero, alertando sobre os possíveis riscos de segurança. Mas gostaríamos de abrir uma discussão mais ampla sobre os modelos de segurança, pois acreditamos que a segurança isolada é um antipadrão que deve ser evitado, principalmente em nosso espaço.
Estamos confiantes de que, à medida que os modelos de segurança isolados, como o LayerZero, se tornam cada vez mais populares, haverá cada vez mais projetos abusando deles, causando muitos danos e aumentando a incerteza sobre toda a indústria.





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)