Старый 15.05.2013, 07:57   #21
slashd
 
Регистрация: 06.07.2010
Сообщений: 47
Репутация: 27
По умолчанию

Цитата:
Сообщение от Oops Посмотреть сообщение
Господа, а объясните "для самых маленьких" как баг работает пожалуйста.

Ну понятно что вызывается
static_key_slow_inc(&perf_swevent_enabled[event_id]);
но там до него этот event_id сто раз проверяется на всякие значения, да и не ясно что нам дает в принципе модификация его.
Код:
 http://www.reddit.com/r/netsec/comments/1eb9iw/sdfucksheeporgs_semtexc_local_linux_root_exploit/c9ykrck
slashd вне форума   Ответить с цитированием
Старый 15.05.2013, 10:05   #22
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию

Цитата:
@grsecurity: Second, I have a PoC demonstrating the exploit on Ubuntu -- sd's exploit doesn't work due to CONFIG_JUMP_LABEL and CONFIG_MODULES being on
@grsecurity: so the size of static_key is now 24 bytes instead of 4 bytes -- this introduces some interesting new constraints
@grsecurity: Most important of these is that I'm not able to modify the upper dword of the handler address of any IDT entry on the Ubuntu 12.04LTS kernel
@grsecurity: You can avoid the decrement side-effect (if you choose) by not closing the returned fd from perf_event_open
@grsecurity: Or, more devious, make the kernel clean up for you by providing 0xffffffff for the upper dword of the event_id
@grsecurity: For x86 exploitation, you'll probably want to fork off a bunch of children and have them all hold open fds returned from perf_event_open
@grsecurity: So that you can increment some NULL function pointer to a mappable address
@grsecurity: The size of static_key will be 4 still if CONFIG_JUMP_LABEL is disabled, or 12 if enabled
Куча логов запуска, правда, как обычно с лором и опеннетом, половина из них в утиль, т.к. очень много неразумных людей:
https://www.linux.org.ru/forum/security/9160925/
https://www.linux.org.ru/news/security/9162177/
http://www.opennet.ru/opennews/art.shtml?num=36933
SynQ вне форума   Ответить с цитированием
Старый 15.05.2013, 11:48   #23
Pashkela
 
Аватар для Pashkela
 
Регистрация: 05.07.2010
Сообщений: 1,243
По умолчанию

Чтобы время не тратить, как проверить, что сплойт сработать может в принципе:

Цитата:
$ grep -i PERF_EVENTS /boot/config-$( uname -r )
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_PERF_EVENTS=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
либо:
Цитата:
$ zgrep -i PERF_EVENTS /proc/config.gz
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_PERF_EVENTS=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
ждем for x86

Последний раз редактировалось Pashkela; 15.05.2013 в 11:53..
Pashkela вне форума   Ответить с цитированием
Старый 15.05.2013, 11:48   #24
snake
 
Регистрация: 05.07.2010
Сообщений: 173
Репутация: 12
По умолчанию

тогда уж и быстрофикс:
Цитата:
sysctl -w kernel.perf_event_paranoid=2
sysctl -w kernel.perf_event_max_sample_rate=-1
snake вне форума   Ответить с цитированием
Старый 15.05.2013, 12:30   #25
nikp
Banned
 
Регистрация: 05.07.2010
Сообщений: 201
Репутация: 183
По умолчанию

Debian 7, свежий, из коробки, поднят на виртуалке, отработал.
Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.41-2 x86_64 GNU/Linux
nikp вне форума   Ответить с цитированием
Старый 15.05.2013, 19:47   #26
snake
 
Регистрация: 05.07.2010
Сообщений: 173
Репутация: 12
По умолчанию

Вот почему то 2.6.32-358.2.1.el6.x86_64 #1 SMP Wed Mar 13 рутался,а Scientific Linux release 6.4 с таким же ядром -нет. =(

grep -i PERF_EVENTS /boot/config-$( uname -r )
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_PERF_EVENTS=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
snake вне форума   Ответить с цитированием
Старый 16.05.2013, 10:02   #27
snake
 
Регистрация: 05.07.2010
Сообщений: 173
Репутация: 12
По умолчанию

у кого нибудь была ошибка
Inappropriate ioctl for device ?
пробовал на разных папках и разделах.
2.6.40.6-0.fc15.x86_64 #1 SMP Tue Oct 4 00:39:50 UTC 2011 x86_64 x86_64 x86_64
snake вне форума   Ответить с цитированием
Старый 16.05.2013, 10:07   #28
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию

Отличное описание работы эксплойта by Petr Matousek:
https://bugzilla.redhat.com/show_bug.cgi?id=962792#c16
Код:
The problem is that event_id index in perf_swevent_init is signed and
checked only for it's upper bound. When assigning event->attr.config value
to event_id at the beginning of the function, any attr.config value
which has the 31st bit set will result in negative event_id.
Negative event_id will pass the >= PERF_COUNT_SW_MAX check later in the
code.

Later in the code, write in the form of

  atomic_inc(&perf_swevent_enabled[event_id]);

is present.

perf_swevent_enabled is defined as

atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];

so on RHEL (which does not have jump labels) it is basically array of ints.

When accessing the perf_swevent_enabled array with event_id being int,
event_id is sign extended to 64-bit. In the case of event_id being -1
(0xffffffff), it is sign extended to 0xffffffffffffffff. Because
perf_swevent_enabled is an array of ints (32-bit), the 64-bit value is
multiplied by 4 (32 / 8) and then added to the perf_swevent_enabled
address.

Let's assume

[cynique@intel-d3ce1-01 ~]$ cat /boot/System.map-2.6.32-358.el6.x86_64 | grep perf_swevent_enabled
ffffffff81f360c0 B perf_swevent_enabled

and event->attr.config == 0xffffffff -->

0xffffffffffffffff * 4 + 0xffffffff81f360c0 == 0xFFFFFFFF81F360BC

similarly when event->attr.config == 0xfffffffe -->

0xfffffffffffffffe * 4 + 0xffffffff81f360c0 == 0xFFFFFFFF81F360B8

So in the perf_swevent_init code path we will end up incrementing kernel
mode addresses.

The interesting thing happens in the destroy path, which gets called
when the file descriptor returned by the perf_event_open (invoking this
syscall with the correct parameters will trigger the perf_swevent_init
code path) is being closed:

static void sw_perf_event_destroy(struct perf_event *event)
{
        u64 event_id = event->attr.config;

        WARN_ON(event->parent);

        atomic_dec(&perf_swevent_enabled[event_id]);
        swevent_hlist_put(event);
}

Now event_id is u64, so it's taken from userspace as is.

Let's assume again event->attr.config == 0xffffffff -->

0xffffffff * 4 + 0xffffffff81f360c0 == 0x0000000381F360BC

similarly when event->attr.config == 0xfffffffe -->

0xfffffffe * 4 + 0xffffffff81f360c0 == 0x0000000381F360B8

So in the sw_perf_event_destroy path, we will end up decrementing
userspace addresses for the same values as in the perf_swevent_init code
path.

Now let's take this knowledge and see what the exploit does:

#define BASE  0x380000000
#define SIZE  0x010000000

  assert((map = mmap((void*)BASE, SIZE, 3, 0x32, 0,0)) == (void*)BASE);
  memset(map, 0, SIZE);
  sheep(-1); sheep(-2);    // sheep will just invoke perf_event_open
                           // syscall with attr.config set to the param
  for (i = 0; i < SIZE/4; i++) if (map[i]) {
    assert(map[i+1]);
    break;
  }

So we will map memory region starting at 0x380000000 (see how the 
addresses looked like when accessing perf_swevent_enabled in the
sw_perf_event_destroy code path above) and perform perf_even_open twice
with attr.config values of 0xffffffff and 0xfffffffe. This will result
in two increments on addresses 0xFFFFFFFF81F360BC and 0xFFFFFFFF81F360B8
and two decrements on addresses 0x0000000381F360BC and 0x0000000381F360B8.
The for loop then finds the addresses where the sw_perf_event_destroy
actually landed. That is important for us because this way we can find
out the address of perf_swevent_enabled as we know (from our testing)

0xfffffffe * 4 + 0xXXXXXXXXXXXXXXXX == 0x0000000381F360B8
0xfffffffe * 4 + 0xffffffffZZZZZZYY == 0x00000003ZZZZZZ(YY - 8)

ZZZZZZ   -> 81F360
(YY - 8) -> B8
YY       -> B8 + 8 (+ 8 because we're looking at -2 index to an array of 32bit
                    element size)
YY       -> C0

0xffffffffZZZZZZYY -> 0xffffffff81F360C0

On RHEL we can simply (even as unprivileged user) grep system map for the
address of perf_swevent_enabled, but there are hardened distros that it's
not possible this way.

Knowing the perf_swevent_enabled we move to the real exploitation part.
Because of the properties of the bug, that allows us to increment 32-bit
values, we can in one step change any kernel mode address to user space
one -- for example taking 0xffffffff81f360c0. If we increment the high
32-bits of this address by one, we end with 0x0000000081f360c0.

For this purposes, we choose interrupt descriptor table. An array of
16-byte descriptors:

Offset 	Size 	Description
0 	2 	Offset low bits (0..15)
2 	2 	Selector (Code segment selector)
4 	1 	Zero
5 	1 	Type and Attributes (same as before)
6 	2 	Offset middle bits (16..31)
8 	4 	Offset high bits (32..63)
12 	4 	Zero

The interesting value is at offset 8, on x86_64 it will be 0xffffffff.

The exploit author chose interrupt descriptor corresponding to interrupt
0x4, so the offset is 0x48 from the start of interrupt descriptor table.
We can actually see the offset in the code,

   *p = j?((g<<32)|u):(idt.addr + 0x48);

which setups the needed values for cleanup.

The interrupt descriptor table was chosen because it is very easy to get it's
address even on hardened builds -- using sidt instruction.

So what we do is setup the landing area with the code that just looks up
credentials of the current task, replaces uid/gids to 0, thus granting
full capabilities and also restores the value in idt + 0x48 to 0xffffffff
(*fixptr = -1;).

Once this is done, we are ready to increment the high bits of interrupt
descriptor offset of int 0x4, taking into account the address of
perf_swevent_enabled (distance from it):

  sheep(-i + (((idt.addr&0xffffffff)-0x80000000)/4) + 16);

In this case we do not care about the decrement, which will again land
in our previously prepared memory region, but in the increment.

Invoking asm("int $0x4"); will finally run our shellcode with ring0
privileges. Our "interrupt handler" will increase our task's privileges,
do the idt cleanup as presented above and return back to userspace.

And now we can run /bin/bash as root:

 return execl("/bin/bash", "-sh", NULL);
RHEL/CentOS, пофикшено в kernel-2.6.32-358.6.2.el6.src.rpm

Последний раз редактировалось SynQ; 17.05.2013 в 10:24..
SynQ вне форума   Ответить с цитированием
Старый 17.05.2013, 13:40   #29
12309
 
Регистрация: 25.12.2011
Сообщений: 265
Репутация: 33
По умолчанию

редхат выложил новое ядро в репы: https://rhn.redhat.com/errata/RHSA-2013-0830.html
пофиксено в 2.6.32-358.6.2

Последний раз редактировалось 12309; 17.05.2013 в 13:42..
12309 вне форума   Ответить с цитированием
Старый 17.05.2013, 15:20   #30
blesse
 
Регистрация: 16.08.2012
Сообщений: 24
Репутация: -2
По умолчанию

2.6.32-279.19.1.el6.x86_64 #1 SMP Wed Dec 19 07:05:20 UTC 2012 x86_64
Запускаю-сервак падает
Код:
./a.out>1.txt
в 1.txt пусто

В чем трабла может быть?
blesse вне форума   Ответить с цитированием
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd. Перевод: zCarot