Если вы когда-нибудь сталкивались с SSTI в Jinja2, то вы наверняка гуглили RCE payload и находили что-то монструозное вроде этого:
Этот пейлоад достает класс
К счастью, всё можно сделать гораздо проще:
Здесь мы используем встроенную в Jinja функцию
Вообще, при эксплуатации SSTI-подобных уязвимостей в питоне полезно помнить о существовании свойства
{{''.__class__.mro()[1].__subclasses__()[46]('touch /tmp/rce',shell=True)}}
Этот пейлоад достает класс
Popen
по индексу из наследников object
и исполняет команду. Он не очень-то удобен: индекс Popen
(который в примере равен 46) различается от сетапа к сетапу, поэтому его нужно подбирать.К счастью, всё можно сделать гораздо проще:
{{lipsum.__globals__["__builtins__"].eval("<python code>")}}
Здесь мы используем встроенную в Jinja функцию
lipsum
(она возвращает текст "Lorem ipsum dolor..."), но вместо того чтобы вызывать её, мы через __globals__
достаем её глобальные переменные — а в них нас ждет модуль __builtins__
с функцией eval
.Вообще, при эксплуатации SSTI-подобных уязвимостей в питоне полезно помнить о существовании свойства
__globals__
у всех питоновских функций (кроме встроенных). Если в вашем окружении нет функций, а только объекты — не беда, найдите у него любой метод и возьмите свойство __func__
. Вы получите unbound функцию, у которой уже будет __globals__
.