Destaque de vulnerabilidade: Um mergulho profundo na conectividade em nuvem do WAGO e nas vulnerabilidades que surgem

Views: 568
0 1
Read Time:15 Minute, 16 Second

Destaque de vulnerabilidade: Um mergulho profundo na conectividade em nuvem do WAGO e nas vulnerabilidades que surgem

A WAGO fabrica vários controladores de automação programáveis que são usados em muitos setores, incluindo automotivo, ferroviário, engenharia de energia, fabricação e gerenciamento de edifícios. A Cisco Talos descobriu 41 vulnerabilidades em seus controladores PFC200 e PFC100. De acordo com nossa política de divulgação coordenada, a Cisco Talos trabalhou com a WAGO para garantir que esses problemas fossem resolvidos e que uma atualização de firmware esteja disponível para os clientes afetados.Como um patch está disponível para clientes afetados há algum tempo, queríamos aproveitar essa oportunidade para discutir várias cadeias de ataque que exploram o cliente de conectividade em nuvem da WAGO conhecido como “dataagent” para obter acesso raiz ao dispositivo. Você também pode assistir a uma apresentação técnica dessas vulnerabilidades na conferência virtual CS3Sthlm em 22 de outubro de 2020.
O WAGO fornece um recurso de conectividade em nuvem para que os usuários acessem a telemetria remota de seus dispositivos e até emitam atualizações de firmware remotamente. A conectividade em nuvem fornece um vetor de ataque interessante, onde o ataque se origina de um provedor de nuvem confiável, mas a própria instância da nuvem é controlada pelo invasor. O cenário em que mergulharemos hoje é aquele em que o invasor tem acesso à infraestrutura de nuvem legítima e pode abusar do protocolo personalizado da WAGO para obter privilégios raiz no dispositivo.
Primeiro mergulharemos nos detalhes técnicos de cada uma das vulnerabilidades em si. Então discutiremos como essas vulnerabilidades podem ser combinadas em duas cadeias de ataque distintas que resultam na capacidade de obter privilégios radiculares no dispositivo.

Reconhecimento

ENTENDENDO AS VULNERABILIDADES

Execução remota de código remoto de comando de atualização de firmware(TALOS-2019-0954/CVE-2019-5161)
Um dos recursos habilitados pelo dataagent é a capacidade de atualizar o firmware em dispositivos da nuvem. Esse recurso imediatamente se destacou para nós, pois envolveria vários arquivos e eventualmente executaria comandos do sistema no dispositivo para executar a atualização. Eventualmente, descobrimos várias vulnerabilidades no manuseio do comando de atualização de firmware do serviço dataagent. Este serviço lida com a comunicação com várias plataformas em nuvem que suportam o protocolo MQ Telemetria Transport (MQTT).
A funcionalidade de atualização de firmware foi projetada de tal forma que o aplicativo em nuvem enviará uma mensagem codificada por JSON através do protocolo MQTT. Aqui está um exemplo do comando para iniciar uma atualização de firmware:

O processo de atualização do firmware é tratado usando uma máquina estatal. O primeiro estado no processo de atualização do firmware é iniciado após o recebimento da mensagem de atualização de firmware da nuvem ‘CommandId: 506’. O código de análise de protocolo dentro do dataagent extrai cada um dos valores contidos na mensagem JSON de atualização de firmware acima. Cada um deles é passado para um utilitário externo chamado ‘fwupdate’ na forma ‘-i “<keyname>=<user-supplied-value>”, resultando na execução total do comando por ‘system()’. [2]

Cada um dos parâmetros ‘<cloud-supplied-value>’ é vulnerável à injeção de comando do sistema operacional porque o comando ‘sudo fwupdate’ é executado através de uma chamada para ‘system()’ sem qualquer higienização de entrada. Essas vulnerabilidades são identificadas como TALOS-2019-0948 através do TALOS-2019-0950 (CVE-2019-5155 – CVE-2019-5157).
Temos injeção de comando do SISTEMA OPERACIONAL. Então, o que podemos fazer com ele? Acontece que não há muito, pois o serviço de dataagent está sendo executado como um usuário não raiz chamado ‘iot’. Isso não nos vai fazer ver o acesso raiz da nuvem como estamos procurando.

O próximo estado afirma que a máquina estatal de atualização de firmware entra é chamada de “DOWNLOAD_FIRMWARE”. Neste estado, o processo de dataagent usa ‘FirmwareStorageAccount’, ‘FirmwareStoragePath’ e ‘FirmwareControlFile’ concadados para formar uma URL para um arquivo que será baixado via curl para o diretório ‘/tmp’ do dispositivo. A partir da mensagem de atualização de firmware acima, isso baixaria o arquivo hospedado em ‘https://attackerstorage.blob.core.windows.net/test/poc_controlFile.xml’. Depois que este arquivo é baixado, libxml2 analisa-o e segue um formato semelhante ao abaixo.

O trecho de código abaixo mostra parte da validação realizada no conteúdo do ‘FirmwareControlFile’. O código está construindo uma lista de arquivos adicionais a serem baixados. Isso mostra que o atributo ‘Tipo’ do nó ‘Arquivo’ deve ser igual a ‘raucb’ a ser adicionado à lista de downloads.

Em seguida, os arquivos adicionais especificados no ‘FirmwareControlFile’ serão baixados da URL especificada por ‘FirmwareStorageAccount’ e ‘FirmwareStoragePath’ do comando original do Firmware Update e do atributo ‘Name’ do nó ‘Arquivo’ dentro do ‘FirmwareControlFile’. Assim, em nosso exemplo, ‘https://attackerstorage.blob.core.windows.net/test/update_V030039_12_r38974.raucb’ será baixado via curl para o local especificado pelo atributo ‘TargetPath’ dentro do ‘FirmwareControlFile’.
Agora podemos baixar qualquer número de arquivos adicionais e especificar o caminho no dispositivo onde eles devem ser armazenados. Não há limite na localização ‘TargetPath’ ou no número de arquivos a serem incluídos se o atributo ‘Tipo’ for ‘raucb’. Mas o atributo ‘Tipo’ não precisa corresponder à extensão do arquivo dentro do ‘Nome’ ou ‘TargetPath’. No entanto, ainda estamos limitados a locais no dispositivo onde o usuário de IoT pode gravar, o que é limitado a ‘/tmp’.
Agora que todos os arquivos necessários foram baixados, o próximo estado no processo de atualização de firmware é ‘START’. Neste estado, a utilidade externa ‘fwupdate’ é executada. Desta vez com o parâmetro ‘start’. O comando completo executado é ‘system(‘sudo fwupdate start’)’. O utilitário ‘fwupdate’ é um invólucro para outros utilitários fwupdate*. O comando ‘fwupdate start’ eventualmente leva a uma chamada para ‘fwupdate_background_service atualização inicial’. Abaixo está um trecho de código dessa função shell:

Aqui, vemos que se um gancho de pré-instalação de atualização de firmware existir, ele será executado. Como lembrete, este script ‘fwupdate_background_service’ está sendo executado com privilégios sudo, de modo que o gancho de pré-instalação também será executado como o usuário raiz. Podemos ver a variável definida abaixo.

O que temos agora é a capacidade de gravar qualquer arquivo para ‘/tmp’ no dispositivo, e se escrevermos um arquivo para o local ‘/tmp/fwupdate/fwupdate_hook_preinstall.sh’ ele será executado como raiz.
Validação inadequada do host (TALOS-2019-0953/CVE-2019-5160)
Agora que encontramos vulnerabilidades no comando de atualização de firmware suportado pelo dataagent, vamos ver se há alguma restrição em relação a qual plataforma de nuvem pode enviar esse comando. O serviço de dataagent pode ser configurado para se conectar a vários fornecedores de infraestrutura em nuvem, incluindo: WAGO Cloud, Microsoft Azure, IBM Cloud, Amazon Web Service e SAP IoT Services.
Aqui, vemos que se um gancho de pré-instalação de atualização de firmware existir, ele será executado. Como lembrete, este script ‘fwupdate_background_service’ está sendo executado com privilégios sudo, de modo que o gancho de pré-instalação também será executado como o usuário raiz. Podemos ver a variável definida abaixo.

O trecho de código acima mostra que o comando de atualização de firmware é processado somente se o serviço de dataagent estiver configurado para usar o tipo de nuvem ‘WAGO Cloud’. Caso contrário, a mensagem é descartada. Quando configurado para ‘WAGO Cloud’, o serviço usa o SDK Azure IoT para se comunicar com uma instância do Azure IoT Hub que está executando um aplicativo personalizado WAGO Cloud. Este aplicativo é um serviço de assinatura oferecido pela WAGO que está hospedado no ‘wagocloud.azure-devices.net’.
A configuração do Dataagent é realizada através do aplicativo web De Gerenciamento Baseado na Web (WBM) fornecido pelo dispositivo. Ao selecionar a plataforma em nuvem como ‘WAGO Cloud’, o aplicativo web não realiza nenhuma validação no hostname fornecido. Todas as instâncias do Azure IoT Hub autenticam com um certificado curinga – garantindo que o nome do host seja ‘*.azure-devices.net’, o que não é um problema em si. No entanto, é um problema com a implementação do comando de atualização de firmware da WAGO. O WAGO pretendia limitar a funcionalidade de atualização de firmware para que esse recurso só estivesse disponível para o aplicativo em nuvem WAGO. O problema é que qualquer instância do Azure IoT Hub terá um certificado válido para autenticar com nosso dispositivo que é um cliente do Azure IoT Hub. Isso significa que qualquer instância do Azure IoT Hub pode usar a funcionalidade de atualização de firmware do WAGO. A falta de validação do hostname do aplicativo de nuvem WAGO configurado é TALOS-2019-0953/CVE-2019-5160. Essa vulnerabilidade permite que um invasor configure o serviço de dataagent para se conectar a uma instância do Azure IoT Hub controlado pelo invasor.
Exposição de informações WBM de credenciais de administração (TALOS-2019-0923/CVE-2019-5134 & TALOS-2019-0924/CVE-2019-5135)
As credenciais de administração WBM são necessárias para configurar o dataagent com um nome de host controlado pelo invasor. Os usuários do WBM são isolados dos usuários do sistema Linux como uma medida de segurança no dispositivo. Com duas vulnerabilidades na função ‘PasswordCorrect’ de ‘login.php’ poderíamos vazar as credenciais de usuário hashed. Abaixo está a função ‘PasswordCorrect’:

O arquivo de senha é separado dos usuários do Linux e é armazenado em ‘/etc/lighttpd/lighttpd-htpassword.user’. As expressões regulares utilizadas na função ‘PasswordCorrect’ não são inacorridas, o que permite que a entrada do usuário contorne o filtro de expressão regular (TALOS-2019-0923/CVE-2019-5134). Por exemplo, um valor ‘$username’ de ‘(?x)administrador….’ corresponderá à linha no arquivo de senha contendo ‘administrador:$6$’. O impacto de ignorar o filtro de expressão regular é que agora somos capazes de testar a entrada do usuário contra o hash de senha contido no arquivo de senha. Se essa primeira verificação do nome de usuário dentro da linha de arquivos de senha passar, a função PHP crypt() será chamada. A função crypt() introduz um atraso perceptível na resposta, o que nos permite realizar um ataque de tempo (TALOS-2019-0924/CVE-2019-5135). Com nosso valor de nome de usuário de bypass de ‘(?x)administrador….’ podemos anexar caracteres ascii a esse valor e medir o atraso na resposta para determinar se a função ‘cripta’ foi chamada ou não. Isso revelará quais caracteres estão contidos no hash da senha.
iocheckCache.xml injeção de comando e execução de código (TALOS-2019-0961/CVE-2019-5166TALOS-2019-0963/CVE-2019-5182)
Anteriormente, discutimos que poderíamos especificar um arquivo a ser baixado através do arquivo de controle de atualização de firmware do dataagent para o dispositivo, bem como o nome e o caminho do arquivo. No entanto, estamos limitados ao diretório ‘/tmp’ onde o usuário limitado de IoT pode escrever.
Para nossa sorte, acontece que um serviço separado no dispositivo chamado iocheckd usa um arquivo chamado ‘iocheckCache.xml’ no diretório ‘/tmp’ para armazenar arquivos de cache para algumas configurações de rede que requerem várias mensagens para configurar corretamente. Normalmente, uma mensagem enviada para o serviço iocheckd gerará ‘/tmp/iocheckCache.xml’ contendo novos parâmetros como hostname ou endereço IP. Em seguida, uma mensagem de parâmetro de salvamento lerá o conteúdo de ‘iocheckCache.xml’ e executará comandos do sistema para modificar as configurações do dispositivo. Como existem muitos nós XML possíveis que compartilham vulnerabilidades semelhantes, há um total de 18 vulnerabilidades relacionadas à análise do iocheckd deste arquivo de cache. Este post se concentrará na injeção de comando do SO (TALOS-2019-0962/CVE-2019-5167-CVE-2019-5175). Abaixo está o código vulnerável:

A injeção de comando do SISTEMA OPERACIONAL é possível porque o ‘xmlHostnameNodeValue’ do arquivo XML é copiado diretamente para o buffer de comando usando sprintf(). Sem qualquer validação, essa sequência é passada para uma chamada para ‘system()’. Adicionando um caractere de expansão de shell, podemos executar comandos adicionais do SO. O serviço iocheckd está sendo executado como usuário raiz, então nossos comandos de SO também serão executados como raiz.

Exploração

Passaremos por duas cadeias de exploração, cada uma executando comandos da nuvem resultando em execução de código no contexto raiz do dispositivo. O primeiro será o uso do gancho de pré-instalação da atualização do firmware, e o segundo envolverá o uso do mecanismo de atualização de firmware para colocar um arquivo iocheckCache.xml no dispositivo que será então aproveitado para obter a execução de comando como usuário raiz. Esses exemplos de exploração foram realizados na versão 13 do firmware PFC 200 que pode ser encontrado aqui.

CONECTE-SE À NUVEM CONTROLADA PELO ATACANTE

Em cada um de nossos cenários de ataque precisamos configurar o dispositivo para que ele se conecte a um Hub Azure IoT sob nosso controle. Usando o TALOS-2019-0923 andTALOS-2019-0924, vazaremos as credenciais de administradores do WBM e, em seguida, decifra a senha usando hashcat. Isso porque precisamos ter privilégios administrativos WBM para configurar o serviço de dataagent no dispositivo. Como mencionado acima, usaremos um ataque de tempo contra a função PHP crypt() para extrair o hash de senha do administrador da Web. O hash de senha de usuário do administrador da web vazado está abaixo.

Agora que temos a senha hashed, podemos decifrá-la usando hashcat.

Como mostrado acima, a senha do usuário administrador do WBM é ‘T@l0s’. Usando o TALOS-2019-0953, podemos configurar o serviço de dataagent para conectar ao nosso ‘attackerIotHub.azure-devices.net’ da instância do IoT Hub com a seguinte solicitação de postagem:

CADEIA DE ATAQUE 1: GANCHO DE PRÉ-INSTALAÇÃO

Agora que o dispositivo está configurado para se conectar à nossa nuvem controlada por invasores, podemos explorar a atualização do firmware pré-instalar a vulnerabilidade do gancho (TALOS-2019-0954) para executar comandos do SISTEMA COMO o usuário raiz. Para explorar essa vulnerabilidade, o invasor deve criar dois arquivos: o arquivo de controle XML e um script shell que será executado como raiz no sistema. Esses dois arquivos devem ser hospedados em um servidor que o dispositivo pode baixar via curl. Para este exemplo, hospedaremos os arquivos em uma conta de armazenamento Microsoft Azure. Aqui está o conteúdo do arquivo de controle XML:

Lembre-se de que cada nó de arquivo com o atributo Tipo “rauc” será escrito no dispositivo no local especificado pelo atributo TargetPath. O arquivo “raucb.txt” é especificado porque um arquivo deve existir no caminho ‘/tmp/fwupdate’ com a extensão do arquivo ‘.raucb’ para que o gancho de pré-instalação seja executado. O conteúdo do arquivo ‘.raucb’ não importa para explorar essa vulnerabilidade. O arquivo ‘rootShell.sh’ contém nosso script que será executado como raiz no dispositivo:

Este script lançará telnetd, que é um servidor de protocolo TELNET. Este é o utilitário telnetd fornecido pela busybox. O parâmetro ‘-l’ especifica um executável para ser executado quando uma nova conexão é feita. O objetivo disso é fornecer funcionalidade de login, mas usaremos essa opção para nos dar uma concha raiz em vez de fazer login. O parâmetro ‘-p’ especifica a porta para telnetd ouvir.
A Microsoft fornece uma extensão útil ao Visual Studio Code, que permite que os usuários monitorem mensagens de dispositivos IoT. Ao se conectar ao Azure IoT Hub pela primeira vez, o dispositivo envia essas duas mensagens indicando as versões do protocolo que o dispositivo suporta:

Para enviar mensagens ao nosso dispositivo IoT Hub, usaremos o azure-sdk-for-jsdo Microsoft Azure . O script de ataque está imitando o comportamento do aplicativo em nuvem do WAGO usando as mesmas sequências de mensagens e estrutura. Este script enviará uma mensagem ‘CloudHello’ para negociar a versão do protocolo com o dispositivo. Em seguida, após o recebimento de uma mensagem ‘Heartbeat’, este script enviará o comando de atualização de firmware que explorará o dispositivo. A atualização do firmware falhará, mas somente após a execução do script de gancho pré-instalado. Depois que o script for executado, podemos nos conectar a ele usando qualquer cliente telnet na porta 1234:

CADEIA DE ATAQUE 2: IOCHECKCACHE.XML

Podemos usar o comando de atualização de firmware para colocar um arquivo iocheckCache no diretório ‘/tmp’ e, em seguida, enviar uma mensagem para o serviço iocheckd para explorar (TALOS-2019-0962). Da mesma forma, precisaremos de dois arquivos para explorar essa vulnerabilidade: o arquivo de controle xml e o arquivo xml iocheckCache. Abaixo estão o conteúdo do arquivo de controle XML:

Para esta exploração, usaremos o nó de nome host dentro do arquivo iocheckCache para injetar um comando do sistema operacional:

Novamente, estamos usando o servidor telnetd para fornecer um shell raiz através da porta 1234. Usaremos o mesmo script de ataque de antes, só que desta vez especificaremos o arquivo de controle acima. De forma semelhante, a atualização do firmware falhará, uma vez que não fornecemos uma imagem de firmware válida dentro do comando. No entanto, o arquivo ‘/tmp/iocheckCache.xml’ permanece no dispositivo:

Mais tarde, podemos enviar uma mensagem separada para o serviço iocheckd em execução no PLC na porta 6626, que acionará a análise do iocheckCache.xml e executará nosso comando injetado. Depois de causar iocheckd para analisar o arquivo de cache, podemos nos conectar a ele usando qualquer cliente telnet na porta 1234:

CONCLUSÃO

Este post destacou um vetor de ataque interessante, usando infraestrutura de nuvem controlada por invasores para se passar por um aplicativo de nuvem de fornecedor. Embora o Azure IoT Hub forneça criptografia e autenticação, o WAGO não implementou validação adicional do aplicativo em nuvem em si. A conectividade em nuvem está aumentando nas aplicações industriais e os fabricantes devem ter em mente que os dados originários da nuvem devem ser tratados como dados não confiáveis. Quando acorrentadas, essas vulnerabilidades fornecem ao atacante acesso remoto raiz. Um invasor poderia então usar esse acesso para interromper qualquer um dos processos críticos que o WAGO PFC manipula.

Cobertura

As seguintes regras do SNORT(R) detectarão tentativas de exploração. Observe que regras adicionais podem ser liberadas em uma data futura e as regras atuais estão sujeitas a alterações pendentes de informações adicionais de vulnerabilidade. Para obter as informações de regras mais atuais, consulte o Centro de Gerenciamento do Poder de Fogo ou Snort.org.

Regras do Snort: 52023, 52131, 52237, 52238, 52407, 52408, 52412

FONTE: TALOS

POSTS RELACIONADOS