
Эксплойт для подтверждения концепции для CVE-2018-1000533, уязвимость удаленного выполнения кода в GitList 0.6.0 через несанитизированный ввод в функции поиска, позволяющая выполнение произвольных команд.
GitList — современный просмотрщик Git-репозиториев.
В GitList версии 0.6.0 и ниже существует уязвимость, связанная с передачей неправильно проверенных входных данных в системные функции, что позволяет выполнять произвольные команды с правами пользователя PHP.
Чтобы запустить сервер GitList 0.6.0, выполните следующую команду:
docker compose up -d
Перед запуском poc.py установите зависимости:
pip install requests
После настройки среды откройте http://127.0.0.1:8080 и проверьте, существует ли тестовый репозиторий с именем example.
GitList использует git grep для поиска кода в репозитории.
public function searchTree($query, $branch)
{
if (empty($query)) {
return null;
}
$query = escapeshellarg($query);
try {
$results = $this->getClient()->run($this, "grep -i --line-number {$query} $branch");
} catch (\RuntimeException $e) {
return false;
}
Здесь $query — ключевое слово поиска, а $branch — целевая ветка для поиска.
Если злоумышленник передаст в качестве запроса --open-files-in-pager=id;, то в системе выполнится команда id.
Эта уязвимость возникает по двум причинам:
Ограничение функции escapeshellarg()
Теоретически после выполнения $query = escapeshellarg($query); входное значение становится строкой, заключенной в одинарные кавычки. Однако escapeshellarg() защищает от инъекций с точки зрения оболочки (shell), но не предотвращает интерпретацию строк, начинающихся с --, как параметров парсером опций самого git.
Особенность опции --open-files-in-pager
Эта опция git grep указывает внешнюю программу пейджера для отображения результатов поиска. Ее особенность в том, что переданное значение напрямую выполняется как системная команда.
[repo_name]/tree/[keyword]/search), содержит два аргумента: [repo_name] и [keyword].[repo_name] должен быть репозиторием, существующим в GitList, а [keyword] — ключевым словом, дающим хотя бы один результат поиска.
(В данной демонстрации используется репозиторий example и ключевое слово a.)Запустите poc.py следующей командой:
Этот скрипт выполняет touch /tmp/success_dddo0, создавая пустой файл success_dddo0 в каталоге /tmp сервера.
python3 poc.py http://127.0.0.1:8080
После отправки запроса проверьте, что success_dddo0 был успешно создан, с помощью следующей команды:
docker compose exec web ls -l /tmp/success_dddo0
После выполнения PoC видно, что произвольная системная команда (touch /tmp/success_dddo0) была успешно выполнена на сервере, создав файл.

docker compose down
Необходимо обновить GitList до последней версии.
Изменения в коде:
public function searchTree($query, $branch)
{
if (empty($query)) {
return null;
}
$query = preg_replace('/(--?[A-Za-z0-9\-]+)/', '', $query);
$query = escapeshellarg($query);
try {
$results = $this->getClient()->run($this, "grep -i --line-number -- {$query} $branch");
} catch (\RuntimeException $e) {
return false;
}
В GitList для исправления уязвимости используется регулярное выражение для удаления недопустимых префиксов - из поискового запроса ($query), а в команду git grep добавляется -- (обозначение конца опций), чтобы принудительно интерпретировать все последующие входные данные как обычные строки (поисковый запрос), а не как параметры команды.