
Mautic < 5.2.3 RCE Autenticado
A sanitização inadequada do conteúdo, tipo e extensão do arquivo enviado no recurso de Edição de Asset permite que um atacante autenticado escreva código PHP arbitrário dentro do diretório web e localize onde o referido arquivo é gravado. Isso resulta em Execução Remota de Código.
A vulnerabilidade de path traversal também permite explorar essa funcionalidade para excluir recursivamente qualquer diretório no sistema de arquivos que o usuário web tenha permissão para modificar.

Ao editar um Asset através da rota /assets/view/{assetID}, é dada a possibilidade de alterar o arquivo do asset.
O envio de um novo arquivo acaba chamando a seguinte função dentro de app/Bundles/AssetBundle/Controller/AssetController.php:
public function editAction(Request $request, UploaderHelper $uploaderHelper, AssetModel $model, $objectId, $ignorePost = false)
A lógica de upload pode ser encontrada aqui:
if (!$ignorePost && 'POST' == $method) {
$valid = false;
if (!$cancelled = $this->isFormCancelled($form)) {
if ($valid = $this->isFormValid($form)) {
$entity->setUploadDir($this->coreParametersHelper->get('upload_dir'));
$entity->preUpload();
$entity->upload();
Mais particularmente, estamos interessados nos métodos preUpload() e upload(), pois eles lidam com a gravação real do arquivo em disco.
O primeiro defeito está em preUpload() em app/Bundles/AssetBundle/Entity/Asset.php, pois a implementação nos permite especificar uma extensão de arquivo arbitrária (contornando assim a proteção normalmente fornecida pelo array allowed_extensions):
$filename = sha1(uniqid(mt_rand(), true));
$extension = $this->getFile()->guessExtension();
if (empty($extension)) {
// get it from the original name
$extension = pathinfo($this->originalFileName, PATHINFO_EXTENSION);
}
$this->path = $filename.'.'.$extension;
A linha $extension = $this->getFile()->guessExtension(); retornará NULL se fornecermos um nome de arquivo terminando em .php e conteúdo começando com a tag <?php.
A verificação empty($extension) será, portanto, avaliada como true, e a extensão do arquivo será então extraída através da chamada pathinfo(), permitindo-nos enviar arquivos temporários com conteúdo e extensão arbitrários. Não podemos controlar o nome real do arquivo, pois ele é gerado com sha1().
Em seguida, dentro do método subsequente upload(), o arquivo será efetivamente gravado em disco dentro do diretório web através da seguinte chamada:
$this->getFile()->move($this->getUploadDir(), $this->path);
Ele usa nossa extensão arbitrária (contida na variável $this->path). O nome do arquivo pode então ser recuperado atualizando a página de detalhes do Asset (/assets/view/{assetId}), na entrada da tabela Nome de arquivo local.
Observação: Isso também funciona alterando as requisições enviadas ao criar um novo Asset. Isso chamará a função newAction(), mas a lógica é idêntica, e os defeitos ainda estão nos métodos preUpload() e upload().
O PoC não será publicado por mais um mês ou algo assim.
Isso é para dar tempo às organizações que dependem deste software para corrigi-lo sem temer que script kiddies estraguem suas coisas.
Depois disso, este repositório será atualizado com o script de exploração completo e as provas. Já há informação suficiente nesta página, de qualquer forma.
Ao validar um upload temporário (via /s/assets/new ou /s/assets/edit/{assetId}), o diretório que armazena o arquivo temporário é excluído recursivamente ao final da requisição. O parâmetro responsável por armazenar o nome do diretório temporário é suscetível a ataques de path traversal, permitindo que um atacante autenticado exclua qualquer diretório do sistema, desde que o usuário web tenha permissão para tal. Isso pode resultar em perda de dados, ou até mesmo destruição de todo o sistema de arquivos se o servidor for executado pelo usuário root.
Especifique qualquer arquivo que exista no sistema através do endpoint usado abaixo. Se o arquivo existir, o servidor tentará excluir o diretório em que ele está armazenado.

Tomada do servidor Negação de Serviço Perda de Dados