### Resumo OnionShare CLI/Desktop 2.6.3 não executa a configuração do modo Receber `disable_files` na pia de upload do arquivo. Quando um serviço Receber é configurado como um endpoint de texto somente (`-- deshable-files` / "Deshabilitar o carregamento de arquivos"), um remitente remoto que pode alcançar o serviço OnionShare ainda pode enviar um pedido multiparte criado contendo `file[]`; OnionShare escreve os bytes carregados no disco antes do gerenciador da rota pular a contabilidade de arquivos. Isto afeta o pacote `onionshare-cli` Python' enviado e o aplicativo de área de trabalho, porque ambos usam a mesma implementação de streaming de pedidos `onionshare_cli.web.receive_mode`. ### Detalhes Arquivo testado: ` no commit ` 8 cc 75 e 1 d 7 e 88 bd 31 f 7276733449 d 412 bf 71 c 8999 `.
Evidências do produto afetadas: - `cli/pyproject.toml` declara `onionshare_cli` versão ` 2.6.3 `. - `desktop/pyproject.toml` declara versão `onionshare` ` 2.6.3 ` e depende de `onionshare_cli` a partir de `../cli`. - `cli/ setup.py` publica `onionshare-cli` e inclui `onionshare_cli.web` mais modelos/ recursos estatísticos. - `desktop/ setup.py` publica `onionshare` e expõe os scripts de console `onionshare` e `onionshare-cli`. Caminhos padrão/comum acessíveis: - O modo CLI Receive é exposto através de `-- receive` (`cli/onionshare_cli/_init__.py: 55 - 57 `). - A opção `-- deshable-files` é documentada e armazenada nas configurações do modo (`cli/onionshare_cli/_init__.py: 156 - 160 `, `cli/onionshare_cli/_init_.py: 254 - 261 `). - O modo Receber o Desktop expõe a mesma configuração através da caixa de seleção "Desabilitar o carregamento de arquivos" e armazena- a como "receive.disable_files` (`desktop/onionshare/tab/mode/receive_mode/_init__.py: 89 - 99 `, `desktop/onionshare/tab/mode/receive_mode/_init__.py: 246 - 254 `). - A documentação do usuário diz "Desabilitar o upload de arquivos" deve "apenas permitir enviar mensagens de texto, como para um formulário de contato anônimo" (`docs/source/features.rst: 64 `). - Listas de documentação avançadas `-- deshable-files` e ` deshable_files` como opção para desativar arquivos de recepção (`docs/source/ advanced.rst: 162 - 163 `, `docs/source/ advanced.rst: 455 `). Causa raíz: - O modelo Receber esconde o entrada do arquivo quando `disable_files` está definido (`cli/onionshare_cli/resources/templates/receive.html: 51 - 56 `), mas este é apenas o lado UI. - A rota `/upload` pula `request.files.getlist("file[]")` e a contabilidade de arquivos quando `disable_files` está ativada (`cli/onionshare_cli/web/receive_mode.py: 96 - 135 `). No entanto, por este ponto o Werkzeug já analizou o corpo multiparte e invocou a fábrica de fluxo personalizado. - `ReceiveModeRequest.__init_()` trata cada `POST /upload' ou `POST /upload-ajax' como um pedido de upload e cria um diretório de receção independentemente de `disable_files` (`cli/onionshare_cli/web/receive_mode.py: 369 - 391 `). - `ReceiveModeRequest._get_file_stream()` cria um 'receiveModeFile' escrito para cada parte carregada sem verificar `self.web.settings.get("receive", "disable_files")` (`cli/onionshare_cli/web/receive_mode.py: 517 - 540 `). - `ReceiveModeFile` abre ` / .part`, escreve bytes controlados pelo atacante, em seguida, renomea o arquivo `.part` para o nome final do arquivo (`cli/onionshare_cli/web/receive_mode.py: 272 - 285 `, `cli/onionshare_cli/web/receive_mode.py: 320 - 346 `).
A triagem falsamente positiva: - `secure_filename()` é usada em `cli/onionshare_cli/web/receive_mode.py: 111 - 113 ` e `cli/onionshare_cli/web/receive_mode.py: 527 - 528 `, assim o problema confirmado não é o caminho transversal; o arquivo é escrito sob o diretório de dados de receção configurado. - A interface de usuário que esconde a entrada do arquivo é desviada pelo POST multiparte direta. - Nível de rota ` se não desabilitar_ arquivos` afeta apenas o comportamento contábil/ estatus/ webhook; ele não impede que o imersão do fluxo crie e escreva o arquivo. - Os serviços de cebola não- público por omissão exigem que o remetente conheça o endereço de cebola e a chave privada, a menos que o usuário opte por modo público. Isto limita a exposição, mas não aplica a política de segurança "só texto" selecionada pelo usuário para remetentes autorizados ou implantações de formulários de contato público. - Um caso de controle com `disable_text=True` mostrou que o texto enviado não foi escrito como arquivo de mensagem, demonstrando que o arnês estava exercendo o limite de configurações. Versão afetada / versões corrigidas: - Versão afetada: desconhecida; confirmada na versão ` 2.6.3 ` no commit ` 8 cc 75 e 1 d 7 e 88 bd 31 f 7276733449 d 412 bf 71 c 8999 `. As versões anteriores não foram testadas durante esta auditoria. - Versão Patched: 2.6.4 Justificação: `AV:N` porque o objetivo Receber é alcançado através do serviço HTTP OnionShare; `AC:L` porque um POST multiparte criado é simples quando o serviço é alcançável; `PR:L` porque o remetente geralmente precisa da chave URL/privada OnionShare a menos que o receptor exerça intencionalmente modo público; `UI:N` porque não é necessária nenhuma interação adicional do receptor após a inicialização do serviço; `S:U` porque o mesmo aplicativo local escreve o arquivo; `C:N` porque este PoC não lê os dados; `I:L` porque o atacante escreve arquivos indesejados num modo configurado para rejeitar arquivos; `A:L` porque o bypass pode consumir disco/ armazenamento apesar da política de arquivos desativada, delimitada pelos controles disponíveis do disco e do operador.
### PoC A seguinte prova local segura usa apenas diretórios temporários e cliente de teste local do Flask. Neste ambiente de auditoria, várias dependências de execução estavam ausentes (`camatera', `flask_compress', `flask_socketio', `unidecode', `stem', `qrcode'), então o arnês estuprou essas importações enquanto executava o real 'receive_mode' pedido de análise e código de escrita de arquivos. Nenhum tráfego de rede externo foi enviado e nenhum arquivo real fora dos diretórios temporários foi modificado. Reprodução do mantenedor a partir de uma checkout limpa com dependências normais pode omitir os stubs de importação e executar a mesma configuração do cliente de teste, ou pode iniciar um serviço local Receba com `--disable-files` e enviar um pedido multiparte para `/upload- ajax`. Configuração e acionamento positivos: ```python import os, tempfile, shutil from io import BytesIO from onionshare_cli.common import Comum from onionshare_cli.settings import Configurações from onionshare_cli.mode_settings import ModeConfigurações from onionshare_cli.web import Web.
base = tempfile.mkdtemp(prefix='os-disable-files-poc-') data_dir = os.path.join(base, 'receive-data') os.mkdir(data_dir). comum = Common() common.settings = Configurações(common) mode_settings = ModeSettings(common) web = Web(common, False, mode_settings, 'receive') web.app.testing = Verdadeiro web.proxies = Nenhum web.settings.set('receive', 'data_dir', data_dir) web.settings.set('receive', 'disable_files', Verdadeiro) com web.app.test_client() como c: res = c.post( '/upload-ajax', buffered=True, content_type='multipart/form-data', data={'file[]': (BytesIO(b'DISABLE_FILES_BYPASS_MARKER'), 'audit.txt'}, ) print(res.status_code) print(res.get_data(as_text=True)) para root, dirs, arquivos em os.walk(data_dir): para nome em arquivos: path = os.path. join(root, name) print(os.path.relpath(path, data_dir), open(path, 'rb'). leia().decode()) shutil.rmtree( base) ```. Saída observada deste ambiente após re- executar a prova após a redação: ```text May 29, 06: 13 PM: Envio do tamanho total 274.0 B está começando => 27.0 B audit.txt positive_ estatus: 200 response_ positive: {"info_flashes": ["Nada enviado ou mensagem foi muito longo (> 524288 caracteres)"]} positivo_ escrito: [(' 2026 - 05 - 29 / 181347904165 /audit.txt', 'DISABLE_FILES_BYPASS_MARKER')].
A resposta diz que nada/sem arquivo foi enviado, mas o arquivo ` audit.txt` foi criado sob a pasta Receber dados. Caso negativo/controle: ``` 'python web 2.settings.set('receive', 'disable_text', Verdadeiro) # POST apenas um campo de texto para /upload-ajax ``` Saída do controle observado: ``` text control_ estatus: 200 controle_resposta: {"info_flashes": ["Nada enviado"]} controle_escrito_archivos: [] cleanup_done: true ```.
Limpeza: - O PoC exclui todos os diretórios temporários com `shutil.rmtree(...)'; a execução da auditoria impresso `cleanup_ done: true'. ### Impacto Um operador de serviço Receber pode configurar o OnionShare como um objetivo de submissão somente de texto (por exemplo, um formulário de contato anônimo) e ainda receber arquivos controlados pelo atacante no disco. Isto evita a restrição explícita selecionada pelo usuário e pode levar à colocação de arquivos indesejados e ao consumo de disco em uma implantação onde os carregamentos de arquivos foram intencionalmente desativados. A resposta e a contabilidade da GUI/história podem ser enganosas porque a rota não processa o arquivo enquanto o fluxo de solicitação de nível inferior já escreveu o arquivo. Isto pode retardar a detecção pelo operador.
O problema confirmado não fornece caminho arbitrário atravessando porque os nomes de arquivos são desinfectados e escreve ocorrem sob o diretório de dados Receber configurado. ### Remediação sugerida Forçar `disable_files` antes de qualquer fluxo de arquivos multiparte ser escrito, não apenas no gerenciador de rotas ou modelo: - Em `ReceiveModeRequest._get_file_stream()', se `self.web.settings.get("receive", "disable_files")` é verdade, rejeitar a parte do arquivo antes de criar `ReceiveModeFile', ou encaminha- o para um fluxo de descarte e marcar o pedido como rejeitado. - Garantir que `/upload' e `/upload-ajax' retornem um erro explícito quando os arquivos são enviados enquanto os arquivos estão desativados. - Evitar criar um subdiretório de receção para um pedido somente de arquivo que é rejeitado pela política. - Adicionar testes de regressão para `/upload' e `/upload-ajax' que provam que nenhum arquivo aparece sob `receive.data_dir` quando `receive.disable_files' é verdadeiro. - Adicionar um teste de regressão de controle que prova `disable_text` ainda impede a criação de arquivo de mensagem.
Registro de aconselhamento: GHSA-v 833 - 3823 - Cmhp. Identificadores relacionados: CVE- 2026 - 54707. Tempo: GitHub Advisory Database publicou este registro em 2026 - 07 - 31 T 16: 27: 59.000 Z e lista a sua última modificação como 2026 - 07 - 31 T 16: 27: 59.000 Z. Gravidade: MODERAR. Dados de pontuação publicados: CVSS_V 3: CVSS: 3.1 /AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L.
Software afetado e informações de versão: pacote PyPI onionshare-cli — ECOSYSTEM: introduzido 0, corrigido 2.6.4. Classificação e evidência: identificadores de fraqueza CWE- 863. O registro contém 4 suporte de referências nestes tipos: WEB, PACKAGE.